Stap 2: OnePixel klok
Vanwege de aard van de RGB LED's geen u donkere kleuren op hen: er is niet zoiets als een bruin LED. Ook wil je altijd de rijkste, meest verzadigde kleuren. Dus wat we met zitten hier is de cirkel van het spectrum in uniforme helderheid, en we moeten uittreksel uit het de maximale hoeveelheid onmiskenbaar duidelijke kleuren. Deze kleuren moeten worden moeiteloos en onmiddellijk verteld uit elkaar: wat is het nut zal onze klok worden als het laat ruimte voor twijfel? Ik heb een heleboel tijd experimenteren, zelf overtuigen en proberen te persen uit de LEDs meer dan ze kunnen doen, en moest uiteindelijk toegeven: er zijn slechts zes gemakkelijk, absoluut en zonder twijfel te onderscheiden RGB LED kleuren:
Rood, oranje, groen, cyaan, blauw en Magenta.
Waarom oranje en niet geel? Omdat geel op een enkele LED teveel groen lijkt en niet gemakkelijk te herkennen zonder verwijzing is. Je kan zien voor jezelf: Schrijf een eenvoudige schets een RGB LED van rood (255, 0, 0) wijzigen naar geel (127, 127, 0) elke seconde. U ziet een rode en groene kleuren.
Terwijl zes een goed nummer voor het omgaan met klokken is, was het niet voldoende voor mijn behoeften. Het is mogelijk om iets te knijpen in de paarse bereik, wat resulteert in zeven kleuren, maar dat zal niet precies helpen met een klok. Dus besloten heb ik om een extra set van tien kleuren te gebruiken voor de taken waar een foutje (verwarrend naburige tinten) aanvaardbaar is:
Rood, oranje, geel, groen, aquamarijn, Gifgroen, Blue, Purple, Fuchsia en wit.
(de namen zijn onder voorbehoud, natuurlijk. Enkel mooie woorden. Het is in feite meer als cyaan-groen, cyaan-blauw, blauw-magenta, rood-magenta, enz. Zie de tabel in de schets hieronder).
De witte is op deze lijst, want het is niet definitief. Als het is niet een kleur, maar in feite een gebrek aan elke tint, het laat veel aan verbeelding en kan gemakkelijk worden verward met iets anders (vooral, cyaan). Wat is meer, zoals een RGB LED maakt wit uit de combinatie van de drie basiskleuren, in feite lijkt het anders afhankelijk van een kijkhoek: als je kijkt naar de LED van het ene punt u ziet meer rood, van erg verschilt – meer groene enz.
De laatste belangrijke 'kleur' (of, juister, het gebrek daaraan) is 'zwart'. Terwijl het niet kan geen bruikbare gegevens overbrengen (omdat het ziet er hetzelfde uit als een LED draaide-off van) is het zeer nuttig als een scheidingsteken.
Dus ik had twee sets van kleuren. Terwijl aanvankelijk ik hoopte te maken van een intuïtieve analoge klok was het duidelijk tegen die tijd dat ik zal moeten houden met digitale. Dat wil zeggen, met tonen van cijfers met gekleurde codes. De twee sets zijn natuurlijk, ideaal voor het tonen van minuten (of seconden): één van de zes kleuren tientallen kunt weergeven, de tien-kleur is goed voor degenen (als het is niet een groot probleem als u de aangrenzende kleuren verwarren – heb je gewoon een fout van één minuut). Slechts twee van een RGB-LED knippert.
Hoe zit het uur? Dezelfde benadering is niet goed hier: ten eerste de set met 10-kleuren is niet definitief genoeg, en ten tweede het display zal worden zonder opmaak saai met de dezelfde tientallen kleuren herhalen over en voorbij. Ik probeerde enkele oplossingen, maar toen keek op mijn horloge en het raakte me: als de normale wijzerplaat het aantal uren in een dag door twee delen kan (het tonen van 12 in plaats van 24) dan waarom kan niet ik hen verder verdelen? Immers, ik ben het maken van een slinger, niet een atoomklok. En, echt, kan men 6 uur met middernacht verwarren? Zodat de Conventie geboekt: een 'klok' van mijn OnePixel klok zullen de 6-uur, wat betekent dat dezelfde kleuren voor 12 en 6, 1 en 7, 2 en 8, enz. Dit Verdrag bleek zeer toereikend: de enige keer dat ik was niet in staat om te lezen het exacte tijdstip van de LED was op 1 januari en had meer te maken met de partij gisteren dan iets (ontwaakt, ik was niet in staat om te vertellen of het is donker al of nog steeds).
Hoewel het mogelijk is te correleren cijfers en kleuren op geen enkele manier, verkies ik te doen volgens het spectrum-geen behoefte om te onthouden om het even wat. Zie de grafieken hierboven.
Uiteindelijk toonde de slinger klok tijd in streepjes: één voor uren lang, twee korte degenen voor minuten. In het volgende jaar moet ik mijn huis vol met zeer verschillende varianten van hetzelfde apparaat, allermeest zij sport meer dan één LED, maar het principe bleef (Bekijk de video). Het enige wat ik niet zeker over tegenwoordig ben is de witte kleur voor 9: Ik denk dat ik wil het een beetje meer pinkyish om te voorkomen dat verwarring met cyaan. Het beter is om in te voegen tussen twee Cyaan tinten van de cyclus van 10-kleur wit kan zijn geweest, maar nu is het te laat voor mij, zoals ik al vrij gewend ben deze klokken zoals ze zijn.
Hier is een schets die toestaat u om tijd te zien op een één RGB LED op drie verschillende manieren (modi uitgeschakeld door een knop; de vierde modus zal worden beschreven in stap 4). U moet een externe klok-module. Als je er geen hebt mag u de bibliotheek van de tijd om te zetten uw Arduino in een tijd-keeping apparaat (aangepast de schets). Ik stel u krijg de RTC-module als u van plan bent te graven in de Arduino klokken-het is echt nogal goedkoop en handig.
<p>#include <Wire.h><br>#define RED 3 // pins the RGB LED is connected to #define GREEN 5 #define BLUE 6 #define BUTTON_PIN 7</p><p>int temperature; byte second, minute, hour; byte temperPos, prevPos, nextPos; byte r, g, b; byte mode = 0;</p><p>// sine wave array const uint8_t lights[360]={ 0, 0, 0, 0, 0, 1, 1, 2, //8 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 17, 18, 20, 22, 24, 26, 28, 30, 32, 35, 37, 39, //32 42, 44, 47, 49, 52, 55, 58, 60, 63, 66, 69, 72, 75, 78, 81, 85, //48 88, 91, 94, 97, 101, 104, 107, 111, 114, 117, 121, 124, 127, 131, 134, 137, //64 141, 144, 147, 150, 154, 157, 160, 163, 167, 170, 173, 176, 179, 182, 185, 188, //96 191, 194, 197, 200, 202, 205, 208, 210, 213, 215, 217, 220, 222, 224, 226, 229, 231, 232, 234, 236, 238, 239, 241, 242, 244, 245, 246, 248, 249, 250, 251, 251, 252, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 252, 251, 251, 250, 249, 248, 246, 245, 244, 242, 241, 239, 238, 236, 234, 232, 231, 229, 226, 224, 222, 220, 217, 215, 213, 210, 208, 205, 202, 200, 197, 194, 191, 188, 185, 182, 179, 176, 173, 170, 167, 163, 160, 157, 154, 150, 147, 144, 141, 137, 134, 131, 127, 124, 121, 117, 114, 111, 107, 104, 101, 97, 94, 91, 88, 85, 81, 78, 75, 72, 69, 66, 63, 60, 58, 55, 52, 49, 47, 44, 42, 39, 37, 35, 32, 30, 28, 26, 24, 22, 20, 18, 17, 15, 13, 12, 11, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // an array of pre-arranged RGB values // for 10mm RGB LED. byte RGBready[13][3] ={ {255, 0, 0}, // hour=0, min=0 {229, 26, 0}, // min=1 {201, 54, 0}, // hour=1 {181, 74, 0}, // min=2 {0, 255, 0}, // hour=2, min=3 {0, 218, 36}, // min=4 {0, 174, 81}, // hour=3 {0, 99, 156}, // min=5 {0, 0, 255}, // hour=4, min=6 {74, 0, 181}, // min=7 {131, 0, 124}, // hour=5 {196, 0, 59}, // min=8 {95, 78, 81}, // min=9 };</p><p>// These arrays point to exact colors of hours and minutes in RGBready // I use them because in my projects RGBready can hold more pre-arranged // colors than just clock (like thermometer). And it's easier. byte hourColor[6]={0,2,4,6,8,10}; byte minuteColor[10]={0,1,3,4,5,7,8,9,11,12};</p><p>void setup() { Wire.begin(); Serial.begin(9600); Serial.println("Starting"); pinMode(BUTTON_PIN, INPUT_PULLUP); // button connects to GND }</p><p>void loop() {</p><p>// get and print time getTime(); Serial.print("Time is "); Serial.print(hour); Serial.print(":"); Serial.print(minute); Serial.print(":"); Serial.print(second); Serial.println("."); hour %= 6; // convert hours to 6-hour 'clock face' //hour = minute%6; //minute = second;</p><p>// to change modes you should press and hold the button // (the reading happens between display cycles) // I decided against ISR here to keep the sketch to the point if (!digitalRead(BUTTON_PIN)) mode++;</p><p>mode %=4; // we have only three modes</p><p>switch (mode) { case 0: showTimeFades(); break; case 1: showTimeTransitions(); break; case 2: simpleMode(); break; case 3: analogClock(); break; } }</p><p>// the following two functions are used to get time from a DS3231 chip // they were salvaged from Time library I think // the Time library itself turns your Arduino into a clock, so if you // don't have an RTC module, you should download it // and change the getTime() function to work with it void getTime () { // the DS3231 RTC chip address is 0x68 Wire.beginTransmission(0x68); Wire.write(byte(0)); Wire.endTransmission();</p><p> Wire.requestFrom(0x68, 3, 1); // request first three bytes, close connection second = bcdToDec (Wire.read()); minute = bcdToDec (Wire.read()); hour = bcdToDec(Wire.read()); // we don't need any further information like weekday, year, etc // from the clock, so read only first 3 bytes. }</p><p>// Convert binary coded decimal to normal decimal numbers byte bcdToDec(byte val) { return ( (val/16*10) + (val%16) ); }</p><p>// The OnePixel clock modes // 1 - the mode I used on a garland void showTimeFades() { int delayVal = 4; // sets the overall display speed</p><p> // fade-in fade-out hours color for (int k=0; k<241; k++) { r = (uint16_t)(RGBready[hourColor[hour]][0]*lights[k])>>8; g = (uint16_t)(RGBready[hourColor[hour]][1]*lights[k])>>8; b = (uint16_t)(RGBready[hourColor[hour]][2]*lights[k])>>8; setRGBpoint (0, r, g, b); delay(delayVal); }</p><p> // fade-in fade-out minute-tens color for (int k=0; k<241; k++) { r = (uint16_t)(RGBready[hourColor[minute/10]][0]*lights[k])>>8; g = (uint16_t)(RGBready[hourColor[minute/10]][1]*lights[k])>>8; b = (uint16_t)(RGBready[hourColor[minute/10]][2]*lights[k])>>8; setRGBpoint (0, r, g, b); delay(delayVal>>1); // two times faster than hours }</p><p> // fade-in fade-out minute-ones color for (int k=0; k<241; k++) { r = (uint16_t)(RGBready[minuteColor[minute%10]][0]*lights[k])>>8; g = (uint16_t)(RGBready[minuteColor[minute%10]][1]*lights[k])>>8; b = (uint16_t)(RGBready[minuteColor[minute%10]][2]*lights[k])>>8; setRGBpoint (0, r, g, b); delay(delayVal>>1); // two times faster than hours } }</p><p>// 2 - sine wave transitions between colors void showTimeTransitions() { int delayVal = 4; // set transitions speed // fade-in for (int k=0; k<121; k++) { r = (uint16_t)(RGBready[hourColor[hour]][0]*lights[k])>>8; g = (uint16_t)(RGBready[hourColor[hour]][1]*lights[k])>>8; b = (uint16_t)(RGBready[hourColor[hour]][2]*lights[k])>>8; setRGBpoint (0, r, g, b); delay(delayVal); }</p><p> // transitions shiftColors(hourColor[hour], hourColor[minute/10], delayVal); delay(50); // briefly stop on the minute-tens value shiftColors(hourColor[minute/10], minuteColor[minute%10], delayVal); // fade-out for (int k=120; k<241; k++) { r = (uint16_t)(RGBready[minuteColor[minute%10]][0]*lights[k])>>8; g = (uint16_t)(RGBready[minuteColor[minute%10]][1]*lights[k])>>8; b = (uint16_t)(RGBready[minuteColor[minute%10]][2]*lights[k])>>8; setRGBpoint (0, r, g, b); delay(delayVal); } }</p><p>// 3 - the simplest possible mode, may be useful as a start for something void simpleMode() { int delayVal = 333; r = RGBready[hourColor[hour]][0]; g = RGBready[hourColor[hour]][1]; b = RGBready[hourColor[hour]][2]; setRGBpoint (0, r, g, b); delay(delayVal);</p><p> r = RGBready[hourColor[minute/10]][0]; g = RGBready[hourColor[minute/10]][1]; b = RGBready[hourColor[minute/10]][2]; setRGBpoint (0, r, g, b); delay(delayVal);</p><p> r = RGBready[minuteColor[minute%10]][0]; g = RGBready[minuteColor[minute%10]][1]; b = RGBready[minuteColor[minute%10]][2]; setRGBpoint (0, r, g, b); delay(delayVal);</p><p> setRGBpoint (0, 0, 0, 0); delay(delayVal>>1); }</p><p>void analogClock() { int delayVal = 8; for (int k=0; k<52; k++) { r = (float)(RGBready[hourColor[hour]][0]*(60-minute) + RGBready[hourColor[(hour+1)%6]][0]*minute)/60; g = (float)(RGBready[hourColor[hour]][1]*(60-minute) + RGBready[hourColor[(hour+1)%6]][1]*minute)/60; b = (float)(RGBready[hourColor[hour]][2]*(60-minute) + RGBready[hourColor[(hour+1)%6]][2]*minute)/60;</p><p> r = (uint16_t)(r*(lights[k]*2+30))>>8; g = (uint16_t)(g*(lights[k]*2+30))>>8; b = (uint16_t)(b*(lights[k]*2+30))>>8; setRGBpoint (0, r, g, b); delay(delayVal); } for (int k=51; k>0; k--) { r = (float)(RGBready[hourColor[hour]][0]*(60-minute) + RGBready[hourColor[(hour+1)%6]][0]*minute)/60; g = (float)(RGBready[hourColor[hour]][1]*(60-minute) + RGBready[hourColor[(hour+1)%6]][1]*minute)/60; b = (float)(RGBready[hourColor[hour]][2]*(60-minute) + RGBready[hourColor[(hour+1)%6]][2]*minute)/60;</p><p> r = (uint16_t)(r*(lights[k]*2+30))>>8; g = (uint16_t)(g*(lights[k]*2+30))>>8; b = (uint16_t)(b*(lights[k]*2+30))>>8; setRGBpoint (0, r, g, b); delay(delayVal); } delay(delayVal*30); }</p><p>// function for color shifting between // positions in the RGBready array. This one uses the // sine wave algorithm and lights[] pre-arranged array above // delayVal sets the speed of transition void shiftColors(byte cur, byte next, byte delayVal) { uint16_t color[3], nextColor[3]; long colorStep[3]; showRGBcolor(cur); // start with clear first color // calculate steps in unsigned int format to avoid using floats for (byte k=0; k<3; k++) { color[k] = RGBready[cur][k]<<8; nextColor[k] = RGBready[next][k]<<8; colorStep[k]=((long)nextColor[k] - color[k])/255; } // set colors in 120 (360/3) steps, converting back to bytes for (byte k=0; k<120;k++) { setRGBpoint(0, (color[0]+colorStep[0]*lights[k])>>8, (color[1]+colorStep[1]*lights[k])>>8, (color[2]+colorStep[2]*lights[k])>>8); delay(delayVal); } showRGBcolor(next); // finish with clear second color }</p><p>// two legacy functions to turn LEDs on. // I use them here to maintain consistency between example sketches // both codes are for common anode LEDs. If you use common cathode ones, // remove the '255-' bits. void setRGBpoint(uint8_t LED, uint8_t red, uint8_t green, uint8_t blue) { analogWrite(RED, 255-red); analogWrite(GREEN, 255-green); analogWrite(BLUE, 255-blue); }</p><p>void showRGBcolor(byte curLED) { analogWrite(RED, 255-RGBready[curLED][0]); analogWrite(GREEN, 255-RGBready[curLED][1]); analogWrite(BLUE, 255-RGBready[curLED][2]); }</p>
Let op de kleurentabel in de schets? Ik kom terug naar het in de laatste stap.