Taglio corto del codice di routine neopixel
Ho lavorato su un misuratore di livello con una striscia neopixel (WS2812).
Il codice è molto semplice: leggere un potenziometro, mappare l'ingresso e mostrare l'uscita nella striscia led.
Fin qui tutto bene. Il codice che includo di seguito funziona bene ma, ovviamente, brutto e ripetitivo. Poiché la mia conoscenza della programmazione è molto debole, mi chiedo se esista un modo loop per tagliare il codice breve. Si prega di notare che i sette led hanno colori diversi. In realtà questo è il punto di confusione per me per costruire un ciclo. Qualche idea, gente?
Sì, so anche che usare così tanti ritardi non è la soluzione più elegante, ma non compromette le prestazioni del dispositivo e il led della barra che appare è piuttosto carino.
void leveller () {
int millivolts;
int level;
millivolts = analogRead(A3);
level = map(millivolts, 0, 1024, 0, 7);
if (level <=0){
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
strip.show ();
}
else if ((level > 0)&&(level<1)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
}
else if ((level>= 1)&&(level<2)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
}
else if ((level>= 2)&&(level<3)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
}
else if ((level>= 3)&&(level<4)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(4, 0, 128, 0);
delay(30);
strip.show ();
}
else if ((level>= 4)&&(level<5)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(4, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(5, 0, 128, 0);
delay(30);
strip.show ();
}
else if ((level>= 5)&&(level<6)) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(4, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(5, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(6, 0, 128, 32);
delay(30);
strip.show ();
}
else if (level>= 6) {
strip.clear();
strip.setPixelColor(0, 128, 0, 0);
delay(30);
strip.show ();
strip.setPixelColor(1, 128, 32, 0);
delay(30);
strip.show ();
strip.setPixelColor(2, 128, 64, 0);
delay(30);
strip.show ();
strip.setPixelColor(3, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(4, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(5, 0, 128, 0);
delay(30);
strip.show ();
strip.setPixelColor(6, 0, 128, 32);
delay(30);
strip.show ();
strip.setPixelColor(7, 0, 128, 64);
delay(30);
strip.show ();
}
}
Risposte
Innanzitutto, una piccola osservazione:
if ((level > 0)&&(level<1))
level è un numero intero e non esiste un numero intero strettamente maggiore di zero e minore di uno.
if ((level>= 1)&&(level<2))
C'è solo un numero intero che verifica questa condizione. Sarebbe più chiaro quindi scrivere solo
if (level == 1)
Ora, per la tua vera domanda: un trucco che spesso funziona per abbreviare il codice ripetitivo è trasformare il codice in dati, archiviare i dati in array ed eseguirli con loop. Qui la sequenza di colori può essere memorizzata in un array:
const uint8_t colors[8][3] = {
{128, 0, 0},
{128, 32, 0},
{128, 64, 0},
{ 0, 128, 0},
{ 0, 128, 0},
{ 0, 128, 0},
{ 0, 128, 32},
{ 0, 128, 64},
};
È quindi possibile chiamare setPixelColor()all'interno di un ciclo che attraversa l'array. Poiché il punto finale del ciclo dipende dal livello misurato, potrebbe essere scritto in questo modo:
void leveller() {
int level = map(analogRead(A3), 0, 1024, 1, 9);
strip.clear();
for (int i = 0; i < level; i++) {
const uint8_t *color = colors[i];
strip.setPixelColor(i, color[0], color[1], color[2]);
strip.show();
delay(30);
}
}
Si noti che, poiché l'output di analogRead()è sempre inferiore a 1024, la variabile levelsarà sempre inferiore a 9, ovvero assumerà valori compresi tra 1 e 8 inclusi. E questo è il numero di colori che verranno mostrati.