{"id":395,"date":"2015-08-10T14:45:57","date_gmt":"2015-08-10T12:45:57","guid":{"rendered":"http:\/\/www.anginf.de\/?p=395"},"modified":"2015-12-17T09:27:39","modified_gmt":"2015-12-17T08:27:39","slug":"low-power-arduino-atmega328p","status":"publish","type":"post","link":"https:\/\/www.anginf.de\/?p=395","title":{"rendered":"Low Power Arduino ATMEGA328P"},"content":{"rendered":"<p>Nachdem ich den Minimal-Arduino auf dem Breadboard aufgebaut hatte, wollte ich diesen gerne \u00fcber eine CR2032-Batterie mit Strom versorgen, und das m\u00f6glichst lange.<\/p>\n<p>Zum Gl\u00fcck gibt es schon einige Artikel im Internet, die sich mit dem Stromverbrauch des ATMEGA328P auseinandergesetzt haben. Allerdings erwarten hier viele einen Interrupt von Extern, was in meinem Anwendungsfall (halbwegs regelm\u00e4ssig einen Sensor auslesen und die Information abspeichern oder verschicken) nicht ganz praktisch war. Vor allem, weil ich den passenden Uhrenquarz nicht verf\u00fcgbar habe&#8230;<\/p>\n<p>Hier also (nachvollziehbar) die einzelnen Schritte, die ich bei meinem ATMEGA328P unternommen habe, um ihn den hohen Stromverbrauch streitig zu machen.<\/p>\n<h3>Step 1: Default blink program with 5s delay, 16 MHz ext. Osz., 3V CR2032-battery<\/h3>\n<pre lang=\"C\">void setup() {\r\n  \/\/ initialize digital pin 13 as an output.\r\n  pinMode(13, OUTPUT);\r\n}\r\n\r\nvoid loop() {\r\n  digitalWrite(13, HIGH);   \/\/ turn the LED on (HIGH is the voltage level)\r\n  delay(5000);              \/\/ wait for a second\r\n  digitalWrite(13, LOW);    \/\/ turn the LED off by making the voltage LOW\r\n  delay(5000);              \/\/ wait for a second\r\n}\r\n<\/pre>\n<p>Result:<\/p>\n<ul>\n<li>LED On: 6.8mA<\/li>\n<li>LED Off: 5.8mA<\/li>\n<\/ul>\n<h3>Step 2: All other pins as input<\/h3>\n<pre lang=\"C\">void setup() {\r\n  \/\/To reduce power, setup all pins as inputs with no pullups\r\n  for(int x = 1 ; x < 18 ; x++){\r\n    pinMode(x, INPUT);\r\n    digitalWrite(x, LOW);\r\n  }\r\n  \/\/ initialize digital pin 13 as an output.\r\n  pinMode(13, OUTPUT);\r\n}\r\n\r\nvoid loop() {\r\n  digitalWrite(13, HIGH);   \/\/ turn the LED on (HIGH is the voltage level)\r\n  delay(5000);              \/\/ wait for a second\r\n  digitalWrite(13, LOW);    \/\/ turn the LED off by making the voltage LOW\r\n  delay(5000);              \/\/ wait for a second\r\n}\r\n<\/pre>\n<p>Result:<\/p>\n<ul>\n<li>LED On: 6.45mA<\/li>\n<li>LED Off: 5.65mA<\/li>\n<\/ul>\n<h3>Step 3: Power Down during sleep<\/h3>\n<p>I'll admit that this next step is a bit confusing, as a lot of things are introduced.<\/p>\n<pre lang=\"C\">#include <avr\/sleep.h> \/\/Needed for sleep_mode\r\n#include <avr\/wdt.h>\r\n\r\nvolatile boolean f_wdt=1;\r\n\r\nvoid setup() {\r\n  \/\/To reduce power, setup all pins as inputs with no pullups\r\n  for(int x = 1 ; x < 18 ; x++){\r\n    pinMode(x, INPUT);\r\n    digitalWrite(x, LOW);\r\n  }\r\n  \/\/ initialize digital pin 13 as an output.\r\n  pinMode(13, OUTPUT);\r\n  setup_watchdog(8);\r\n}\r\n\r\nbyte state=0;\r\n\r\nvoid loop() {\r\n    if (f_wdt==1) {  \/\/ wait for timed out watchdog \/ flag is set when a watchdog timeout occurs\r\n    f_wdt=0;       \/\/ reset flag\r\n    switch (state){\r\n    case 0:\r\n      digitalWrite(13, HIGH);   \/\/ turn the LED on (HIGH is the voltage level)\r\n      state = 1;\r\n      setup_watchdog(0);\r\n      break;\r\n    case 1:\r\n      digitalWrite(13, LOW);    \/\/ turn the LED off by making the voltage LOW\r\n      state = 0;\r\n      setup_watchdog(8);\r\n      break;\r\n    }\r\n    system_sleep();\r\n  }\r\n}\r\n\r\n\/\/****************************************************************  \r\n\/\/ set system into the sleep state \r\n\/\/ system wakes up when watchdog is timed out\r\nvoid system_sleep() {\r\n  \/\/ power_adc_disable()\r\n  set_sleep_mode(SLEEP_MODE_PWR_DOWN); \/\/ sleep mode is set here\r\n  sleep_enable();\r\n  sleep_mode();                        \/\/ System sleeps here\r\n  sleep_disable();                     \/\/ System continues execution here when watchdog timed out \r\n  \/\/ power_adc_enable()\r\n}\r\n\r\n\/\/****************************************************************\r\n\/\/ 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms\r\n\/\/ 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec\r\nvoid setup_watchdog(int ii) {\r\n\r\n  byte bb;\r\n  if (ii > 9 ) ii=9;\r\n  bb=ii & 7;\r\n  if (ii > 7) bb|= (1<<5);\r\n  bb|= (1<<WDCE);\r\n\r\n  MCUSR &#038;= ~(1<<WDRF);\r\n  \/\/ start timed sequence\r\n  WDTCSR |= (1<<WDCE) | (1<<WDE);\r\n  \/\/ set new watchdog timeout value\r\n  WDTCSR = bb;\r\n  WDTCSR |= _BV(WDIE);\r\n}\r\n\/\/****************************************************************  \r\n\/\/ Watchdog Interrupt Service \/ is executed when  watchdog timed out\r\nISR(WDT_vect) {\r\n  f_wdt=1;  \/\/ set global flag\r\n}\r\n<\/pre>\n<p>Result:<\/p>\n<ul>\n<li>LED On: 1.07mA<\/li>\n<li>LED Off: 0.02mA (206uA)<\/li>\n<\/ul>\n<p>As long as we depend on the internal oscillator, we won't get any further then 206uA, as the watchdog is still enabled and drawing current. Time to get one of those nice 32kHz-oscillators.<\/p>\n<p>Here are some more links related to this topic, some of those helped me in my process (some in german):<\/p>\n<ul>\n<li>http:\/\/www.mikrocontroller.net\/articles\/Sleep_Mode<\/li>\n<li>http:\/\/interface.khm.de\/index.php\/lab\/interfaces-advanced\/sleep_watchdog_battery\/<\/li>\n<\/ul>\n<p><!--\n\n\n<h3>Step 4: Accessing the fuses<\/h3>\n\n\nAfter we've already burnt the arduino bootloader on the ATMEGA328P, we're <a href=\"http:\/\/shawnhymel.com\/622\/quick-tip-reading-fuse-bits-in-an-arduino\/\">unable to access the fuses<\/a> via avrdude. So we have to use another arduino as ISP to set the fuses.\n\nUsing avrdude, you must use \"avrisp\" as the device and limit the baud rate to 19200.\n\nThis should output the current state of the fuses:\n\n\n<pre lang=\"winbatch\">\r\navrdude -cavrisp -pm328p -P\\\\.\\COM6 -n -v -b 19200\r\n<\/pre>\n\n\n\nExample:\n\n\n<pre lang=\"winbatch\">\r\n...\r\navrdude: safemode: lfuse reads as FF\r\navrdude: safemode: hfuse reads as DE\r\navrdude: safemode: efuse reads as 5\r\navrdude: safemode: Fuses OK (E:05, H:DE, L:FF)\r\n...\r\n<\/pre>\n\n\n\nResult:\n\n\n<ul>\n\t\n\n<li>LED On: 0mA<\/li>\n\n\n\t\n\n<li>LED Off: 0mA<\/li>\n\n\n<\/ul>\n\n\n\n\n<h3>Step : ...<\/h3>\n\n\n\n\n<pre lang=\"C\"><\/pre>\n\n\nResult:\n\n\n<ul>\n\t\n\n<li>LED On: 0mA<\/li>\n\n\n\t\n\n<li>LED Off: 0mA<\/li>\n\n\n<\/ul>\n\n\n--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nachdem ich den Minimal-Arduino auf dem Breadboard aufgebaut hatte, wollte ich diesen gerne \u00fcber eine CR2032-Batterie mit Strom versorgen, und das m\u00f6glichst lange. Zum Gl\u00fcck gibt es schon einige Artikel im Internet, die sich mit dem Stromverbrauch des ATMEGA328P auseinandergesetzt haben. Allerdings erwarten hier viele einen Interrupt von Extern, was in meinem Anwendungsfall (halbwegs regelm\u00e4ssig &hellip; <a href=\"https:\/\/www.anginf.de\/?p=395\" class=\"more-link\"><span class=\"screen-reader-text\">Low Power Arduino ATMEGA328P<\/span> weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-395","post","type-post","status-publish","format-standard","hentry","category-allgemein"],"_links":{"self":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/395","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=395"}],"version-history":[{"count":11,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/395\/revisions"}],"predecessor-version":[{"id":421,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/395\/revisions\/421"}],"wp:attachment":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=395"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=395"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=395"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}