ADC mit dem Arduino
ADC mit dem Arduino
Ich habe einmal eine Frage an die Arduino- und Programmierspezialisten.
Ich habe einen Sensor (für die Wetterstation), der den UV-Index 1-30 in einen Spannungswert 0 - 5V umwandelt. Der UV-Index ist also Umess * 6. Genau gibt der Sensor 166 mV je UVI ab, also UVI = Umess/0,166 oder Umess*5,88. Ganz einfach.
Arduino gibt am ADC die gemessene Spannung aus als Integer 1024 für 5V, daraus ergibt sich der UVI als Messzahl/34. Auch ganz einfach.
Zum Testen lege ich ein Poti zwischen Gnd und Vcc(5V) und den Schleifer auf PIN A0.
Definiere ich den Messwert als integer,den UVI als float und rechne UVI =(Messzahl/34) Gibt mir die Anzeige das Ergebnis als 0,00 ... 30,00 wie erwartet, aber ohne Dezimalstellen aus.
Definiere ich auch den UVI als integer und rechne UVI = int(Messzahl/34) wird es spannend: Die Anzeige ist, wie erwartet ohne Nachkommastellen. Von 5 V heruntergehend zeigt die Anzeige 30 ......10 an, wie gewünscht. gehe ich unter 10, zeigt sie plötlich 90-10 an, also den gewünschten Wert *10.
Dies Verhalten zeigt sich auch bei impliziter Wandlung, also ohne den int Befehl.
Natürlich kann ich das Ganze als float belassen,aber ich will wissen, warum.
Kann mir jemand das Verhalten erklären?
Danke vorab
Ich habe einen Sensor (für die Wetterstation), der den UV-Index 1-30 in einen Spannungswert 0 - 5V umwandelt. Der UV-Index ist also Umess * 6. Genau gibt der Sensor 166 mV je UVI ab, also UVI = Umess/0,166 oder Umess*5,88. Ganz einfach.
Arduino gibt am ADC die gemessene Spannung aus als Integer 1024 für 5V, daraus ergibt sich der UVI als Messzahl/34. Auch ganz einfach.
Zum Testen lege ich ein Poti zwischen Gnd und Vcc(5V) und den Schleifer auf PIN A0.
Definiere ich den Messwert als integer,den UVI als float und rechne UVI =(Messzahl/34) Gibt mir die Anzeige das Ergebnis als 0,00 ... 30,00 wie erwartet, aber ohne Dezimalstellen aus.
Definiere ich auch den UVI als integer und rechne UVI = int(Messzahl/34) wird es spannend: Die Anzeige ist, wie erwartet ohne Nachkommastellen. Von 5 V heruntergehend zeigt die Anzeige 30 ......10 an, wie gewünscht. gehe ich unter 10, zeigt sie plötlich 90-10 an, also den gewünschten Wert *10.
Dies Verhalten zeigt sich auch bei impliziter Wandlung, also ohne den int Befehl.
Natürlich kann ich das Ganze als float belassen,aber ich will wissen, warum.
Kann mir jemand das Verhalten erklären?
Danke vorab
vy73
Wolfgang
DC8PP
Wolfgang
DC8PP
Re: ADC mit dem Arduino
Böse Falle
Der Fehler lag nur zum Teil im Programm, zum Teil im Display.
Wenn ich alle(!) Variablen sauber als float definiere, hat das Programm auch alle einzelnen Dezimalstellen ausgerechnet und angezeigt. Also unsaubere Programmierung.
Die falsche Anzeige in integer liegt offenbar im LCD-Display. Gebe ich das Ergebnis über Putty auf den Bildschirm zeigt das Programm die Werte sauber als 0..........30 rauf und runter an bei Umess 0 .....5V.
Zeige ich sie über den LCD 20*4 an, zeigt er nach dem reset korrekt 0.......30 an, wenn ich von 0 auf 5V laufen lasse.
Lasse ich ihn danach wieder runter laufen, oder direkt nach reset von 5V auf 0 zeigt er 30......10, 90, 80 bis 00, also mit führender 0.
Also lcd.Init bei jedem Durchlauf der loop ?? Mal sehen.
Gruß
![Laughing :lol:](./images/smilies/icon_lol.gif)
![Laughing :lol:](./images/smilies/icon_lol.gif)
Der Fehler lag nur zum Teil im Programm, zum Teil im Display.
Wenn ich alle(!) Variablen sauber als float definiere, hat das Programm auch alle einzelnen Dezimalstellen ausgerechnet und angezeigt. Also unsaubere Programmierung.
Die falsche Anzeige in integer liegt offenbar im LCD-Display. Gebe ich das Ergebnis über Putty auf den Bildschirm zeigt das Programm die Werte sauber als 0..........30 rauf und runter an bei Umess 0 .....5V.
Zeige ich sie über den LCD 20*4 an, zeigt er nach dem reset korrekt 0.......30 an, wenn ich von 0 auf 5V laufen lasse.
Lasse ich ihn danach wieder runter laufen, oder direkt nach reset von 5V auf 0 zeigt er 30......10, 90, 80 bis 00, also mit führender 0.
Also lcd.Init bei jedem Durchlauf der loop ?? Mal sehen.
Gruß
vy73
Wolfgang
DC8PP
Wolfgang
DC8PP
Re: ADC mit dem Arduino
Es ist tatsächlich die Anzeige.
Obwohl ich vor jedem Schreibbefehl den Cursor positioniere, tritt der Fehler auf. Wenn ich in der Loop vor der Ausgabe lcd.init eingebe, ist die Ausgabe korrekt, nur extrem gebremst. Also muß ich für die Anzeige eine Lösung finden, oder float ausgeben.
Gruß.
Obwohl ich vor jedem Schreibbefehl den Cursor positioniere, tritt der Fehler auf. Wenn ich in der Loop vor der Ausgabe lcd.init eingebe, ist die Ausgabe korrekt, nur extrem gebremst. Also muß ich für die Anzeige eine Lösung finden, oder float ausgeben.
Gruß.
vy73
Wolfgang
DC8PP
Wolfgang
DC8PP
- ProgBernie
- Beiträge: 535
- Registriert: 19 Dez 2018, 22:49
- Wohnort: Labenz
Re: ADC mit dem Arduino
Das ist klar, denn (int) x / (int) 34 ergibt eine Integerdivison, das Ergebnis wird zu float konvertiert. Korrekt würde man rechnen:
float UVI;
UVI = (float)Messzahl/34.0f;
Das ist schräge und ich kann das auch nicht nachhvollziehen, sicher daß dies nicht nur ein Darstellungsproblem des Wertes UVI ist?wolfgang hat geschrieben: ↑29 Jun 2023, 13:50 Definiere ich auch den UVI als integer und rechne UVI = int(Messzahl/34) wird es spannend: Die Anzeige ist, wie erwartet ohne Nachkommastellen. Von 5 V heruntergehend zeigt die Anzeige 30 ......10 an, wie gewünscht. gehe ich unter 10, zeigt sie plötlich 90-10 an, also den gewünschten Wert *10.
Dies Verhalten zeigt sich auch bei impliziter Wandlung, also ohne den int Befehl.
Ich bekomme aus mess=250:
int uvi = mess/34: 7
float uvi = mess/34: 7.00
float uvi = (float)mess/34.0f: 07.35
Ddie floats mit dtostrf(uvi,5,2,buff) gewandelt (die Standard sprintf in Arduino hat aus Platzgründen keinen Float-Support).
Hier das Progrämmchen und die Ausgaben:
Code: Alles auswählen
#include <Arduino.h>
void doFloat();
void doInt();
void doCorrect();
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
doFloat();
doInt();
doCorrect();
}
void loop() {
// put your main code here, to run repeatedly:
}
void doFloat() {
int mess;
float uvi;
char buff[128];
char buff2[16];
Serial.println("Float");
for (mess = 0; mess<=1024; mess += 10) {
uvi = mess/34;
dtostrf(uvi, 5, 2, buff2);
sprintf(buff, "%d: %s", mess, buff2);
Serial.println(buff);
}
}
void doInt() {
int mess;
int uvi;
char buff[128];
Serial.println("Int");
for (mess = 0; mess<=1024; mess += 10) {
uvi = mess/34;
sprintf(buff, "%d: %d", mess, uvi);
Serial.println(buff);
}
}
void doCorrect() {
int mess;
float uvi;
char buff[128];
char buff2[16];
Serial.println("Correct");
for (mess = 0; mess<=1024; mess += 10) {
uvi = (float)mess/34.0f;
dtostrf(uvi, 5, 2, buff2);
sprintf(buff, "%d: %s", mess, buff2);
Serial.println(buff);
}
}
Code: Alles auswählen
Float
0: 0.00
10: 0.00
20: 0.00
30: 0.00
40: 1.00
50: 1.00
60: 1.00
70: 2.00
80: 2.00
90: 2.00
100: 2.00
110: 3.00
120: 3.00
130: 3.00
140: 4.00
150: 4.00
160: 4.00
170: 5.00
180: 5.00
190: 5.00
200: 5.00
210: 6.00
220: 6.00
230: 6.00
240: 7.00
250: 7.00
260: 7.00
270: 7.00
280: 8.00
290: 8.00
300: 8.00
310: 9.00
320: 9.00
330: 9.00
340: 10.00
350: 10.00
360: 10.00
370: 10.00
380: 11.00
390: 11.00
400: 11.00
410: 12.00
420: 12.00
430: 12.00
440: 12.00
450: 13.00
460: 13.00
470: 13.00
480: 14.00
490: 14.00
500: 14.00
510: 15.00
520: 15.00
530: 15.00
540: 15.00
550: 16.00
560: 16.00
570: 16.00
580: 17.00
590: 17.00
600: 17.00
610: 17.00
620: 18.00
630: 18.00
640: 18.00
650: 19.00
660: 19.00
670: 19.00
680: 20.00
690: 20.00
700: 20.00
710: 20.00
720: 21.00
730: 21.00
740: 21.00
750: 22.00
760: 22.00
770: 22.00
780: 22.00
790: 23.00
800: 23.00
810: 23.00
820: 24.00
830: 24.00
840: 24.00
850: 25.00
860: 25.00
870: 25.00
880: 25.00
890: 26.00
900: 26.00
910: 26.00
920: 27.00
930: 27.00
940: 27.00
950: 27.00
960: 28.00
970: 28.00
980: 28.00
990: 29.00
1000: 29.00
1010: 29.00
1020: 30.00
Int
0: 0
10: 0
20: 0
30: 0
40: 1
50: 1
60: 1
70: 2
80: 2
90: 2
100: 2
110: 3
120: 3
130: 3
140: 4
150: 4
160: 4
170: 5
180: 5
190: 5
200: 5
210: 6
220: 6
230: 6
240: 7
250: 7
260: 7
270: 7
280: 8
290: 8
300: 8
310: 9
320: 9
330: 9
340: 10
350: 10
360: 10
370: 10
380: 11
390: 11
400: 11
410: 12
420: 12
430: 12
440: 12
450: 13
460: 13
470: 13
480: 14
490: 14
500: 14
510: 15
520: 15
530: 15
540: 15
550: 16
560: 16
570: 16
580: 17
590: 17
600: 17
610: 17
620: 18
630: 18
640: 18
650: 19
660: 19
670: 19
680: 20
690: 20
700: 20
710: 20
720: 21
730: 21
740: 21
750: 22
760: 22
770: 22
780: 22
790: 23
800: 23
810: 23
820: 24
830: 24
840: 24
850: 25
860: 25
870: 25
880: 25
890: 26
900: 26
910: 26
920: 27
930: 27
940: 27
950: 27
960: 28
970: 28
980: 28
990: 29
1000: 29
1010: 29
1020: 30
Correct
0: 0.00
10: 0.29
20: 0.59
30: 0.88
40: 1.18
50: 1.47
60: 1.76
70: 2.06
80: 2.35
90: 2.65
100: 2.94
110: 3.24
120: 3.53
130: 3.82
140: 4.12
150: 4.41
160: 4.71
170: 5.00
180: 5.29
190: 5.59
200: 5.88
210: 6.18
220: 6.47
230: 6.76
240: 7.06
250: 7.35
260: 7.65
270: 7.94
280: 8.24
290: 8.53
300: 8.82
310: 9.12
320: 9.41
330: 9.71
340: 10.00
350: 10.29
360: 10.59
370: 10.88
380: 11.18
390: 11.47
400: 11.76
410: 12.06
420: 12.35
430: 12.65
440: 12.94
450: 13.24
460: 13.53
470: 13.82
480: 14.12
490: 14.41
500: 14.71
510: 15.00
520: 15.29
530: 15.59
540: 15.88
550: 16.18
560: 16.47
570: 16.76
580: 17.06
590: 17.35
600: 17.65
610: 17.94
620: 18.24
630: 18.53
640: 18.82
650: 19.12
660: 19.41
670: 19.71
680: 20.00
690: 20.29
700: 20.59
710: 20.88
720: 21.18
730: 21.47
740: 21.76
750: 22.06
760: 22.35
770: 22.65
780: 22.94
790: 23.24
800: 23.53
810: 23.82
820: 24.12
830: 24.41
840: 24.71
850: 25.00
860: 25.29
870: 25.59
880: 25.88
890: 26.18
900: 26.47
910: 26.76
920: 27.06
930: 27.35
940: 27.65
950: 27.94
960: 28.24
970: 28.53
980: 28.82
990: 29.12
1000: 29.41
1010: 29.71
1020: 30.00
Zuletzt geändert von ProgBernie am 29 Jun 2023, 19:02, insgesamt 1-mal geändert.
Gruß Bernd
- ProgBernie
- Beiträge: 535
- Registriert: 19 Dez 2018, 22:49
- Wohnort: Labenz
Re: ADC mit dem Arduino
Ah, hat sich überschnitten. Am einfachsten bei der Formatierung die restlichen Zeichen im Display mit Leerzeichen überschreiben. Ansonsten ist klar wenn man zuerst "Dummer Sack" ins display schreibt und danach die Zeile mit "Hallo!" übeschreibt, wird nur "Dummer" überschrieben, der Rest bleibt im Display stehen.
Gruß Bernd
Re: ADC mit dem Arduino
Bernd,
Du hast völlig Recht, der erste Fehler war die Integerdivision.
Der Anzeigefehler ist aber tricky und ich weiß noch nicht wie es dazu kommt. Über Terminalausgabe habe ich das Format kontrolliert, es ist in Ordnung. Integer 1 .....30, float 1.00 ..... 30.00.
Du hast völlig recht, wenn ich "Dummer Sack" auf das Display gebe und dann "Lieber" hinterherschreibe, steht da "Lieber Sack".
Ich positioniere den "Cursor" vor der Ausgabe aber immer auf 0,2, also Spalte 0. "Hinten" könnte etwas übrig bleiben, "Vorne" aber nicht.
Nach lcd.init war der Fehler weg (aber die Anzeige langsam), lcd.clr versuche ich morgen. Das erklärt aber nicht, woher die führende "0" im Display kommt. Möglich sind da I2C zu Parallel Wandler oder die Anzeige selbst.
Da muß ich nochmal im Detail die Doku lesen. Deinen Beitrag zu float und int muß ich mal in Ruhe morgen lesen.
schönen Abend
Du hast völlig Recht, der erste Fehler war die Integerdivision.
Der Anzeigefehler ist aber tricky und ich weiß noch nicht wie es dazu kommt. Über Terminalausgabe habe ich das Format kontrolliert, es ist in Ordnung. Integer 1 .....30, float 1.00 ..... 30.00.
Du hast völlig recht, wenn ich "Dummer Sack" auf das Display gebe und dann "Lieber" hinterherschreibe, steht da "Lieber Sack".
Ich positioniere den "Cursor" vor der Ausgabe aber immer auf 0,2, also Spalte 0. "Hinten" könnte etwas übrig bleiben, "Vorne" aber nicht.
Nach lcd.init war der Fehler weg (aber die Anzeige langsam), lcd.clr versuche ich morgen. Das erklärt aber nicht, woher die führende "0" im Display kommt. Möglich sind da I2C zu Parallel Wandler oder die Anzeige selbst.
Da muß ich nochmal im Detail die Doku lesen. Deinen Beitrag zu float und int muß ich mal in Ruhe morgen lesen.
schönen Abend
vy73
Wolfgang
DC8PP
Wolfgang
DC8PP
- ProgBernie
- Beiträge: 535
- Registriert: 19 Dez 2018, 22:49
- Wohnort: Labenz
Re: ADC mit dem Arduino
Das ist aber doch keine führende Null beim herunterzählen, sondern eine folgende Null. Es wird geschrieben:
"11" -> 11
"10" -> 10
"9" -> 9
"8" -> 8
und die Null von der "10" bleibt am Ende stehen. Bei einem direkten Übergang 11 -> 9 bekommst Du 91 angezeigt. Das lässt sich durch Formatierung der Zahl auf feste Breite rechtsbündig vermeiden, bei sprintf müsste die Formatangabe, wenn ich mich recht erinnere, dann %2d lauten. Dann wird geschrieben:
"11"
"10"
" 9"
" 8"
Ob die Arduino-implementierung das berücksichtigt weiß ich nicht, denke aber schon.
Gruß Bernd
Re: ADC mit dem Arduino
Danke Bernd.
Du hast recht. Manchmal übersehe ich das naheliegende......Oder ist's Demenz? Es fehlt das passende Emoji, daß mit der Mauer und dem Kopf.....
Klar, dann geht es mit Formatierung. Dann habe ich etwas für das Wochenende.
Gru0
Das ist aber doch keine führende Null beim herunterzählen, sondern eine folgende Null. Es wird geschrieben:
"11" -> 11
"10" -> 10
"9" -> 9
"8" -> 8
![Embarrassed :oops:](./images/smilies/icon_redface.gif)
![Embarrassed :oops:](./images/smilies/icon_redface.gif)
![Embarrassed :oops:](./images/smilies/icon_redface.gif)
![Embarrassed :oops:](./images/smilies/icon_redface.gif)
Du hast recht. Manchmal übersehe ich das naheliegende......Oder ist's Demenz? Es fehlt das passende Emoji, daß mit der Mauer und dem Kopf.....
Klar, dann geht es mit Formatierung. Dann habe ich etwas für das Wochenende.
Gru0
vy73
Wolfgang
DC8PP
Wolfgang
DC8PP