Go Down

Topic: Arduino Sleep (Read 135 times) previous topic - next topic

kollimann

Jul 21, 2016, 01:41 pm Last Edit: Jul 21, 2016, 01:51 pm by kollimann
Hallo, ich mache meine ersten Gehversuche mit Arduino Nano und einem Projekt dazu.
Durch viel lesen im Internet gehts auch gut voran, nun stolper ich aber über die Sleep Funktion.

Mein Anliegen, ich frage an einem Analog Pin einen Zustand ab, ist der Pin >999 sag ich "mache deine Arbeit", ist < 999 "geh schlafen".

soweit sogut, im Internet ein feines Beispiel dazu gefunden, geht auch soweit.
Mein Problem das Aufwachen, bzw. versteh ich nicht was er wirklich in der Schlafphase tut.

hier erstmal die wichtigen Auszüge aus dem Sketch.
Code: [Select]

#include <avr/sleep.h>
#include <avr/power.h>

volatile int sleepcounter = 0; // Schlafzyklen mitzählen

int campin = A3;
int lanpin = A4;
int routerpin = A5;
int solarpin = A7;

//bla bla bla
void setup() { 
  pinMode (lanpin, OUTPUT);         //LAN Pin
  pinMode(campin, OUTPUT);          //Cam Pin
  pinMode(routerpin, OUTPUT);       //Router Pin
  pinMode(solarpin, INPUT);         //Solar Pin

watchdogOn(); // Watchdog timer einschalten für Sleep

  currentTime = millis();        //Zeitzeug
}

void loop()
{
//Laufzeit des Boards   
  currentTime = millis();
//Zeitfunktion aufrufen
  uptime();
//Werte  setzem
   if (secs==00) {
   //schauen ob Solar anliegt
   int solarvalue = analogRead(solarpin);
   if (solarvalue <= 999) {           
   digitalWrite(lanpin, LOW);           //LAN anschalten LOW=AUS, HIGH=AN
   digitalWrite(campin, LOW);           //Cam LOW=AUS, HIGH=AN
   digitalWrite(routerpin, LOW);        //Router LOW=AUS , HIGH=AN
   pwrDown(180); //180Sekunden Sleep da kein Solar
  }
}
delay(1000);
}

void uptime()
{
 secs = currentTime/1000; //convect milliseconds to seconds
 mins=secs/60; //convert seconds to minutes
 hours=mins/60; //convert minutes to hours
 secs=secs-(mins*60); //subtract the coverted seconds to minutes in order to display 59 secs max
 mins=mins-(hours*60); //subtract the coverted minutes to hours in order to display 59 minutes max
}

void pwrDown(int sekunden) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // den tiefsten Schlaf auswählen PWR_DOWN
  for(int i=0; i < sekunden; i++) {
    sleep_enable(); // sleep mode einschalten
 power_all_disable ();// turn off various modules
 // power_adc_disable(); // ADC converter
 power_spi_disable(); // SPI
 power_usart0_disable();// Serial (USART)
 // power_timer0_disable();// Timer 0
 // power_timer1_disable();// Timer 1
 // power_timer2_disable();// Timer 2
 power_twi_disable(); // TWI (I2C)
    sleep_mode(); // in den sleep mode gehen
   
   sleep_disable(); // sleep mode ausschalten nach dem Erwachen
   power_all_enable();
   int solarvalue = analogRead(solarpin);
   if (solarvalue <= 999) {
   digitalWrite(lanpin, LOW);        //LAN anschalten LOW=AUS, HIGH=AN
   digitalWrite(campin, LOW);        //Cam aus=LOW AN=HIGH
   digitalWrite(routerpin, LOW);     //Router LOW=AUS , HIGH=AN
    pwrDown(180); //180Sekunden Sleep da immer noch kein Solar
  } else {
  asm volatile ("jmp 0");
  }
 }
}
void watchdogOn() {
  MCUSR = MCUSR & B11110111; // Reset flag ausschalten, WDRF bit3 vom MCUSR.
  WDTCSR = WDTCSR | B00011000; // Bit 3+4 um danach den Prescaler setzen zu können
  WDTCSR = B00000110; // Watchdog Prescaler auf 128k setzen > ergibt ca. 1 Sekunde
  WDTCSR = WDTCSR | B01000000; // Watchdog Interrupt einschalten
  MCUSR = MCUSR & B11110111;
}

ISR(WDT_vect) {
  sleepcounter ++; // Schlafzyklen mitzählen
}




so wer sich jetzt die Mühe gemacht hat da durch zu steigen ...........................

zu Deutsch, im Loop frage ich jede Minute ab Solar JA/NEIN wenn NEIN (<999) dann geh schlafen.

So nun wenn er wieder Aufwacht, will ich eigentlich das er schaut ob Solar anliegt, wenn NEIN wieder schlafen, wenn JA einfach komplett neu starten, weil ich find das am einfachsten das sich alles andere neu initialisiert.
Bei mir ist es im Moment so, er geht schlafen, wenn ich nun Solar JA sage (per anlegen 5V) fährt er SOFORT neu hoch, wie kann das sein? er müsste doch noch im Schlafmodus sein wenn ich 5V anlege und erst wenn die 180Sekunden um sind schauen ob PIN > 999 ???
Ich glaube der schläft nicht richtig?

Danke Heiko

DrDiettrich

Je nach Schlafmodus laufen die Timer etc. mit, so daß der Controller regelmäßig wieder aufwacht, oder er kann nur noch auf einen externen Interrupt reagieren. Die Auswahl des passenden Schlafmodus ist einfacher (und empfehlenswerter) als das einzelne Abschalten unterwünschter Interrupts.

Wenn Du den Controller alle 180 Sekunden weiterlaufen lassen möchtest, dann müssen dafür die Timer (zumindest T0) weiterlaufen, und regelmäßig Interrupts liefern. Dann fragt man in loop() ab, ob die Weckzeit schon erreicht ist, und legt den Controller andernfalls gleich wieder schlafen. So wie Du das in pwrDown() vorhast, funktioniert das nicht.

Wenn der Controller schon mal wach ist, kann man in loop() auch das Aufwach-Signal (mit analogRead) abfragen, und entsprechend weitermachen oder wieder schlafen gehen.

kollimann

OK Danke.

Gibts irgendwo ein Stück Code dafür ?

Ich versteh nicht so recht wo es "nach" dem Aufwachen weiter geht im Code, daher wo soll ich erneut abfragen ob sich der Zustand des Pin geändert hat?

Danke Heiko


DrDiettrich

Es geht weiter direkt nach
Code: [Select]
   sleep_mode(); // in den sleep mode gehen
Danach läuft loop() wieder, und dort kann man abfragen was man braucht.

kollimann

OK, hab aus dem Link ein Bsp. genommen welches funktioniert, das mit dem Wakeup at Interupt (Sketch J).

Wenn ich den nun noch von meinen Pin A7 wecken könnte wäre es fertig.

Das andere versuch ich auch mal.

Danke

Serenifly

#6
Jul 22, 2016, 04:35 pm Last Edit: Jul 22, 2016, 04:55 pm by Serenifly
A6 und A7 sind rein analog. Wie soll da ein Interrupt gehen?

Was evtl. gehen würde ist ein Pin Change Interrupt auf einem der anderen Analog Pins. Dann könnte man aufwachen wenn der Pegel über die High-Schwelle ansteigt und danach messen.

Pin Change Interrupts sind aber recht kompliziert. Man könnte auch das Signal gleichzeitig auf einen der normalen externen Interrupt Pins und einen Analog Pin geben.

Oder wenn du eh nur bei einer bestimmten Schwelle aufwachen willst, bau doch einfach einen Komparator vor einen Interrupt-Eingang. Der interne Komparator des Arduino (ein oft verschwiegenes Feature das nicht durch die IDE unterstützt wird) kann auch direkt einen Interrupt auslösen. Ich weiß aber nicht ob man damit aus dem Sleep Modus aufwachen kann. Sollte eigentlich gehen.
Hier gibt es eine Library dafür:
http://www.leonardomiliani.com/en/2012/analogcomp-una-libreria-per-gestire-il-comparatore-analogico/
Vergleicht die Spannung an zwei Pins und macht was wenn eine höher als die andere ist (je nach Anschluss und Konfiguration). Dann schließt man das Signal an einen Pin an und an den anderen einen Spannungsteiler oder einen Trimmer um die Vergleichssspannung einzustellen.

kollimann

mal blöd gefragt,
einfach von A7 mit ner Diode zu D2? D2 im Code auf LOW also das er auf HIGH reagiert.
Wenn A7 5V anliegt = D2 HIGH ?

und......der Code einzeln aus dem Link = 20mA im Sleep, eingefügt in meinen Code = 80mA im Sleep.
Irgend etwas geht in meinem Code nicht aus, obwohl ich alle PINs INPUT habe wenn er schlafen soll? Den Rest einfach übernommen aus dem Link. Einzeln geht ja auch.Hab nur noch die Ethernet.h per include drinnen, muss ich die "entladen", oder Timer noch einzeln stoppen?

Danke Heiko

Serenifly

#8
Jul 22, 2016, 05:26 pm Last Edit: Jul 22, 2016, 05:29 pm by Serenifly
Die Pins sind normal als Eingang definiert. Da muss man sonst nichts machen, weil nichts passieren kann

Aber wie gesagt, wäre das sauberste ein Komparator.

Quote
.der Code einzeln aus dem Link = 20mA im Sleep, eingefügt in meinen Code = 80mA im Sleep.
Spannungsregler, USB Konverter und LEDs brauchen einiges an Strom. Was auf der Seite steht gilt für einen nackten Prozessor wenn sonst nichts dabei steht. Wobei 80mA etwas hoch ist. Ein UNO im Schlafmodus braucht etwa 35mA

DrDiettrich

Ich weiß nicht, was an den Pin Change Interrupts kompliziert sein soll, außer daß es dafür keine Standard-Funktionen gibt.

Jeder Port hat einen Interrupt Vektor (und damit ISR) und Interrupt Enable Bit, jeder Pin nochmal ein eigenes Enable Bit.

Zudem sind diese Interrupts asynchron, funktionieren also in jedem Schlafmodus.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy