mikrocontroller.net

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


Autor: Stefan Hütter (stefan_h)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
for(;;)
{
  MESS_Mittelung();//Messen und Mitteln
  MESS_BerechnungNI1000();//Messwete in Temperaturen umrechnen
  Messung2LCD();//Messwerte ausgeben
  WarteMS(500);//Warte 500ms
}

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

Autor: Ppp Mmm (sanic)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Könntest du evtl. noch den Code von der kritischen Funktion posten ?

Grüße

Autor: Ppp Mmm (sanic)
Datum:

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

Grüße

Autor: Stefan Hütter (stefan_h)
Datum:

Bewertung
0 lesenswert
nicht 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)
void MESS_BerechnungNI1000()
{
  unsigned char ucKanal;
  float fRNi[2];
  // Ni-1000
  for(ucKanal=0;ucKanal<2;ucKanal++)
  {
    fRNi[ucKanal] = R1000*fSpg[ucKanal];
    fRNi[ucKanal] /= (VREF-fSpg[ucKanal]);
    fRNi[ucKanal] -= fRNiOffset[ucKanal];
    fTempNi[ucKanal] = 0.0314*fRNi[ucKanal];
    fTempNi[ucKanal] -= 1.9151;
    fTempNi[ucKanal] = sqrt(fTempNi[ucKanal]);
    fTempNi[ucKanal] -= 5.43;
    fTempNi[ucKanal] *= 63.694;
  }
}

Autor: Stefan Hütter (stefan_h)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Ppp Mmm (sanic)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

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

Grüße

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ist das denn für eine Zeile:


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


????

Autor: Stefan Hütter (stefan_h)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Fehler ist anscheinend im Forum passiert. Bei mir steht

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

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

lg,

Stefan

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
// Ni-1000
for(ucKanal=0;ucKanal<2;ucKanal++)
{
fRNi[ucKanal] = (float)R1000*fSpg[ucKanal];
fRNi[ucKanal] /= ((float)VREF-fSpg[ucKanal]);
fRNi[ucKanal] -= fRNiOffset[ucKanal];
fTempNi[ucKanal] = 0.0314f*fRNi[ucKanal];
fTempNi[ucKanal] -= 1.9151f;
fTempNi[ucKanal] = (float)sqrt(fTempNi[ucKanal]);
fTempNi[ucKanal] -= 5.43f;
fTempNi[ucKanal] *= 63.694f;
}
so jetzt müssten die typen stimmen

Autor: Stefan Hütter (stefan_h)
Datum:

Bewertung
0 lesenswert
nicht 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.
void MESS_BerechnungNI1000()
{
  unsigned char ucKanal;
  float fRNi[2];
  // Ni-1000
  for(ucKanal=0;ucKanal<2;ucKanal++)
  {
    fRNi[ucKanal] = R1000*fSpg[ucKanal];
    fRNi[ucKanal] /= (VREF-fSpg[ucKanal]);
    fRNi[ucKanal] -= fRNiOffset[ucKanal];
    fTempNi[ucKanal] = 0.0314*fRNi[ucKanal];
    fTempNi[ucKanal] -= 1.9151;
    fTempNi[ucKanal] = sqrt(fTempNi[ucKanal]);
    fTempNi[ucKanal] -= 5.43;
    fTempNi[ucKanal] *= 63.694;  
}
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:
void MESS_BerechnungNI1000()
{
  unsigned char ucKanal;
  float fRNi[2];
  // Ni-1000
  for(ucKanal=0;ucKanal<2;ucKanal++)
  {
    fRNi[ucKanal] = R1000*fSpg[ucKanal];
    fRNi[ucKanal] /= (VREF-fSpg[ucKanal]);
    fRNi[ucKanal] -= fRNiOffset[ucKanal];
    fTempNi[ucKanal] = 0.0314*fRNi[ucKanal];
    fTempNi[ucKanal] -= 1.9151;

    fTempNi[1] = sqrt(fTempNi[1]);//Um zu sqrt zu testen!!

    fTempNi[ucKanal] -= 5.43;
    fTempNi[ucKanal] *= 63.694;  
}

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.

Autor: Stefan Hütter (stefan_h)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
das lcd

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also hab jetzt mal die sqrtf funktion von nc30 m16c compiler hier kannst
ja mal probieren obs dann geht
float sqrtf(float x)
{
  float s, last;

  if (x > 0) {
    s = ((x > 1) ? x : 1);
    do {
      last = s;
      s = (x / s + s) / 2;
    } while (s < last);
    return last;
  }
  if (x != 0) {
    /*
    error zahl negative
    */
  }
  return 0;
}
ach mich würd jetzt echt mal interessieren ob bei dir der compiler
keine warnung ausgibt möglicher datenverlust durch double in float
speichern?????

Autor: Stefan Hütter (stefan_h)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hätte da mal das was der compiler so sagt

Autor: Unbekannter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach mal:

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

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und schon die funktion ausprobiert???

Autor: Stefan Hütter (stefan_h)
Datum:

Bewertung
0 lesenswert
nicht 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:
for(unsigned int iIndex=0; iIndex<10;++iIndex)
auf das geändert
unsigned int iIndex;
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.