Forum: Mikrocontroller und Digitale Elektronik Arduino analogRead funktioniert nicht mit ATTiny85


von Anna log (Gast)


Lesenswert?

ich dachte, man kann die analoge Spannung, die an einem analogen Eingang 
hängt, bei Arduino einfach so auslesen - geht bei mir aber nicht. Die 
Spannungen, die anliegen, sind so zwischen 1V und 0,5V, aber es blinkt 
immer gleich (4x):
1
#define ANALOG_PIN (A1)
2
#define SWITCH_PIN (1)
3
4
int vcc_int_messen() {
5
  analogReference(DEFAULT);
6
  delay(100);
7
  int aval = analogRead(ANALOG_PIN);
8
  aval = analogRead(ANALOG_PIN);
9
  aval = analogRead(ANALOG_PIN);
10
  return aval;
11
}
12
13
void blinken(int mal,int ms) {
14
  for (int i=0; i < mal; i++){
15
    digitalWrite(SWITCH_PIN, HIGH);  
16
    delay(ms);                       
17
    digitalWrite(SWITCH_PIN, LOW);   
18
    delay(ms);  
19
  }
20
}
21
22
void setup()
23
{
24
  pinMode(SWITCH_PIN,OUTPUT);
25
  digitalWrite(SWITCH_PIN, LOW);    
26
27
  while (true){
28
    int bval = vcc_int_messen;
29
    if (bval<100) {blinken(1,200);} else
30
    if (bval<150) {blinken(2,200);} else
31
    if (bval<200) {blinken(3,200);} else
32
    if (bval<250) {blinken(4,200);} else
33
    if (bval<300) {blinken(5,200);} else
34
    if (bval<350) {blinken(6,200);} else
35
    if (bval<400) {blinken(7,200);} else
36
     {blinken(8,200);}
37
    delay(2000);
38
 }
39
}
40
41
void loop() {
42
}

Woran kann es liegen? Die Spannung liegt an Pin 7 an (kann man mit dem 
Messgerät nachmessen) der Chip läuft mit 5V..

von Dr. Sommer (Gast)


Lesenswert?

Anna log schrieb:
> int bval = vcc_int_messen;

Und das ist ganz sicher der korrekte kompilierbare Code?

Warum setzt du immer wieder die Referenz neu? Warum ist die Schleife in 
setup() und nicht in loop()?
Sicher dass delay() mit variablen Werten korrekt funktioniert?

von Anna log (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Und das ist ganz sicher der korrekte kompilierbare Code?

ja.


> Warum setzt du immer wieder die Referenz neu?

Ist übrig aus einem größeren Programm, wo sie verändert wurde. Solle 
nicht schaden..

Warum ist die Schleife in
> setup() und nicht in loop()?

ich glaub das ist in meinem Fall Wurscht.. ist ja nur ein Testprogramm.

> Sicher dass delay() mit variablen Werten korrekt funktioniert?

ja.

von Carl D. (jcw2)


Lesenswert?

Dr. Sommer schrieb:
> Anna log schrieb:
>> int bval = vcc_int_messen;
>
> Und das ist ganz sicher der korrekte kompilierbare Code?

Compilieren kann man das schon, nur hat dann bval immer den selben Wert. 
Nämlich die Adresse der Funktion vcc_int_messen.
Wollte man die ausführen, würde man () dahinter schreiben.

von Dr. Sommer (Gast)


Lesenswert?

Anna log schrieb:
> ja.

Und wie kann dann ein Funktionspointer ohne Fehler implizit in einen 
Integer konvertiert werden?

Anna log schrieb:
> Ist übrig aus einem größeren Programm, wo sie verändert wurde. Solle
> nicht schaden..

Nach dem Umschalten der Referenz liefert der ADC etwas Müll. Kann sein 
dass du das immer wieder auslöst. Schiebe die eine Zeile doch an den 
Anfang der setup().

Anna log schrieb:
> ich glaub das ist in meinem Fall Wurscht.. ist ja nur ein Testprogramm.

Sicher dass das Auslesen des ADC usw in der setup() klappt und Arduino 
nicht zwischen setup() und loop() nicht noch irgendwas einrichtet?

Carl D. schrieb:
> Nämlich die Adresse der Funktion vcc_int_messen

Ich würde eher auf 1 tippen, weil hier vermutlich erst nach bool 
konvertiert wird.

von Carl D. (jcw2)


Lesenswert?

Anna log schrieb:
> Dr. Sommer schrieb:
>> Und das ist ganz sicher der korrekte kompilierbare Code?
>
> ja.
Mit einigen Warnungen, die nicht unbedeutend sind.


>> Warum setzt du immer wieder die Referenz neu?
>
> Ist übrig aus einem größeren Programm, wo sie verändert wurde. Solle
> nicht schaden..
Danach braucht der ADC eventuell eine Wandlung, um wieder auf der Spur 
zu sein.

> Warum ist die Schleife in
>> setup() und nicht in loop()?
>
> ich glaub das ist in meinem Fall Wurscht.. ist ja nur ein Testprogramm.
Wurscht schon, aber wenn loop() eh schon da steht, warum nicht gleich 
richtig?

>> Sicher dass delay() mit variablen Werten korrekt funktioniert?
>
> ja.
Nein!
Es macht wohl was, aber sicher nicht ein delay mit dem übergebenen Wert. 
Das geht nur wenn man z.B. delay(1) in einer Schleife aufruft, dann darf 
der Schleifenzähler dynamisch mit den 200 zu wartenden ms gefüllt 
werden.

von Anna log (Gast)


Lesenswert?

Carl D. schrieb:
> Wollte man die ausführen, würde man () dahinter schreiben.

Vielen Dank, das war das Problem :-)
So ein Mist - ich mach nicht so viel mit Arduino, und die Warnungen 
werden bei mir gar nicht ausgegeben..

von Carl D. (jcw2)


Lesenswert?

Nachtrag(/Rückname meiner Behauptung) zu delay:
Arduino delay hat nichts mit den AVRLibc Delay-Macros zu tun und 
funktioniert wie gewünscht.

von Berta trog (Gast)


Lesenswert?

Anna log schrieb:
> und die Warnungen
> werden bei mir gar nicht ausgegeben..

Nur wenn du so naiv bist und deiner IDE nicht zulässt dass sie
die Warnungen ausgibt.

von Anna log (Gast)


Lesenswert?

irgendwie ist es nicht leicht zu debuggen in der Arduino IDE, wenn man 
nur eine LED als Anzeigen hat.. :-)

Wäre diese Funktion ok, um den Wert als float zu lesen? Schaltung läuft 
auf 5V, A1 misst externe Spannung (12V) angeschlossen über 
Spannungsteiler..
1
#define ANALOG_PIN (A1)
2
#define adc_disable() (ADCSRA &= ~(1<<ADEN))
3
#define adc_enable()  (ADCSRA |= 1<<ADEN)
4
5
6
float vcc_messen() {
7
  adc_enable();
8
  analogReference(DEFAULT);
9
  delay(100);
10
11
  int aval = analogRead(ANALOG_PIN);
12
  // mehrmals weil erste Messung Müll?
13
  aval = analogRead(ANALOG_PIN);
14
  aval = analogRead(ANALOG_PIN);
15
  float rvcc = aval * 5 / 1023 * 12; // Spannungsteiler 1+11 
16
  adc_disable();
17
  return rvcc;
18
}

von Anna log (Gast)


Lesenswert?

Berta trog schrieb:
> Nur wenn du so naiv bist und deiner IDE nicht zulässt dass sie
> die Warnungen ausgibt.

"Naiv" scheint die Voreinstellung zu sein - meine Arduino IDE zeigt mir 
keine Warnungen.

Aber ich habe die Stelle jetzt gefunden. :-)

von Manfred (Gast)


Lesenswert?

Anna log schrieb:
> irgendwie ist es nicht leicht zu debuggen in der Arduino IDE, wenn man nur eine 
LED als Anzeigen hat.. :-)

Die Arduino IDE nennt sich so, weil sie für Arduino gedacht ist. Da 
ist es kein Problem, Werte mit Serial.print auszugeben.

von Carl D. (jcw2)


Lesenswert?

Anna log schrieb:
> irgendwie ist es nicht leicht zu debuggen in der Arduino IDE, wenn
> man
> nur eine LED als Anzeigen hat.. :-)
.
> Wäre diese Funktion ok, um den Wert als float zu lesen? Schaltung läuft
> auf 5V, A1 misst externe Spannung (12V) angeschlossen über
> Spannungsteiler..
.
> #define ANALOG_PIN (A1)
> #define adc_disable() (ADCSRA &= ~(1<<ADEN))
> #define adc_enable()  (ADCSRA |= 1<<ADEN)
>
> float vcc_messen() {
>   adc_enable();
>   analogReference(DEFAULT);
>   delay(100);
>
>   int aval = analogRead(ANALOG_PIN);
>   // mehrmals weil erste Messung Müll?
>   aval = analogRead(ANALOG_PIN);
>   aval = analogRead(ANALOG_PIN);
>   float rvcc = aval * 5 / 1023 * 12; // Spannungsteiler 1+11
>   adc_disable();
>   return rvcc;
> }
Warum nicht, die FP-Lib wird in 8k passen.
Nur wird der Ausdruck als int berechnet (da alle Beteiligten int) und 
erst das ganzzahlige Ergebnis nach float konvertiert. Wenn die 
konstanten Werte mit Nachkommastellen da stehen ("x.0"), dann passiert 
das Gewünschte.

von Anna log (Gast)


Lesenswert?

Carl D. schrieb:
> Nur wird der Ausdruck als int berechnet (da alle Beteiligten int) und
> erst das ganzzahlige Ergebnis nach float konvertiert.

Ah.. sollte ich besser schreiben

float rvcc = aval * 5 *12 / 1023;

und außerdem nach long konvertieren? denn int geht ja nur bis 65535.. - 
und wenn aval maximal 1023 ist, dann geht's schon drüber?

Also ich würde gerne alles als Gleitkomma rechnen lassen.. oder 
zumindest in der Reihenfolge wie oben.

von Sven K. (quotschmacher)


Lesenswert?

Anna log schrieb:
> * 5 *12 / 1023

Meinste nicht, dass könnte man schon vorher zusammenfassen und dann 
einfach mit 0.05-irgendwas multiplizieren?

von Carl D. (jcw2)


Lesenswert?

Anna log schrieb:
> Carl D. schrieb:
>> Nur wird der Ausdruck als int berechnet (da alle Beteiligten int) und
>> erst das ganzzahlige Ergebnis nach float konvertiert.
>
> Ah.. sollte ich besser schreiben
>
> float rvcc = aval * 5 *12 / 1023;

Eher so:
1
float rvcc = aval * 5.0 / 1023.0 * 12.0;
Dann berechet der Compiler den konstanten Teil zur Übersetzungszeit und 
generiert eine FP-Multiplikation dieser Konstante mit aval.

> und außerdem nach long konvertieren? denn int geht ja nur bis 65535.. -
> und wenn aval maximal 1023 ist, dann geht's schon drüber?
Wozu, aval kann gleich nach float konvertiert werden.

> Also ich würde gerne alles als Gleitkomma rechnen lassen.. oder
> zumindest in der Reihenfolge wie oben.
Siehe oben

von Nick (Gast)


Lesenswert?

Anna log schrieb
>Vielen Dank, das war das Problem :-)
>So ein Mist - ich mach nicht so viel mit Arduino, und die Warnungen
>werden bei mir gar nicht ausgegeben..

Gibt's da nicht den Spruch "das Problem sitzt vor dem Arduino" ?

von Einer K. (Gast)


Lesenswert?

Carl D. schrieb:
> float rvcc = aval * 5.0 / 1023.0 * 12.0;

Auch wenn es nicht viel ausmacht...
Quasi im Rauschen unter geht...
Muss es nicht 1024.0 heißen, statt 1023.0?

von Manfred (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
>> float rvcc = aval * 5.0 / 1023.0 * 12.0;
> Auch wenn es nicht viel ausmacht...
> Quasi im Rauschen unter geht...
> Muss es nicht 1024.0 heißen, statt 1023.0?

Mir stellt sich eher die Frage, wie weit die Auflösung verloren geht. 
5/1023 = 0,0048876, da hätte ich doch gerne 5 Nachkommastellen in der 
Berechnung.

von Johannes S. (Gast)


Lesenswert?

Werden in der Arduino IDE fp Konstanten als float compiliert? Beim CM0 
wird mein Code immer gleich viel größer wenn ich f hinter den Konstanten 
vergesse und double Mathe gelinkt wird.

von Johannes S. (Gast)


Lesenswert?

Manfred schrieb:
> da hätte ich doch gerne 5 Nachkommastellen in der Berechnung.

Hast du, fp werden intern normiert. Hier müssten die Konstanten sogar 
als Double behandelt werden wenn die nicht per compilerschalter als 
float angenommen werden.

von Johannes S. (Gast)


Lesenswert?

Johannes S. schrieb:
> Werden in der Arduino IDE fp Konstanten als float compiliert?

habe es ausprobiert und kann es mir selber beantworten: das ABI des gcc 
behandelt float und double gleich, es gibt nur 4 Byte floats.
Daher ist es für Arduino Programme mit AVR als MCU egal. Portiert man 
die Programme oder Libs auf einen 32 Bitter ist es ein grosser 
Unterschied ob eine Konstante 10.0 oder 10.0f geschrieben wird.

von S. R. (svenska)


Lesenswert?

Johannes S. schrieb:
> Werden in der Arduino IDE fp Konstanten als float compiliert?

Auf dem AVR gibt es keine Unterstützung für double, von daher: Ja.
Das gilt aber nicht, wenn du einen nicht-AVR Arduino benutzt.

von Manfred (Gast)


Lesenswert?

Johannes S. schrieb:
> Manfred schrieb:
>> da hätte ich doch gerne 5 Nachkommastellen in der Berechnung.
> Hast du, fp werden intern normiert.

Carl D. schrieb:
> Eher so:float rvcc = aval * 5.0 / 1023.0 * 12.0;

Bei "1023.0" bekomme ich in Arduino einen Wert mit einer Nachkommastelle 
geliefert, mit "1023.00" wären es zwei. Ich habe noch nicht untersuchen 
müssen, was hinter den Kulissen passiert, mit wieviel Auflösung 
tatsächlich gerechnet wird.

von Joachim B. (jar)


Lesenswert?

Anna log schrieb:
> ich dachte, man kann die analoge Spannung, die an einem analogen Eingang
> hängt, bei Arduino einfach so auslesen - geht bei mir aber nicht. Die
> Spannungen, die anliegen, sind so zwischen 1V und 0,5V

Anna log schrieb:
> irgendwie ist es nicht leicht zu debuggen in der Arduino IDE, wenn man
> nur eine LED als Anzeigen hat.. :-)

dafür haben die Erfinder doch Serial.print eingebaut

Anna log schrieb:
> float rvcc = aval * 5 *12 / 1023;

warum will man ausgerechne float nutzen?

besser und kleiner gehts doch mit Ganzzahlwerten

ich rechne da immer mV milliVolt oder dV deziVolt

da passen in ein int16_t ohne float Berechnung 65000 mV oder 65000 dV

Bei deinem Bereich sollte das doch völlig ausreichend sein in mV mit 
65000 mV kommst du auf Umax von 65V mit 3 Kommastellen, so genau ist der 
ADC eh nicht und auflösen kann er es auch nicht.

Man kann sogar die ADC Werte aufsummieren und mitteln 8-32 fach (2^n) 
und durch rechtshiften wieder schnell teilen.

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

Manfred schrieb:
> Bei "1023.0" bekomme ich in Arduino einen Wert mit einer Nachkommastelle
> geliefert, mit "1023.00" wären es zwei.


https://de.wikipedia.org/wiki/IEEE_754

eine 1023.0 wird intern normalisiert (nicht normiert wie ich geschrieben 
hatte) zu 1,023 E3. Ein single float hat 7-8 signifikante Stellen, 
(fast) egal wie gross der Wert ist. Ein Problem gibts nur wenn man 
grosse und kleine Werte addiert, dann geht die Genauigkeit verloren wenn 
eben diese 7-8 Stellen überschritten werden.

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.