Forum: Mikrocontroller und Digitale Elektronik m328 adc-Verständnisproblem


von Karl K. (leluno)


Lesenswert?

hallo,

ich verstehe es mal wieder nicht.

an dieser Stelle -
lcd_int4(adc_read()); // <== hier mehrere ADC-Auslesungen angezeigt
- werden mehrere Messungen angezeigt und überschrieben. D.h. die 
Funktion 'lcd_int4' wird nur einmal ausgeführt da sonst hintereinander 
geschrieben würde - aber der Wert wird mehrfach angezeigt.




Wie kann das sein? Was mache ich falsch?

1
void main(void)
2
//
3
{
4
5
clock_prescale_set(clock_div_2);//8mhz
6
7
init_timer_smh();
8
led1_init;
9
10
//usart_init;
11
//USART0_init(9600);
12
//relais_init;
13
i2c_init();
14
lcd_init();
15
adc_init();
16
17
lcd_clear(RED);
18
lcd_int4(adc_read());  // <== hier eine ADC-Auslesung
19
20
//while(1);
21
22
23
24
25
timer_smh=0;
26
27
while(1)
28
{
29
30
//------------------- smh timer ------------------
31
  if (timer_smh>99)
32
  {
33
    sec=sec++;
34
    timer_smh=0;
35
      if(sec>59){
36
        sec=sec-60;  min=min+1;
37
        lcd_goto(1,4);//              
38
        lcd_int2(min);//
39
        lcd_write(":");
40
      if(min==60){
41
        min=0; hou++;
42
        if(hou==24)
43
        {
44
        hou=0;
45
        sub_day_start();
46
        
47
        }
48
        lcd_goto(1,1);//              
49
        lcd_int2(hou);//
50
        lcd_write(":");              
51
        }
52
      }
53
    lcd_goto(1,7);//              
54
    lcd_int2(sec);//
55
//    led1_tog;              
56
  }
57
//------------------------------------------------
58
59
if(sec==3 && min%6==0/**/  )//alle sechs Minuten auslesen
60
{
61
62
  if(min==0/**/)//jede Stunde -------
63
  {
64
  }
65
66
67
//wr_read_reg();
68
//sub_regelung();
69
}
70
71
72
if(sec%5==1)
73
{
74
  u8 i=0;
75
  lcd_goto(10+i++,1);
76
lcd_int4(i);// <== hier 1mal angezeigt
77
  
78
lcd_int4(adc_read()); // <== hier mehrere ADC-Auslesungen angezeigt
79
80
}
81
82
83
84
85
 }//while
86
}//main

von Nemopuk (nemopuk)


Lesenswert?

Deine Anfrage ist unklar formuliert. Gebe mal Beispiele der fehlerhaften 
Ausgabe und was du srattdessen erreichen willst.

Korrektes Einrücken hilft ungemein, den Quelltext zu verstehen.

Wo sind die Quelltexte von lcd_int4() und adc_read()? Ich will sie 
sehen, nicht nur anhand des Namens erraten, was sie tun sollten.

: Bearbeitet durch User
von Karl K. (leluno)


Angehängte Dateien:

Lesenswert?

Nemopuk schrieb:
> Wo sind die Quelltexte von lcd_int4() und adc_read()? Ich will sie
> sehen, nicht nur anhand des Namens erraten, was sie tun sollten.

pardon gehören natürlich dazu:
1
void adc_init()
2
{
3
   // Set the ADC reference to AVcc
4
    ADMUX = (1 << REFS0);
5
    
6
    // Enable ADC and set prescaler to 128 (16 MHz / 128 = 125 kHz)
7
    ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
8
}
9
10
11
#define ADCchannel 2
12
13
int16_t adc_read()
14
{
15
    // Select ADC channel (0-7) by setting the lower bits of ADMUX
16
    ADMUX = (ADMUX & 0xF8) | (ADCchannel & 0x07);
17
    
18
    // Start the conversion
19
    ADCSRA |= (1 << ADSC);
20
    
21
    // Wait for the conversion to complete
22
    while (ADCSRA & (1 << ADSC));
23
    
24
    // Return the ADC result
25
    return ADC;
26
}
27
28
 lcd_int4(i16 x){
29
  uint8_t dum[5]={' ',' ',' ','0','\0'};
30
  u8 neg=0;
31
if (x!=0)  
32
{
33
  
34
if (x<0){x=x*-1;neg=1;}
35
36
    if (x>999){
37
        dum[0]=(x/1000+48);
38
        x=x%1000;
39
    dum[1]='0';
40
    dum[2]='0';
41
    
42
        }
43
  
44
    if (x>99){
45
        dum[1]=(x/100+48);
46
        x=x%100;
47
    if(neg){neg=0;dum[0]='-';}
48
     dum[2]='0';
49
       }
50
    if (x>9){
51
        dum[2]=(x/10+48);
52
        x=x%10;
53
    if(neg){neg=0;dum[1]='-';}
54
        }
55
         dum[3]=(x+48);
56
     if(neg){dum[2]='-';}
57
58
59
}
60
    lcd_write(dum);
61
}
Die ADC-Wandlung wird auf dem Bild unten mehrfach ausgeführt und 
angezeigt - sollte aber nur ein mal ausgeführt und angezeigt werden.

von Wastl (hartundweichware)


Angehängte Dateien:

Lesenswert?

Karl K. schrieb:
> pardon gehören natürlich dazu:

.... und vielleicht mal an die Hinweise zum Posten von
Quellcode denken.

von Nemopuk (nemopuk)


Lesenswert?

Es ist zwar nicht dein Hauptproblem, ich wollte es aber trotzdem zeigen:

Deine Funktion lcd_int4() gibt positive Zahlen mit bis zu 4 Stellen aus. 
Negative Zahlen mit mehr als 3 Stellen führen zu einer fehlerhaften 
Ausgabe:

Der Test
1
int main(void) {
2
    lcd_int4(5);
3
    lcd_int4(50);
4
    lcd_int4(500);
5
    lcd_int4(5000);
6
    lcd_int4(-5);
7
    lcd_int4(-50);
8
    lcd_int4(-500);
9
    lcd_int4(-5000);
10
    return 0;
11
}

erzeugt folgende Ausgabe:
1
   5
2
  50
3
 500
4
5000
5
  -5
6
 -50
7
-500
8
50-0

von Nemopuk (nemopuk)


Lesenswert?

So sieht main() einigermaßen ordentlich formatiert aus:
1
void main(void) {
2
    
3
    clock_prescale_set(clock_div_2);  //8mhz  
4
    init_timer_smh();
5
    led1_init;
6
    //usart_init;
7
    //USART0_init(9600);
8
    //relais_init;
9
    i2c_init();
10
    lcd_init();
11
    adc_init();
12
    lcd_clear(RED);
13
    lcd_int4(adc_read());  // <== hier eine ADC-Auslesung
14
       
15
    timer_smh = 0;
16
    while (1) {
17
        
18
        //------------------- smh timer ------------------        
19
        if (timer_smh > 99) {
20
            
21
            sec = sec++;
22
            timer_smh = 0;
23
            
24
            if (sec > 59) {
25
                sec = sec - 60;
26
                min = min + 1;
27
                
28
                lcd_goto(1, 4); 
29
                lcd_int2(min);  
30
                lcd_write(":");
31
                
32
                if (min == 60) {
33
                    
34
                    min = 0;
35
                    hou++;
36
                    
37
                    if (hou == 24) {                        
38
                        hou = 0;                        
39
                        sub_day_start();
40
                    }
41
                    
42
                    lcd_goto(1, 1);                     
43
                    lcd_int2(hou);                     
44
                    lcd_write(":");
45
                }
46
            }
47
            
48
            lcd_goto(1, 7);             
49
            lcd_int2(sec);             
50
        }
51
        
52
        //------------------------------------------------       
53
        if (sec == 3 && min % 6 == 0) { //alle sechs Minuten auslesen
54
            
55
            if (min == 0)  //jede Stunde -------
56
            {
57
                // nichts?
58
            }
59
            
60
            //wr_read_reg();            
61
            //sub_regelung();
62
        }
63
        
64
        if (sec % 5 == 1)   {
65
            
66
            u8 i = 0;            
67
            lcd_goto(10 + i++, 1);
68
            
69
            lcd_int4(i);  // <== hier 1mal angezeigt
70
            lcd_int4(adc_read());  // <== hier mehrere ADC-Auslesungen angezeigt
71
        }
72
        
73
    }  //while
74
    
75
}  //main

Und auf den problematischen Teil reduziert:
1
void main(void) {
2
    
3
    while (1) {
4
        
5
        if (timer_smh > 99) {            
6
            sec = sec++;
7
            timer_smh = 0;
8
        }
9
                   
10
        if (sec % 5 == 1)   {
11
            
12
            u8 i = 0;            
13
            lcd_goto(10 + i++, 1);
14
            
15
            lcd_int4(i);  // <== hier 1mal angezeigt
16
            lcd_int4(adc_read());  // <== hier mehrere ADC-Auslesungen angezeigt
17
        }
18
        
19
    }  //while
20
    
21
}  //main

Hier fallen mir folgende Dinge auf:

Ist timer_smh als "volatile" und 8 Bit Integer deklariert? Wenn nicht, 
können Lesezugriffe im Hauptprogramm durch Schreibzugriffe in der 
Timer-ISR gestört werden und zu unerwartetem Verhalten führen. 
Allerdings nicht zu dem konkreten Verhalten, dass wir hier sehen. Dafür 
muss es noch einen anderen Grund geben.

> lcd_goto(10 + i++
ergibt immer 10, weil i immer 0 ist.

> lcd_int4(i);
gibt immer 1 aus, weil i immer 1 ist.

> lcd_int4(adc_read());
Gibt mit Sicherheit nur eine ADC Messung aus. Denn etwas anderes kann 
diese Funtkion nicht tun.

Offenbar kommt die Ausgabe "   1 813" von diesen beiden Aufrufen.

Die unerwarte Ausgabe in der dritten Display-Zeile stimmt nicht mit dem 
Quellcode überein. Denn er enthält kein "lcd_goto(3,1)". Sie kann auch 
nicht von "lcd_int4()" kommen, weil diese Funktion immer 4 Ziffern 
rehtsbündig ausgibt.

Vermutlich ist der Fehler ganz woanders, in einem Stück Code, den du 
nicht gezeigt hast. Ich würde mal alle andere Display-Ausgaben 
auskommentieren um auszuschließen, dass sie stören.

: Bearbeitet durch User
von Karl K. (leluno)


Lesenswert?

Nemopuk schrieb:
> Die unerwarte Ausgabe in der dritten Display-Zeile stimmt nicht mit dem
> Quellcode überein.

stimmt - "lcd_goto(3,1)" hab ich nachträglich eingefügt weil es in der 
ersten Zeile sonst blöd aussieht.


lcd_goto(10 + i++
ergibt immer 10, weil i immer 0 ist.

stimmt auch, habe die Deklaration nach oben gezogen. Ergebnis bleibt. 
Stelle wird nur einmal aufgerufen.

Nemopuk schrieb:
> Negative Zahlen mit mehr als 3 Stellen führen zu einer fehlerhaften
> Ausgabe:

Das ist bewusst in kauf genommen. Die Funktion dient zur Positionierung 
auf dem Display. Wenn größere negative Werte zu erwarten sind muss man 
das anders machen.


Nemopuk schrieb:
> Allerdings nicht zu dem konkreten Verhalten, dass wir hier sehen. Dafür
> muss es noch einen anderen Grund geben.

Jedenfalls Dank für dein Bemühen. Es hilft schon weiter zu wissen, dass 
mein Unverständnis nicht ganz unberechtigt ist.

: Bearbeitet durch User
von Nemopuk (nemopuk)


Lesenswert?

Karl K. schrieb:
> stimmt - "lcd_goto(3,1)" hab ich nachträglich eingefügt
> stimmt auch, habe die Deklaration nach oben gezogen

Wenn du hilfreiche Hilfe bekommen willst, solltest du deine Probleme 
ordentlich beschreiben. Wenn man sich Mühe gibt, erkennt man die Ursache 
beim verfassen der Problembeschreibung sogar oft selbst.

> Ergebnis bleibt. Stelle wird nur einmal aufgerufen.

Damit kann ich nichts anfangen. Ist das jetzt eine gute oder eine 
schlechte Nachricht?

Nochmal von vorne: Zeige den kompletten Quelltext (ordentlich 
formatiert!), die dazugehörige Ausgabe, und was du stattdessen 
erwartest.

: Bearbeitet durch User
von Wastl (hartundweichware)


Lesenswert?

Nemopuk schrieb:
> So sieht main() einigermaßen ordentlich formatiert aus:

Stefan Frings darf sich auch an die Regeln zum Posten von
Sourcecode halten.

von Karl K. (leluno)


Lesenswert?

Nemopuk schrieb:
> Nochmal von vorne: Zeige den kompletten Quelltext (ordentlich
> formatiert!), die dazugehörige Ausgabe, und was du stattdessen
> erwartest.

ich werde den code noch mal komplett neu aufsetzen und dann hier 
einstellen.

Das Merkwürdige ist, dass die Messwerte überschrieben werden obwohl die 
Cursorposition bei lcd_write eigentlich mit jedem Wert fortgeschrieben 
wird:
1
void lcd_write_(uint8_t* str)
2
{
3
while(*str>31)
4
    {
5
        lcd_char_(*str++);
6
        curposx =curposx+ f_width;
7
        if(frame)curposx++;
8
    }
9
}

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Karl K. schrieb:
> ich werde den code noch mal komplett neu aufsetzen und dann hier
> einstellen.

Aber dann bitte als Dateianhang, nicht im Posting selbst.

von Joachim B. (jar)


Lesenswert?

Wastl schrieb:
> Stefan Frings darf sich auch an die Regeln zum Posten von
> Sourcecode halten.

ach Regeln?
er editiert ja nicht mal Beiträge innerhalb von 2 Minuten nur um seinen 
Beitragszähler hochzuschrauben.

von Harald K. (kirnbichler)


Lesenswert?

Joachim B. schrieb:
> er editiert ja nicht mal Beiträge innerhalb von 2 Minuten nur um seinen
> Beitragszähler hochzuschrauben.

a) Geht das?

b) Ist der Beitragszähler irgendwie wichtig?

von Joachim B. (jar)


Lesenswert?

Harald K. schrieb:
> a) Geht das?

solange keiner geantwortet hat kann jeder editieren, es müssen keine 2 
Beiträge innerhalb 2 Minuten im Thread sein.

Harald K. schrieb:
> b) Ist der Beitragszähler irgendwie wichtig?

frage Stefan, niemand nutzt so viele Nickname wie er und immer mit 
derselben langsam unglaubwürdigen Begründung und oft nur Gesabbel am 
Thema vorbei und ohne Sachkenntnis.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Joachim B. schrieb:
> und immer mit
> derselben langsam unglaubwürdigen Begründung und oft nur Gesabbel am
> Thema vorbei und ohne Sachkenntnis.

Projektion!

von Joachim B. (jar)


Lesenswert?

Arduino F. schrieb:
> Projektion!

keine Ahnung was du meinst, habe seit ich hier angemeldet bin nur ein 
Name und in gleicher Zeit nur 1/6 Beiträge und verkneife mir im 
Gegensatz zu Stefan auch mal Kommentare.

von Manfred P. (pruckelfred)


Lesenswert?

Joachim B. schrieb:
> und verkneife mir im
> Gegensatz zu Stefan auch mal Kommentare.

Lügner!

In diesem Thread hast Du bislang drei Beiträge, die nichts zur Sache 
beitragen. Du plapperst den Schulmeister nach und führst einen 
persönlichen Krieg, was der Sache einfach nur schadet.

Stefan hat hier versucht, etwas zur Sache beizutragen - das storpedierst 
Du mit vermeidbarer Leermeisterei.

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.