Forum: Mikrocontroller und Digitale Elektronik Analoger Messwert nach Sleep falsch


von Torsten W. (toto1975)


Lesenswert?

Hallo in die Runde,

ich möchte mit meinem Attiny85 die Daten eines Feuchtigkeitssensor per 
Funk versenden. Da im Sleep Modus der ADC mit ADCSRA = 0; ausgeschaltet 
wird habe ich nun das Problem das er nach dem anschalten mit ADCSRA |= 
(1<<ADEN); immer den Wert 0 anzeigt wird.

Ich habe mir mit keep_ADCSRA = ADCSRA; bzw. mit ADCSRA = keep_ADCSRA; 
delay(50); (siehe auch Code) beholfen.

Wie mache ich es aber richtig mit ADCSRA |= (1<<ADEN); ?

Danke und Gruß
Torsten
1
// ATMEL ATTINY 25/45/85 / ARDUINO
2
//
3
//                  +-\/-+
4
// Ain0 (D 5) PB5  1|    |8  Vcc
5
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
6
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
7
//            GND  4|    |5  PB0 (D 0) pwm0
8
//                  +----+
9
10
11
12
#include <avr/sleep.h>    // Sleep Modes
13
#include <avr/power.h>    // Power management
14
#include <avr/wdt.h>      // Watchdog timer
15
#include <VirtualWire.h>
16
17
int sensorPin = A1; //zum lesen der Daten
18
char daten[10];
19
int ID;
20
const int PIN_LED = 4;
21
const int strom =  1;
22
int keep_ADCSRA; 
23
int a;
24
25
26
ISR (PCINT0_vect) 
27
 {
28
 // do something interesting here
29
 }  // end of PCINT0_vect
30
31
 // watchdog interrupt
32
ISR (WDT_vect) 
33
{
34
   wdt_disable();  // disable watchdog
35
   
36
}  // end of WDT_vect
37
38
void resetWatchdog ()
39
  {
40
  // clear various "reset" flags
41
  MCUSR = 0;     
42
  // allow changes, disable reset, clear existing interrupt
43
  WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);
44
  // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
45
  WDTCR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
46
  // pat the dog
47
  wdt_reset();  
48
  }  // end of resetWatchdog
49
50
  void setup ()
51
  {
52
  resetWatchdog ();  // do this first in case WDT fires
53
   // Transmitter is connected to Arduino Pin #10  
54
  pinMode(PIN_LED, OUTPUT);
55
  pinMode(strom, OUTPUT);
56
  // VirtualWire setup
57
  vw_setup(1000); // Bits per sec
58
  vw_set_tx_pin(3);// 
59
  
60
61
 }
62
63
void loop ()
64
  {
65
   //ADCSRA |= (1<<ADEN); 
66
   //delay(50);
67
  
68
   ID = 1;
69
   //a++;
70
   keep_ADCSRA = ADCSRA;
71
    
72
   memset(daten, 0, sizeof daten);                           // Inhalt der Variblen (char) löschen
73
   digitalWrite(strom, HIGH);
74
   digitalWrite(PIN_LED, HIGH);
75
   delay(450);
76
77
  
78
  sprintf(daten, "%d,%d", ID, analogRead(sensorPin));
79
   //delay(1000); 
80
   vw_send((uint8_t *)daten, strlen(daten));
81
   vw_wait_tx(); // Wait until the whole message is gone
82
83
   //delay(1000);
84
   digitalWrite(strom, LOW);
85
   digitalWrite(PIN_LED, LOW);
86
   //Schlafen gehen
87
   for (int i=0; i<450; i++){  //Hier schläft er jetzt 8 Sekunden 450 ist eine Stunde
88
      goToSleep ();
89
      
90
  }
91
   
92
   ADCSRA = keep_ADCSRA;
93
   delay(50);
94
  }  // end of loop
95
  
96
void goToSleep ()
97
  {
98
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
99
  ADCSRA = 0;            // turn off ADC 0,27 mA ohne 6,51
100
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
101
  noInterrupts ();       // timed sequence coming up
102
  resetWatchdog ();      // get watchdog ready
103
  sleep_enable ();       // ready to sleep
104
  interrupts ();         // interrupts are required now
105
  sleep_cpu ();          // sleep                
106
  sleep_disable ();      // precaution
107
  power_all_enable ();   // power everything back on
108
  }  // end of goToSleep

von HildeK (Gast)


Lesenswert?

Ich weiß nicht, ob es damit etwas zu tun hat: nach ADC-Off / 
ADC-Power-Off  bzw. auch nach dem Reset sollte mit dem ADC eine 
Dummy-Messung erfolgen.

In deinem veröffentlichten Code fehlen allerdings viele Funktionen, so 
dass man nicht alles beurteilen kann.

von Torsten W. (toto1975)


Lesenswert?

Hallo,

danke für die Antwort. Der Code ist eigentlich so wie ich ihn in Moment 
habe. Ich habe also nichts weggelassen. Da ich noch Anfänger bin kann es 
sehr gut sein das da noch einiges an Code fehlt. :-|

Wie würde denn solch eine Dummy.Messung aussehen?

Ich sollte eventuell noch hinzufügen das ich den Code mit der Arduino 
1.6.5 IDE geschrieben habe.

Viele Grüße
Torsten

von HildeK (Gast)


Lesenswert?

Torsten W. schrieb:
> Der Code ist eigentlich so wie ich ihn in Moment
> habe. Ich habe also nichts weggelassen.

Ich meinte die Funktionen wie z.B. power_all_enable (). Aber ich sehe 
jetzt: Die sind aus der Arduino Lib - das kenne ich nicht.

Torsten W. schrieb:
> Wie würde denn solch eine Dummy.Messung aussehen?

Einfach vor der Printausgabe eine extra Zeile der Art
1
analogRead(sensorPin);
einbringen, ohne das Ergebnis zu nutzen.

von Manfred (Gast)


Lesenswert?

Torsten W. schrieb:
> Da im Sleep Modus der ADC mit ADCSRA = 0; ausgeschaltet
> wird habe ich nun das Problem das er nach dem anschalten mit ADCSRA |=
> (1<<ADEN); immer den Wert 0 anzeigt wird.

Vermutlich ist es nur der erste Wert. Also Meßwert abholen, kurze Pause 
und nochmal.

Du kannst natürlich auch in eine Schleife gehen, "Wenn Meßwert kleiner 
irgendwas dann Pause und nochmal" - hängt davon ab, wieviel Zeit Du 
hast.

von Torsten W. (toto1975)


Lesenswert?

Manfred schrieb:
> Torsten W. schrieb:
>> Da im Sleep Modus der ADC mit ADCSRA = 0; ausgeschaltet
>> wird habe ich nun das Problem das er nach dem anschalten mit ADCSRA |=
>> (1<<ADEN); immer den Wert 0 anzeigt wird.
>
> Vermutlich ist es nur der erste Wert. Also Meßwert abholen, kurze Pause
> und nochmal.
>
> Du kannst natürlich auch in eine Schleife gehen, "Wenn Meßwert kleiner
> irgendwas dann Pause und nochmal" - hängt davon ab, wieviel Zeit Du
> hast.

Hallo,

leider ändert sich an dem Problem nichts. Ich habe jetzt folgenden Code:
1
   digitalWrite(strom, HIGH);
2
   digitalWrite(PIN_LED, HIGH);
3
   delay(50);
4
   analogRead(sensorPin);
5
   delay(300);
6
   wert = analogRead(sensorPin);

Allerdings wenn er eigentlich "0" anzeigen müsste zeigt er mir immer die 
letzten zwei Zahlen des vorherigen Wertes an. Beispiel:

Wert: 157 nächster Wert 57 müsste aber eigentlich 0 sein da Luft 
zwischen den "Fühlern" ist
Wert: 489 nächster Wert 89 müsste aber eigentlich 0 sein da Luft 
zwischen den "Fühlern" ist

Lediglich der erste Wert wenn keine Verbindung zwischen den Fühlern 
besteht zeigt "0" an.

Hier noch mal der komplette Code
1
// ATMEL ATTINY 25/45/85 / ARDUINO
2
//
3
//                  +-\/-+
4
// Ain0 (D 5) PB5  1|    |8  Vcc
5
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
6
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
7
//            GND  4|    |5  PB0 (D 0) pwm0
8
//                  +----+
9
10
11
12
#include <avr/sleep.h>    // Sleep Modes
13
#include <avr/power.h>    // Power management
14
#include <avr/wdt.h>      // Watchdog timer
15
#include <VirtualWire.h>
16
17
int sensorPin = A1; //zum lesen der Daten
18
char daten[10];
19
int ID;
20
const int PIN_LED = 4;
21
const int strom =  1;
22
int keep_ADCSRA; 
23
int a;
24
int wert;
25
26
27
ISR (PCINT0_vect) 
28
 {
29
 // do something interesting here
30
 }  // end of PCINT0_vect
31
32
 // watchdog interrupt
33
ISR (WDT_vect) 
34
{
35
   wdt_disable();  // disable watchdog
36
   
37
}  // end of WDT_vect
38
39
void resetWatchdog ()
40
  {
41
  // clear various "reset" flags
42
  MCUSR = 0;     
43
  // allow changes, disable reset, clear existing interrupt
44
  WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);
45
  // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
46
  WDTCR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
47
  // pat the dog
48
  wdt_reset();  
49
  }  // end of resetWatchdog
50
51
  void setup ()
52
  {
53
  resetWatchdog ();  // do this first in case WDT fires
54
   // Transmitter is connected to Arduino Pin #10  
55
  pinMode(PIN_LED, OUTPUT);
56
  pinMode(strom, OUTPUT);
57
  // VirtualWire setup
58
  vw_setup(1000); // Bits per sec
59
  vw_set_tx_pin(3);// 
60
  
61
62
 }
63
64
void loop ()
65
  {
66
   ADCSRA |= (1<<ADEN); 
67
   delay(100);
68
  
69
   ID = 2;
70
   //a++;
71
   //keep_ADCSRA = ADCSRA;
72
    
73
   memset(daten, 0, sizeof daten);                           // Inhalt der Variblen (char) löschen
74
   digitalWrite(strom, HIGH);
75
   digitalWrite(PIN_LED, HIGH);
76
   delay(50);
77
   analogRead(sensorPin);
78
   delay(300);
79
80
  wert = analogRead(sensorPin);
81
  sprintf(daten, "%d,%d", ID, wert);
82
   //delay(1000); 
83
   vw_send((uint8_t *)daten, strlen(daten));
84
   vw_wait_tx(); // Wait until the whole message is gone
85
86
   //delay(1000);
87
   digitalWrite(strom, LOW);
88
   digitalWrite(PIN_LED, LOW);
89
   //Schlafen gehen
90
   for (int i=0; i<2; i++){  //Hier schläft er jetzt 8 Sekunden 450 ist eine Stunde
91
      goToSleep ();
92
      
93
  }
94
   
95
   //ADCSRA = keep_ADCSRA;
96
   //delay(50);
97
  }  // end of loop
98
  
99
void goToSleep ()
100
  {
101
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
102
  ADCSRA = 0;            // turn off ADC 0,27 mA ohne 6,51
103
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
104
  noInterrupts ();       // timed sequence coming up
105
  resetWatchdog ();      // get watchdog ready
106
  sleep_enable ();       // ready to sleep
107
  interrupts ();         // interrupts are required now
108
  sleep_cpu ();          // sleep                
109
  sleep_disable ();      // precaution
110
  power_all_enable ();   // power everything back on
111
  }  // end of goToSleep

Ich denke ADCSRA |= (1<<ADEN);  ist auch an der richtigen stelle oder?

Muss man ADC erst kalibrieren nach dem man ihn mit ADCSRA = 0; 
ausgeschaltet hat?

Bin für weitere Ideen Tipps und natürlich Lösungen dankbar

Viele Grüße
Torsten

von Torsten W. (toto1975)


Lesenswert?

Lösung gefunden:

Auf der Empfängerseite habe ich folgende Zeile vergessen
1
memset(StringReceived, 0, sizeof(StringReceived));

Manchmal sucht man einfach an der falschen Stelle :-)

Danke für eure Hilfe

Viele Grüße
Torsten

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.