Forum: Mikrocontroller und Digitale Elektronik Verzögerung der Messwert Übertragung


von Anton L. (pavlov)


Lesenswert?

Hallo liebe Mikrocontroller Gemeinde,
Ich habe folgendes Problem und zwar arbeite ich im mom. mit einer 
Digital-Wert Übertragung an eine Java GUI.
Das Programm an sich und die Übertragung des Digital wertes an sich 
funktioniert einwandfrei, nur möchte ich dort eine kleine Änderung 
einbauen, wofür ich sehr dankbar währe wenn ihr mir helfen könntet.

Ist Zustand: Momentan überträgt das Programm den Digitalwert eines sich 
stetig ändernden Widerstandes,  sobald der Taster „PINB,0“ betätigt 
wird, sendet dass Programm wiederholt im Sekunden tackt an die GUI. So 
dass immer der Aktuelle Digitalwert in der GUI gezeigt wird.

Soll Zustand: Ich möchte dass nach Betätigung des Tasters „PINB,0“ 
innerhalb 10 Sekunden der Maximal wert des Widerstandes ermittelt wird 
und dann dieser Maximale wert nur ein mahl an die GUI gesendet wird.

lg Tony
1
// ----------------------------------------------------------------
2
// CPU Takt des verbauten Quarz vorgeben
3
// ----------------------------------------------------------------
4
5
#define F_CPU 3686400u
6
7
// ----------------------------------------------------------------
8
// UART Bautrate w?hlen
9
// ----------------------------------------------------------------
10
#define BAUD 9600UL
11
12
// ?berpr?fung der gew?hlten UART Bautrate im Verh?ltnis zum CPU Takt
13
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // Runden
14
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
15
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)    // Fehler in Promille, 1000 = kein Fehler.
16
17
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
18
// Build Fehler ausgeben, wenn die gew?hlte Baudrate nicht zur CPU Frequenz passt
19
#error "Falsche Baudrate zum CPU Takt gew?hlt (Fehler >1%)!"
20
#endif
21
22
#include <avr/io.h>
23
#include <util/delay.h>
24
25
26
// ----------------------------------------------------------------
27
// Funktion - Initialisierung des ADC (Analog Digital Converter)
28
// ----------------------------------------------------------------
29
void initAdc()
30
{
31
    // --- Konfiguration des ADC "Multiplexer Selection Register" ---
32
    // Referenzspannung AREF = AVcc einstellen
33
    ADMUX = (1<<REFS0);
34
    
35
    // --- Konfiguration des ADC "Control and Status Register A" ---
36
    // ADC aktivieren und prescaler auf 32 (3686400/32 = 115200) einstellen
37
    ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS0);
38
}
39
40
41
// ----------------------------------------------------------------
42
// Funktion - Auslesen des ADC Messwert
43
// ----------------------------------------------------------------
44
uint16_t readAdc(uint8_t kanal)
45
{
46
    // Sicherstellen, das der Kanalwert maximal 7 wird
47
    kanal &= 0b00000111;
48
    
49
    // vor der Kanalwahl die ersten 3 bits in ADMUX zurücksetzen
50
    // und durch verodern mit Kanal auswählen
51
    ADMUX = (ADMUX & 0b11111000)|kanal;
52
53
    // "single convertion" starten
54
    ADCSRA |= (1<<ADSC);
55
56
    // warten bis die Wandlung abgeschlossen wurde (ADSC = 0) und...
57
    while(ADCSRA & (1<<ADSC));
58
    
59
    // ...den ermittelten Messwert zurückgeben (0-1023 / 2^10)
60
    return (ADC);
61
}
62
63
64
65
66
67
// ----------------------------------------------------------------
68
// Funktion - Initialisierung des UART (Universal Asynchronous
69
//                     Receiver Transmtter)
70
// ----------------------------------------------------------------
71
void initUart()
72
{
73
    UBRRH = UBRR_VAL >> 8;
74
    UBRRL = UBRR_VAL & 0xFF;
75
    
76
    UCSRB |= (1<<TXEN);                           // UART TX (senden) einschalten
77
    UCSRC = (1<<URSEL)|(1 << UCSZ1)|(1 << UCSZ0); // Asynchron 8N1
78
    
79
}
80
81
// Hier wird die jeweils aufgerufene Sendefunktion bearbeitet.
82
// Es wird jedes Zeichen einzeln an das Hyperterminal ?bergeben.
83
void sende ( char zeichen[])                // ?bergebene Variable ist ein Feld mit max. 256 Zeichen
84
{                                          // Dieses enth?lt die auszugebenden Zeichen (als char)
85
    for (int x=0; zeichen[x] != 0; x++)    // solange 'kein Satzende' als aktuelles Zeichen
86
    {
87
        
88
        while ( bit_is_clear(UCSRA,5))      // solange Zeichen noch nicht gesendet (dann Bit 5 = 0)
89
        {                                   // UCSRA ist das Unterregister in USART
90
            ;                                // warten bis vorheriges Zeichen fertig gesendet
91
        }
92
93
        UDR = zeichen[x];                   // aktuelles (x-tes) Zeichen senden
94
    }
95
}
96
97
98
99
int main ( void )
100
{
101
102
    // Definitionen
103
    
104
    DDRB = 0b00000000;       // Port B0 und B1 als Eingang definieren
105
    PORTB = 0b00000011;      // Pull-Up's an Port B0 und B1 setzen
106
    PORTC = 0b00000000;
107
    
108
    int messwertuebertragung;
109
    uint16_t adc_result0;
110
    char int_buffer[10];
111
    
112
    // Initialisierung
113
    initUart();
114
    initAdc();
115
116
117
118
    while ( 1 )
119
    {
120
        if( bit_is_clear(PINB,0 ))
121
        {
122
            _delay_ms(50);                // Prellen abwarten
123
            messwertuebertragung = 1;
124
        }
125
126
        if( bit_is_clear(PINB,1))
127
        {
128
            _delay_ms(50);                // Prellen abwarten
129
            messwertuebertragung =0;
130
        }
131
        
132
        if( messwertuebertragung == 1 )
133
134
        {
135
            /////////// Uebertragung an sich 
136
            
137
            // ADC Werte einlesen
138
            adc_result0 = readAdc(0);  // at PC0
139
            
140
            _delay_ms(500); //normal 5000
141
            
142
            itoa(adc_result0, int_buffer, 10);
143
            sende(int_buffer);
144
            
145
            sende ("\r\n") ;                 // ENDE der ?bertragung
146
            _delay_ms(50);
147
            if ( bit_is_set(UCSRA,7))
148
            {
149
                PORTC = 0b00000100;
150
            }
151
        }
152
    }
153
}

von Viktor N. (Gast)


Lesenswert?

Was spricht denn dagegen den Mittelwert dauernd zu messen resp zu 
bestimmen, und auf Tastendruck sofort zu uebertragen ?

von Karl H. (kbuchegg)


Lesenswert?

Anton L. schrieb:

> Soll Zustand: Ich möchte dass nach Betätigung des Tasters „PINB,0“
> innerhalb 10 Sekunden der Maximal wert des Widerstandes ermittelt wird
> und dann dieser Maximale wert nur ein mahl an die GUI gesendet wird.

Ja, dann mach das doch.

Was ist denn ein Maximalwert?
Zunächst mal ist Grundvoraussetzung für einen Maximalwert, dass man 
mehrere Messungen durchführt. Das sollte doch logisch sein, denn wenn 
man nur 1 Messung macht, dann ist es ein wenig witzlos von einem 
'Maximum' zu sprechen.

D.h. du musst mehrere Messungen machen. Da du von 10 Sekunden gesprochen 
hast - in welchen Zeitabständen machst du denn deine Messungen. Machst 
du zb alle halbe Sekunde eine Messung, dann bedeutet das, dass nach 21 
Messungen 10 Sekunden vergangen sind. Auch das sollte ja jetzt nicht 
allzu schwer zu verstehen sein. Denk einfach an einen Gartenzaun, 
wieviele senkrechte Steher gibt es (das sind die Messungen) und wieviele 
Zwischenräume (das sind die Zeiten dazwischen)


Und was ist denn ein 'Maximalwert'?
Nun das ist der Wert, der größer ist als alle anderen. Du wirst also 
vergleichen müssen. Wie machst du das? Genau so, wie du selbst es auch 
tun würdest. Du nimmst einfach nach der ersten Messung an, dass dies der 
Maximalwert wäre. Bei jeder weiteren Messung vergleichst du: Ist der 
Messwert größer als mein bisher angenommenes Maximus? Wenn ja, dann ist 
der alte Wert sicher nicht das Maxium, denn du hast ja jetzt einen 
größeren Wert gemessen.

  dein erster Messwert sei zb 30
  In Ermangelung besseren Wissens nimmst du mal an: das
    Maximum sei 30

  nächste Messung: 28

  ist 28 größer als 30?
  Wohl eher nicht, also können die 28 nicht das Maximum sein
  egal was du weiterhin missen wirst.

  nächste Messung: 33

  ist 33 größer als 30?
  Jawohl, das ist es. Ergo können die 30 nicht das Maximum sein,
  denn die 33 sind ja größer.

  nächste Messung: 31

  ist 31 größer als 33?
  Nein, ist es nicht. die 33 bleiben weiterhin der größte gemessene
  Wert


Das Maximum aus deinen Messwerten
    30, 28, 33, 31
war also 33. Und du hast das festgestellt, indem du jede neue Messung 
mit dem bisherigen Maximum verglichen hast. Das Maximum ist also 
sozusagen nach jeder einzelnen Messung neu festgelegt worden.

Hast du deine 21 Messungen durch, dann
* sind deine geforderten 10 Sekunden vergangen
* kennst du das Maximum der Messwerte

und das überträgst du zum PC

von Anton L. (pavlov)


Lesenswert?

Viktor N. schrieb:
> Was spricht denn dagegen den Mittelwert dauernd zu messen resp zu
> bestimmen, und auf Tastendruck sofort zu uebertragen ?

Dass Programm soll einem selbst  gebautem Alkoholtester dienen und es 
soll 10 Sekunden lang in einen Gas  Sensor Gepustet werden, worauf hin 
der Maximale gemessene Wert nur ein mal übertragen werden soll.

von Anton L. (pavlov)


Lesenswert?

Ja dass stimmt schon dass mit diesem geschriebenen Programm mehrere 
messungen gemacht werden, und permament an die GUI übertragen werden.

wass in der GUI wie volgt aussieht
z.B.  450; 460; 522; 495 …... usw  (Ständig endernd)

Ich möchte das beim Pusten in den Alkohol Tester innerhalb den 10 
sekunten der Maximale wert ermittelt wird und dann dieser übertragen 
wird.
Wobei die Idee den Mittelwert nach den 10 Sekunden zu übertragen auch 
sehr gut ist.
Ich danke euch  jetzt schonmal dass Ihr euch meinem Problem anschließt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.