Forum: Mikrocontroller und Digitale Elektronik Analoger Messwert nach Sleep falsch


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Torsten W. (toto1975)


Bewertung
0 lesenswert
nicht 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
// ATMEL ATTINY 25/45/85 / ARDUINO
//
//                  +-\/-+
// Ain0 (D 5) PB5  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0
//                  +----+



#include <avr/sleep.h>    // Sleep Modes
#include <avr/power.h>    // Power management
#include <avr/wdt.h>      // Watchdog timer
#include <VirtualWire.h>

int sensorPin = A1; //zum lesen der Daten
char daten[10];
int ID;
const int PIN_LED = 4;
const int strom =  1;
int keep_ADCSRA; 
int a;


ISR (PCINT0_vect) 
 {
 // do something interesting here
 }  // end of PCINT0_vect

 // watchdog interrupt
ISR (WDT_vect) 
{
   wdt_disable();  // disable watchdog
   
}  // end of WDT_vect

void resetWatchdog ()
  {
  // clear various "reset" flags
  MCUSR = 0;     
  // allow changes, disable reset, clear existing interrupt
  WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);
  // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
  WDTCR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
  // pat the dog
  wdt_reset();  
  }  // end of resetWatchdog

  void setup ()
  {
  resetWatchdog ();  // do this first in case WDT fires
   // Transmitter is connected to Arduino Pin #10  
  pinMode(PIN_LED, OUTPUT);
  pinMode(strom, OUTPUT);
  // VirtualWire setup
  vw_setup(1000); // Bits per sec
  vw_set_tx_pin(3);// 
  

 }

void loop ()
  {
   //ADCSRA |= (1<<ADEN); 
   //delay(50);
  
   ID = 1;
   //a++;
   keep_ADCSRA = ADCSRA;
    
   memset(daten, 0, sizeof daten);                           // Inhalt der Variblen (char) löschen
   digitalWrite(strom, HIGH);
   digitalWrite(PIN_LED, HIGH);
   delay(450);

  
  sprintf(daten, "%d,%d", ID, analogRead(sensorPin));
   //delay(1000); 
   vw_send((uint8_t *)daten, strlen(daten));
   vw_wait_tx(); // Wait until the whole message is gone

   //delay(1000);
   digitalWrite(strom, LOW);
   digitalWrite(PIN_LED, LOW);
   //Schlafen gehen
   for (int i=0; i<450; i++){  //Hier schläft er jetzt 8 Sekunden 450 ist eine Stunde
      goToSleep ();
      
  }
   
   ADCSRA = keep_ADCSRA;
   delay(50);
  }  // end of loop
  
void goToSleep ()
  {
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  ADCSRA = 0;            // turn off ADC 0,27 mA ohne 6,51
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  noInterrupts ();       // timed sequence coming up
  resetWatchdog ();      // get watchdog ready
  sleep_enable ();       // ready to sleep
  interrupts ();         // interrupts are required now
  sleep_cpu ();          // sleep                
  sleep_disable ();      // precaution
  power_all_enable ();   // power everything back on
  }  // end of goToSleep 
  

von HildeK (Gast)


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


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


Bewertung
0 lesenswert
nicht 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
analogRead(sensorPin);
einbringen, ohne das Ergebnis zu nutzen.

von Manfred (Gast)


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


Bewertung
0 lesenswert
nicht 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:
   digitalWrite(strom, HIGH);
   digitalWrite(PIN_LED, HIGH);
   delay(50);
   analogRead(sensorPin);
   delay(300);
   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
// ATMEL ATTINY 25/45/85 / ARDUINO
//
//                  +-\/-+
// Ain0 (D 5) PB5  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0
//                  +----+



#include <avr/sleep.h>    // Sleep Modes
#include <avr/power.h>    // Power management
#include <avr/wdt.h>      // Watchdog timer
#include <VirtualWire.h>

int sensorPin = A1; //zum lesen der Daten
char daten[10];
int ID;
const int PIN_LED = 4;
const int strom =  1;
int keep_ADCSRA; 
int a;
int wert;


ISR (PCINT0_vect) 
 {
 // do something interesting here
 }  // end of PCINT0_vect

 // watchdog interrupt
ISR (WDT_vect) 
{
   wdt_disable();  // disable watchdog
   
}  // end of WDT_vect

void resetWatchdog ()
  {
  // clear various "reset" flags
  MCUSR = 0;     
  // allow changes, disable reset, clear existing interrupt
  WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);
  // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
  WDTCR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
  // pat the dog
  wdt_reset();  
  }  // end of resetWatchdog

  void setup ()
  {
  resetWatchdog ();  // do this first in case WDT fires
   // Transmitter is connected to Arduino Pin #10  
  pinMode(PIN_LED, OUTPUT);
  pinMode(strom, OUTPUT);
  // VirtualWire setup
  vw_setup(1000); // Bits per sec
  vw_set_tx_pin(3);// 
  

 }

void loop ()
  {
   ADCSRA |= (1<<ADEN); 
   delay(100);
  
   ID = 2;
   //a++;
   //keep_ADCSRA = ADCSRA;
    
   memset(daten, 0, sizeof daten);                           // Inhalt der Variblen (char) löschen
   digitalWrite(strom, HIGH);
   digitalWrite(PIN_LED, HIGH);
   delay(50);
   analogRead(sensorPin);
   delay(300);

  wert = analogRead(sensorPin);
  sprintf(daten, "%d,%d", ID, wert);
   //delay(1000); 
   vw_send((uint8_t *)daten, strlen(daten));
   vw_wait_tx(); // Wait until the whole message is gone

   //delay(1000);
   digitalWrite(strom, LOW);
   digitalWrite(PIN_LED, LOW);
   //Schlafen gehen
   for (int i=0; i<2; i++){  //Hier schläft er jetzt 8 Sekunden 450 ist eine Stunde
      goToSleep ();
      
  }
   
   //ADCSRA = keep_ADCSRA;
   //delay(50);
  }  // end of loop
  
void goToSleep ()
  {
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  ADCSRA = 0;            // turn off ADC 0,27 mA ohne 6,51
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  noInterrupts ();       // timed sequence coming up
  resetWatchdog ();      // get watchdog ready
  sleep_enable ();       // ready to sleep
  interrupts ();         // interrupts are required now
  sleep_cpu ();          // sleep                
  sleep_disable ();      // precaution
  power_all_enable ();   // power everything back on
  }  // 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)


Bewertung
0 lesenswert
nicht lesenswert
Lösung gefunden:

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

Manchmal sucht man einfach an der falschen Stelle :-)

Danke für eure Hilfe

Viele Grüße
Torsten

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.