Buongiorno, ho acquistato una striscia a led neopixel con 12 led. Vorrei fare in modo che premendo un pulsante si cambino i colori e ruotando un potenziometro si vari la luminosità.
Ho provato a guardare gli esempi della libreria Adafruit e sono riuscito a modificare l'intensità dei colori mappando il potenziometro.
E sono riuscito anche a cambiare i colori ma mai tutto insieme.
Non conosco la programmazione per cui mi sono basato sullo sketch buttoncyler, purtroppo però o cambio colore o riduco la luminosità.
Potreste aiutarmi? sto cercando di illuminare una litofania da regalare a Natale.
Grazie
Il colore lo cambi cambiando il rapporto tra i tre colori fondamentali, quindi una determinata tripletta RGB ti da un certo colore. Per cambiare l'intensità devi variare proporzinalmente tutti e tre i colori quindi, se vuoi diminuire del 50% l'intensità, devi calare del 50% ogni singolo colore del singolo LED.
Esempio ... 255, 255, 255 ti da bianco ... se vuoi ridurre a metà fai 128, 128, 128.
Ricorda però che, come abbiamo detto molte volte (e, se cerchi, trovi varie discussioni) l'occhio umano NON è affatto lineare, per cui NON vedrai quello che ti aspetti, ma un qualche altra cosa dovuto alla NON linearità dell'occhio. Inolte, altro "difetto" umano, l'occhio NON è sensibile in uguale misura ai vari colori (R,G,B) quindi ... questo introduce un'altro errore di visione ripetto alla reltà oggettiva se si effettuano misure con strumenti.
Guglielmo
#include <Adafruit_NeoPixel.h>
#define BUTTON_PIN 2
#define PIXEL_PIN 10 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 12 // number of neopixel (change this accordingly)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
bool oldState = HIGH;
int showType = 0;
int sensorValue = A0;
int currentColourValue;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin();
strip.setBrightness(255);
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
// Get current button state.
bool newState = digitalRead(BUTTON_PIN);
//adjust brightness here
currentColourValue = ( map( analogRead(sensorValue), 0, 1023, 0, 255 ) );
// Check if state changed from high to low (button press).
if (newState == LOW && oldState == HIGH) {
// Short delay to debounce button.
delay(20);
// Check if button is still low after debounce.
newState = digitalRead(BUTTON_PIN);
if (newState == LOW) {
showType++;
if (showType > 3)
showType=0;
startShow(showType);
}
}
// Set the last button state to the old state.
oldState = newState;
}
void startShow(int i) {
switch(i){
case 0: colorWipe(strip.Color(0, 0, 0), 50);// Black/off
break;
case 1: colorWipe(strip.Color(currentColourValue, 0, 0), 50); // Red
break;
case 2: colorWipe(strip.Color(0,currentColourValue , 0), 50); // Green
break;
case 3: colorWipe(strip.Color(0, 0, currentColourValue), 50); // Blue
break;
}
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
Grazie Guglielmo.
Questo è il codice, che come vedi mi legge il potenziometro solo una volta perché poi quando premo il pulsante e cambio colore, il programma va in "break" attendendo una successiva pressione del pulsante.
Vorrei fare in modo invece che non si fermasse il loop e che quindi girando il potenziometro riesca a cambiare l'intensità del colore del led.
Qualche aiuto?
Grazie
GianRav:
Questo è il codice, che come vedi mi legge il potenziometro solo una volta perché poi quando premo il pulsante e cambio colore, il programma va in "break" attendendo una successiva pressione del pulsante.
Vorrei fare in modo invece che non si fermasse il loop e che quindi girando il potenziometro riesca a cambiare l'intensità del colore del led.
Qualche aiuto?
Qualche consiglio sparso...
- l'istruzione (che hai usato nel setup) setBrightness() non ti dice nulla?
- i nomi delle variabili dovrebbero rispettare ciò che la variabile è "destinata" a fare
- l'istruzione digitalRead()... legge un registro del microntrollore. E' del tutto inutile usare una variabile che è solo una copia di quanto già disponibile e come nel tuo caso complica inutilmente lo sketch facendoti fare dei voli pindarici che potevi tranquillamente evitare
- ad esempio, era davvero necessario tutto quel giro per eseguire le istruzioni solo sul fronte quando basta un debounce?
#include <Adafruit_NeoPixel.h>
#define BUTTON_PIN 2
#define PIXEL_PIN 10 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 12 // number of neopixel (change this accordingly)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
int showType = 0;
const int POT = A0;
int lastPot;
int currentColourValue;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin();
strip.setBrightness(255);
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
// Cambio intensità solo se il potenziometro è stato effettivamente mosso (abs() resituisce il valore assoluto)
if (abs(lastPot - analogRead(POT)) > 5) {
lastPot = analogRead(POT) ;
currentColourValue = map( analogRead(POT), 0, 1023, 0, 255 );
}
// lettura del pulsante con semplice debounce senza delay()
static uint32_t bounceTime;
if ( (digitalRead(BUTTON_PIN) == LOW) && (millis() - bounceTime > 100) )
{
// Memorizzo il momento in cui il pulsante è stato premuto cosi da poterlo confrontare nel ciclo successivo
bounceTime = millis();
/////////////////////////////////
/*
showType++;
if (showType > 3) {
showType=0;
}
///////////////////////////////////
*/
// tutto questo blocco può essere sostitito con:
showType = (showType + 1) % 4;
startShow(showType);
}
}
void startShow(int i) {
switch (i) {
case 0: colorWipe(strip.Color(0, 0, 0), 50);// Black/off
break;
case 1: colorWipe(strip.Color(currentColourValue, 0, 0), 50); // Red
break;
case 2: colorWipe(strip.Color(0, currentColourValue , 0), 50); // Green
break;
case 3: colorWipe(strip.Color(0, 0, currentColourValue), 50); // Blue
break;
}
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
Grazie cotestatnt per i suggerimenti. Anche io avevo pensato a millis per il debounce del pulsante, ma il problema era un altro: riuscire a modificare la luminosità dei led sempre, mentre così, anche con il tuo sketch, leggo il valore del potenziometro e quello rimane quando vado a premere il pulsante ed illuminare i led.
Se scelgo di visualizzare un singolo colore, posso tranquillamente modificare la luminosità con il potenziometro. Io vorrei riuscirci con più colori.
... ma perche' non "sprecare" un condensatore da 100n ed una resistenza da 10K, cosi ci si levano i debounce software del tutto dai co...riandoli ? ...
Anzi, dato che parliamo di sprechi, aggiungiamo pure un'altra costosissima resistenza da 100 ohm, cosi lo facciamo il meglio possibile, sto debounce hardware ...
EDIT: e se si usano le pullup interne si risparmia pure la resistenza da 10K
GianRav:
leggo il valore del potenziometro e quello rimane quando vado a premere il pulsante ed illuminare i led.
Non avevo capito bene allora...
Tu vuoi che la variazione di luminosità sia continua e globale? Ed allora a maggior ragione l'istruzione corretta da usare è setBrightness() quindi invece di modificare la variabile currentColourValue che agisce solo sul singolo colore usane una per memorizzare il brightness e che andrai a modificare ogni volta che il potenziometro viene spostato.
Per quanto riguarda la continuità della variazione, dovrebbe essere sufficiente spostare l'istruzione strip.show(); nel loop principale.
I colori puoi anche definirli come costanti unsigned long:
#define RED 0xFF0000
#define GREEN 0x00FF00
#define BLUE 0x0000FF
#define YELLOW 0xFFFF00
#define CYAN 0x00FFFF
#define MAGENTA 0xFF00FF
etc etc ....
Etemenanki:
cosi ci si levano i debounce software del tutto dai co...riandoli ? ...
Sono d'accordo Etemenanki, ma per una rapida prototipazione, magari su breadboard dove lo spazio non basta mai, il debounce software secondo me torna utile ed è "pratico", poi magari sul circuito definitivo si fanno le cose per bene senza dubbio!
Mah... Certe volte stiamo a faticare per risparmiare FLASH e RAM, spostando anche da RAM a FLASH, ma fa fatica aggiungere un piccolo condensatore per alleggerire il software, togliendosi problemi dai co...techini e dai panettoni (per essere in tema con il periodo corrente)!
Vero che e' pratico se manca spazio, ma potrebbe introdurre problemi se non implementato correttamente ...
Poi magari il programma non funziona regolarmente e si da la colpa a qualcos'altro perche' al semplice debounce non ci si pensa proprio ...
Peraltro ormai le breadboard costano relativamente poco (basta prenderne due o tre alla volta) ... si comincia con le prime due o tre, poi c'e' l'assuefazione e se ne vogliono sempre di piu, sempre di piu, sempre di piu ...
Io ero arrivato a 28 (un pannello da 7x4 incollate su una vecchia lastra di plexiglass trovata di scarto da un'insegna rotta per tenerle rigide) ... e ci stava su un po di tutto, perfino i miei accrocchi mostruosi ... poi qualche anno fa ha avuto uno sfortunato incontro con un saldatore scivolato da un supporto mentre non ero presente, ed ora quello che ne rimane ha formato tre diversi pannelli piu piccol, da 2, 5 e 18 pezzi, ma comunque sempre validi ...
Buonasera, volevo ringraziarvi per il vostro aiuto prezioso.
Sono riuscito ad ottenere esattamente l'effetto che volevo.
Siete mitici!
#include <Adafruit_NeoPixel.h>
#define BUTTON_PIN 2
#define PIXEL_PIN 10 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 12 // number of neopixel (change this accordingly)
#define RED 0xFF0000
#define GREEN 0x00FF00
#define BLUE 0x0000FF
#define YELLOW 0xFFFF00
#define CYAN 0x00FFFF
#define MAGENTA 0xFF00FF
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
int showType = 0;
const int POT = A0;
int lastPot;
int brightness;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin();
strip.setBrightness(240);
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
// Cambio intensità solo se il potenziometro è stato effettivamente mosso (abs() resituisce il valore assoluto)
if (abs(lastPot - analogRead(POT)) > 5) {
lastPot = analogRead(POT) ;
brightness = map( analogRead(POT), 0, 1023, 5, 240 );
strip.setBrightness(brightness);
strip.show();
}
// lettura del pulsante con semplice debounce senza delay()
static uint32_t bounceTime;
if ( (digitalRead(BUTTON_PIN) == LOW) && (millis() - bounceTime > 50) )
{
// Memorizzo il momento in cui il pulsante è stato premuto cosi da poterlo confrontare nel ciclo successivo
bounceTime = millis();
// tutto questo blocco può essere sostitito con:
showType = (showType + 1) % 8;
startShow(showType);
}
}
void startShow(int i) {
switch (i) {
case 0: colorWipe(strip.Color(0, 0, 0), 50);// Black/off
break;
case 1: colorWipe(RED, 50);
break;
case 2: colorWipe(GREEN, 50);
break;
case 3: colorWipe(BLUE, 50);
break;
case 4: colorWipe(YELLOW, 50);
break;
case 5: colorWipe(CYAN, 50);
break;
case 6: colorWipe(MAGENTA, 50);
break;
case 7: colorWipe(strip.Color(255, 192, 203), 50);
break;
}
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
Grazie a tutti e Buone Feste
Ciao,
ho scaricato il tuo codice, poichè avrei la necessità di realizzare qualcosa di simile, quindi l'ho preso come punto di partenza.
Però, ho una certa difficoltà nella gestione dei colori;
ovvero, se creo nuovi colori, come #define o direttamente all'interno dei cavi case, ed agisco sul potenziometro per dimmare, i nuovi colori creati cambiano puntando verso il loro colore base.
faccio un esempio, se creo un arancio, ed agisco sul dimmer, questo diventa rosso.
avete una soluzione?
p.s. essendo un circuito prova, sto alimentando i 4 led neopixel ed il potenziometro, direttamente da arduino.
danke
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.