{"id":1020,"date":"2013-06-11T22:33:28","date_gmt":"2013-06-11T20:33:28","guid":{"rendered":"http:\/\/blog.ulrichard.ch\/?p=1020"},"modified":"2013-06-11T22:33:28","modified_gmt":"2013-06-11T20:33:28","slug":"attiny-advent-wreath","status":"publish","type":"post","link":"https:\/\/ulrichard.ch\/blog\/?p=1020","title":{"rendered":"AtTiny  Advent Wreath"},"content":{"rendered":"<p>An advent wreath in late spring, you ask? Yes, the timing is a bit off, and that&#8217;s not just because the coldest spring in ages has not finished yet. While browsing for the topic of my <a href=\"http:\/\/blog.ulrichard.ch\/?p=1012\">last post<\/a>, I discovered a nice little one-evening-project: <a href=\"http:\/\/tinkerlog.com\/2009\/12\/12\/geeky-advent\/\">Geeky advent from tinkerlog<\/a>.<br \/>\nI had all the required parts here, so I just gave it a try. The adaptation from the AtTiny13 to an AtTiny45 was straight forward. But finding the right threshold value for the ambient light sensor was a bit trickier. Especially, as the ADC didn&#8217;t work at first. That was probably a difference between the two AtTiny&#8217;s. But once I configured the ADC properly for the AtTiny45, I flashed it a couple of times with different values, and turned the room light on an off, until I had a good threshold value.<br \/>\nIt&#8217;s interesting how the flickering is done with the random values and the manual PWM. And especially, how one of the LED&#8217;s is used to sense the ambient light was intriguing. To save battery power during the day, it goes to sleep and waits for the watchdog timer to wake it up. It then senses the ambient light. If it is bright, it goes straight back to sleep. If it&#8217;s dark, it lights up the LED&#8217;s. Going through the four modes for the four weeks of advent is done by resetting, or just quickly disconnecting the power from the battery.<\/p>\n<p>But now I look forward for the summer to come, before we can put the mini advent wreath to use&#8230;<\/p>\n<table>\n<tbody>\n<tr>\n<td><a href=\"https:\/\/ulrichard.ch\/piwigo\/index.php?\/category\/38\"><img decoding=\"async\" src=\"https:\/\/ulrichard.ch\/piwigo\/_data\/i\/upload\/2015\/11\/09\/20151109231913-98151398-th.jpg\" alt=\"\" \/><\/a><\/td>\n<td><a href=\"https:\/\/ulrichard.ch\/piwigo\/index.php?\/category\/38\"><img decoding=\"async\" src=\"https:\/\/ulrichard.ch\/piwigo\/_data\/i\/upload\/2015\/11\/09\/20151109231912-fd5ee2c3-th.jpg\" alt=\"\" \/><\/a><\/td>\n<td><a href=\"https:\/\/ulrichard.ch\/piwigo\/index.php?\/category\/38\"><img decoding=\"async\" src=\"https:\/\/ulrichard.ch\/piwigo\/_data\/i\/upload\/2015\/11\/09\/20151109231912-26eb7c5e-th.jpg\" alt=\"\" \/><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As my modified code is so similar to the original, it&#8217;s not really worth to create a project on github. So, I just pasted the code below.<\/p>\n<p><!--more--><\/p>\n<pre class=\"brush: c; gutter: false; first-line: 1\">\/* -----------------------------------------------------------------------\n * Title:    advent.c\n *           Flicker 4 LEDs\n * Author:   Alexander Weber\n *           http:\/\/tinkerlog.com\/2009\/12\/12\/geeky-advent\/\n * Date:     22.11.2009\n * Hardware: ATtiny13v\n * Software: CrossPack-AVR-20090415\n *\n * Modified to use an AtTiny45 by Richard Ulrich &lt;richi@paraeasy.ch&gt; 11.06.2013\n *\n * Credits:\n * This code is based heavily on sritesmods version.\n * Find the original at http:\/\/spritesmods.com\/?art=minimalism&amp;f=gpl\n *\n * Changes:\n * - support 4 LEDs\n * - added a bit of sampling for light detection\n * - moved the \"power down\" out of the ISR, was always resetting\n * - removed callibration, replaced by hardwired value.\n *\/\n\n#include &lt;avr\/io.h&gt;\n#include &lt;util\/delay.h&gt;\n#include &lt;avr\/interrupt.h&gt;\n#include &lt;avr\/eeprom.h&gt;\n#include &lt;avr\/pgmspace.h&gt;\n#include &lt;avr\/sleep.h&gt;\n#include &lt;avr\/wdt.h&gt;\n\n#define LED1  PB4\n#define LED2  PB3\n#define LED3  PB2\n#define LED4  PB1\n#define ADC2 2\n#define AMBIENT_LIGHT 55\n\n#define TRUE 1\n#define FALSE 0\n\n\/\/Bunch o' random numbers: I'm too lazy to write or port a real random number\n\/\/generator.\n\/\/generated using bash:\n\/\/for x in `seq 0 255`; do echo -n $(($RANDOM%256)),; done\nconst uint8_t randomvals[] PROGMEM = {\n\t234,191,103,250,144,74,39,34,215,128,9,122,144,74,137,105,123,218,158,175,205,\n\t118,149,13,98,7,173,179,194,97,115,110,213,80,220,142,102,102,36,152,90,135,\n\t105,176,173,49,6,197,48,140,176,122,4,53,83,216,212,202,170,180,214,53,161,\n\t225,129,185,106,22,12,190,97,158,170,92,160,194,134,169,98,246,128,195,24,\n\t198,165,156,77,126,113,136,58,156,196,136,41,246,164,84,138,171,184,42,214,\n\t203,128,89,39,198,85,140,148,149,36,215,78,170,234,131,124,152,239,154,214,\n\t130,194,49,3,69,248,120,179,101,163,131,124,184,148,213,118,213,81,177,149,\n\t58,213,33,201,63,10,195,215,190,7,86,245,128,9,8,40,102,51,125,94,92,5,159,\n\t75,253,158,40,4,6,178,241,92,124,73,248,1,157,61,50,86,136,113,22,16,171,209,\n\t230,144,240,14,188,2,167,22,88,57,50,86,171,73,114,175,34,226,245,57,180,111,\n\t220,186,170,242,141,229,49,158,30,82,161,49,124,65,139,24,95,14,133,65,238,\n\t116,180,190,49,130,30,30,59,93,173,139,19,187,2,163,102,26,255,23,239,196,19,\n\t6,162\n};\n\nuint8_t mode_ee EEMEM = 0;                      \/\/ stores the mode in eeprom\nstatic volatile uint8_t sleep = 0;\n\n\/\/ Gets a semi-random number between 0 and 255\nuint8_t getRandom(void)\n{\n\t\/\/This'll probably give a warning because we use it uninitialised. Little\n\t\/\/does the compiler know: that's actually what we _want_ :)\n\tstatic uint8_t random1, random2;\n\trandom1++;\n\tif(random1 == 0)\n\t\trandom2 += 0x41;\n\treturn pgm_read_byte(randomvals + random1) ^ random2;\n}\n\nuint16_t getLight(void)\n{\n\tuint16_t val = 0;\n\tuint8_t i;\n\n\tADMUX = (0 &lt;&lt; REFS0) \t\/\/ Set ADC reference to AVCC\n\t\t  | (0 &lt;&lt; REFS1) \t\/\/ Set ADC reference to AVCC\n\t\t  | (1 &lt;&lt; MUX1);    \/\/ Use ADC2 or PB4 pin for Vin\n\/\/\t\t  | ADC2;        \t\/\/ use ADC2 on PB4\n\n\tADCSRA = (1 &lt;&lt; ADEN)    \/\/ enable ADC\n\t\t   | 3; \t\t\t\/\/  prescaler 8\n\n\t\/\/ kill all leds\n\tPORTB &amp;= ~((1 &lt;&lt; LED1) | (1 &lt;&lt; LED2) | (1 &lt;&lt; LED3) | (1 &lt;&lt; LED4));\n\t_delay_ms(5);\n\n\tDDRB &amp;= ~(1 &lt;&lt; LED1); \/\/ let led generate some voltage\n\t_delay_ms(5);\n\n\t\/\/ warm up the ADC, discard the first conversion\n\tADCSRA |= (1 &lt;&lt; ADSC);\n\twhile(ADCSRA &amp; (1 &lt;&lt; ADSC))\n\t\t; \/\/ wait for the measurement to complete\n\n\tfor(i = 0; i &lt; 4; i++)\n\t{\n\t\t_delay_ms(5);\n\t\tADCSRA |= (1 &lt;&lt; ADSC);\n\t\twhile(ADCSRA &amp; (1 &lt;&lt; ADSC))\n\t\t\t; \/\/ wait for the measurement to complete\n\t\tval += ADC;\n\t}\n\tval &gt;&gt;= 2; \/\/ divide by 4\n\n\tADCSRA = 0;             \/\/ disable adc\n\tDDRB |= (1 &lt;&lt; LED1);    \/\/ re-enable led\n\n\treturn val;\n}\n\nISR(WDT_vect)\n{\n  \/\/check if it's still dark\n  sleep = (getLight() &gt; AMBIENT_LIGHT) ? TRUE : FALSE;\n}\n\nint main(void)\n{\n\tuint8_t lval1, lval2, lval3, lval4;\n\tuint8_t i, x, y;\n\tuint8_t mode;\n\n\t\/\/ set up wdt\n\twdt_enable(WDTO_2S);\n\n\tWDTCR |= 0x40; \/\/ WDT generates interrupts instead of resets now.\n\t\t\t\t   \/\/ We want interrupts because a reset clears our nice random\n\t\t\t\t   \/\/ seeds, and an interrupt doesn't.\n\n\tfor(i = 0; i &lt; 10; i++)\n\t{\n\t\t_delay_ms(100);\n\t}\n\n\t\/\/ retrieve mode from eeprom and write back mode + 1\n\tmode = eeprom_read_byte(&amp;mode_ee);\n\tmode = mode % 4;\n\teeprom_write_byte(&amp;mode_ee, mode + 1);\n\n\tsei(); \/\/ enable interrupts\n\n\t\/\/ go directly into sleep mode and lets wake up by the wdt\n\tsleep = TRUE;\n\n\t\/\/ enable leds\n\tDDRB = (1 &lt;&lt; LED1) | (1 &lt;&lt; LED2) | (1 &lt;&lt; LED3) | (1 &lt;&lt; LED4);\n\n\twhile(1)\n\t{\n\t\tWDTCR |= 0x40; \/\/ make sure wdt keeps generating an int instead of a reset\n\n\t\tif(sleep)\n\t\t{\n\t\t\t\/\/ switch off all LEDs and power down\n\t\t\tPORTB &amp;= ~((1 &lt;&lt; LED1) | (1 &lt;&lt; LED2) | (1 &lt;&lt; LED3) | (1 &lt;&lt; LED4));\n\t\t\tset_sleep_mode(SLEEP_MODE_PWR_DOWN);\n\t\t\tsleep_mode();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t\/\/ get a random value for the leds intensity\n\t\t\tlval1 = getRandom();\n\t\t\tlval2 = getRandom();\n\t\t\tlval3 = getRandom();\n\t\t\tlval4 = getRandom();\n\t\t\t\/\/ Manually do some pwm\n\t\t\tfor(x = 0; x &lt; 20; x++)\n\t\t\t{\n\t\t\t\tif(mode == 0)\n\t\t\t\t\tPORTB |= (1 &lt;&lt; LED1);\n\t\t\t\telse if(mode == 1)\n\t\t\t\t\tPORTB |= (1 &lt;&lt; LED1) | (1 &lt;&lt; LED2);\n\t\t\t\telse if(mode == 2)\n\t\t\t\t\tPORTB |= (1 &lt;&lt; LED1) | (1 &lt;&lt; LED2) | (1 &lt;&lt; LED3);\n\t\t\t\telse if(mode == 3)\n\t\t\t\t\tPORTB |= (1 &lt;&lt; LED1) | (1 &lt;&lt; LED2) | (1 &lt;&lt; LED3) | (1 &lt;&lt; LED4);\n\n\t\t\t\tfor(y = 0; y != 255; y++)\n\t\t\t\t{\n\t\t\t\t\tif(y == lval1)\n\t\t\t\t\t\tPORTB &amp;= ~(1 &lt;&lt; LED1);\n\t\t\t\t\tif(y == lval2)\n\t\t\t\t\t\tPORTB &amp;= ~(1 &lt;&lt; LED2);\n\t\t\t\t\tif(y == lval3)\n\t\t\t\t\t\tPORTB &amp;= ~(1 &lt;&lt; LED3);\n\t\t\t\t\tif(y == lval4)\n\t\t\t\t\t\tPORTB &amp;= ~(1 &lt;&lt; LED4);\n\t\t\t\t\t_delay_us(5);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>An advent wreath in late spring, you ask? Yes, the timing is a bit off, and that&#8217;s not just because the coldest spring in ages has not finished yet. While browsing for the topic of my last post, I discovered a nice little one-evening-project: Geeky advent from tinkerlog. I had all the required parts here, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,7,1],"tags":[26],"class_list":["post-1020","post","type-post","status-publish","format-standard","hentry","category-projects","category-software","category-uncategorized","tag-attiny"],"_links":{"self":[{"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1020","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1020"}],"version-history":[{"count":0,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1020\/revisions"}],"wp:attachment":[{"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1020"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1020"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ulrichard.ch\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1020"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}