Hodiny z NeoPixel Ring - prispôsobenie jasu okolitému osvetleniu

Zápisník experimentátora

Hierarchy: WS2812

V druhom článku na tému hodín z NeoPixel Ring sa pozrieme na prispôsobenie jasu diód ku okolitému osvetleniu. Pomocou fotorezistora budeme merať intenzitu osvetlenia a pomocou plávajúceho priemeru budeme túto hodnotu vyhladzovať, aby nám hodiny nekmitali pri každom malom tieni, ktorý prejde ponad fotorezistor.

Základom budú dva články, ktoré som na túto tému napísal:

  • Meranie intenzity svetla cez fotorezistor - Fotorezistor funguje tak, že podľa intenzity svetla mení svoj odpor. Preto je možné ho skombinovať s iným rezistorom a vytvoriť deličku napätia. Toto napätie môžeme merať a získať tak intenzitu osvetlenia pomocou analógového vstupu.
  • Vyhladzovanie analógového merania pomocou plávajúceho priemeru - Aj keď je fotorezistor označovaný za pomaly reagujúci, jeho pomalosť nie je až taká pomalá a už pohyb rukou ponad fotorezistor vyvoláva viditeľné odchylky. Keďže nechceme, aby nám každá okololetiaca mucha ovplyvňovala intenzitu LED diód, použijeme vyhladenie pomocou plávajúceho priemeru.

​Schéma

Voči predchádzajúcej schéme sa na obrázku zmenilo len to, že do nej pribudol jeden fotorezistor a jeden rezistor 10k. Je to zapojené tak, že Vcc sa pripojí na fotorezistor, delička napätia na analógový vstup A0 a opačná strana deličky sa pripojí na Gnd. Hodnota rezistora 10k je univerzálna a zaručí nám dobré rozpätie meraného signálu. Meraný signál bude vďaka tomuto zapojeniu malý pri tme a veľký pri jasnom svetle.

Program

V programe pribudlo niekoľko nových premenných. Premenná ma je nastavená tak, aby pri meraní každých 500 ms priemerovala posledných 64 hodnôt. To nám vytvára časový úsek 32 s, ktoré slúžia na získanie priemernej hodnoty. To je dostatočne dlho na to, aby nebol jas diód ovplyvňovaný náhodnými chybami a celý systém nám vďaka tomu nekmital.

// measure every 500 ms
#define STEPTIME 500
unsigned long lasttime=0;
// 64 items in buffer=32 s until full adaptation to light level
MovingAverage<uint16_t,64> ma;

///
/// Main loop
///
void loop()
{
// measure light every 500 ms
unsigned long ms=millis();
if(ms>lasttime)
  {
  uint16_t sv = analogRead(A0);
  ma.Push(sv);
  uint16_t sva = ma.MA();
  int svc=constrain(sva,300,900); // below 300 is always darkest brightness
  int m=map(svc,300,900,1,100); // we map this brightness to maximum value of brightness=100
  strip.setBrightness(m); // brightness 100 is enough on direct sun
  lasttime=ms+STEPTIME;
  }

clock.Update();
clock.Draw();
}

Meranie jasu je predradené nastavovaniu jednotlivých diód. Celý kód slúži na to, aby sme nameranú a spriemerovanú hodnotu osvetlenia najprv dostali do intervalu <300,900>. Všetko tmavšie alebo jasnejšie nemá pre nás význam a orežeme to na nastavené hranice.

Následne tento interval premapujeme na interval <1,100>. 1 nám zaručí, že pri minimálnom osvetlení budú diódy aspoň trochu svietiť. Hodnota 100 je rozumný kompromis maximálneho jasu LED, pretože nad touto hranicou už sú diódy príliš jasné a sú nepríjemné na oči.

Po premapovaní sa získaná hodnota použije ako parameter do funkcie setBrightness, ktorá nastaví celý systém na jednotnú intenzitu. V kóde si ešte všimnite, že ako základné farby používam teraz intenzívnejšie farby, pretože sú pomocou funkcie automaticky skorigované na konkrétne hodnoty podľa okolitého osvetlenia. Výsledkom je príjemne sa adaptujúce osvetlenie hodín, ktoré je dobre viditeľné aj v tme, aj na jasnom slnku.



Download

10.08.2015


Menu