Forum: Mikrocontroller und Digitale Elektronik LCD spielt verückt bei Berechnung


von Stefan H. (stefan_h)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich habe einen ATmega128 und programiere mit AVR-GCC.
Mein Board: Am ADC hängen 2 NI1000, und an PORTA hängt das LCD.
Wenn ich nun die ADC's auslese und die Werte in Spannungen umrechne
und dann auf dem LCD ausgebe, kommen die richtigen werte an. doch wenn
ich die Spannung in Temperaturen umrechne, wird als erstes am gesamten
LCD EURO-Zeichen ausgegeben. Diese Zeichen werden dan von der
Ausgabefunktion überschrieben.

Im Anhang ist die Messen.c in der alle Funktionen zur messung und
Berrechnung sind. In der Main werden diese wie folgt aufgerufen:
1
for(;;)
2
{
3
  MESS_Mittelung();//Messen und Mitteln
4
  MESS_BerechnungNI1000();//Messwete in Temperaturen umrechnen
5
  Messung2LCD();//Messwerte ausgeben
6
  WarteMS(500);//Warte 500ms
7
}

Wenn ich die Funktion MESS_BerechnungNI1000 auskommentiere, passt die
ausgabe am LCD. Nur wenn sie ausgeführt wird gibt es Pprobleme.

Ich habe mir schon gedacht ob das daran liegt, das das LCD auf dem Port
hängt das auch für ein externes Ram verwendet werden kann. Kann doch
sein, das der kompiler nicht weiß, das keines drann hängt?

Ich weis auf jeden Fall nicht mehr weiter.

lg,

Stefan

von Ppp M. (sanic)


Lesenswert?

Könntest du evtl. noch den Code von der kritischen Funktion posten ?

Grüße

von Ppp M. (sanic)


Lesenswert?

Sorry, hab deinen Anhang übersehen.
Ist denn die Beschaltung deines ADC-Eingangs richtig ?
Ein Schaltplan wäre hilfreich.

Grüße

von Stefan H. (stefan_h)


Lesenswert?

Was genau der kritische code ist, ist schwer zu sagen. Ich habe nur
herrausgefunden, das der Fehler nur dan auftritt wenn die Funktion
MESS_BerechnungNI1000 aufgerufen wird. Die Funktion ist in der
messen.c(oben angehängt)
1
void MESS_BerechnungNI1000()
2
{
3
  unsigned char ucKanal;
4
  float fRNi[2];
5
  // Ni-1000
6
  for(ucKanal=0;ucKanal<2;ucKanal++)
7
  {
8
    fRNi[ucKanal] = R1000*fSpg[ucKanal];
9
    fRNi[ucKanal] /= (VREF-fSpg[ucKanal]);
10
    fRNi[ucKanal] -= fRNiOffset[ucKanal];
11
    fTempNi[ucKanal] = 0.0314*fRNi[ucKanal];
12
    fTempNi[ucKanal] -= 1.9151;
13
    fTempNi[ucKanal] = sqrt(fTempNi[ucKanal]);
14
    fTempNi[ucKanal] -= 5.43;
15
    fTempNi[ucKanal] *= 63.694;
16
  }
17
}

von Stefan H. (stefan_h)


Lesenswert?

Hallo,

Nachdem ich die Spannung richtig messe(Wenn ich die Funktion
MESS_BerechnungNI1000 weglasse und die Spannung ausgebe) nehme ich an,
dass die Beschaltung stimmt.

Der NI1000 hängt direkt am PORT-Pin und hat einen 1kOhm PullUp. An
AVref hängen 2,5V(Z-Diode) und AVCC ist bei 5V und AVGND ist auf
Ground.

Aber wie gesagt, glaub ich nicht, dass es daran liegt.

lg,

Stefan

von Ppp M. (sanic)


Lesenswert?

Hallo,

hast du schonmal einzelne Codezeilen auskommentiert und geprüft ob es
dann funktioniert ?

Grüße

von Unbekannter (Gast)


Lesenswert?

Was ist das denn für eine Zeile:


    fTempNi[ucKanal] = 0.03140.0314*fRNi[ucKanal];


????

von Stefan H. (stefan_h)


Lesenswert?

Dieser Fehler ist anscheinend im Forum passiert. Bei mir steht

fTempNi[ucKanal] = 0.03140*fRNi[ucKanal];

kleiner Versuch:
1
fTempNi[ucKanal] = 0.03140*fRNi[ucKanal];

lg,

Stefan

von Jochen (Gast)


Lesenswert?

ich kenn zwar den AVR-GCC nich aber kurz was mir im kopf rumgeht:
also beim compilieren müssten bei dir schon einige warnungen kommen
double -> float
wenn nicht könnte das problem sein das der compiler double in float
schreibt was mehr speicher braucht und nen buffer overflow hast
(das wäre dann ein fehler vom compiler)
aber wie gesagt ich kenn den avr-gcc nicht weiß auch nicht wieviel
platz der compiler für double und für float vorsieht

gruß
jochen

von Rahul (Gast)


Lesenswert?

@Unbekannter:
Im Sourcecode ist der Fehler nichtvorhanden.

Welche Variable übergibst du denn an das LCD?
Vielleicht sieht der Wert dieser Variable etwas komisch aus, und die
LCD-Anzeigeroutine macht daraus €... (ob man für €-Drucken verknackt
werden kann?)
Ich vermute den Fehler beim Umwandeln der Zahl (float?) in den
LCD-String.

von Jochen (Gast)


Lesenswert?

1
// Ni-1000
2
for(ucKanal=0;ucKanal<2;ucKanal++)
3
{
4
fRNi[ucKanal] = (float)R1000*fSpg[ucKanal];
5
fRNi[ucKanal] /= ((float)VREF-fSpg[ucKanal]);
6
fRNi[ucKanal] -= fRNiOffset[ucKanal];
7
fTempNi[ucKanal] = 0.0314f*fRNi[ucKanal];
8
fTempNi[ucKanal] -= 1.9151f;
9
fTempNi[ucKanal] = (float)sqrt(fTempNi[ucKanal]);
10
fTempNi[ucKanal] -= 5.43f;
11
fTempNi[ucKanal] *= 63.694f;
12
}
so jetzt müssten die typen stimmen

von Stefan H. (stefan_h)


Lesenswert?

Durch das ein und auskommentieren hat das display wieder richtig
gearbeitet(k.A. warum).

Doch an der Berechnung gibt es einen Fehler. Habe das von Jochen
ausprobiert, hat aber nichts geholfen.
1
void MESS_BerechnungNI1000()
2
{
3
  unsigned char ucKanal;
4
  float fRNi[2];
5
  // Ni-1000
6
  for(ucKanal=0;ucKanal<2;ucKanal++)
7
  {
8
    fRNi[ucKanal] = R1000*fSpg[ucKanal];
9
    fRNi[ucKanal] /= (VREF-fSpg[ucKanal]);
10
    fRNi[ucKanal] -= fRNiOffset[ucKanal];
11
    fTempNi[ucKanal] = 0.0314*fRNi[ucKanal];
12
    fTempNi[ucKanal] -= 1.9151;
13
    fTempNi[ucKanal] = sqrt(fTempNi[ucKanal]);
14
    fTempNi[ucKanal] -= 5.43;
15
    fTempNi[ucKanal] *= 63.694;  
16
}
wenn die Routine so aussieht gibt es keine LCD Probleme allerdings
passt die Berechnung nicht. Bevor die Wurzel gezogen wird stimmt die
berechnung der beiden Kanäle noch. Danach ist der Kanal 0 total daneben
(ca. 30 statt 5,4) und und Kanal 1 passt auch nicht ganz, aber ist in
der Toleranz.

Wenn ich nur den teil mit der Wurzel rausnehme sind beide Werte wieder
annähernd gleich und richtig.

Habe auch getestet, ob die Wurzelfunktion richtig arbeitet, indem ich
einfach vor der Wurzel fTempNi[ucKanal] gesetzt habe(z.B auf 4.0f)
dadurch kam dann bei beiden nach der Wurzel 2 heraus.

Jetz wirds erst richtig interresant:
1
void MESS_BerechnungNI1000()
2
{
3
  unsigned char ucKanal;
4
  float fRNi[2];
5
  // Ni-1000
6
  for(ucKanal=0;ucKanal<2;ucKanal++)
7
  {
8
    fRNi[ucKanal] = R1000*fSpg[ucKanal];
9
    fRNi[ucKanal] /= (VREF-fSpg[ucKanal]);
10
    fRNi[ucKanal] -= fRNiOffset[ucKanal];
11
    fTempNi[ucKanal] = 0.0314*fRNi[ucKanal];
12
    fTempNi[ucKanal] -= 1.9151;
13
14
    fTempNi[1] = sqrt(fTempNi[1]);//Um zu sqrt zu testen!!
15
16
    fTempNi[ucKanal] -= 5.43;
17
    fTempNi[ucKanal] *= 63.694;  
18
}

Wenn ich die Funktion so verändere, dann sind meine EUROS wieder da.
Die EUROS werden über das ganze Display geschrieben und die Funktion
Messung2LCD überschreibt sie an den entsprechenden Stellen. Wenn ich
die Funktion Messung2LCD auskommentiere, kommen keine EUROS. also
werden in der Messung2LCD die EUROS auf das Display geworfen und
dannach werden sie wieder von den Messergebnissen überschrieben(siehe
Anhang). Ich weiß nicht mehr weiter.

von Stefan H. (stefan_h)


Angehängte Dateien:

Lesenswert?

das lcd

von Jochen (Gast)


Lesenswert?

also hab jetzt mal die sqrtf funktion von nc30 m16c compiler hier kannst
ja mal probieren obs dann geht
1
float sqrtf(float x)
2
{
3
  float s, last;
4
5
  if (x > 0) {
6
    s = ((x > 1) ? x : 1);
7
    do {
8
      last = s;
9
      s = (x / s + s) / 2;
10
    } while (s < last);
11
    return last;
12
  }
13
  if (x != 0) {
14
    /*
15
    error zahl negative
16
    */
17
  }
18
  return 0;
19
}
ach mich würd jetzt echt mal interessieren ob bei dir der compiler
keine warnung ausgibt möglicher datenverlust durch double in float
speichern?????

von Stefan H. (stefan_h)


Angehängte Dateien:

Lesenswert?

Hätte da mal das was der compiler so sagt

von Unbekannter (Gast)


Lesenswert?

Mach mal:

   avr-gcc -c -Wall -O2 xyz.c

von Jochen (Gast)


Lesenswert?

und schon die funktion ausprobiert???

von Stefan H. (stefan_h)


Lesenswert?

Es läuft :-)

Ich habe nun follgendes geändert:
- die funktion sqrt() mit der von Jochen ausgetauscht
- durch den compileraufruf  avr-gcc -mmcu=atmega128 -c -Wall -O2 lcd.c
wurden 2 Fehler aufgelistet: sinngemäß "for-schleife ist nicht C99
standart".(versteh nur nicht, warum bei "make" der Fehler nicht
kam)
Hat so ausgesehen:
1
for(unsigned int iIndex=0; iIndex<10;++iIndex)
auf das geändert
1
unsigned int iIndex;
2
for(iIndex=0; iIndex<10;++iIndex)

Wenn ich nun die alte sqrt-routine verwende gibt es nur noch den Fehler
mit dem falsch-rechnen, EURO drucken tuts nicht mehr. Also eine
kombination von mehreren Fehlern.

Vielen Dank für eure Hilfe und Ratschläge.

lg,

Stefan

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.