Forum: Mikrocontroller und Digitale Elektronik Nochmals bitte um Hilfe bei ADC


von Wilfried H. (willi_2)


Lesenswert?

Hallo guten Morgen an alle,
ich hatte ja vor ein paar Tage im Beitrag "ADC-Mega8, Hilfe bitte ich 
komme nicht weiter", schon mal um Hilfe gebeten und konnte das Problem 
danach auch beheben. War eigentlich keine große Sache ich hatte es nur 
nicht gesehen. Jetzt gibt es wieder ein Problem (sicherlich ähnlich 
banal) und mir ist einfach nicht klar wo der Fehler liegt. Vielleicht 
erkennt Ihr den "Kasus Knacksus". :-)

U.a. soll  folgender Code ausgeführt werden:

ISR (TIMER1_OVF_vect){
…
result = Read_Channel(0);     // ACD – Wert wird zugewiesen

…

lcd_out(result);

return;
}

void lcd_out(uint16_t wert){

  set_cursor(0,2);

  if(wert>963){
    lcd_string("wird geladen");
  }else if(wert>928 && wert<963){
    lcd_string("Batterie voll");
  }else if(wert>785){
    lcd_string("Ladung gring!");
  }else if(wert<=737 && wert>717){
    lcd_string("Ladung kritisch!");
  }else if(wert==917){
    lcd_string("abgeschaltet!!");
  }else if(wert==0){
    lcd_string("Schalter aus!");
  }
}

Es wird offenbar keine der If-Anweisungen ausgeführt, den ich erhalte 
auf dem Display keine Anzeige.
Lieg es an der Notation der Vergleiche, ist es ein Typ-Konflikt … ???



Gruß Wilfried

von Lord Z. (lordziu)


Lesenswert?

Prinzipiell ist es schlecht, Code in einer ISR aufzurufen, der längere 
Zeit für die Abarbeitung braucht.

Ohne deine Beschreibung, wie sich der Controller verhält, wird es 
schwierig genaues zu sagen.

Als erstes würde ich aber den ADC-Wert direkt auf dem Display ausgeben, 
um zu sehen, dass die Ausgabe-Funktion überhaupt abgearbeitet wird.

von Lord Z. (lordziu)


Lesenswert?

Um aus der ISR die LCD-Ausgabe zu "triggern", verwendet man eigentlich 
z.B. folgenden Mechanismus (Pseudo-Code):
1
#define IDLE    0
2
#define LCD_OUT 1
3
4
volatile uint8_t command;
5
6
ISR(TIMER1_OVF_vect)
7
{
8
    //...
9
    command = LCD_OUT;
10
}
11
12
int main()
13
{
14
    //...
15
16
    for(;;)
17
    {
18
        if(command == LCD_OUT)
19
        {
20
            lcd_out(...);
21
            command = IDLE;
22
        }
23
    }
24
    return 0;
25
}

von Karl H. (kbuchegg)


Lesenswert?

Wilfried H. schrieb:

> Lieg es an der Notation der Vergleiche, ist es ein Typ-Konflikt … ???

Wie wäre es mit:
Der Wert ist nicht der, den du erwartest?

Du hast zb keine Ausgabe für Werte
* die kleiner als 717 sind
* die sich im Bereich  738 bis 785 bewegen.

Welche Werte hast du denn?

von Wilfried H. (willi_2)


Lesenswert?

Ich glaube ich habe meinen Fehler gefunden. Wenn ich dem ADC-Wert über 
die Funktion "itoa" wandele und direkt anzeigen lasse erhalte ich z.B. 
bei 2,5V Eingangsspannung die Anzeige "0000000511". Ich schließe daraus, 
das ich die führenden Nullen beim Vergleich berücksichtigen muß, 
richtig?

von Karl H. (kbuchegg)


Lesenswert?

Diese Schreibweise
1
  if(wert>963){
2
    lcd_string("wird geladen");
3
  }else if(wert>928 && wert<963){
4
    lcd_string("Batterie voll");
5
  }else if(wert>785){
6
    lcd_string("Ladung gring!");
7
  }else if(wert<=737 && wert>717){
8
    lcd_string("Ladung kritisch!");
9
  }else if(wert==917){
10
    lcd_string("abgeschaltet!!");
11
  }else if(wert==0){
12
    lcd_string("Schalter aus!");
13
  }

ist sehr unübersichtlich. Ist dir zb aufgefallen, dass der Fall 
(wert==917) nie ausgeführt werden kann?

Beobachtung:
Wenn der Wert zb 980 ist, dann wird dieser if Teil
1
    if( wert > 963 )
genommen. Da alle andere Abfragen mittels else if an dieses if gekoppelt 
sind, werden sie gar nicht mehr ausgewertet. Du musst daher hier
1
    else if( wert > 928 && wert < 963 )
gar nicht mehr abfragen, ob der Wert kleiner als 963 ist.  Er kann nicht 
mehr größer als 963 sein, ansonsten würde das Programm gar nicht bei 
dieser Abfrage sein!

was soll eigentlich passieren, wenn der Wert exakt 963 ist. Das ist ein 
Tippfehler, da muss es <= heißen :-).

Aber besser ist es, das ganze zu vereinfachen und immer nur auf die 
Untergrenze zu prüfen und die in absteigender Reihenfolge anzuordnen:
1
  //
2
  // zuerst die fixen Werte
3
  //
4
  if( wert == 917 )
5
    lcd_string( "abgeschaltet!!" );
6
7
  else if( wert == 0 )
8
    lcd_string( "Schalter aus!" );
9
10
  else {    // dann Wertebereiche
11
    if( wert > 963 )
12
      lcd_string( "wird geladen" );
13
14
    else if( wert > 928 )
15
      lcd_string( "Batterie voll" );
16
17
    else if( wert > 785 )
18
      lcd_string( "Ladung gring!" );
19
20
    else if( wert > 717 )
21
      lcd_string( "Ladung kritisch!" );
22
23
    else
24
      lcd_string( "massive Unterspannung !" );
25
  }

auf die Art kann es dir nie passieren, dass Bereichsgrenzen nicht 
aneinanderpassen und du unbeabsichtigt Lücken in deinen Bereichen hast. 
Auch solltest du dir angewöhnen einen 'default'-else Zweig einzufügen, 
der alles andere auffängt.

von Karl H. (kbuchegg)


Lesenswert?

Wilfried H. schrieb:
> Ich glaube ich habe meinen Fehler gefunden. Wenn ich dem ADC-Wert über
> die Funktion "itoa" wandele und direkt anzeigen lasse erhalte ich z.B.
> bei 2,5V Eingangsspannung die Anzeige "0000000511". Ich schließe daraus,
> das ich die führenden Nullen beim Vergleich berücksichtigen muß,
> richtig?

Falsch.
Dein Code arbeitet schon richtig.
Für den Fall, dass der wert 511 beträgt, hast du ganz einfach keine 
Ausgabe vorgesehen.

(Siehe auch meinen vorhergehenden Beitrag, wie du das besser machen 
kannst)

von Wilfried H. (willi_2)


Lesenswert?

Soory, die 917 im Code ist falsch muß heißen 717!

von Karl H. (kbuchegg)


Lesenswert?

Wilfried H. schrieb:
> Soory, die 917 im Code ist falsch muß heißen 717!

Und wahrscheinlich hätte es im Original auch nicht == sondern < heissen 
sollen :-)

-> was lernen wir daraus:
optische Formatierung und Aufbereitung des Codes ist kein Selbstzweck 
sondern hilft auch mit Fehler zu sehen!

Wer die Einzelteile einer Anweisung auf Knirsch ohne Leerzeichen 
aneinanderpappt, hat es nicht besser verdient. Seit du klein bist, hast 
du dein Gehirn darauf trainiert, dass zwischen Wörtern Leerraum steht. 
Warum man diese Konditionierung bei der C Programmierung über Bord 
werfen muss nur weil es erlaubt ist, entzieht sich meinem Verständnis. 
Wäre ja auch zu einfach, wenn man eine Anweisung lesen kann ohne erst 3 
mal vorwärts/rückwärts mit den Augen durch die Anweisung laufen zu 
müssen um die Einzelteile optisch zu identifizieren.

von Wilfried H. (willi_2)


Lesenswert?

Hallo Karl Heinz,
danke Dir ein weiteres mal. Du hast natürlich völlig recht.
Aber so ist das wenn man lange nicht programmiert hat, dann verlernt man 
doch vieles. Vor allen Dingen bei den eigentlich so logischen Basics, da 
denkt man garnicht mehr richtig nach, denn "das muß ja stimmen".

Also danke noch mal Wilfried

von Falk B. (falk)


Lesenswert?


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.