Forum: Compiler & IDEs GLCD mit Arduino soll Variable anzeigen


von Ulrich R. (boalt)


Angehängte Dateien:

Lesenswert?

Hallo Wissende,
vielleicht ist es das Alter oder ....
ich komme nicht darauf, wie ich auf dem GLCD die über den Analogeingang
eingelesene Temperatur auf dem Display auch angezeigt bekomme.
Als Info anbei das Arduino-Programm.
Ich wäre ja sowas von dankbar.

von Peter D. (peda)


Lesenswert?

Z.B. mit sprintf() den Wert in einen Text umwandeln.

von Ralph S. (jjflash)


Lesenswert?

Peter D. schrieb:
> Z.B. mit sprintf() den Wert in einen Text umwandeln.

Das wird nicht funktionieren, weil im Arduino Framework mit sprintf 
keine Floats implementiert sind (er aber genau Floats ausgeben möchte - 
warum auch immer - ).

Hier wäre ein geeigneterer Weg (aber nicht unbedingt guter Weg) ein 
dtostrf:
1
float f;
2
char s[20];
3
4
f= 2.3 * 4.6;
5
dtostrf(f,6, 2, s);    // 6 Zeichen insgesamt, 2 Nachkommastellen
6
u8g.drawStr(10, 24, s);

von Ulrich R. (boalt)


Lesenswert?

Hallo Ralf S.
zuerst Peter D. Variante funktioniert wirklich nicht.
Das Tragische, Deine Variante aber auch nicht.
Nun noch einmal zum Verständnis:
Ich habe nach dem gesendeten Programm auf dem GLCD die Aufschrift
"Der Test" zur anzeige.
In dem Programm lese ich über den Analog-Pin 0 einen Temp.-Fühler LM35
ein.

Bei einer Ausgabe von resultTemp über den seriellen Monitor ist auch 
alles i.O.
NUR, ich möchte diesen Temperaturwert auf dem GLCD angezeigt bekommen.
95 % der Verweise im Internet beziehen sich auf die Ausgabe zum 
seriellen
Monitor (frustierend).

Vielleicht hast Du noch 5 Minuten.

von Ralph S. (jjflash)


Lesenswert?

Zu allererst: Ich bin sicherlich nicht der Arduino-Experte und 
beschäftige mich aufgrund eines anderen Spaßprojektes gerade damit.

Für dich habe ich jetzt einmal die u8glib Library installiert und hoffe, 
dass es dieselbe Library ist, die du hast. In Ermangelung deines 
Displays habe ich ein Display genommen, das ich hier verfügbar habe, ein 
N5110 (84x48 Pixel) mit PCD8544 Controller. Aus diesem Grund habe ich 
dann auch einen kleineren Schriftstil als Deinen gewählt.

Grundsätzlich sollte aber das folgende kurze Demoprogramm Aufschluß 
geben, da du auf Deinem Display ja schon etwas gesehen hast (und von 
daher das Display richtig verdrahtet und initialisiert ist):
1
/* 
2
 ------------------------------------------
3
           u8g_floatout.ino
4
 ------------------------------------------
5
*/
6
7
#include "U8glib.h"
8
9
U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);    // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
10
11
void setup(void) { 
12
  u8g.setRot180(); 
13
  u8g.setFont(u8g_font_profont10r);  
14
}
15
16
float f = 4.61;
17
char s[30];
18
19
void loop(void) 
20
{  
21
  f += 2.61;                 // irgendeine Rechnung
22
  if (f > 300) f= 4.61;    
23
24
  delay(500);
25
26
  dtostrf(f,6, 2, s);    // 6 Zeichen insgesamt, 2 Nachkommastellen
27
28
  // Hier kommt die Ausgabe hin !
29
  u8g.firstPage();
30
  do
31
  {
32
    u8g.drawStr(0,24, "Ergebnis:");
33
    u8g.drawStr(46, 24, s);    
34
  } while(u8g.nextPage() );   
35
}

Grundsätzlich erfolgt eine Ausgabe zuerst im RAM des Mikrocontrollers 
und nicht auf das Display. In der Beschreibung zu u8glib wird das als 
"Display-Loop" bezeichnet. Soll die Ausgabe auf dem Display erscheinen 
wird dieses "Display-Loop" mit "u8g.firstPage();" eingeleitet und in 
einer do-while Schleife deren Abbruchbedingung "u8g.nextPage()" ist dann 
angezeigt. Nach Abarbeitung dieser Schleife ist der Ram im 
Mikrocontroller (ich und andere auch nennen das Framebuffer) 
grundsätzlich gelöscht und du hast keinen Zugriff mehr auf gemacht 
Ausgabe. Jedes neue Beschreiben mittels Methoden von u8glib beschreiben 
einen leeren Framebuffer.

Beitrag #6571724 wurde vom Autor gelöscht.
von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

... jetzt habe ich noch eine Variante aus meinen C-Quellen (nicht C++)
in Arduino ausprobiert und hat auch gleich funktioniert.

Ich habe die Funktion "my_ftoa" benannt:

         void my_ftoa(char *s, float f, char komma)

my_ftoa erwartet als Parameter für "*s" einen Pufferspeicher, der den
String aufnimmt, mit "f" den Floatwert, der in einen String konvertiert
werden soll und in "komma" die Anzahl der Nachkommastellen, die der
String haben soll.

Als String ist hier ein Ansi-String (nullterminiert) gemeint und kein
String aus "class string".

von Ulrich R. (boalt)


Angehängte Dateien:

Lesenswert?

Hallo Ralph S.
zuerst vielen Dank für Deine Nachtarbeit.
Es funktioniert !! siehe beiliegendes Float.jpg.

Jetzt werde ich nur noch versuchen, aus dem ursprünglichen
Programm den Temperaturwert zur Anzeige zu bringen

Noch einmal Danke ( und ich habe übrigens noch solch ein
Display - falls Interesse ? dann Bescheid sagen)
Gruß Ulrich

von Ralph S. (jjflash)


Lesenswert?

Freut mich, dass das geklappt hat. Die Temperatur zur Anzeige zu bringen 
sollte jetzt aber kein großes Problem mehr sein.

Bei deinem Code
1
float resultTemp = 0.0;
2
for(int i = 0; i < cycles; i++)
3
{
4
  int analogValue = analogRead(sensorPin);
5
  float temperature = (5.0 * 100.0 * analogValue) / 1024;
6
  resultTemp += temperature;
7
  delay(DELAY);
8
  resultTemp /= cycles;
9
}
glaube ich nicht, dass das so gewollt ist. Zumindest wirst du in 
resultTemp nicht den Mittelwert der Temperatur haben.
resultTemp /= cyles
muß hier ausserhalb der Schleife liegen.
1
float resultTemp = 0.0;
2
for(int i = 0; i < cycles; i++)
3
{
4
  int analogValue = analogRead(sensorPin);
5
  float temperature = (5.0 * 100.0 * analogValue) / 1024;
6
  resultTemp += temperature;
7
  delay(DELAY);
8
}
9
resultTemp /= cycles;
Außerdem solltest du dir Gedanken darüber machen, ob du jedesmal in der 
Schleife (hier also 20 mal) den Meßwert schon auf einen Float 
umrechnest, diesen addierst und dann mittelst. Besser wäre es wohl, eine 
uint32_t Variable aufzuaddieren und nach Beendigung der Schleife in eine 
Temperatur umzurechnen:
1
  uint32_t valadd= 0;
2
  float resultTemp= 0.0;
3
  for (i= 0; i< cycles; i++)
4
  {
5
    valadd += analogRead(sensorPin);    
6
  }  
7
  resultTemp = (5.0 * 100.0 * valadd) / (1024.0 * cycles);
Das Ganze sollte dann in etwa so lauffähig sein (ich hab den analogen 
Teil jetzt nur simuliert):
1
char s[30];
2
3
void loop(void) 
4
{  
5
  uint32_t valadd= 0;
6
  float resultTemp= 0.0;
7
  for (i= 0; i< cycles; i++)
8
  {
9
    valadd += analogRead(sensorPin);    
10
    delay(DELAY);
11
  }  
12
  resultTemp = (5.0 * 100.0 * valadd) / (1024.0 * cycles);
13
  dtostrf(resultTemp,6, 2, s);    // 6 Zeichen insgesamt, 2 Nachkommastellen
14
15
  // Hier kommt die Ausgabe hin !
16
  u8g.firstPage();
17
  do
18
  {
19
    u8g.drawStr(0,24, "Temp.:");
20
    u8g.drawStr(46, 24, s);    
21
  } while(u8g.nextPage() );   
22
}

Anmerkung hierzug: Macht man aus nur 20 Meßwerten eine Mittelung, würde 
für valadd auch eine Variable vom Typ uint16_t reichen, weil bei einem 
Aufaddieren der Maximalwerte die der ADC liefern kann (1024) der 
Wertebereich eines 16-Bit Integers noch nicht überschritten ist.

Vielleicht solltest du auch über die Referenzspannung des ADC 
nachdenken, da du mit einer sehr kleinen Steigung arbeitest. Bspw. 
liefert ein LM35 bei 20°C 200mV. Am ADC mit 5V als Referenz wird (bei 
absoluter Genauigkeit der Referenz und keinem Fehler am LM35) der ADC 
den Wert 40 liefern: 0,2V * 1024 / 5V = 40,96. Der Nachkommateil kann 
natürlich nicht abgebildet werden und so wird für 200mV der Wert 40 
geliefert.

Nach der Temperaturumrechnungsformel oben ergibt ein ADC-Wert von 40 den 
Temperaturwert 19.53°C. Immerhin schon hier (ohne Sensor- und 
ADC-Fehler) schon ein systematischer Fehler von 0.47 Kelvin.

Hier wäre es besser, die interne Spannungsreferenz des ATMega zu nutzen 
(wenn es ein ATMega328 ist, sind das 1.1V).

analogReference(INTERNAL);

Deine Temperaturumrechnung müßte dann lauten:

  resultTemp = (1.1 * 100.0 * valadd) / (1024.0 * cycles);

Hier ergibt sich dann für 20°C = 200mV ein ADC-Wert von (uint8_t)186.18 
= 186. Das Umrechnen in eine Temperatur ergibt hier dann: 19.98°C

Ulrich R. schrieb:
> ( und ich habe übrigens noch solch ein
> Display - falls Interesse ? dann Bescheid sagen)

Vielen Dank, aber wenn ich Displays in dieser Größe und mit 240 Pixeln 
oder mehr verwende, nehme ich ein farbiges TFT-Display (und dann 
meistens einen STM32 Controller).

Ich wünsche dir viel Erfolg mit deiner Temperaturmessung

von Ulrich R. (boalt)


Lesenswert?

Hallo Ralph S.
nochmals Danke - ich werde die Temp. Umrechnung nach Deinem Beispiel
vornehmen.
Die in meinem alten Programm genutzte LM35 Routine stammt übrigens
aus "Die elektronische Welt mit Arduino entdecken"
     von Erik Bartmann
     O´REILLY Verlag 2014
Die Beschreibung Deiner Berechnungsroutine ist natürlich
einleuchtender und genauer.

Nun ja, er kannte Dich nicht.
Gruß Ulrich

von Ralph S. (jjflash)


Lesenswert?

... würde mich dann interessieren, ob es dann auch so geklappt hat wie 
gewünscht !

von Ulrich R. (boalt)


Angehängte Dateien:

Lesenswert?

Hallo Ralph,
im Anhang ein Beweisfoto und das Programm (wird natürlich
noch um weitere Spielereien erweitert).

Nochmals Danke
Ulrich

von Ralph S. (jjflash)


Lesenswert?

:-) welches Foto ?

von Ulrich R. (boalt)


Angehängte Dateien:

Lesenswert?

Mea Culpa, hatte ich wahrscheinlich nicht ordentlich angehangen.

von Ralph S. (jjflash)


Lesenswert?

Freut mich sehr, dass es ausschaut wie es ausschaut ! Viel Spaß beim 
weiteren Ausbau und herumspielen

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.