{"id":1341,"date":"2015-12-31T07:29:11","date_gmt":"2015-12-31T07:29:11","guid":{"rendered":"http:\/\/www.richa1.com\/RichardAlbritton\/?p=1341"},"modified":"2016-06-14T11:37:44","modified_gmt":"2016-06-14T11:37:44","slug":"coding-for-the-lediva","status":"publish","type":"post","link":"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/","title":{"rendered":"Coding for the LEDiva\u2122"},"content":{"rendered":"<p>Tonight I got some real headway on my small LED driver. I added the ability to change the number of NeoPixels that are displayed, then update the onboard flash memory so that the ATtiny remembers what you selected even after a power cycle.<\/p>\n<p>So now if you press and hold either of the two buttons, then turn the board on, it will let you select the number of LEDs to use. Just press the Color or Mode buttons to add or remove an LED address.<\/p>\n<p><strong>Q:<\/strong> why would I want to change the number of LEDs that I am using on the fly?<\/p>\n<p><strong>A:<\/strong> Basically, the LEDiva\u2122 is intended to be a generic all purpose NeoPixel driver. You could use 140 NeoPixels, or just one. Some of the animations, like colorWipe();, start with the first LED address and loop until it gets to the last LED, as defined by the number of Pixels the NeoPixel library was told are available on startup. There is no way for the LEDs to tell the micro controller how many of them you just connected. So the animations will just run all the way out to 140 LEDs be damned. This can slow things as down if you are only using 3 physical LED. To fix this I simply tell the NeoPixel library that I want to use all 140, but make it so that the loop that updates the LEDs stops when it reaches the user defined number of LEDs.<\/p>\n<p>So if you use the new sequence to tell the LEDiva\u2122 that you want to use 3 LEDs, it will only loop LED updates 3 time rather than 140. Now that I have added storage to the EEPROM, it will remember the number of LEDs you selected the next time you turn it on. Are it and forget it.<\/p>\n<p>Here is the latest code I have:<\/p>\n<pre class=\"lang:arduino decode:true \" title=\"LEDiva Code with Sensor, LED Selector, and EEPROM Save\">\/\/Color and Pattern Mode selector for NeoPixels\r\n\/\/Uses C_BUTTON to cycle through 9 colors and P_BUTTON to select any of the 8 pattern sequences.\r\n\/\/ 64 total options are available\r\n\/\/code by Richard Albritton\r\n\r\n#include &lt;Adafruit_NeoPixel.h&gt;\r\n#include &lt;avr\/power.h&gt;\r\n#include &lt;EEPROM.h&gt;\r\n\r\n\/\/ Interrupt Code start\r\n#ifndef cbi\r\n#define cbi(sfr, bit) (_SFR_BYTE(sfr) &amp;= ~_BV(bit))\r\n#endif\r\n#ifndef sbi\r\n#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))\r\n#endif\r\n\/\/ Interrupt Code end\r\n\r\n#define PIN 0\r\n#define Sensor 1\r\n#define C_BUTTON 4\r\n#define P_BUTTON 3\r\n#define Pixels 60\r\n\r\nAdafruit_NeoPixel strip = Adafruit_NeoPixel(Pixels, PIN, NEO_GRB + NEO_KHZ800);\r\n\r\nint C_MODE = 1; \/\/ Current color mode.\r\nint P_MODE = 5; \/\/ Current pattern mode.\r\nint Cn = 9; \/\/The number of Color options.\r\nint Pn = 10; \/\/The number of Pattern options.\r\nint STrigger = 0; \/\/ This tells us if the sensor interrupt was triggered.\r\nint LEDs = 5;\r\nint R;\r\nint G;\r\nint B;\r\nlong randNumber;\r\nint wait = 10;\r\n\r\nvoid setup(){\r\n     \/\/ This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket\r\n#if defined (__AVR_ATtiny85__)\r\n  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);\r\n#endif\r\n  \/\/ End of trinket special code\r\n\r\n  pinMode(C_BUTTON, INPUT_PULLUP);\r\n  pinMode(P_BUTTON, INPUT_PULLUP);\r\n  strip.begin();\r\n  strip.show(); \/\/ Initialize all pixels to 'off'\r\n  if (!digitalRead(C_BUTTON)||!digitalRead(P_BUTTON)){\r\n    colorChange(strip.Color(50, 50, 50));\r\n    delay(500);\r\n    LESsetup(1);\r\n  }\r\n  if(EEPROM.read(0)&gt;0){\r\n    LEDs = EEPROM.read(0);\r\n  }\r\n  pinMode(Sensor,INPUT); \/\/ Interrupt Code\r\n  sbi(GIMSK,PCIE); \/\/ Turn on Pin Change interrupt\r\n  sbi(PCMSK,PCINT1); \/\/ Which pins are affected by the interrupt\r\n\r\n    colorMode(C_MODE);\r\n  colorChange(strip.Color(R, G, B));\r\n}\r\n\r\nvoid loop(){\r\n\/\/ Change the line below to alter the color of the lights\r\n\/\/ The numbers represent the Red, Green, and Blue values\r\n\/\/ of the lights, as a value between 0(off) and 1(max brightness)\r\nColorSelect(); \r\nPatternSelect();\r\n    \/\/colorMode(C_MODE);\r\n    patternMode(P_MODE);\r\n    STrigger = 0;\r\n}\r\nvoid ColorSelect(){\r\n  while (digitalRead(P_BUTTON) == LOW) {\r\n    colorChange(strip.Color(R\/4, G\/4, B\/4));\r\n    while (digitalRead(C_BUTTON) == LOW) {\r\n      delay(500);\r\n      C_MODE += 1;\r\n      if (C_MODE &gt; Cn) {\r\n        C_MODE = 1; \r\n      }\r\n      colorMode(C_MODE);\r\n      colorChange(strip.Color(R\/4, G\/4, B\/4));\r\n    } \r\n  }\r\n} \r\nvoid PatternSelect(){\r\n  while(digitalRead(C_BUTTON) == LOW) {\r\n    \/\/colorChange(strip.Color(R\/4, G\/4, B\/4));\r\n    while(digitalRead(P_BUTTON) == LOW) {\r\n      delay(500);\r\n      P_MODE += 1;\r\n      if (P_MODE &gt; Pn) {\r\n        P_MODE = 1; \r\n      }\r\n      patternMode(P_MODE);\r\n    }\r\n  }\r\n} \r\n\/\/ Fill the dots one after the other with a color\r\nvoid colorChange(uint32_t c) {\r\n  for(uint16_t i=0; i&lt;LEDs; i++) {\r\n      strip.setPixelColor(i, c);\r\n  }\r\n  strip.show();\r\n}\r\n\r\n\/\/ Fill the dots one after the other with a color\r\nvoid colorWipe(uint32_t c) {\r\n  for(uint16_t i=0; i&lt;LEDs; i++) {\r\n      strip.setPixelColor(i, c);\r\n      strip.show();\r\n      \r\n      delay(50);\r\n  }\r\n}\r\n\r\n\/\/ Fill the dots one after the other with a color\r\nvoid Sparkle(uint32_t c) {\r\n  for(uint16_t i=0; i&lt;LEDs; i++) {\r\n      strip.setPixelColor(i, c);\r\n      strip.show();\r\n      delay(50);\r\n  }\r\n}\r\n\r\nvoid colorMode(uint32_t m) {\r\n  switch (m) {\r\n    case 1: \/\/ Red\r\n      R = 100;\r\n      G = 0;\r\n      B = 0;\r\n      break;\r\n    case 2: \/\/ Orange\r\n      R = 75;\r\n      G = 25;\r\n      B = 0;\r\n      break;\r\n    case 3: \/\/ Yellow\r\n      R = 50;\r\n      G = 50;\r\n      B = 0;\r\n      break;\r\n    case 4: \/\/ Green\r\n      R = 0;\r\n      G = 100;\r\n      B = 0;\r\n      break;\r\n    case 5: \/\/ Sky Blue\r\n      R = 0;\r\n      G = 50;\r\n      B = 50;\r\n      break;\r\n    case 6: \/\/ Blue\r\n      R = 0;\r\n      G = 0;\r\n      B = 100;\r\n      break;\r\n    case 7: \/\/ Violet\r\n      R = 25;\r\n      G = 0;\r\n      B = 75;\r\n      break;\r\n    case 8: \/\/ Pink\r\n      R = 50;\r\n      G = 0;\r\n      B = 50;\r\n      break; \r\n    case 9: \/\/ White\r\n      R = 34;\r\n      G = 33;\r\n      B = 33;\r\n      break;     \r\n  }\r\n}\r\nvoid patternMode(uint32_t p) {\r\n  switch (p) {\r\ncase 1: \/\/ Solid bright\r\n      colorChange(strip.Color(R, G, B));\r\n      break;\r\n    case 2: \/\/ Solid dim\r\n      colorChange(strip.Color(R\/2, G\/2, B\/2));\r\n      break;\r\n    case 3: \/\/ Slow strobe\r\n      wait = 800;\r\n      colorChange(strip.Color(R, G, B));\r\n      delay(wait);\r\n      colorChange(strip.Color(0, 0, 0));\r\n      delay(wait);\r\n      break;\r\n    case 4: \/\/ Fast strobe\r\n      wait = 300;\r\n      colorChange(strip.Color(R, G, B));\r\n      delay(wait);\r\n      colorChange(strip.Color(0, 0, 0));\r\n      delay(wait);\r\n      break;\r\n    case 5: \/\/ Pulsate\r\n      wait = 100;\r\n      uint16_t i;\r\n      for(i=0; i&lt;7; i++) {\r\n        if (STrigger) wait = 20;\r\n        strip.setBrightness(255-(36*i));\r\n        colorChange(strip.Color(R, G, B));\r\n        delay(wait);\r\n      }\r\n      for(i=0; i&lt;7; i++) {\r\n        if (STrigger) wait = 20;\r\n        strip.setBrightness(0+(36*i));\r\n        colorChange(strip.Color(R, G, B));\r\n        delay(wait);\r\n      }\r\n      break;\r\n    case 6: \/\/ Tracer\r\n    for(uint16_t i=0; i&lt;LEDs; i++) {\r\n      strip.setPixelColor(i, strip.Color(R, G, B));\r\n      strip.show();\r\n            PatternSelect();\r\n          if (P_MODE != p) break;\r\n      delay(50);\r\n    }\r\n    for(uint16_t i=0; i&lt;LEDs; i++) {\r\n        strip.setPixelColor(i, strip.Color(0, 0, 0));\r\n        strip.show();\r\n              PatternSelect();\r\n            if (P_MODE != p) break;\r\n        delay(50);\r\n    }\r\n      \r\n      break;\r\n    case 7: \/\/ Sparkle\r\n      randNumber = 300;\r\n      for(uint16_t i=0; i&lt;LEDs; i++) {\r\n        if (STrigger) randNumber = 60;\r\n        if (random(randNumber) &lt; 50) {\r\n          strip.setPixelColor(i, strip.Color(R, G, B));\r\n        } else {\r\n          strip.setPixelColor(i, strip.Color(0, 0, 0));\r\n        }\r\n                strip.show();\r\n        delay(20);\r\n      }\r\n\r\n      break;\r\n    case 8: \/\/ Rainbow (This will not use the selected colors)\r\n        uint16_t j;\r\n        for(j=0; j&lt;256; j++) {\r\n          for(i=0; i&lt;LEDs; i++) {\r\n            strip.setPixelColor(i, Wheel((i+j) &amp; 255));\r\n          }\r\n          strip.show();\r\n          PatternSelect();\r\n          if (P_MODE != p) break;\r\n          delay(20);\r\n        }\r\n      break;\r\n  case 9: \/\/ Color Pulsate\r\n      wait = 100;\r\n      for(i=0; i&lt;7; i++) {\r\n        if (STrigger){\r\n          C_MODE += 1;\r\n          if (C_MODE &gt; 10)C_MODE = 1;\r\n          colorMode(C_MODE);\r\n        }\r\n        strip.setBrightness(255-(36*i));\r\n        colorChange(strip.Color(R, G, B));\r\n        delay(wait);\r\n      }\r\n      for(i=0; i&lt;7; i++) {\r\n        if (STrigger){\r\n          C_MODE += 1;\r\n          if (C_MODE &gt; 10)C_MODE = 1;\r\n          colorMode(C_MODE);\r\n        }\r\n        strip.setBrightness(0+(36*i));\r\n        colorChange(strip.Color(R, G, B));\r\n        delay(wait);\r\n      }\r\n      break;  \r\n  case 10: \/\/ red\/white\r\n      wait = 100;\r\n      colorMode(1);\r\n      for(i=0; i&lt;7; i++) {\r\n        strip.setBrightness(255-(36*i));\r\n        colorChange(strip.Color(R, G, B));\r\n        delay(wait);\r\n      }\r\n      for(i=0; i&lt;7; i++) {\r\n        strip.setBrightness(0+(36*i));\r\n        colorChange(strip.Color(R, G, B));\r\n        delay(wait);\r\n      }\r\n      colorMode(9);\r\n      for(i=0; i&lt;7; i++) {\r\n        strip.setBrightness(255-(36*i));\r\n        colorChange(strip.Color(R, G, B));\r\n        delay(wait);\r\n      }\r\n      for(i=0; i&lt;7; i++) {\r\n        strip.setBrightness(0+(36*i));\r\n        colorChange(strip.Color(R, G, B));\r\n        delay(wait);\r\n      }\r\n      break;  \r\n  }\r\n}\r\n\r\n\/\/ Input a value 0 to 255 to get a color value.\r\n\/\/ The colours are a transition r - g - b - back to r.\r\nuint32_t Wheel(byte WheelPos) {\r\n  WheelPos = 255 - WheelPos;\r\n  if(WheelPos &lt; 85) {\r\n   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);\r\n  } else if(WheelPos &lt; 170) {\r\n    WheelPos -= 85;\r\n   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);\r\n  } else {\r\n   WheelPos -= 170;\r\n   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);\r\n  }\r\n}\r\n\/\/ Set the number of LEDs that will be used\r\nvoid LESsetup(int l) {\r\n  uint16_t t=0;\r\n  while(l){\r\n    t++;\r\n    if (digitalRead(C_BUTTON) == LOW) {\r\n        delay(250);\r\n        LEDs += 1;\r\n        t=0;\r\n    } \r\n    if (digitalRead(P_BUTTON) == LOW) {\r\n      delay(250);\r\n      LEDs -= 1;\r\n      t=0;\r\n    } \r\n    for(uint16_t i=0; i&lt;strip.numPixels(); i++) {\r\n      if (i&lt;LEDs){\r\n        strip.setPixelColor(i, strip.Color(50, 50, 50));\r\n      }else{\r\n        strip.setPixelColor(i, strip.Color(0, 0, 0));\r\n      }\r\n    }\r\n    strip.show();\r\n    if (t&gt;1000){\r\n      EEPROM.update(0, LEDs);\r\n      l=0;\r\n    }\r\n  }\r\n}\r\nISR(PCINT0_vect) {\r\n        STrigger = 1;\r\n}<\/pre>\n<p>Now I just need to save the color and mode to EEPROM, but I will save that for another day \ud83d\ude42<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Share this:<\/h3><div class=\"sd-content\"><ul><li class=\"share-print\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-print sd-button share-icon\" href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/\" target=\"_blank\" title=\"Click to print\"><span>Print<\/span><\/a><\/li><li class=\"share-email\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-email sd-button share-icon\" href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/?share=email\" target=\"_blank\" title=\"Click to email this to a friend\"><span>Email<\/span><\/a><\/li><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-1341\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/?share=facebook\" target=\"_blank\" title=\"Click to share on Facebook\"><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-1341\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/?share=twitter\" target=\"_blank\" title=\"Click to share on Twitter\"><span>Twitter<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>Tonight I got some real headway on my small LED driver. I added the ability to change the number of NeoPixels that are displayed, then update the onboard flash memory so that the ATtiny remembers what you selected even after a power cycle. So now if you press and hold either of the two buttons, &hellip; <a href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Coding for the LEDiva\u2122<\/span><\/a><\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Share this:<\/h3><div class=\"sd-content\"><ul><li class=\"share-print\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-print sd-button share-icon\" href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/\" target=\"_blank\" title=\"Click to print\"><span>Print<\/span><\/a><\/li><li class=\"share-email\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-email sd-button share-icon\" href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/?share=email\" target=\"_blank\" title=\"Click to email this to a friend\"><span>Email<\/span><\/a><\/li><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-1341\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/?share=facebook\" target=\"_blank\" title=\"Click to share on Facebook\"><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-1341\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/www.richa1.com\/RichardAlbritton\/coding-for-the-lediva\/?share=twitter\" target=\"_blank\" title=\"Click to share on Twitter\"><span>Twitter<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[57,59,56,64,61],"tags":[97,96],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5AhH6-lD","_links":{"self":[{"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/posts\/1341"}],"collection":[{"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/comments?post=1341"}],"version-history":[{"count":4,"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/posts\/1341\/revisions"}],"predecessor-version":[{"id":1507,"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/posts\/1341\/revisions\/1507"}],"wp:attachment":[{"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/media?parent=1341"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/categories?post=1341"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.richa1.com\/RichardAlbritton\/wp-json\/wp\/v2\/tags?post=1341"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}