Arduino Forum

International => Deutsch => Topic started by: Doc_Arduino on Jul 31, 2014, 07:40 pm

Title: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Jul 31, 2014, 07:40 pm
Hallo,

habe mich nach langer Zeit wieder mit dem Thema Strom sparen beschäftigt und haben den Bsp. Code vom Arduino Playground probiert. Im Vergleich zum Code und zur lesenswerten Seite vom Nick Gammon gibts jedoch keinen Unterschied. Vielleicht weil er für beides verantwortlich zeichnet. Gehört ja zur Arduino Truppe soweit ich das verstanden habe.

Also der Code funktioniert soweit, dass er vom normalen Idle Zustand mit 62mA in den Power Down Modus geht mit 27mA. Es leuchtet nur noch die Power LED auf dem Arduino Board. Mit einem Taster an Pin 2 kann man ihn wieder aufwecken, bevor er nach erneuten 10sec Wartezeit wieder in den Power Down Modus wechselt.

Ich speise von einem Netzteil 5V direkt ein an den 5V Pin und GND Pin und messe dabei den Strom.

Jetzt möchte ich fragen. Ist das auf dem Mega2560 wirklich das maximale an Strom sparen was per Code möglich ist?
Die 27mA wird vom Rest auf dem Board verschluckt? Es ist ja nur der USB-RS232 Wandler und der Spannungsregler zusätzlich vorhanden. Der Spannungsregler sollte außen vor sein, wenn ich extern hinter seinem Rücken einspeise. Und der USB-RS232 IC kann doch keine mA ziehen? Hat sich jemand damit schon näher beschäftigt? Wenn er PowerDown ist, ist es doch egal ob der sonst mit 16 oder 8 oder 1MHz taktet? (von 5V auf 3,3V kann ich nicht runtergehen, wegen externer Beschaltung)

Ich müßte mir erst einen 2. Mega2560 kaufen bevor ich weitermachen kann und darauf rum löte bzw. Teile auslöte.

Die einzelnen power .... disable()  Funktionen werden nur benötigt um gezielt einzelne Funktionen abzuschalten? Richtig?

Statt dem Taster zum aufwecken möchte ich die RTC DS3231 verwenden. Könnte doch funktionieren? Wenn die den AVR aller einer Sekunde aufweckt. Laufen die millis() im PowerDown Modus weiter oder bleibt der Zähler stehen? Eigentlich müßte der stehen bleiben, laut meiner Überlegung. Das heißt ich müßte meine Warteschleifen mit millis() komplett umschreiben auf Zähler die von der RTC im Sekundentakt dann letztlich gezählt werden?



Code: [Select]

/* Sleep Demo Serial
* -----------------
* Example code to demonstrate the sleep functions in a Arduino. Arduino will wake up
* when new data is received in the serial port USART
* Based on Sleep Demo Serial from http://www.arduino.cc/playground/Learning/ArduinoSleepCode
*
* Copyright (C) 2006 MacSimski 2006-12-30
* Copyright (C) 2007 D. Cuartielles 2007-07-08 - Mexico DF
*
*  With modifications from Ruben Laguna  2008-10-15
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
*/

//  27mA mit direkter 5V Einspeisung an 5V Pin / GND

#include <avr/sleep.h>

int sleepStatus = 0;        // variable to store a request for sleep
int count = 0;              // counter

int ledPin = 13;            // LED connected to digital pin 13
//int interruptPin = 10;      // LED to show the action of a interrupt
int wakePin = 2;            // active LOW, ground this pin momentary to wake up
//int sleepPin = 12;          // active LOW, ground this pin momentary to sleep


void wakeUpNow()        // here the interrupt is handled after wakeup
{
  // execute code here after wake-up before returning to the loop() function
  // timers and code using timers (serial.print and more...) will not work here.
  // digitalWrite(interruptPin, HIGH);  // LED an Pin 10 ein
}


void sleepNow()
{
    /* Now is the time to set the sleep mode. In the Atmega8 datasheet
     * http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
     * there is a list of sleep modes which explains which clocks and
     * wake up sources are available in which sleep modus.
     *
     * In the avr/sleep.h file, the call names of these sleep modus are to be found:
     *
     * The 5 different modes are:
     *     SLEEP_MODE_IDLE         -the least power savings
     *     SLEEP_MODE_ADC
     *     SLEEP_MODE_PWR_SAVE
     *     SLEEP_MODE_STANDBY
     *     SLEEP_MODE_PWR_DOWN     -the most power savings
     *
     *  the power reduction management <avr/power.h>  is described in
     *  http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
     */ 
       
  //set_sleep_mode(SLEEP_MODE_IDLE);   // sleep mode is set here
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

  sleep_enable();          // enables the sleep bit in the mcucr register
                           // so sleep is possible. just a safety pin
 
    /* Now it is time to enable an interrupt. We do it here so an
     * accidentally pushed interrupt button doesn't interrupt
     * our running program. if you want to be able to run
     * interrupt code besides the sleep function, place it in
     * setup() for example.
     *
     * In the function call attachInterrupt(A, B, C)
     * A   can be either 0 or 1 for interrupts on pin 2 or 3. 
     *
     * B   Name of a function you want to execute at interrupt for A.
     *
     * C   Trigger mode of the interrupt pin. can be:
     *             LOW        a low level triggers
     *             CHANGE     a change in level triggers
     *             RISING     a rising edge of a level triggers
     *             FALLING    a falling edge of a level triggers
     *
     * In all but the IDLE sleep modes only LOW can be used.
     */

  attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
                                     // wakeUpNow when pin 2 gets LOW
 
  /*                                   
  power_adc_disable();     // dafür wird die   #include <avr/power.h>  benötigt
  power_spi_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_timer2_disable();
  power_timer3_disable();
  power_timer4_disable();
  power_timer5_disable();
  power_twi_disable();       // I2C Interface
  power_usart0_disable();    // RS232 Interfaces
  power_usart1_disable();
  power_usart2_disable();
  power_usart3_disable();
  */
   
  sleep_mode();            // here the device is actually put to sleep!!

                           // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
  sleep_disable();         // first thing after waking from sleep:
                           // disable sleep...
 
  detachInterrupt(0);      // disables interrupt 0 on pin 2 so the
                           // wakeUpNow code will not be executed
                           // during normal running time.
   
}


void setup()
{
  // Serial.begin(57600);
 
  pinMode(ledPin, OUTPUT);         // LED connected to digital pin 13
  //pinMode(interruptPin, OUTPUT);   // LED to show the action of a interrupt pin 10
 
  pinMode(wakePin, INPUT);         // active LOW, ground this pin momentary to wake up
  digitalWrite(wakePin, HIGH);     // Pullup aktiv
  //pinMode(sleepPin, INPUT);        // active LOW, ground this pin momentary to sleep
  //digitalWrite(sleepPin, HIGH);    // Pullup aktiv
 
  attachInterrupt(0,wakeUpNow, LOW);   // use interrupt 0 (pin 2) and run function
                                       // wakeUpNow when pin 2 gets LOW
}



void loop()
{
 
  count++;
  delay(1000);                           // waits for a second

  // check if it should go asleep because of time
  if (count >= 10) {
    count = 0;
    digitalWrite(ledPin, LOW);   
    sleepNow();     // sleep function called here
  }
 
  digitalWrite(ledPin, HIGH);   
 
}
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Serenifly on Jul 31, 2014, 07:46 pm
Du kannst die Power-LED auslöten oder die Leiterbahn auftrennen. Aber das war es dann.

Der USB-seriell Wandler ist ja auch ein Mikrokontroller. Und dessen Verbrauch ist in der Größenordnung wie es für dessen Klasse üblich ist.

Quote

Laufen die millis() im PowerDown Modus weiter oder bleibt der Zähler stehen?

Wenn Timer0 abgeschaltet ist, ist auch der millis() Zähler gestoppt. Es gibt auch Modi wo der weiterläuft. Dann wacht der Prozessor aber alle 1ms auf und der Stromverbrauch steigt entsprechend.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: combie on Jul 31, 2014, 08:12 pm
Quote
Statt dem Taster zum aufwecken möchte ich die RTC DS3231 verwenden. Könnte doch funktionieren? Wenn die den AVR aller einer Sekunde aufweckt. Laufen die millis() im PowerDown Modus weiter oder bleibt der Zähler stehen? Eigentlich müßte der stehen bleiben, laut meiner Überlegung. Das heißt ich müßte meine Warteschleifen mit millis() komplett umschreiben auf Zähler die von der RTC im Sekundentakt dann letztlich gezählt werden?

Du kannst die Millis Variable bei jedem aufwachen einfach "AlterStand" +1000 rechnen.
Dann stimmt sie wieder.

Oder den Watchdog nutzen und aus der RTC Zeit den neuen Millistand setzen


Und ca 20 mA für den USB Prozessor scheint mir plausibel.
Auch den kannst du in den Sleep schicken.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Jul 31, 2014, 08:54 pm
Hallo,

okay, soweit sind die Hinweise verstanden. Nur wie kann man den USB-RS232 µC schlafen legen? Ausbauen wollte ich den nicht. Der muß noch funktionieren wenn ich später ggf. ein Update vom Sketch einspielen muß.


Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: uwefed on Jul 31, 2014, 09:32 pm
Indem Du den Atmega16U2 neu programmierst.
Du mußt aber in den Code die Sleepfunktion einfügen und zwar so daß es die Bootload-Funktion und die Serial-USB Funtion noch funktioniert.
In einfachen Worten: sehr schwierig.
Grüße Uwe
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 01, 2014, 07:33 am
Hallo,

das würde mir sehr schwer fallen, den neu zu programmieren. Bin froh das ich mein Anliegen so programmieren konnte. Mit Eurer Hilfe natürlich.   ;)

Was würde denn passieren, wenn ich den AVR 16U2 komplett runternehme von der Platine und dann mittels USB<>RS232 Adapterkabel oder Miniadapter mit FTDI-232 an Pin 0/1 direkt rangehe und den Rest der Änderungen flashen möchte. Klappt das dann noch mit der IDE so wie jetzt oder hat der 16U2 noch irgendwelche Sonderaufgaben? Was hat der mit dem Bootloader zu tun. Der Code sitzt doch im großen µC drin? Könnte mir denken man muß den µC zum flashen dann erstmal mit Jumper in den Programmiermodus bringen.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: uwefed on Aug 01, 2014, 09:20 am

Was würde denn passieren, wenn ich den AVR 16U2 komplett runternehme von der Platine und dann mittels USB<>RS232 Adapterkabel oder Miniadapter mit FTDI-232 an Pin 0/1 direkt rangehe und den Rest der Änderungen flashen möchte. Klappt das dann noch mit der IDE so wie jetzt ...


Das funktioniert.
Das einzige Problem ist den Atmega auszulöten weil er so winzig ist. Dann kannst Du auch den Operationsverstärket LM358, Den Transistor, den Spannungsstabilisator ( 5V und 3,3V) und die LED auslöten, um allen nicht notwendigen Strom zu sparen.
Ich würde einen Adapter mit dem ATmega16U2 nehmen wie Arduino ihn anbietet statt einen mit FT232.

Grüße Uwe
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jurs on Aug 01, 2014, 09:34 am

Was würde denn passieren, wenn ich den AVR 16U2 komplett runternehme von der Platine und dann mittels USB<>RS232 Adapterkabel oder Miniadapter mit FTDI-232 an Pin 0/1 direkt rangehe und den Rest der Änderungen flashen möchte.


Halte Deinen 16U2 doch einfach im Reset, dann taktet er nicht!

Dein MEGA Board hat einen zweiten ICSP-Header, der für den 16U2 ist. Dort ist unter anderem der Reset-Pin des 16U2 herausgeführt. Verbinde Reset des 16U2 mit GND, dann ist er stillgelegt. Zum Programmieren öffnest Du diese Dauer-Reset Leitung dann wieder.

Allerdings dürfte das nicht die Masse der 27mA im PowerDown ausmachen, die der 16U2 verbraucht, sondern im wesentlichen wird dieser Verbrauch durch den falsch beschalteten Spannungsregler auf dem Board verursacht. Der ist nämlich verboten falsch beschaltet, wenn er am Ausgang mit einer höheren Ausgangsspannung als am Eingang betrieben wird. Und die wenigsten Spannungsreglertypen haben gegen diese Falschbeschaltung eine interne Schutzschaltung, die diesen Fehlerfall erkennt und den Spannungsregler dann gegen Rückwärts-Stromfluss schützt.

Also den Spannungsregler und Power-On LED wirst Du wohl auslöten müssen. Den 16U2 würde ich einfach durch Dauer-Reset stilllegen, so dass er zum Programmieren des Boards leicht wieder aktiviert werden kann.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Serenifly on Aug 01, 2014, 09:42 am
Vielleicht willst du eher das hier statt ein komplettes Mega Board:
http://www.ebay.de/itm/Mikrocontroller-Atmel-ATMega2560-ATMega-SMD-Adapter-/271224130246?pt=Bauteile&hash=item3f2637cac6

Das ist nur ein Atmega2560 auf einem SMD Adapter. Damit kommst du sogar an Pins, die auf dem normalen Arduino Board gar nicht drauf sind
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: SkobyMobil on Aug 01, 2014, 12:00 pm
Hallo,
das ist ja mal ein nützlicher Link. Bekomme ich den aud dem selben Wege programmiert wie einen 328P?

Also Arduino Mega 2560 -> 328P das sollte ja "keine" Probleme bereiten.
aber Arduino Mega 2560 -> 2560 (Dein Link) geht das dort genau so?

Dann könnte man auf dem Arduino Mega ohne SpeicherPlatzProbleme etwas entwickeln, das dann auf dieses Board schieben-
und klitzekleine Gehäuse verwenden.
Gruß und Dank
Andreas
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Serenifly on Aug 01, 2014, 12:32 pm
Hier ist eine Anleitung wo man sich dafür die Platine für die grundlegende Peripherie bauen kann:
http://www.instructables.com/id/DIY-Arduino-Mega-2560/?ALLSTEPS (ab Schritt 7)
oder hier:
http://tsjwang.blogspot.de/2013/08/diy-arduino-mega-2560.html

Man muss erst mal den Bootloader per ISP installieren. Wenn man das geschafft hat, lässt er sich ganz normal programmieren.

Den Teil wo er sagt, dass es für den Atmega1280 geht, aber nicht mit dem Atmega2560 verstehe ich aber nicht. Wieso soll man den 2560 Bootloader nicht über die IDE installieren könnnen? In den Kommentaren deutet er an dass es irgendwas damit zu tun, dass er den UART geschrottet hat aber das ist nicht richtig erklärt.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: SkobyMobil on Aug 01, 2014, 01:03 pm
Hallo,
so verstehe ich das auch. Der hat seine UART verbastelt. Wenn man sich die Kommentare der beiden Beiträge durchliest, dann sollte es also
genau so funktionieren wie mit dem 328P. Den Eindruck habe ich jedenfalls. Mal sehen, ob hier noch jemand etwas dazu sagen kann...
Gruß und Spaß
Andreas
P.S.
könnte das der Grund dafür sein:
"The reason for this is because there is a bug in the Arduino MEGA 2560/ADK firmware that does not allow flash write commands to start at anywhere but the beginning of flash memory (0x000000). See the bottom of this page for more technical details. "

http://www.robotc.net/wiki/ARDUINO_MEGA_Update_Bootloader
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Serenifly on Aug 01, 2014, 01:34 pm
Der 2560 Bootloader hatte früher noch mehr Bugs (drei Ausrufezeichen, die Sache mit dem Watchdog Reset und irgendwas mit dem EEPROM).

Allerdings muss das laut dem hier auch mit dem Mega gehen:
http://www.gammon.com.au/forum/?id=11635

Hier wird es auch gemacht:
http://androm12.blogspot.de/2013/10/arduino-bootloader-atmega.html
http://cisana.net/burning-the-bootloader-onto-the-arduino-mega-2560/


Wenn ich mir das nochmal anschaue, dann bezieht sich das mit UART auch auf das originale Mega Board, das er kaputt gemacht hat. Nicht auf das Breakout Board.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: SkobyMobil on Aug 01, 2014, 02:00 pm
Hallo,
wenn man das so liest, dann ist es eigentlich "ganz einfach" Ich werde das einmal probieren.
20€ Lehrgeld habe ich in der Kasse.
Gruß und Dank
Andreas
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 01, 2014, 05:18 pm
Hallo,

den 16U2 im Dauer-Reset zu halten war ein sehr guter Hinweis. Das senkt die Stromaufnahme im PowerDown von 27mA auf 15mA für das gesamte nackte Board. Das ist ordentlich. Beim Spannungsregler habe ich die "Schutzdiode" zwischen 5V und VIN extern nachgerüstet, so wie es üblich wäre. Das bringt aber keine Änderung, auch in der Kommastelle, mit sich.

Jetzt stellt sich die Frage, ob das mit dem Dauerreset vom 16U2 alles ist was möglich ist. Wenn ich den Arduino Reset Taster drücke messe ich 36mA. Mit 16U2 Resetjumper. Wenn man sagt der Mega verbraucht im PowerDown quasi nichts, wären das dann die 15mA Differenz die der 16U2 auch noch beitragen könnte, wenn er ordentlich im PowerDown oder ganz runter vom Board wäre. Das würde bedeuten, Reset ist ungleich PowerDown. Sehe ich das richtig?

Ich habe mal einen LM2940 5V aus der Bastelkiste geholt Da fließt völlig unbeschalten ein Strom von 11mA, egal ob ich 5V an OUT-GND oder IN-GND anschließe. Dann habe ich noch einen 7805 rausgeholt, hier fließen, wieder völlig unbeschalten, nur 2mA richtig beschalten und 18mA falsch beschalten. Das widerlegt meine Theorie.

Die Miniplatine mit dem Mega2560 klingt auch verlockend. Nur fängt man dann wieder bei Null an. Mal sehen ob meine Zusatzschaltung in das Format eines Mega-Shields paßt. Sonst ergeben sich neue Freiheiten.

Ich glaube ich muß erstmal gucken wie groß meine externe Zuschaltung wird, die nimmt z.Z. 11mA. Vielleicht kann ich da nochwas optimieren. Das BT-Modul HC-06 habe ich schon "optimiert" Das wird per Transistorbeschaltung PNP/NPN, quasi ein High-Side Switch Nachbau, und Taster am Arduino und etwas Code ein- und ausgeschalten. Denn wenn das nichts macht, nimmt das durch die ständige suche pulsend bis 80mA auf, hat es einen Connect sind es immer noch stabile 40mA. Das ist zu viel für einen Akkubetrieb. Je tzt kann es mittels Taster nur bei Bedarf eingeschalten werden.  ;)

Was wäre der Vorteil einen 16U2 Adapters im Gegensatz zum FTDI? Machen doch beide das gleiche?

Edit:
ich messe noch einen Unterschied von 2mA, wenn ich den 16U2 gejumpert lasse und dann 5V anschließe oder erst 5V ran und dann jumper.
Also, 5V ran, 16U2 jumpern, warten bis PowerDown, messe 15mA.
Jumper gesteckt lassen. 5V weg nehmen, warten, wieder ran, warten bis PowerDown, messe 17mA.
Jetzt den Jumper ziehen und wieder stecken macht keinen Unterschied, sind immer 17mA.
Erst das Jumper ziehen und 5V wegnehmen und dann wieder alles ran, macht 15mA.
Hab noch keine Erklärung für den Effekt.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 03, 2014, 11:49 am
Hallo,

was wäre der Vorteil einen 16U2 Adapters im Gegensatz zum FTDI? Machen doch beide das gleiche?
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: SkobyMobil on Aug 03, 2014, 12:17 pm
Hallo,
beim "16U2" ist die Firmware "fest" installiert und weiß was sie zu tun hat. Kabel ran, läuft.
Beim "FTDI" brauchst Du normalerweise irgend welche Treiber und Software. Du bist damit
aber flexibler, weil Du es für mehrere Systeme einsetzen kannst.
Gruß und Spaß
Andreas
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Serenifly on Aug 03, 2014, 12:21 pm
Der Treiber ist aber schnell installiert:
http://www.ftdichip.com/Drivers/VCP.htm
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 03, 2014, 12:55 pm
Hallo,

ach'so. Der 16U2 funktioniert mit Windows Standardtreiber und sonst muß man den FTDI Treiber installieren?

Wenn es wirklich nur der eine Unterschied ist, wäre mir das egal. FTDI Treiber ist eh installiert.

Interessanter wäre dann bestimmt der hier:  http://arduino.cc/en/Main/ArduinoISP
Wobei ich da wieder fragen müßte, was der Unterschied zu den AVR ISP Programmer wäre?

Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: SkobyMobil on Aug 03, 2014, 02:42 pm
Hallo,
was der Unterschied ist kann ich nicht sagen. Aber- wenn Du mit Arduino´s und Arduino IDE fummelst,
dann würde ich mich hier auf der sicheren Seite fühlen.
Ich habe so ein wenig das Gefühl, das alles was mit Programmern zusammenhängt erst einmal nur
Ärger verursacht.
Wenn Du auch andere Software/Hardware nutzt, würde ich den nicht kaufen.
Gruß und Spaß
Andreas
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 03, 2014, 05:29 pm
Hallo,

die Antwort ist jetzt im gesamten aber nicht ganz klar und widersprüchlich in sich.   :)
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: SkobyMobil on Aug 03, 2014, 06:22 pm
Hallo,
"was der Unterschied zu den AVR ISP Programmer wäre?"

in Bezug auf den ArduinoProgrammer…
Bei dem Arduino könnte ich mir vorstellen, das er mit der Arduino IDE sehr
schön funktionieren könnte.
Bei einem AVR ISP Programmer hätte ich da schon Bauchweh.
und auch umgekeht…
ein AVR ISP Programmer muß nicht umbedingt mit der Arduino IDE funktionieren
und der ArduinoProgrammer nicht mit jeder AVR-Soft.
Das meinte ich.
Gruß und Spaß
Andreas
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 03, 2014, 09:01 pm
Hallo,

okay verstanden, Du hättest Bauchschmerzen beides zu jeweils zu kombiniert zu nutzen.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 18, 2014, 12:16 pm
Hallo,

hab meinen zweiten Mega 2560 erhalten und habe beim "alten" den Spannungsregler runtergelötet und nochmal verglichen. Die Messung bzw. Stromaufnahme reagiert empfindlich auf jeden Unterschied der Versorgungsspannung. Deswegen komme ich auch nicht mehr auf die alten 27mA in Sleep ohne Jumper. Habe beide Boards nochmal vermessen.

In Idle leuchtet LED 13, in Sleep ist die aus.

Den Effekt ohne Spannungsregler hatte ich etwas größer erwartet. Dachte an 5mA in Sleep. Aber nun gut, sind immerhin 5mA weniger, was der Batterielaufzeit auch einiges bringt. Der Jumper am 16U2 hat seine Wirkung behalten. Sehr wichtig zu wissen.

Testcode:
Code: [Select]

/* Sleep Demo Serial
* -----------------
* Example code to demonstrate the sleep functions in a Arduino. Arduino will wake up
* when new data is received in the serial port USART
* Based on Sleep Demo Serial from http://www.arduino.cc/playground/Learning/ArduinoSleepCode

"Aufwach-Schalter" an Pin 2 gegen Masse

Originalboard Arduino Mega 2560
Idle 59,2mA   Sleep 22,3mA   ohne 16U2 Jumper
Idle 54,5mA   Sleep 15,5mA   mit Jumper auf GND-Reset für 16U2

ohne Spannungsregler auf Board, abgegelötet
Idle 55,1mA   Sleep 16,5mA   ohne 16U2 Jumper
Idle 49,9mA   Sleep  9,8mA   mit Jumper auf GND-Reset für 16U2

*/   
   

#include <avr/sleep.h>

int sleepStatus = 0;        // variable to store a request for sleep
int count = 0;              // counter

int ledPin = 13;            // LED connected to digital pin 13
//int interruptPin = 10;      // LED to show the action of a interrupt
int wakePin = 2;            // active LOW, ground this pin momentary to wake up
//int sleepPin = 12;          // active LOW, ground this pin momentary to sleep
int ledState = LOW;

void wakeUpNow()        // here the interrupt is handled after wakeup
{
  // execute code here after wake-up before returning to the loop() function
  // timers and code using timers (serial.print and more...) will not work here.
  // digitalWrite(interruptPin, HIGH);  // LED an Pin 10 ein
}


void sleepNow()
{
    /* Now is the time to set the sleep mode. In the Atmega8 datasheet
     * http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
     * there is a list of sleep modes which explains which clocks and
     * wake up sources are available in which sleep modus.
     *
     * In the avr/sleep.h file, the call names of these sleep modus are to be found:
     *
     * The 5 different modes are:
     *     SLEEP_MODE_IDLE         -the least power savings
     *     SLEEP_MODE_ADC
     *     SLEEP_MODE_PWR_SAVE
     *     SLEEP_MODE_STANDBY
     *     SLEEP_MODE_PWR_DOWN     -the most power savings
     *
     *  the power reduction management <avr/power.h>  is described in
     *  http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
     */ 
       
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

  sleep_enable();          // enables the sleep bit in the mcucr register
                           // so sleep is possible. just a safety pin
 
    /* Now it is time to enable an interrupt. We do it here so an
     * accidentally pushed interrupt button doesn't interrupt
     * our running program. if you want to be able to run
     * interrupt code besides the sleep function, place it in
     * setup() for example.
     *
     * In the function call attachInterrupt(A, B, C)
     * A   can be either 0 or 1 for interrupts on pin 2 or 3. 
     *
     * B   Name of a function you want to execute at interrupt for A.
     *
     * C   Trigger mode of the interrupt pin. can be:
     *             LOW        a low level triggers
     *             CHANGE     a change in level triggers
     *             RISING     a rising edge of a level triggers
     *             FALLING    a falling edge of a level triggers
     *
     * In all but the IDLE sleep modes only LOW can be used.
     */

  attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
                                     // wakeUpNow when pin 2 gets LOW
     
  sleep_mode();            // here the device is actually put to sleep!!

                           // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
  sleep_disable();         // first thing after waking from sleep:
                           // disable sleep...
 
  detachInterrupt(0);      // disables interrupt 0 on pin 2 so the
                           // wakeUpNow code will not be executed
                           // during normal running time.
   
}


void setup()
{
   
  pinMode(ledPin, OUTPUT);         // LED connected to digital pin 13
  //pinMode(interruptPin, OUTPUT);   // LED to show the action of a interrupt pin 10
 
  pinMode(wakePin, INPUT);         // active LOW, ground this pin momentary to wake up
  digitalWrite(wakePin, HIGH);     // Pullup aktiv
  //pinMode(sleepPin, INPUT);        // active LOW, ground this pin momentary to sleep
  //digitalWrite(sleepPin, HIGH);    // Pullup aktiv
     
  attachInterrupt(0,wakeUpNow, LOW);   // use interrupt 0 (pin 2) and run function
                                       // wakeUpNow when pin 2 gets LOW
                           
}


void loop()
{
   if ( digitalRead(2) == LOW ) {
     digitalWrite(ledPin, HIGH);     
   }
   else {
     digitalWrite(ledPin, LOW);
     sleepNow();     // sleep function called here
   }
     
}

Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jurs on Aug 18, 2014, 12:46 pm

hab meinen zweiten Mega 2560 erhalten und habe beim "alten" den Spannungsregler runtergelötet und nochmal verglichen.


Und was ist mit der Power-On LED?
Hast Du die nicht ausgelötet?

Laut Schaltplan ist die LED auf dem MEGA2560 Board grün und hat einen 1K Vorwiderstand.
Grüne LED = 2,5V Vorwärtsspannung, macht 2,5V an 1K, I=2,5/1000= 2,5 mA

D.h. Auslöten der ständig leuchtenden Power-On LED bringt ca. 2,5 mA.

Edit/Nachtrag: Und was ist eigentlich mit dem 3.3V Spannungsregler? Brauchst Du 3.3V? Weil der 3.3V Regler braucht doch auch einen Ruhestrom von ca. 5.5 mA laut Datenblatt, falls auf Deinem Board der MC33269D-5.0 verbaut ist, wie er im Referenzdesign des MEGA-Boards enthalten ist. Wenn Deine Schaltung keine 3.3V benötigt, kannst Du also nochmal sparen, wenn Du auch den 3.3V Regler auslötest und nicht nur den 5V-Regler.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: uwefed on Aug 18, 2014, 01:54 pm

Hallo,

ach'so. Der 16U2 funktioniert mit Windows Standardtreiber und sonst muß man den FTDI Treiber installieren?

Wenn es wirklich nur der eine Unterschied ist, wäre mir das egal. FTDI Treiber ist eh installiert.

Interessanter wäre dann bestimmt der hier:  http://arduino.cc/en/Main/ArduinoISP
Wobei ich da wieder fragen müßte, was der Unterschied zu den AVR ISP Programmer wäre?



* Der Upload über die serielle Schnittstelle und eventuellen USB-Serial-Adapter funktioniert über einen im Flash vorhandenen Bootloader. So können Programme raufgeladen werden. Es können aber keine Einstellungen an der Fuse Bits gemachet werden. Dazu braucht es keine zusätzliche Hardware weil über USB-Kabel und ist somit für Anfänger am einfachsten.

* ISP braucht keinen Bootloader und man hat vollen zugriff auf die Einstellungen. Man kann einen Kontroller aber auch kaputtprogrammieren wenn man falsche Einstellungen macht (zB Watchdog mit zu kurzen Intervallen oder externen Quarz aktiviert wenn in der Schaltung keiner vorgesehen ist ecc) Es braucht eine Programmierer. Ein Arduino kann, wie Du erwänst, dazu programmiert werden.

* HV-Programming. Mittels einer Spannung von 12V an Reseteingang und einer bestimmten Programmierungssequenz kann der Controller aus einem zerschossenen Situation gerettet werden und auf den Auslieferungszustand gebracht werden.

ISP und HV prog kann mittels eines zweiten Arduinos und dem entsprechenden Sketch/Shield gemacht werden.

Grüße Uwe
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 18, 2014, 11:57 pm
Hallo,

Danke für die Programmer Erklärung, bedeutet, ich lass das erstmal sein, kann ich zu viel falsch machen.  ;)

Ich habe mich erstmal mit dem 5V Spannungsregler beschäftigt um zu sehen was das bringt. Die Power LED kann ich noch auslöten. Kann ich auch zum Schluss machen wenn alles fertig ist. Die 2,5mA sind zum Glück konstant und bekannt. Den 3,3V Regler kann ich noch loswerden. Brauch ich nicht. Allerdings ist laut Schaltplan ein LP2985 verbaut und wenn ich mit Lampe auf beide Boards schaue, lese ich was von LPF9 oder so ähnlich, kann auch LP29 sein, womit durchaus der LP2985 gemeint sein könnte. Die Position ist rechts neben dem Quarz, wenn Power/USB links ist.

Auf welchen Board ist der MC33269D-5.0 verbaut? Wobei die 5.0 am Ende auf 5V Ausgangsspannung hindeuten würden. Mein 5V Spannungsregler ist ein NCP1117ST50T3G. Irgendwas mit 17-50 steht drauf.

Der LP2985 bekommt ja von mir dann trotzdem 5V an Vin und ON/OFF Pin. Jetzt weis ich nicht recht wie ich das Datenblatt lesen soll. Bei 0mA Laststrom, wären es wohl max. 125µA was er sich nimmt. Bei 5V an ON/OFF sind es max 15µA. Heißt das jetzt der nimmt sich in Leerlauf in meinem Fall zusammen 140µA? Das dürfte keine Rolle spielen, wenn meine Annahme stimmt. Den könnte ich drin lassen. Oder?

Wobei natürlich jetzt die Frage wäre, was sich noch 7,5mA gönnt, abzüglich der 2,5mA der LED von 10mA in Sleep. Der Sleepmodus ist doch vollständig richtig? Mehr geht mit Code nicht?


Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jurs on Aug 19, 2014, 09:31 pm

Auf welchen Board ist der MC33269D-5.0 verbaut? Wobei die 5.0 am Ende auf 5V Ausgangsspannung hindeuten würden.


Stimmt, da habe ich mich vertan, das ist ein 5V Regler, und zwar wohl der auf dem ersten MEGA-Board.

Auf dem MEGA2560-R3 sollte ein LP2985-33DBVR als 3.3V Regler sitzen, und der braucht laut Datenblatt wirklich nur knappe 0,1mA und sollte nicht gross zum Stromverbrauch beitragen.

Aber hast Du ein Original-Board mit diesem speziellen LP2985-33DBVR Regler?
Übliche Regler können deutlich mehr Strom fressen als dieser spezielle Lowdrow/LowBias-Regler von TI.
Und wenn Dein 3.3V Regler eher ein "üblicher" als ein "LP2985-33DBVR" ist, kannst Du mit dem auch einsparen, wenn Du ihn auslötest, wenn Du ihn nicht brauchst.


Wobei natürlich jetzt die Frage wäre, was sich noch 7,5mA gönnt, abzüglich der 2,5mA der LED von 10mA in Sleep. Der Sleepmodus ist doch vollständig richtig? Mehr geht mit Code nicht?


Also vom Sleepmode her ist PowerDown schon das niedrigste. Da kann man zwar womöglich noch etwas rausholen über die Abschaltung der Brownout-Detection (keine Ahnung ob das beim 2560 auch per Software geht oder nur über die Fuses), oder die Deaktivierung des ADC, aber da ist man mehr im Microamperebereich als bei Milliampere.

Was ist denn mit den zwei Milliampere, die Du in  Reply #14 beim 16U2 noch als Sparpotential erkannt hast?
Die sparst Du bisher noch nicht ein, oder?
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 20, 2014, 07:36 am
Hallo,

meine beiden Mega 2560 sind beides Originale. Bei exp-tech gekauft. Laut Chip Aufdruck lese ich das verstümmelte bzw. abgekürzte LP...., was auf den TI hinweisen würde wie im Schaltplan bezeichnet. Deshalb löte ich den erstmal nicht aus.

Den seltsamen Effekt mit den 2mA konnte ich nicht mehr nachstellen. Der kam zu stande mit der Reihenfolge wann man den 16U2 Reset jumpert.

Übrigens haben die neuen Arduinoboards seitlich an den Headerleisten den Pinaufdruck. Aber nur für die digitalen und die Powerleiste. Und die GND Beschriftung ist dicker ausgemalt. "ARDUINO.CC" und Made in Italy" liegt nicht mehr hochkant sondern auch quer leserlich.

Abzüglich der Power LED und dann 7,5mA im Sleep-Mode, liege ich schon deutlich unter dem Idle Wert. Da bin ich doch schon sehr glücklich. Danke an dieser Stelle für die Hinweise zum Energie sparen

Wenn ich mir den Schaltplan so anschaue, sehe ich nur noch jeweils 0,5mA für den Resetstrom. Beim 16U2 wegen Jumper und beim Mega 2560 dauerhafter Pullup 10k. Daran kann man jedoch nichts ändern. Dann gibts noch 2x 10k Pullups für I2C. Der OPV zieht auch nur im unterirdischen µA Bereich Strom laut Datenblatt. Der Rest sind bestimmt parasitäre Boardquerströme   ....  :)   :)   Irgendwann ist eben das Ende der Fahnenstange erreicht.



.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jurs on Aug 20, 2014, 09:40 am

Den seltsamen Effekt mit den 2mA konnte ich nicht mehr nachstellen. Der kam zu stande mit der Reihenfolge wann man den 16U2 Reset jumpert.


Dazu hattest Du geschrieben:
> ich messe noch einen Unterschied von 2mA, wenn ich den 16U2 gejumpert lasse und
> dann 5V anschließe oder erst 5V ran und dann jumper.

Also leitet der 16U2 auf dem Board irgendwelche Stromsparmaßnahmen mit dem ersten Bootvorgang ein.

Was passiert denn jetzt, wenn Du folgendes machst:
- Reset vom 16U2 NICHT direkt mit GND verbinden
- sondern Reset vom 16U2 mit einem freien digitalen Pin des 2560 Controllers verbindest, z.B. 22
- und dann in der setup-Funktion:

Code: [Select]
#define RESET16U2 22  // Reset für 16U2 an Pin 22
pinMode(RESET16U2,OUTPUT);


Dann wird beim PowerOn der Reset-Pin zunächst mal nicht auf Low gesetzt, der 16U2 kann genau so normal starten wie der 2560, und sobald der 2560 sein setup ausführt, wird erst in dem Augenblick der Reset vom 16U2 auf OUTPUT/LOW gesetzt.

Das sollte dann doch die zusätzlichen 2mA aus Reply #14 einsparen?
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Aug 20, 2014, 09:06 pm
Hallo,

habe das heute nochmal mit der ganzen Jumperei wiederholt. Mit meinem Board ohne 5V Spannungswandler.

Alle Werte im Sleep Mode:

nur 5V anlegt: 21,4mA
5V angelegt gelassen und Jumper gesetzt: 9,9mA
Jumper gesetzt gelassen, 5V weggenommen und wieder angelegt: 12,2mA
5V bleiben angelegt und Jumper entfernt: 16,2mA
Jumper wieder gesetzt: 9,9mA

Bedeutet wirklich, der Jumper darf erst nach Spannung anlegen gesetzt werden um minimalen Strom zu messen.

Dann habe ich den Code um Deine Idee ergänzt und siehe da, funktionert stabil und dauerhaft. Egal ob ich 5V wegnehme und wieder anlege oder mehrfach resete, lande immer im Sleep bei 9,9mA. Wenn das mal nicht geil ist.   :)   Auf die Idee einfach einen Pin dafür zubenutzen wäre ich wohl nicht gekommen. Hätte das mit Transisitor erstmal gelöst bzw. lösen wollen. Habe vorher noch sicherheitshalber den Resetstrom vom 16U2 gemessen. Sind 0,6mA. Wirklich nahe den ausgerechneten 0,5mA.

Besten Dank für die Unterstützung!

Code: [Select]

/* Sleep Demo Serial
* -----------------
* Example code to demonstrate the sleep functions in a Arduino. Arduino will wake up
* when new data is received in the serial port USART
* Based on Sleep Demo Serial from http://www.arduino.cc/playground/Learning/ArduinoSleepCode

"Aufwach-Taster" an Pin 2 gegen Masse

Originalboard Arduino Mega 2560
Idle 59,2mA   Sleep 22,3mA   ohne 16U2 Jumper
Idle 54,5mA   Sleep 15,5mA   mit Jumper auf GND-Reset für 16U2

ohne Spannungsregler auf Board, abgegelötet
Idle 55,1mA   Sleep 16,5mA   ohne 16U2 Jumper
Idle 49,9mA   Sleep  9,8mA   mit Jumper auf GND-Reset für 16U2

alles Sleep Mode nochmals durchgemessen:
nur 5V anlegen: 21,4mA
5V anlegt und Jumper gesetzt: 9,9mA
Jumper gesetzt gelassen, 5V weggenommen und wieder angelegt: 12,2mA
5V bleiben angelegt und Jumper entfernt: 16,2mA
Jumper wieder gesetzt: 9,9mA

Reset Pin 16U2 ergänzt für sicheren und dauerhaften 9,9mA Effekt.

*/   
   

#include <avr/sleep.h>

#define RESET16U2  22       // Reset für 16U2 an Pin 22

int sleepStatus = 0;        // variable to store a request for sleep
int count = 0;              // counter

int ledPin = 13;            // LED connected to digital pin 13
//int interruptPin = 10;      // LED to show the action of a interrupt
int wakePin = 2;            // active LOW, ground this pin momentary to wake up
//int sleepPin = 12;          // active LOW, ground this pin momentary to sleep
int ledState = LOW;

void wakeUpNow()        // here the interrupt is handled after wakeup
{
  // execute code here after wake-up before returning to the loop() function
  // timers and code using timers (serial.print and more...) will not work here.
  // digitalWrite(interruptPin, HIGH);  // LED an Pin 10 ein
}


void sleepNow()
{
    /* Now is the time to set the sleep mode. In the Atmega8 datasheet
     * http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
     * there is a list of sleep modes which explains which clocks and
     * wake up sources are available in which sleep modus.
     *
     * In the avr/sleep.h file, the call names of these sleep modus are to be found:
     *
     * The 5 different modes are:
     *     SLEEP_MODE_IDLE         -the least power savings
     *     SLEEP_MODE_ADC
     *     SLEEP_MODE_PWR_SAVE
     *     SLEEP_MODE_STANDBY
     *     SLEEP_MODE_PWR_DOWN     -the most power savings
     *
     *  the power reduction management <avr/power.h>  is described in
     *  http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
     */ 
       
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

  sleep_enable();          // enables the sleep bit in the mcucr register
                           // so sleep is possible. just a safety pin
 
    /* Now it is time to enable an interrupt. We do it here so an
     * accidentally pushed interrupt button doesn't interrupt
     * our running program. if you want to be able to run
     * interrupt code besides the sleep function, place it in
     * setup() for example.
     *
     * In the function call attachInterrupt(A, B, C)
     * A   can be either 0 or 1 for interrupts on pin 2 or 3. 
     *
     * B   Name of a function you want to execute at interrupt for A.
     *
     * C   Trigger mode of the interrupt pin. can be:
     *             LOW        a low level triggers
     *             CHANGE     a change in level triggers
     *             RISING     a rising edge of a level triggers
     *             FALLING    a falling edge of a level triggers
     *
     * In all but the IDLE sleep modes only LOW can be used.
     */

  attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
                                     // wakeUpNow when pin 2 gets LOW
     
  sleep_mode();            // here the device is actually put to sleep!!

                           // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
  sleep_disable();         // first thing after waking from sleep:
                           // disable sleep...
 
  detachInterrupt(0);      // disables interrupt 0 on pin 2 so the
                           // wakeUpNow code will not be executed
                           // during normal running time.
   
}


void setup()
{
  pinMode(RESET16U2,OUTPUT);       // 16U2 wird dauerhaft
  digitalWrite(RESET16U2, LOW);    // im Reset Mode gehalten, spart 2mA
 
  pinMode(ledPin, OUTPUT);         // LED connected to digital pin 13

  pinMode(wakePin, INPUT);         // active LOW, ground this pin momentary to wake up
  digitalWrite(wakePin, HIGH);     // Pullup aktiv
     
  attachInterrupt(0,wakeUpNow, LOW);   // use interrupt 0 (pin 2) and run function
                                       // wakeUpNow when pin 2 gets LOW
                           
}


void loop()
{
 
   if ( digitalRead(2) == LOW ) {
     digitalWrite(ledPin, HIGH);     
   }
   else {
     digitalWrite(ledPin, LOW);
     sleepNow();                   // sleep function called here
   }
     

}




Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Oct 23, 2014, 04:41 pm
Hallo,

paßt hier vielleicht besser rein, als in den anderen Thread mit dazu unpassender Betreffzeile.


Mit Ausbau vom IC7 (OPV) und T1 (Mosfet) komme ich nun auf 9,6mA. Bei 4,96V gemessen direkt am Arduino. Ist immer noch nicht der große Bringer. Da bleibt doch wirklich nur noch der Ausbau vom 16U2?  Der sich im Reset-Zustand bestimmt immer noch wenige mA gönnt. Oder? Wie seht ihr das?

Warum ist der Schwellwert für die  Brownout Detection mit 2,7V so niedrig angesetzt? Hab ich mir gerade überlegt. Wenn der µC mit 16MHz mindestens 4,5V benötigt.


Wenn ich den 16U2 nun doch vielleicht ausbaue, muß ich danach über den ISP Anschluss programmieren. Ist der AVR mkII immer noch der geeigneste Programmer dafür? Ist der mit dem kommenden Arduino Zero kompatibel?
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: sschultewolter on Oct 23, 2014, 04:53 pm
Hallo Doc,

über den ISP Anschluss kannst du die M0 Cortex nicht programmieren!
Anstatt des AVRISP mkii bräuchtest du einen AVR JTAGICE mkII bzw. AVR JTAGICE mkIII. Die Preise sind da aber ganz andere. Letztere wäre noch so eben verschmerzbar.

Warum in den Fuses 2V7 für BOD genutzt wird, kann ich dir nicht genau sagen. Kannst es doch auf 4V3 setzen. Alternativ kannst du das ganze auch noch komplett abschalten, wenn du andere Vorkehrungen treffen kannst.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Oct 23, 2014, 06:31 pm
Hallo,


nochmal. Mit einem AVR JTAGICE mkII oder AVR JTAGICE mkIII kann man einen "AVR Cortex" am ISP programmieren? Das funktioniert dann nur noch über AVR Studio, nicht mehr mittels Arduino IDE?

Damit sich der AVR JTAGICE lohnt, könnte man ihn zum debuggen verwenden. Ist der Debugger mit dem Kauf freigeschalten oder muß man dafür extra bezahlen? Der Debugger von Visual Micro kostet ja Geld. Der vom AVR Studio sicherlich auch. Weist Du mehr darüber?

Am liebsten würde ich den Mega2560 dauerhaft mit 8MHz laufen lassen. Das geht nur über Bootloader flashen am ISP und Quarzwechsel. Richtig? Meine Sorge ist aber, dass danach sämtliche Timings nicht mehr stimmen. Ist die Annahme auch richtig? Also dann ein delay(5)  in der Software, als Bsp., in Wirklichkeit dann 10ms sind. Was die Hardwareschnittstellen machen weis ich nicht. ?


Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: sschultewolter on Oct 23, 2014, 09:28 pm
Hallo Doc,

ich gehe mal davon aus, dass wenn du dir auch nur den mkIII zulegen würdest. Der ICE mkII ist doch recht teuer für den Privaten gebrauch.

AVR JTAGICE mkIII
• Unterstützt Programmieren via JTAG, SPI, PDI, aWire
• Unterstützt Debuggen via debugWire, JTAG, PDI, aWire

Wobei du den Zero auch einfach wie den Due über USB programmieren kannst. Habe noch keinen JTAG Programmer.

Für die AVR 8Bit kannst du fast jeden beliebigen Programmer von der Bucht nehmen. Sinnvoller ist dort aber direkt etwas gescheites zu holen um sich viel Arbeit zu ersparen. Die Diamex die ich habe sind hochwertig verbaut (oranges Acrylglas) aber können auch manchmal zicken. Habe mir den orginalen von Atmel bereits im Reichelt Warenkorb gelegt
http://www.reichelt.de/Programmer-Entwicklungstools/AT-AVR-ISP/3/index.html?&ACTION=3&LA=2&ARTICLE=45040&GROUPID=2969&artnr=AT+AVR+ISP

Zum Debugger kann ich nichts sagen. Habe ich noch nicht im Einsatz gehabt.
 Den Visual Micro Debugger kann man soweit ich weiß auch testen.

Den Mega2560 nur mit 8MHz zu betreiben ist kein Problem. Musst nur aufpassen das alles reibungslos verläuft. Resonator 16MHz stecken lassen, über AVR Studio die Fuses umsetzen für die Taktquelle. Programmieren. Nun alten Resonator auslöten und 8MHz verbauen, oder diese weglassen und die interne Taktquelle nutzten.

Timing ist, solange du das Programm nicht änderst natürlich falsch. Aus delay(5) wird 10. In der IDE sollte es reichen, wenn du das #define F_CPU überschreibst. Danach passen die Timings wieder.

Kann leider nicht nachschauen, keine A IDE auf dem Laptop.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Spexx on Oct 24, 2014, 07:31 am
Schau dir mal die Datei "board.txt" an. Dort kannst du dir einen neuen Eintrag für den Mega2560 erstellen mit 8MHz. Du kannst dann in der Arduino IDE dieses Board auswählen, somit passt das Timing dann auch wieder.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Oct 24, 2014, 03:54 pm
Hallo,

Danke ihr zwei. Das bringt mich auf eine neue Idee. Am 8MHz Quarz sollte es nicht scheitern. Aber. Wäre es denkbar den Takt in der Board.txt zu ändern und im Sketch gleich zu Anfang den Takt auf 8MHz zu ändern? Alles weiterhin mit 16MHz Quarz. Oder kommt dann alles durcheinander?

Wird eigentlich der Inhalt der Board.txt jedesmal beim Sketch Upload mit neu übertragen? Also jedesmal die Fuse Bits usw. neu gesetzt? Oder geht das nur mit so einem ISP Programmer? Oder sagt die Board.txt nur dem Compiler was gespielt wird?





Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Oct 24, 2014, 08:22 pm
Hallo,


obige Fragen bleiben bestehen. Nur weis ich jetzt etwas mehr über die Programmer/Debugger mehr.

Die AVR µC kann man mit einem mkII oder mkIII nur per ISP programmieren. Nicht debuggen.
Mit Debugfunktion wäre der AVR One! oder JTAGICE3 notwendig.

Wenn man AVR und AVR Cortex programmieren/debuggen möchte muß man zum neuen Atmel-ICE greifen. Der SAM-ICE versteht sich nur mit AVR Cortex µC.

Der neue Atmel ICE kostet bei Reichelt 111,- €uro. Etwas viel für meine Nutzung.

Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Spexx on Oct 25, 2014, 08:43 am
Die Fuses aus der Board.txt werden nur gesetzt, wenn du auf "Burn Bootloader" klickst, also nicht bei jedem Upload.

Wenn ich mich nicht Irre, dann muß der Takt in der Board.txt und der eingestellte im Mikrocontroller der gleiche sein, sonst kannst du keinen Sketch uploaden. Ob es nun einen Unterschied macht, den Takt über den Sketch festzulegen, kann ich dir auch nicht sagen.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Oct 25, 2014, 03:59 pm
Hallo,

okay, denke das erstmal verstanden zu haben. Danke!

Noch eine kleine Korrektur. Der AVRISP mkII ist ein reiner Programmer. Der Rest ist Debugger und Programmer.

Ich liebäugel stark mit dem neuen Atmel ICE. Wegen dem kommenden Arduino Zero und der eierlegendenwollmilchsau.



Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: sschultewolter on Oct 25, 2014, 04:08 pm
Warum nicht den Zero weiterhin über USB programmieren, oder hast du vor, diese später standalone aufzubauen? -> PN
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Oct 25, 2014, 05:59 pm
Hallo,

ich habe nicht vor einen µC standalone aufzubauen. Egal welcher. Nur wenn ich bei meinem Mega2560 den 16U2 runterlöte, brauche ich mindestens einen Programmer. Dafür wäre der AVRISP mkII ausreichend. Wenn ich mir noch einen Arduino kaufe, hab noch einen zweiten Mega2560 da, dann wird es der Arduino Zero als logische Folge. Hier wollte ich dann den Programmer und Debugger nutzen. Dafür bräuchte ich dann aber den neuen Atmel ICE. Den gibt es für 88,39 Euro. Damit könnte man den Zero auch debuggen. Ist aber viel wenn, könnte und sein im Gedankenspiel. Ob man das dann wirklich nutzt steht auf einen anderen Blatt.

Der Arduino Zero hat aber zwei USB Schnittstellen laut Bildern. Wenn der schon von Haus aus mit Debug Zugriff vorgesehen ist über die Arduino IDE, dann wäre der Kauf eines Atmel ICE natürlich sinnlos. Ich schwanke in der Entscheidung ständig hin und her.

Ich weis nicht wie ich Sätze wie die hier verstehen soll?


"Zusätzlich enthält das Board Atmels Embedded Debugger (EDBG), einen Hardware-Debugger für Microcontroller von Atmel. Er soll die direkte Programmierung des Controllers vereinfachen."

oder

"Das Board verfügt außerdem über flexible Peripherie sowie Atmels Embedded Debugger (EDBG). Es bietet ein Debugging-Interface auf den SAMD21 ohne zusätzliche Hardware und vereinfacht das Software-Debugging. EDBG unterstützt einen virtuellen COM-Port für die Geräteprogrammierung sowie die herkömmliche Arduino-Boot-Loader-Funktion."

Heißt das, der hat den Debugger wirklich mittels Atmels EDBG IC onboard und der Rest ist Software? (die JTAG und SWD Schnittstelle sieht man allerdings auf dem Board) Dann hätte Arduino alles komplett richtig gemacht. Naja, fast alles, die 38 I/O Pins können im Uno Format nicht alle herausgeführt werden.

Wie versteht ihr das?
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Nov 07, 2014, 07:50 pm
Hallo,

ein Update.  :)

Habe heute den 16U2 runtergelötet, wobei man löten eigentlich nicht mehr sagen konnte. Es ging etwas grob zu, sagen wir mal so. ;)   Der dicke 16MHz Quarz daneben ist auch runter.

Leute was soll ich sagen, im Sleep-Mode geniale 3,3mA, wobei die Power-On LED noch drauf ist. Die kommt erst zum Schluss runter. Also sind es im Endeffekt ca. 1,3mA im Sleepmode. Geil!  :)   Damit wird mein bestellter XTPower Akku sehr lange halten.

Edit: XTPower kam heute, geladen, probiert, Dauerbetreib funktioniert tatsächlich.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Nov 10, 2014, 06:21 pm
Hallo,

für alle die das interessiert wie die Powerbank von innen aussieht. :)
Voll geladen 4,17 Volt Zellenspannung.
An den Zellen sieht man hellgelben Klebstoff. Wie dicker Schaumgummi. Damit war der Deckel mit verklebt. Seitlich sind nur paar Nasen nach innen zusätzlich verteilt.

Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Jul 09, 2015, 06:12 pm
Hallo,

das Projekt nähert sich dem Ende woraufhin ich heute noch als letztes die Power LED runtergelötet habe. Effekt ist im sleep mode geniale 220µA bei 5,00V Ub für den kastrierten Arduino Mega 2560.  :) :) :)
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 03, 2015, 11:47 am
Hallo Doc-Arduino,

habe bei einem meiner Mega auch mal alle hier beschriebenen Hardwareänderungen vorgenommen (Spannungsregler, Mosfet, 16U2 und Power-LED runter) und kann den Stromverbrauch im SleepMode (fast) bestätigen, mein Wald-und-Wiesen-Multimeter zeigt im mA Messbereich <1mA und im uA Bereich ca. 500uA (BOD war aktiv). Ich bin zufrieden, was das angeht,

NUR leider bekomme ich ihn jetzt nicht mehr Programmiert!  :smiley-fat:

Einen Bootloader bekomme ich noch drauf gebrannt mit einem anderen UNO oder Mega (sowhol mit der Methode von Nick Gammon (http://www.gammon.com.au/forum/?id=11635) als auch mit der IDE und einem "Arduino as ISP") , aber keine Sketch! Beim "Arduino as ISP" geht sofort die Rot Fehler LED an beim versuch einen Sketch zu rbennen und in der IDE kommt Timeout Fehlermeldung.

Wobei ich es irgendwie schon (versehentlich) geschafft habe meinen Stromsparsketch zu überschreiben, so dass jetzt die LED13 munter blinkt (ca. 1000ms on, 100ms off, das habe ich so nicht versucht zu proggen).

Und nu steh ich bisschen im Regen...habe das Problem auch hier im Forum (http://forum.arduino.cc/index.php?topic=345324.0) schon mal beschreiben, bisher ohne zündende Idee.

Hast Du noch einen Tip für mich? Gibt es vielleicht einen alternativen Code für Arduino as ISP als den aus der IDE (1.6.5 unter Ubuntu 14.04)?

Vielen Dank und schöne Grüße!
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Sep 03, 2015, 12:51 pm
Hallo,

das ist natürlich total doof. Ich programmiere den kastrierten Mega mittels AVR mkII Programmer. Meiner sieht so aus siehe Anhang. Optisch nicht schön, funktioniert jedoch.

(http://fs1.directupload.net/images/150903/temp/oc6v6gky.jpg) (http://www.directupload.net/file/d/4099/oc6v6gky_jpg.htm)

Wie versorgst Du den Mega jetzt mit Spannung?
Vin ist tot gelegt, weil der Spannungsregler fehlt.
USB ist tot, weil T1 fehlt.
Hier hatte ich damals noch eine Brücke bei T1 eingelötet, dass ich die Platine wenigstens über USB noch eine Weile mit Spannung versorgen kann. Mittlerweile ist die USB Buchse auch weg. Die Platine wird jetzt und für immer direkt mit 5V an der Power-Buchsenleiste versorgt. 5V / GND. Dafür bräuchte man die Brücke eigentlich nicht mehr.

Zum programmieren muß aber 5V als Ub anliegen. Messe mal am ICSP nach ob da wirklich 5V vorhanden sind, wenn Du alles verkabelt hast. Pin 2 und 6 und Pin 2 gegen andere Masse.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 03, 2015, 03:17 pm
Hallo,

vielen dank für die schnelle Rückmeldung.

Ich konnte das Problem lösen/Umgehen dank eines Tipps von combie (http://forum.arduino.cc/index.php?topic=345324.msg2382128#msg2382128) doch einen UNO-Board zu nehmen, den 328 raus und Serial, Reset und Vcc/GND Verbinden. Klappt erst mal sehr gut!

Über das leere UNO Board habe ich auch Serial Verbindung zum PC zum Debuggen. Ist eine feine Sache den Mega etwas zu modifizieren und damit Batteriebetrieb zu ermöglichen. Danke auch noch mal an alle für diesen Thread hier.

So siehts bei mir aus:
(https://picload.org/thumbnail/pgipraw/mega.jpg) (https://picload.org/view/pgipraw/mega.jpg.html)


Und mit diesem Test Code ( original von Nick Gammon (http://www.gammon.com.au/forum/?id=11497&reply=8#reply8), leicht Modifiziert für Mega) bekomme ich jetzt 359,2uA (laut meinem Multimeter). Damit bin ich einverstanden.  :)

Test Code für Mega mit waikup by Serial Input:
Code: [Select]
/*
 * Sorce: Nick Gammon http://www.gammon.com.au/forum/?id=11497&reply=8#reply8
 * 03.09.2015:  Edit for Mega250 support and added some Serial Output 4 Debugging
 */

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

const byte AWAKE_LED = 13;
const byte GREEN_LED = 12;
const unsigned long WAIT_TIME = 3000;

ISR (PCINT2_vect)
{
  // handle pin change interrupt for D0 to D7 here
}  // end of PCINT2_vect

void setup()
{
  pinMode (GREEN_LED, OUTPUT);
  pinMode (AWAKE_LED, OUTPUT);
  digitalWrite (AWAKE_LED, HIGH);
  Serial.begin(230400);
  Serial.print(F("\n\nStarting...\n File: " __FILE__ "\n Date: " __DATE__ "\n Time: " __TIME__ "\n IDE : "));
  Serial.println(ARDUINO);
  Serial.println();
} // end of setup

unsigned long lastSleep;

void loop()
{
  
  if (millis () - lastSleep >= WAIT_TIME)
  {
    lastSleep = millis ();

    Serial.print(F("\n go sleeping"));
    Serial.flush();
    
    noInterrupts ();

    byte old_ADCSRA = ADCSRA;
    // disable ADC
    ADCSRA = 0;  
    /*    // pin change interrupt (example for D0) Uno/328P!
    PCMSK2 |= bit (PCINT16); // want pin 0
    PCIFR  |= bit (PCIF2);   // clear any outstanding interrupts
    PCICR  |= bit (PCIE2);   // enable pin change interrupts for D0 to D7
*/
    // pin change interrupt (example for D0) Mega 2560!
    PCMSK1 |= bit (PCINT8); // want pin 0
    PCIFR  |= bit (PCIF1);   // clear any outstanding interrupts
    PCICR  |= bit (PCIE1);   // enable pin change interrupts for D0 to D7

    set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
    power_adc_disable();
    power_spi_disable();
    power_timer0_disable();
    power_timer1_disable();
    power_timer2_disable();
    power_twi_disable();

    UCSR0B &= ~bit (RXEN0);  // disable receiver
    UCSR0B &= ~bit (TXEN0);  // disable transmitter

    sleep_enable();
    digitalWrite (AWAKE_LED, LOW);
    interrupts ();
    sleep_cpu ();      
    
    digitalWrite (AWAKE_LED, HIGH);
    sleep_disable();
    power_all_enable();

    ADCSRA = old_ADCSRA;
    //PCICR  &= ~bit (PCIE2);   // disable pin change interrupts for D0 to D7
    PCICR  &= ~bit (PCIE1);   // disable pin change interrupts for D0 to D7
    
    UCSR0B |= bit (RXEN0);  // enable receiver
    UCSR0B |= bit (TXEN0);  // enable transmitter
     Serial.print(F("\n Woke. "));
  }  // end of time to sleep

  if (Serial.available () > 0)
  {
    byte flashes = Serial.read () - '0';
    if (flashes > 0 && flashes < 10)
      {
      // flash LED x times
      for (byte i = 0; i < flashes; i++)
        {
        digitalWrite (GREEN_LED, HIGH);
        Serial.print(F("\n Flasch: "));
        Serial.print(i);
        delay (200);  
        digitalWrite (GREEN_LED, LOW);
        delay (200);  
        }
      }        
  }  // end of if

}  // end of loop

 
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 03, 2015, 03:21 pm
PS: Welche Funktion hat/hatte der winzige 8-beinige IC der neben/unter dem Quarz liegt/lag? Ist das ein Komparator? (Wofür?) Und wie viel ließ sich dadurch einsparen?
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: combie on Sep 03, 2015, 03:38 pm
Quote
Welche Funktion hat/hatte der winzige 8-beinige IC der neben/unter dem Quarz liegt/lag?
2 fach OP
Treiber für die Pin 13 LED und Stromversorgungsumschaltung.
Wenn du den abbaust, kann auch der zugehörige Spannungsteiler weg.

https://www.arduino.cc/en/uploads/Main/arduino-mega2560_R3-sch.pdf (https://www.arduino.cc/en/uploads/Main/arduino-mega2560_R3-sch.pdf)


Nachtrag:
Es gibt noch weiteres Stomsparpotential.
Mit 1,8V versorgen, dann muss aber der Quarz deaktiviert werden.
Also intern takten.
So ist dann per Fuses 1 und 8MHz möglich.
Per Teiler auch noch weitere Einstellungen.
Als noch langsamere Taktquelle: Internen Takt abschalten und den Watchdog Takt nutzen,

So solltest du auf wenige µA runter kommen können, ohne sleep.





Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Sep 03, 2015, 05:00 pm
Hallo,

was der OPV spart habe ich jetzt nicht extra notiert. Einige Einzelmessungen sind im Thread enthalten.
Edit:
der OPV und T1 spart nicht sehr viel, nur 0,x mA. Posting # 30, 31
Erst das entfernen des 16U2 hat wieder paar mA Einsparung gebracht.

Nur solltest Du Dich für eins von beiden entscheiden. sleep.h oder power.h
Wenn Du den tiefsten Schlafzustand sowieso wählst, mußte danach nicht noch extra die einzelnen Funktion lahm legen. Lege vorher den Interrupt fest worauf er reagieren/aufwachen soll und lege das Teil schlafen. Mehr mußte nicht machen. Bzw. nur die UART am leben halten und den Rest schlafen legen.

Ohne sleep packste keine µA. Ohne sleep Mode bleibt man im einstelligen mA Bereich.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: combie on Sep 03, 2015, 05:20 pm
Quote
Ohne sleep packste keine µA. Ohne sleep Mode bleibt man im einstelligen mA Bereich.
;) Wetten? ;)
Ich biete 80µA im aktiven Zustand, mit dem WDT Takt.


Am liebste würde ich jetzt meinen Mega rupfen, um das zu beweisen....
Aber nein, den Beweis bleibe ich schuldig ....
Der bleibt, solange es geht, heile.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Sep 03, 2015, 05:34 pm
Hallo,

wenn ich mir die Messwerte von Nick anschaue, hatte ich angeschaut, dann sehe ich nur µA Werte im Sleepmode. Deswegen mein Einspruch. Was ich nicht verstehe "80µA im aktiven Zustand mit WDT". WDT ist doch Sleepmode!!!
Also wenn er regelmäßig laut WDT aufweckt.

Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: combie on Sep 03, 2015, 05:49 pm
Quote
Was ich nicht verstehe "80µA im aktiven Zustand mit WDT". WDT ist doch Sleepmode!!!
Also wenn er regelmäßig laut WDT aufweckt.
Nee, man kann auch den Takt des Watchdog Timers als Taktquelle für den Rest nutzen.
Dann bleiben Quarz und interne RC Taktquelle aus.

Der Prozessor arbeitet dann mit ca 128kHz.
Durch die Vorteiler kann man noch weiter runter teilen.
bis 32kHz? runter (ohne Gewähr)
16kHz mit CKDIV8 Fuse

Dann ist man voll auf Schleichfahrt ;-)

Viel sparsamer kann ein durch WDT unterbrochener Sleepmode dann auch nicht mehr sein.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Sep 03, 2015, 06:25 pm
Hallo,

naja okay, wenn das so funktioniert wäre das ein verkappter dauerhafter Sleepmode, theoretisch möglich, meinetwegen auch praktisch, aber ohne echten Sinn. Wenn er was machen soll, dauert das ewig und die Einsparung wäre dahin. Wenn man mal ehrlich ist.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 03, 2015, 09:46 pm
Ok der OPV  ist auch runter, jetzt sind aus den 359uA nette 77uA geworden (mit WDT aktiv)
Ohne WDT und nur PCI wake up durch Serial sind es 70uA. Bin sehr begeistert.  :)

Alles bei 5,08V. Jetzt könnte ich noch die Spannung reduzieren. Auch das senken des Taktes ist sicherlich für mein Projekt ohne Probleme möglich auf 8/4 vielleicht auch auf 1Mhz. Aber das kommt dann noch.
Dann wird es interessant, denn um so länger der uC braucht für z.B. Datenerfassen und Speicher bzw. Versenden um so länger ist auch die (ext.) Hardware an (z.B. Funkmodul, SD Karte, ADC,..) und Energie ist ja Leistung * Zeit. Bin gespannt. Hmm aber vielleicht lande ich ja bei 128kHz  :)


Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 03, 2015, 10:25 pm
Nur solltest Du Dich für eins von beiden entscheiden. sleep.h oder power.h
Wenn Du den tiefsten Schlafzustand sowieso wählst, mußte danach nicht noch extra die einzelnen Funktion lahm legen. Lege vorher den Interrupt fest worauf er reagieren/aufwachen soll und lege das Teil schlafen. Mehr mußte nicht machen. Bzw. nur die UART am leben halten und den Rest schlafen legen.

Das habe ich jetzt nicht ganz verstanden.
 
Die ganzen internen Hardware Sachen sind scheinbar automatisch im low Power sleep aus. Ich konnte da keinen unterschied Messen. ABER das ausschalten des ADC (mit  ADCSRA = 0;                            // disable ADC) hat noch einen Unterschied gemacht.

Später möchte ich auch die anderen SleepModes nutzen z.B. ADC und während dessen unbenutzte Komponenten ausschalten. Auch während des aktiven Betriebs des uC würde ich nicht benutzte Funtionen abschalten. Dafür brauche ich doch dann beide sleep.h und power.h. Oder bringe ich da was durcheeinader?

Ich würde gerne den uC periodisch durch den WDT aufwecken und zusätzlich bei Serial Rx. Einzeln klappt beiden, aber zusammen habe ich da gerade ein Bug drin, er wacht nicht richtig auf bei Serial event, bzw. die PCI-ISR für Pin 0 (Rx) wird nicht erreicht...
Scheinbar ist er beim ersten erreichen der PCI ISR ja noch im sleep-Mode und schaltet deswegen keine Kontroll-LED ein?? Hm naja werde da morgen mal weiter dran forschen.

 

Aber was genau macht eigentlich:
Code: [Select]
UCSR0B &= ~bit (RXEN0);  // disable receiver (Serial? I2C?)
      UCSR0B &= ~bit (TXEN0);  // disable transmitter

Habe ich auch von Nick, aber mir nicht ganz klar. Seriel sollte doch schon mit disable_all() aus sein oder?

Was kann mann denn noch ausschalten?  Wie ist das mit dem BOD (Brown-out) beim Mega? Habe da was im Datenblatt gefunden. Geht wohl über die Fuses, aber geht es auch via Software?

Schöne Grüße

Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 03, 2015, 10:31 pm
2 fach OP
Treiber für die Pin 13 LED und Stromversorgungsumschaltung.
Wenn du den abbaust, kann auch der zugehörige Spannungsteiler weg.
Wo finde ich denn denn der Spannungsteiler auf dem Board? Ist das das Teil mit der "103" zwischen dem OPV und den 2 großen C?

Danke!
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 04, 2015, 11:13 am
Ich würde gerne eine Slaf Funktion mit folgender Funktionalität benutzen (PsydoCode):

Code: [Select]

volatile sleep_enabel = 1;        // global Flag is set to 0 in any waking ISR to stop sleeping


PowerDownExternalHardware( byte settings){
  if(bitset(settings,0)){
    //swirch off Hardware A by switching off Pin x
    digitalWrite(Pin0, LOW);
  }
  if(bitset(settings,1)){
    //swirch off Hardware A by switching off Pin x
    digitalWrite(Pin1, LOW);
  }
  //...

}//PowerDownExternalHardware


PowerDownInternalHardware( byte settings){
  if(bitset(settings,0)){
    disable_TWI();
  }
  if(bitset(settings,1)){
    disable_ADC();
  }
  //...

}//PowerDownInternalHardware

// Sleep Function, set: SleepMode, WDT Sleep Periode, if Serial waiks up, PCI Pins to wake up uC,
//                      Settings for external and internal Hardware shutdown
mySleep(byte Mode, unsigned int wdtPeriode, bool wakeBySerialRx, byte pciWakePins[],\
        byte pinCount, byte extHwSet, byte intHwSet)
{
  PowerDownExternalHardware( extHwSet);     // shut down associated ext. Harware
  PowerDownInternalHardware( intHwSet);     // shut down associated int. Harware

  if(wakeBySerialRx){
    //set PCI for Pin 0, Provide PCI ISR!!
  }

  for(byte i = 0;i< pinCount;i++){
    //enable Pci for Pins and ports, provide PCI ISRs !!
    //enable PCI for acording pciWakePins[i],
  }

  if(wdtPeriode){       // enable wake by WDT only if WDT Periode is set
  // setup wdt to periode and sleep x times till prriode is over
    
    if(WDT Periode >= 8000){                   // Sleep 8 sec
    
      noInterrupts();
      bool sleep_enabel_copy = sleep_enabel;  // check if sleep is still enabled
      interrupts();

      While(sleep_enabel_copy && wdtPeriode >= 8000){   // sleep for x * 8sec
        Periode -= 8000;
        //set WDT
        // start sleeping...
        // disable sleeping
        noInterrupts();
        sleep_enabel_copy = sleep_enabel;   // check if sleep is still enabled
        interrupts();
      }//while
    }//if(WDT Periode > 8sec)

    // skip 4 and 2 Sec    

    if(WDT Periode >= 1000){                   // Sleep 1 sec
    
      noInterrupts();
      bool sleep_enabel_copy = sleep_enabel;  // check if sleep is still enabled
      interrupts();

      While(sleep_enabel_copy && wdtPeriode >= 1000){   // sleep for x * 8sec
        Periode -= 1000;
        //set WDT
        // start sleeping...
        // disable sleeping
        noInterrupts();
        sleep_enabel_copy = sleep_enabel;   // check if sleep is still enabled
        interrupts();
      }//while
    }//if(WDT Periode > 1sec)

    // same for 128ms
    // same for 16ms  

  }// if(wdtPeriode){
 
  else{                             // no WDT Periode was given =>don't wake periodicly
                                    // wake only by Interrtupt from PCI, ADC, Serial RX ...
    // start sleeping...
    // disable sleeping after Interrupt (or better disable sleep in ISRs?)
  }
 
  PowerUpInternalHardware();
  PowerUpExternalHardware();
  
}

/* in all ISRs:
  Disable sleep in wakeISRs !?
  Set sleep enable == 0;          // needed?
  Set (global and local) ISR_has_happend_Flags
  Disable own ISRs? (PCI: not if used for someting else, Serial: yes, not needed in
                      active state, WDT: disable and reste does extra overhed, keep
                      running and just reset intervall,  ok/ possible??????)
*/


Kann mir jamdn dazu Tipps geben oder ob es überhaupt so möglich ist bzw was dagegen spricht? z.B. Welche Sequenzen mü+ssen dringen aufeinander folgen?

Vielen Dank.

PS: Das ganze funktioniert in Teilen schon, nur in der Kombination von mereren Wake-Quellen bekomme ich gerade Probleme.

Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Sep 04, 2015, 12:37 pm
Hallo,

hast du den gesamten Text von Nick gelesen? Posting #30 kannste auch wie schon erwähnt lesen?
SLEEP_MODE_PWR_DOWN legt alles lahm, hat den tiefst möglichen Schlafzustand.

Wegen dem BOD (Brown Out Detection). Das ist eine Schutzfunktion in Hardware. Das hat nichts mit Strom sparen zu tun. Das Spannungslevel wird über die Fuses eingestellt. Wenn die µC Ub drunter liegt, schaltet der µC ab bevor der Mist macht. Standardmäßig ist bei Arduino auf 2,7V gesetzt.

Spannungsteiler am OPV finde ich nur den links vom IC7B im Schaltplan. Da Vin tot ist, ist der Spannungsteiler auch tot. Damit erübrigt sich das auslöten meinerseits.

Für mehrere WakeUp Quellen kann ich dir folgenden Code geben als Basis. Der ist damals hier im Forum entstanden. Finde den Link nicht mehr zum Thread.

Der Text im Code ganz am Anfang ist für mich, muß nicht unbedingt für jeden Sinn ergeben. Weil ich immer wieder erweitert hatte. Auf jeden Fall ist das ein Bsp. für 6 externe Interrupt Eingänge. Pin 2, 3, 18, 19, 20, 21.
Die schalten für mich in dem Bsp. LEDs an Pin 30-35.
Du mußt die Interrupts auf jeden Fall vorher definieren und weil die im µC fest verdrahtet sind, gehen die an unterschiedliche Pins raus. Steht aber alles im Code kommentiert drin.

Viel Spass beim probieren, testen und coden.



Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: combie on Sep 04, 2015, 12:52 pm
Quote
Wegen dem BOD (Brown Out Detection). Das ist eine Schutzfunktion in Hardware. Das hat nichts mit Strom sparen zu tun.
Eine aktivierte BOD braucht Strom.

Also:
Stromsparen -->> BOD aus.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Doc_Arduino on Sep 04, 2015, 12:56 pm
Hallo,

okay, macht aber keinen Sinn ohne anders geartete Spannungsüberwachung. Meinste nicht auch. Das BOD wirkt zwar mit dem wenigen Leveln sehr grob, aber man hat wenigstens etwas.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: combie on Sep 04, 2015, 01:05 pm
Quote
Meinste nicht auch.
Ja, es macht nicht immer Sinn das abzuschalten ....
z.B. beim EEPROM gefummel, kann sich das sonst fatal auswirken.
Aber das tut man ja im Sleep nicht ;)



Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 04, 2015, 02:25 pm
Hallo,

vielen Dank für die Rückmeldung. Werde mir das mal am Wochenende ansehen, habe gerade wenig Zeit.

Was BOD angeht, habe ich bei Nick was zu gelesen, und wenn ich mich recht erinnere waren es 20uA. So kommt er am Ende auf einstellige uA für den 328P.

Er stellt den BOD in Software ab. Aber die Register heißen beim Mage anders oder es geht nich via Soft? Konnte ich noch nicht klären im Datenblatt. Weiß jemand zufällig genaueres?

Nick schreibt, dass der BOD den uC in Reset versetzt, da braucht er dann 1-2-stellige mA. Das hilft bei einer Batterieanwendung dann auch nicht weiter, wenn der BOD wegen zu geringer Spannung ein Reset auslöst. Die Batterie/Akku/ großes C (1F) sind dann ums o schneller ganz am Ende.

Soweit würde ich es gar nicht erst kommen lassen wollen und immer schön die Spannung des Akkus/Batt/C via Funkmodul zum Master übertragen. Der steht bei mit am Tisch, hat ein Netzteil gepufferten Akku und gibt dann eine Fehlermeldung (LED/LCD) (soll mal ein Funk-Sensor-Datennetz mit einem Master. z.B. Wetterstation, Home automation werden).

VG
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: Serenifly on Sep 04, 2015, 03:57 pm
Ja, die entsprechenden Bits im MCUCR Register gibt es wohl auf dem Mega nicht.

Du kannst BOD aber immer noch über die Fuse-Bits deaktivieren. Dann ist er aber immer aus. Nicht nur im Sleep Mode.
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 04, 2015, 08:49 pm
Ja, die entsprechenden Bits im MCUCR Register gibt es wohl auf dem Mega nicht.

Du kannst BOD aber immer noch über die Fuse-Bits deaktivieren. Dann ist er aber immer aus. Nicht nur im Sleep Mode.
Danke!  :)
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 04, 2015, 11:59 pm
Noch mal eine Frage zu den Sleep-Modes und Aufwachen durch WDT und oder Serial Rx und oder PCI.

Bei Nick Gammon habe ich gesehen, dass er wenn er mehr als 8sec im LowPowerMode schalfen möchte, die Sleep Funktion mehrfach ausführt. z.B in seinem Low-power temperature monitor (http://gammon.com.au/forum/?id=11497&reply=5#reply5) Oder das zu schlafende WDT-Intervall mit in die Schlaf-Funktion übergibt.

Dabei wird jedes mal beim ausführen der Schlaf Funktion die Hardware aus- und nach dem Schlafen weider eingeschaltet.

Möchte man nun z.B ein vielfaches von 8Sec. oder eine "ungerade" Zeit z.B. 9796ms schlafen, wird jedes mal wenn ein WDT-Interverall beendet ist die gesamte Hardware ein- und dann weider aus geschaltet. ( Bsp: 9796ms: 1. WDT-Intervall 8sec, Rest 1796ms, 2. 1sec, Rest 796ms, 3. 512ms, Rest 284 ...usw.)

Meine Idee war es nun in der Sleep-Funktion nur ein mal am Anfang den gewünschten Sleep-Mode zu setzen (z.B. LowPowerSleep), dann die benötigte größte WDT-Periode zu setzen (z.B. 8sec) und in einer while-loop so lange sleep_enable () und sleep_cpu () bis die zu schlafende Zeit kleiner 8Sec ist. Das ganze dann mit dem nächste kleineren Intervall so lange wiederholen bis man bei 16ms angekommen ist.

Leider rast mein TestCode durch die Sleep Funktion durch ohne (wirklich) zu schlafen. Nur ganz kurz wird die WAKE_LED mal ausgeschaltet/flackert. Der uC scheint nicht wirklich in den Sleep Mode zu gehen, oder wird gleich weider aufgeweckt. Viellicht, weil der WDT nicht frisch gesetzt wurde??

Würde mich sehr freuen, wenn jemand einen Tipp für mich hat. Eventuell müssen ja gewisse Abfolgen im Code eingehalten werden oder ...

Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 05, 2015, 12:08 am
Hier mal die wichtigsten Ausschnitte (gesamt Code ist zu lang zu Posten, daher oben als Download):
Code: [Select]

//### mySleep set wake sources, switch off Hardware and sleep uC (for given Periode / till Interrupt) ##
unsigned long mySleep(byte sleep_mode, long toSleep, bool wakeBySerialRx, byte pci_pins[] ,\
byte pin_cnt, byte extHwSet, byte intHwSet){
// Sleep Function, set: SleepMode, WDT Sleep Periode, if Serial waiks up*, PCI Pins to wake up uC*,
// Settings for external* and internal Hardware shutdown*
// *) ... not yet (fully) implemented

long recent_sleeped = 0; // in recent mySleep call actual sleeped ms (in low Power + delay)
// is -1 if WDT was off => no information abaut sleeped ms! (check RTC)

byte oldSREG = SREG; // Save old interrupt state
noInterrupts(); // disable Interrupts
sleep_en = 1; // set save-way
SREG = oldSREG; // restore old interrupt state (enable)

PowerDownExternalHardware( extHwSet); // shut down associated ext. Harware

PowerDownInternalHardware( intHwSet); // shut down associated int. Harware

if((toSleep > 0) && (sleep_mode > 0)){ // enable wake by WDT only if WDT Periode is set
// setup wdt to periode and sleep x times till periode is smaler then the WDT Sleep Periode

// Set Sleep Mode
byte oldSREG = SREG; // Save old interrupt state
noInterrupts(); // disable Interrupts
switch (sleep_mode){
//case 0: break; //no sleep mode, stay on, only delay
case 1: set_sleep_mode (SLEEP_MODE_IDLE); break;
case 2: set_sleep_mode (SLEEP_MODE_ADC); break;
case 3: set_sleep_mode (SLEEP_MODE_PWR_SAVE); break;
case 4: set_sleep_mode (SLEEP_MODE_EXT_STANDBY); break;
case 5: set_sleep_mode (SLEEP_MODE_STANDBY); break;
//case 6: == default:
default: set_sleep_mode (SLEEP_MODE_PWR_DOWN); // Sleep Mode (lowest)
}//switch
SREG = oldSREG; // restore old interrupt state (enable)

WDT_while_loop(toSleep, recent_sleeped, WDT_8000MS); // Sleep in WDT_Periode as long as toSleep > WDT_Periode
WDT_while_loop(toSleep, recent_sleeped, WDT_1000MS); // Sleep in WDT_Periode as long as toSleep > WDT_Periode
WDT_while_loop(toSleep, recent_sleeped, WDT_128MS); // Sleep in WDT_Periode as long as toSleep > WDT_Periode
WDT_while_loop(toSleep, recent_sleeped, WDT_16MS); // Sleep in WDT_Periode as long as toSleep > WDT_Periode

// indicate that not sleeping anymore
oldSREG = SREG; // Save old interrupt state
noInterrupts(); // disable Interrupts
is_sleeping = 0; // indicate for ISR that NOT sleeping anymore
SREG = oldSREG; // restore old interrupt state (enable)

// 'Waste' rest time in Delay OR return early(er) to loop? (more Power saving possible with IDEL MODE or ...??)
//byte shorten_sleep = 3; // ms to shorten sleep (only for this delay part, not for WDT part!
while(toSleep > shorten_sleep){
toSleep -= 1;
delayMicroseconds(DELAY_1SEC); // correct measurement needed, then DELAY_1SEC [us]
total_sleeped += 1;
recent_sleeped += 1; // in this mySleep call actual sleeped ms
}

}// if((toSleep > 0) && (sleep_mode > 0))

else if(toSleep < 0){ // no WDT Periode was given =>don't wake periodicly
// wake only by Interrtupt from PCI, ADC, Serial RX ...
// start sleeping...
// disable sleeping after Interrupt (or better disable sleep in ISRs?)
byte oldSREG = SREG; // Save old interrupt state
noInterrupts(); // disable Interrupts
bool sleep_en_c = sleep_en; // get local copie save
SREG = oldSREG; // restore old interrupt state (enable)

if(sleep_en_c){

recent_sleeped = -1; // Sleeped ms are unknown!

noInterrupts(); // disable Interrupts

//setSleepMode(sleep_mode);

// for now just power down
set_sleep_mode (SLEEP_MODE_PWR_DOWN);

is_sleeping = 1; // indicate for ISR that sleep is activ

sleep_enable ();
interrupts ();
sleep_cpu ();
//sleeps here...

//...wakes in ISR and comes back here.

// check if(is_sleeping) ?? NOT NEEDED HERE!
sleep_disable ();
// indicate that not sleeping anymore
oldSREG = SREG;
noInterrupts();
is_sleeping = 0; // indicate for ISR that NOT sleeping anymore
SREG = oldSREG; // restore old interrupt state (enable)


}//if(sleep_en_c)
}//else

PowerUpInternalHardware(0b1111111); // internal Hardware back on
PowerUpExternalHardware(0b1111111); // external Hardware back ton

return recent_sleeped; // in this mySleep call actual sleeped ms, -1 unknown because WDT was not activ;
}// mySleep()





//### WDT while Loop (waste Time in sleep Mode with WDT on till toSleep ms is < WDT Intervall)##
void WDT_while_loop(long &toSleep, long &recent_sleeped, unsigned int wdt_intervall){
if(toSleep >= wdt_intervall){

byte oldSREG = SREG; // Save old interrupt state
noInterrupts(); // disable Interrupts
bool sleep_en_c = sleep_en; // get local copie save
SREG = oldSREG; // restore old interrupt state (enable)

byte wdt_periode = 0; // set WDT periode (see Datasheet)
switch (wdt_intervall){
case 10000 ... 6500: wdt_periode = 0b100001; break; // 8sec
// skip 4 and 2 sec
case 1500 ... 600: wdt_periode = 0b000110; break; // 1sec
// skip 512, 256ms
case 200 ... 80: wdt_periode = 0b000011; break; // 128ms
//skip 64, 32ms
//case 4 ... 30: wdt_periode = 0b000000; break; // 16ms
default: wdt_periode = 0b000000; break; // 16ms
}

myWatchdogEnable(wdt_periode); // set to wdt periode and enable

while(sleep_en_c && toSleep >= wdt_intervall){ // sleep for x * 8sec
toSleep -= wdt_intervall;

// final prepare sleeping...
noInterrupts();
is_sleeping = 1; // indicate for ISR that sleep is activ
digitalWrite (LED_AWAKE, LOW); // Idicate CPU is off
//myWatchdogEnable(wdt_periode); // set to wdt periode and enable
set_sleep_mode (SLEEP_MODE_STANDBY);
sleep_enable ();
interrupts ();
sleep_cpu ();
//sleeps here...

//...wakes here or in ISR and comes back here.

// check if(is_sleeping) ?? not needed!?
// sleep_disable (); // precautio, here or at end of this loop? ???
//wdt_disable();
digitalWrite (LED_AWAKE, HIGH); // Idicate CPU is on

//if(is_sleeping){ // if an other ISR, not WDT, woke this will be wrong! => check RTC for current time
total_sleeped += wdt_intervall; // store sleeped ms for millis_sleep() (might be wrong! Tasks are done to early.)
recent_sleeped += wdt_intervall; // in this mySleep call actual sleeped ms

oldSREG = SREG;
noInterrupts();
sleep_en_c = sleep_en;
SREG = oldSREG;
}//while

wdt_disable();

}//if(WDT Periode > 8sec)

}//void WDT_while_loop()



//### Set Watchdogtimer Intervall and enable WDT
void myWatchdogEnable (const byte interval){
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset
WDTCSR = bit (WDCE) | bit (WDE);
// set interrupt mode and an interval
WDTCSR = bit (WDIE) | interval; // set WDIE, and requested delay
wdt_reset(); // pat the dog, only 1.st time needed? is it possible to let it running while in
//sleep-loops??

}


 
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 05, 2015, 02:37 am
So wird es letztendlich im "Innern" von mySleep auch gemacht.

...ich kann inzwischen / sollte meine Frage auch verkürzen:

Als Vorlage nehme ich mal diesen Code von Nick:
pin change interrupts, and a watchdog timer interrupt, for the ATtiny 85 (http://gammon.com.au/forum/?id=11497&reply=6#reply6)

Original von Nick:
Code: [Select]

// ATtiny85 sleep mode, wake on pin change interrupt or watchdog timer
// Author: Nick Gammon
// Date: 12 October 2013

// 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

const byte LED = 3;  // pin 2
const byte SWITCH = 4; // pin 3 / PCINT4

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
 
  pinMode (LED, OUTPUT);
  pinMode (SWITCH, INPUT);
  digitalWrite (SWITCH, HIGH);  // internal pull-up
 
  // pin change interrupt (example for D4)
  PCMSK  = bit (PCINT4);  // want pin D4 / pin 3
  GIFR  |= bit (PCIF);    // clear any outstanding interrupts
  GIMSK |= bit (PCIE);    // enable pin change interrupts
  }  // end of setup

void loop ()
  {
  digitalWrite (LED, HIGH);
  delay (500);
  digitalWrite (LED, LOW);
  delay (500);
  goToSleep ();
  }  // end of loop
 
void goToSleep ()
  {
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  ADCSRA = 0;            // turn off ADC
  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


Und würde folgende Änderungen vornehmen:
Code: [Select]


// watchdog interrupt
ISR (WDT_vect) {
 // wdt_disable(); // DON'T disable watchdog here, done after sleeping x_times
} // end of WDT_vect


void resetWatchdog (byte wdtPeriode) { // 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) |  wdtPeriode; // set WDIE, and WDT Periode !

  // pat the dog
  wdt_reset();
} // end of resetWatchdog


void goToSleep (long msToSleep) {  // sleep x times eg. 16sec x_times = 2
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
 
  // powerDownExternalHardware(extHwSettings);
  ADCSRA = 0; // turn off ADC
  power_all_disable (); // power off ADC, Timer 0 and 1, serial interface
 
  // WDT for 8sec
  noInterrupts (); // timed sequence coming up
  resetWatchdog (wdtPeriode8sec); // get watchdog ready just once??
  interrupts (); // interrupts are required here ???

  while(msToSleep >= 8000){
    msToSleep -= 8000;
    noInterrupts (); // timed sequence coming up 
    sleep_enable (); // ready to sleep
    interrupts (); // interrupts are required
    now sleep_cpu (); //

    sleep sleep_disable (); // precaution
  }//while


  // WDT for 1sec
  noInterrupts (); // timed sequence coming up
  resetWatchdog (wdtPeriode1sec); // get watchdog ready just once??
  interrupts (); // interrupts are required here ???

  while(msToSleep >= 1000){
    msToSleep -= 1000;
    noInterrupts (); // timed sequence coming up 
    sleep_enable (); // ready to sleep
    interrupts (); // interrupts are required
    now sleep_cpu (); //

    sleep sleep_disable (); // precaution
  }//while

  // WDT for x ms ...and so on ...so why not putting this while loops in one function
  // wich is called with the msToSleep periode and byte for WDT Periode as input?

  //  now disable wdt once ( not in wdt isr) is that ok so?
  wdt_disable();

  power_all_enable (); // power everything back on
  //powerUpExternalHardware(extHwSettings);
} // end of goToSleep



Ist das so sauber und wird es funktionieren? Kann es leider erst mal nicht testen.



Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 05, 2015, 04:04 am
Ok, dieser Sketch tut es (fast) so wie ich es mir gewünscht habe, außer das wake up by Serial Rx ( PCI Pin 0, beim Mega ist das PCINT8  auf PCI1) funktioniert nicht richtig. Sendet man etwas per Serial wird er scheinbar ein mal kurz wach, schläft aber dann weiter, stat wie beim PCI vom Switch das Schlafen komplett abzubrechen. Senden man schnell hintereinander (Enter gedrückt) wird scheinbar jede WDT Sleep periode abgebrochen und er kehrt sehr schnell zurück in die loop.  Versteh ich nicht warum, denn beim PCI vom switch klappt es ja??

Code: [Select]
/*
 * Original from Nick Gammon at http://gammon.com.au/forum/?id=11497&reply=6#reply6
 * Changed by Jim Beam on 05/09/15 to work with Meag2560, changed toSleep Function
 * Thanks to the guys of the Arduino Forum and Nick Gammon!
 * To-DO: add Wake by Serial Rx (D0) by PCI, simplify more PCI Pins, disable more Hardware,
 *        set sleepMode for toSleep Function, Auomatic detect WDT Periodes and bytes,
 *        add setable ext-Hardware-FCN and setable int. Hwardware FCN
 */

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

const byte LED = 12;  // pin 13
const byte LEDWAKE = 13;  // pin 13
const byte SWITCH = 10; // pin 10 / PCINT4
volatile bool sleep_enable = 1;     // 0= stop sleeping, go back to loop, set 0 by any ISR
volatile bool serial_isr = 0;       // Serial Rx isr was activ



ISR (PCINT0_vect)   // Wake Pin 10
 {
 // do something interesting here
  sleep_disable (); // precaution
  wdt_disable();
  sleep_enable = 0;
 }  // end of PCINT0_vect



 ISR (PCINT1_vect)  // Serial
 {
 // do something interesting here
  
  sleep_disable (); // precaution
  wdt_disable();
  sleep_enable = 0;
  serial_isr = 1;
 }  // end of PCINT0_vect


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



  
void setup ()
  {
  resetWatchdog (0b100001);  // do this first in case WDT fires
  pinMode (LED, OUTPUT);
  pinMode (LEDWAKE, OUTPUT);
  digitalWrite (LEDWAKE, HIGH);
  
  Serial.begin(115200);
  Serial.print(F("\n\nStarting...\n File: " __FILE__ "\n Date: " __DATE__ "\n Time: " __TIME__ "\n IDE : "));
  Serial.println(ARDUINO);
  Serial.println();
  
 
  pinMode (SWITCH, INPUT);
  digitalWrite (SWITCH, HIGH);  // internal pull-up


    //set PCI for Pin 0, Provide PCI ISR!!
    // pin change interrupt (example for D0) Mega 2560! to Waik by Serial if wanted!
    PCMSK1 |= bit (PCINT8); // want pin 0
    PCIFR  |= bit (PCIF1);   // clear any outstanding interrupts
    PCICR  |= bit (PCIE1);   // enable pin change interrupts for D0 to D7
    
    PCMSK0 |= bit (PCINT4); // want pin 10
    PCIFR  |= bit (PCIF0);   // clear any outstanding interrupts
    PCICR  |= bit (PCIE0);   // enable pin change interrupts for D0 to D7
  }  // end of setup



void loop ()
  {
  Serial.print(F("\n Loop"));
  checkSerial();
    
  for(byte i=0;i<15;i++){
    digitalWrite (LED, HIGH);
    delay (100);
    digitalWrite (LED, LOW);
    delay (100);
  }
  doSerial();
  Serial.flush();
  goToSleep (15999L);
  }  // end of loop


  
void goToSleep (long msToSleep)
  {
  noInterrupts ();       // timed sequence coming up
  sleep_enable = 1;
  byte old_ADCSRA = ADCSRA;
  // disable ADC
  ADCSRA = 0;  

  PCMSK1 |= bit (PCINT8); // want pin 0
  PCIFR  |= bit (PCIF1);   // clear any outstanding interrupts
  PCICR  |= bit (PCIE1);   // enable pin change interrupts for D0 to D7
  
  interrupts ();         // interrupts are required now
  
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface

  UCSR0B &= ~bit (RXEN0);  // disable receiver
  UCSR0B &= ~bit (TXEN0);  // disable transmitter


  wdtWhileLoop(msToSleep, 8000UL, 0b100001);  //8Sec  //Change: just give msToSleep, max WDT Periode and byte will be
                                                      //determined in FCN by switch case
  wdtWhileLoop(msToSleep, 1000UL, 0b000110);  //1Sec
  wdtWhileLoop(msToSleep, 128UL,  0b000011);  //128ms
  wdtWhileLoop(msToSleep, 16UL,   0b000000);  //16ms
  

  //  now disable wdt once ( not in wdt isr) is that ok so?
  wdt_disable();
  
  power_all_enable ();   // power everything back on
  ADCSRA = old_ADCSRA;
  PCICR  &= ~bit (PCIE1);   // disable pin change interrupts for Serial D0 Pin0 (Mega)
  UCSR0B |= bit (RXEN0);  // enable receiver
  UCSR0B |= bit (TXEN0);  // enable transmitter
  }  // end of goToSleep



void wdtWhileLoop(long &msToSleep, int wdtPeriodeMs, byte wdtPeriodeByte){

  //Change: just give msToSleep, max WDT Periode and byte will be
   //determined in FCN by switch case
  
  noInterrupts ();       // timed sequence coming up
  resetWatchdog (wdtPeriodeByte);      // get watchdog ready
  bool sleep_enable_c = sleep_enable;
  interrupts ();         // interrupts are required now
  
  while((msToSleep >= wdtPeriodeMs) && sleep_enable_c){
    msToSleep -= wdtPeriodeMs;
    noInterrupts (); // timed sequence coming up
    digitalWrite (LEDWAKE, LOW);
    sleep_enable (); // ready to sleep
    interrupts (); // interrupts are required now
    sleep_cpu (); //

    sleep_disable (); // precaution
    digitalWrite (LEDWAKE, HIGH);
    
    noInterrupts ();       // timed sequence coming up
    sleep_enable_c = sleep_enable;
    interrupts ();         // interrupts are required now
    
  }//while
}



void resetWatchdog (byte interval)
  {
  //byte interval = 0b100001; //8sec
   // clear various "reset" flags
  MCUSR = 0;    
  // allow changes, disable reset
  WDTCSR = bit (WDCE) | bit (WDE);
  // set interrupt mode and an interval
  WDTCSR = bit (WDIE) | interval;    // set WDIE, and requested delay
  wdt_reset();                       // pat the dog, only 1.st time needed? is it possible to let it running while in
                                     //sleep-loops??
  }  // end of resetWatchdog



void doSerial(){
  Serial.println();
  Serial.print(F("Echo: "));
  while(Serial.available()){
    Serial.print(Serial.read());
  }
  Serial.println();
}


void checkSerial(){
  noInterrupts ();
  bool serial_isr_c = serial_isr;
  interrupts ();

  if(serial_isr_c){
  noInterrupts ();
  serial_isr = 0;;
  interrupts ();

  Serial.println(F("\nWoke by Serial. pls. reenter Command now within 3 sec."));
  }
}







  
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 06, 2015, 01:33 am
Ok konnte das Problem deutlich weiter eingrenzen!

Kurz: Die PCI ISR an Serial-Rx-Pin 0 wird nicht ausgeführt wenn ein (zu) kurzer low Puls (Daten) kommt. Lediglich der uC wird geweckt!!  :o 

Nur bei Baudraten von 9600 und kleiner wird die PCI ISR sauber auch schon von einem gesendeten Zeichen durchlaufen! Bei höheren BaudRaten müssen es mehr Zeichen sein. Bei 230400 die ich sonst so standardmäßig nutze kam die PCI ISR nie!. Aber der uC wacht auf.

Habe lange gesucht und hatte auch am Ende nicht wirklich dran gedacht, aber mal zu "Spass" Baudrate geändert. Kann dass Jemand (mir) erklären??

Es scheint ja, dass die PCI-ISR nicht angesprungen wird, das der low-Puls durch die schnellen Daten zu kurz ist!?

Ein Test mit einem Käbelchen in Pin0 und (internem) Pullup funktioniert sauber! Die (vermeintliche) Serial RX ISR wird ausgeführt (Test-LED an, und Flag gesetzt). 

Ich muss dazu sagen, dass ich meinen 16U2 nicht mehr drauf habe auf dem Mega, ist mit 10cm Kabel an ein leeres UNO Board zum proggen und für Serial verbunden. Könnte ev. auch eine Rolle spielen??

Hier mein TestCode. Freue mich über Rückmeldungen. Vielen Dank!  :)
Title: Re: Mega 2560 - Power Saving - Strom sparen
Post by: jim_beam on Sep 06, 2015, 01:51 pm
Juhu jetzt läuft alles wie gewünscht und braucht im Schlaf nur 57uA (mit WDT an) und 51uA ohne WDT.   :)  (BOD bei beiden aus, brachte ca 20uA)

Das Problem ist tatsächlich, dass der sehr kurze Serial Rx zwar den uC weckt, aber der ja braucht weil CPU Clock aus war bis er so weit ist und bis dahin ist der PCI-Interrupt nicht mehr erkennbar/längst vorbei.

Code: [Select]
Datasheet 2560, Page 109
15. External Interrupts

Note that if a level triggered interrupt is used for wake-up from Power-down, the required level must be
 held long enough for the MCU to complete the wake-up to trigger the level interrupt. If the level
 disappears before the end of the Start-up Time, the MCU will still wake up, but no interrupt will be
generated. The start-up time is defined by the SUT and CKSEL Fuses as described in "System Clock and
 Clock Options" on page 39.


1. Lösung:
nur in den SLEEP_MODE_STANDBY Mode gehen, da bleibt die Clock Sourse an => 570uA (mir zu viel)

2. Lösung:
um zu erkennen dass es ein sehr schnelle Serial Rx war, das zwar den uC geweckt hat, aber kein Flag in der ISR gestzt hat,
setze ich vor jedem sleep selbst ein Flag ("volatile bool unrecodnised_isr = 1"), dass jede andere ISR (z.B WDT, andere PCI Pins, ...) wieder löscht.
An der Stelle wo der uC wieder aufwacht im Code frage ich das Flag ab, ist es noch gesetzt, wird es wohl ein wake up aufgrund des sehr schnell Serial Rx Signals gewesen sein, dass keine ISR geschafft hat zu triggern. (Und falls das Serial Rx sehr langsam/oder extrem lang ist, wird es auch richtig erkannt.)

Codeausschnitte, alle ISRs:
Code: [Select]

// alle ISRs clearen unrecodnised_isr

ISR (PCINT0_vect)               // Pin10
{
  sleep_disable();              // stop sleeping (needeed? or to just make sure?)
  sleep_enable = 0;             // stop further multiple sleeping in while loop (not yet implementet)
  unrecodnised_isr = 0;         // disable, since this ISR was carried out, too short SerialRx ISR wont clear this
 
  if(!digitalRead(10)){         //Pin is low = activ
    isr_pin10_flag = 1;         // indicate ISR has run
    PCMSK0 &= ~bit (PCINT4);    // clear pin 10 of PCI0, no further ISR
  }



ISR (PCINT1_vect)               // Pin 0 (Serial Rx), Pin 14 (wire 4 testing)
{
  sleep_disable();
  sleep_enable = 0;
  unrecodnised_isr = 0;         // disable, since this ISR was carried out, too short SerialRx ISR wont clear this
   
  if(!digitalRead(14)){         //Pin is low = activ
    isr_pin14_flag = 1;
    PCMSK1 &= ~bit (PCINT10);   // clear pin 14
  }
  //else if(!digitalRead(0)){   // with checking the stae (might be too slow and fast chaging while Data RXed)
  else{                         // must have been a LONG SerialRx! So manually set back unrecodnised_isr=1
                                // to ensure Serial is done in Main loop
    PCMSK1 &= ~bit (PCINT8);    // clear pin 0 of PCI1 alreaddy so cant be called again
    unrecodnised_isr = 1;       // manually set back unrecodnised_isr=1 to ensure Serial is done in Main loop
    //isr_serial_flag = 1;      // this is done after sleep in if(unrecodnised_isr){}
    digitalWrite (TEST_LED, HIGH);  // Some Extra Debug Serial Rx erkannt
  }
}   


ISR (PCINT2_vect)               // empty
{
  sleep_disable();              // stop sleeping (needeed? or to just make sure?)
  sleep_enable = 0;             // stop further multiple sleeping in while loop (not yet implementet)
  unrecodnised_isr = 0;         // disable, since this ISR was carried out, too short SerialRx ISR wont clear this



ISR (WDT_vect)
{     
  isr_wdt_flag = 1;
  unrecodnised_isr = 0;          // disable, since this ISR was carried out, too short SerialRx ISR wont clear this
  if(!sleep_enable){           // sleep was stopped by any other ISR
    wdt_disable();             // disable watchdog 
    wdt_time = millis();       // get time of wdt has fired (not implemented)
  }
}  // end of WDT_vect



Der Teil vor und nach dem schlafen legen des uC:
Code: [Select]
sleep_enable();
    unrecodnised_isr = 1;           // set, normal ISR will clear, too short SerialRx ISR wont clear
    digitalWrite (AWAKE_LED, LOW);  // show uC goes sleeping
   
    if(!sleep_enable){              // only sleep if not diesabled yet by any ISR (except WDT) (later while loop)
      // don't go sleeping, has already been disabled!
       interrupts ();               // but eable Interrtups anyway
      //break;  // in loop later
      //return;
    }
    else{                           // go sleeping
      interrupts ();
      sleep_cpu ();     
      //sleeps here...
     
      //...wakes here
      sleep_disable();
           
    }
   
    digitalWrite (AWAKE_LED, HIGH); // show uC is on
   
    byte SREG_old = SREG;
    noInterrupts();
       
    if(unrecodnised_isr){           // has not clear by ordanary ISR, so it must have been an short Serial woke
      sleep_enable = 0;             // stop further sleeping
      PCMSK1 &= ~bit (PCINT8);      // clear pin 0 of PCI1 if it was this Pin!?
      isr_serial_flag = 1;
      //digitalWrite (TEST_LED, HIGH);  // Debug Serial Rx erkannt
    }
   
    // nach while loop test for disabling wdt
    if(sleep_enable){               // sleep not stopped by any other ISR, so normal sleep end,         
      wdt_disable();                // then disable watchdog
    }                               // else: any other ISR has cleard sleep_enable, leave WDT 1x more on to measure time
                                    // WDT will disable it selfe if sleep_enable==0
    SREG = SREG_old;                // Interrupts might be enabled again



So ist alles unter einem Hut:
- großer Bruder vom Uno/328P (vergleichsweise viel Speicher)
- trotzdem extrem Strom Sparen (leider etwas um löten am Bord, und Programmieren "von außen" nötig)
- beliebig langes schlafen legen (durch mehrfach WDT Sleep in while loop)
- beim aufwachen aus WDT Sleeps trotzdem die Zeit etwa kennen (millis() + sleeped_ms)
- Aufwachen durch beliebige PinChangeInterrupts, auch
- aufwachen durch Serial Rx (1. Empfagnegen Daten werden verworfen, Serielles Kommando kann schon nach einigen ms gesendet werden)

Finde ich genial, so habe ich mir das vorgestellt. Mein Dank gilt allen hier im Forum und Nick für die vielen Tipps, Code-Beispiele und Ideen!!  :)