Rotary encoder attiny85 neopixel color wheel

Rotary encoder attiny85 neopixel color wheel ti permette di realizzare un nuovo effetto con la rotazione dell’encoder ed il controllo diretto dei NeoPixel WS2812B

Rotary encoder attiny85 neopixel color wheel

Leggendo il precedete articolo hai visto il controllo della rotazione dei led dell’anello a 24 neopixel WS2812B con u unico colore dal led #1 al led #23.

In questo articolo usi un array multidimensionale con l’IDE Arduino per definire la matrice colori da eseguire con il rotary encoder attiny85 neopixel ring 24 WS2812B .. in pratica l’effetto color wheel.

Definizione dei colori del Rotary encoder attiny85 neopixel color wheel

Per definire i colori da utilizzare puoi servirti dello strumento grafico con cui sei più comodo ( es. inkscape ) o di validi strumenti online.

Ciò di cui hai bisogno è solo la “color wheel” da cui selezionare i valori RGB che vuoi inserire nella matrice o array multidimensionale.

Io ho scelto il nero come primo colore, per il quale non è necessario alcuno strumento grafico è dato dai valori r=0,g=0,b=0; poi ho selezionato i 7 colori partendo dal 38,114,184 ( r,g,b ):

Rotary encoder attiny85 neopixel color wheel 38_114_184

e successivamente il 75,38,184:

Rotary encoder attiny85 neopixel color wheel 75_38_184

come terzo colore ho scelto il 184,38,174:

Rotary encoder attiny85 neopixel color wheel 184_38_174

e come quarto il 214,28,56:

Rotary encoder attiny85 neopixel color wheel 214_28_56

quinto 250,189,5:

Rotary encoder attiny85 neopixel color wheel 250_189_5

sesto 159,230,38:

Rotary encoder attiny85 neopixel color wheel 159_230_38

ed infine il settimo 38,230,163:

Rotary encoder attiny85 neopixel color wheel 38_230_163

quindi il colore di chiusura non poteva che essere il bianco 255,255,255 in contrapposizione al nero di apertura.

Creazione dell’array multidimensionale

L’array multidimensionale è semplicemente un array primario in cui ogni elemento dellarray stesso è a sua volta un array invece di essere un valore singolo.

In particolare con l’IDE arduino ed in questo esempio ho usato come indice di entrambi gli array quello numerico generato dalla posizione degli elementi negli array stessi.

Ecco come si presenta nell’IDE:

byte wheel[][3] = 
{ 
   {0,0,0},
   {38,114,184}, 
   {75,38,184}, 
   {184,38,174}, 
   {214,28,56}, 
   {250,189,5}, 
   {159,230,38}, 
   {38,230,163},
   {128,128,128}
};

Inoltre nota che la struttura è composta da un array primario di 9 elementi, gli otto colori più il nero iniziale per avere tutti i led spenti e ciascun elemento dell’array è composto da un array di tre valori corrispondenti ai R,G e B da inviare al led.

Il tipo di array, come per le variabili, va definito anteponendo la definizione al nome arbitrario, nell’esempio “wheel” ed è in funzione del tipo di dato che dovrà contenere. Nell’esempio essendo R,G e B valori da 0 a 255 puoi utilizzare la definizione byte.

Sketch Rotary encoder attiny85 neopixel color wheel

Riporto tutto lo sketch, anche se i cambiamenti rispetto al precedente sono davvero minimi:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define encA 3
#define encB 4
#define swtc 1
#define PIN  2
#define NUMPIXELS      24

volatile byte currentValue = 0;
volatile int  lastEncoded  = 0;
volatile byte mybrightness = 128;

byte wheel[][3] = 
{ 
   {0,0,0},
   {38,114,184}, 
   {75,38,184}, 
   {184,38,174}, 
   {214,28,56}, 
   {250,189,5}, 
   {159,230,38}, 
   {38,230,163},
   {128,128,128}
};

Adafruit_NeoPixel pixels=Adafruit_NeoPixel(NUMPIXELS,PIN,NEO_GRB+NEO_KHZ800);

void setup() {
    pinMode(encA, INPUT);
    pinMode(encB, INPUT);
    pinMode(swtc, INPUT);
    digitalWrite(encA, HIGH);
    digitalWrite(encB, HIGH);
   
    GIMSK = 0b00100000;       // Enable pin change interrupts
    PCMSK = 0b00011010;       // Enable pin PB3 and PB4 and PB1
    sei();                    // Turn on interrupts
    
    pixels.setBrightness(mybrightness);
    pixels.begin();
}
 
void loop() {
    // 32=8 giri / 64=4 giri / 128=2 giri
    byte numLed = ((currentValue*NUMPIXELS/32)%NUMPIXELS);
    if (currentValue==255) numLed+=1;
    // numero giro 1,2,...
    byte ln = ((currentValue*NUMPIXELS/32)/NUMPIXELS)+1; 
    for(int i=0;i<numLed;i++) { 
       pixels.setPixelColor(i, wheel[ln][0],wheel[ln][1],wheel[ln][2], mybrightness); 
    }
    ln -= 1;
    for(int i=numLed;i<NUMPIXELS;i++) { 
       pixels.setPixelColor(i, wheel[ln][0],wheel[ln][1],wheel[ln][2], 0); 
    }
    pixels.show();

    delay(20);
}

ISR(PCINT0_vect) {
  byte MSB=digitalRead(encA); //MSB=most significant bit
  byte LSB=digitalRead(encB); //LSB=least significant bit
  
  int encoded = (MSB << 1) |LSB;
  int sum  = (lastEncoded << 2) | encoded;
 
  if(sum==0b1101||sum==0b0100||sum==0b0010||sum==0b1011) currentValue++;
  if(sum==0b1110||sum==0b0111||sum==0b0001||sum==0b1000) currentValue--;
  
  lastEncoded = encoded; //store this value for next time
}

riprendendo le parti cambiate trovi che la prima modifica riguarda l’array, vedi paragrafo precedente, nelle linee da 16-27; i successivi cambiamenti riguardano la funzione loop();

linea 48: calcola il led da accendere, come nel precedente caso mostrato ma lo fa con una formula nuova in cui il valore letto sul potenziometro moltiplicato per il numero di led definiti alla linea 10 viene diviso per un valore da 32 a 128 in funzione di quanti giri vuoi eseguire e calcolato il modulo, ossia il resto, della divisione per il numero di pixel. Attenzione il % ( modulo ) restituisce il valore del resto e non il risultato della divisione, fai riferimento alle funzione matematiche sul sito arduino.cc

linea 49: per ottenere l’accensione anche dell’ultimo led al termine dell’ottavo giro è necessario aggiungere il valore 1 al numero di led quando l’encoder raggiunge il limite superiore ossia il valore 255 ( byte );

linea 51: calcola il numero di giri eseguiti in funzione del valore letto sul potenziometro, per farlo usa la formula in cui il valore letto dall’encoder lo moltiplichi per il numero di led e dividi per il medesimo coefficiente definito alla linea 48, in modo da avere una corrispondenza tra i due valori calcolati, e poi dividi per il numero di pixel.

Attenzione: questa volta è una divisione ed il valore restituito è il risultato dell’operazione.

Al risultato somma 1 in quanto inizi a contare dal primo giro e non dal giro 0;

linea 52: è invariata;

linea 53: applica il colore al led da accendere valorizzando i campi R,G,B con valori recuperati dalla matrice il cui primo campo tra [ln] è dato dal numero di giro in cui sei, calcolato alla linea 51, ed il secondo valore è la posizione di r,g e b nella matrice, rispettivamente 0,1,2;

linea 56: calcola il valore precedente di ln con la formula ln -= 1 per indicare il colore che devono avere i led restanti;

linee 57-59: applica i valori calcolati alla linea precedente ai led restanti della rotary encoder attiny85 neopixel color wheel;

linee 60-76: restano invariate e si occupano della visualizzazione del colore sui led e dell’acquisizione dei valori da 0 a 255 dell’encoder.

Il video dell’Rotary encoder attiny85 neopixel color wheel

Il video mostra sia come scorrono gli 8 colori sulla ruota facendo ruotare l’encoder in senso orario sia come i colori precedenti siano visualizzati facendo ruotare l’encoder in senso antiorario:

Puoi provare ad aggiungere più valori alla lettura dell’encoder ed impostare molti più colori dei neopixel ring.

Cortesemente, prima di inserire i commenti leggi il regolamento

Permanent link to this article: http://www.mauroalfieri.it/elettronica/rotary-encoder-attiny85-neopixel-color-wheel.html

Lascia un commento

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.