Comando striscia led rgb con potenziometro

Buonasera a tutti ed innanzitutto grazie per tutti i consigli che di volta in volta trovo su questo bel forum.
Ma non voglio farvi perdere troppo tempo, così passo direttamente alla domanda saliente.

Ho in mete un piccolo progetto che mi permette di comandare tre led, come se dovessero essere i tre colori di una striscia a led. Tutto questo con un potenziometro. Ora, come si vede spesso sui centri commerciali (IKEA compreso) esistono dei driver che permettono di variare il colore con un sistema tuch. Io vorrei avere lo stesso effetto usando però un potenziometro.

Avevo in mente di fare una cosa ben precisa.
Il potenziometro viene letto da arduino con un valore che va da 0 a 1023
I piedini pwm di arduino possono essere comandati con un valore che varia dallo 0 a 255

Quello che volevo fare io è semplicemente dividere il valore del potenziometro, in maniera che il PWM possa essere sfruttato totalmente, senza dover avere il valore al massimo. Diciamo quindi che girando il potenziometro di metà, vorrei che il led collegato all’uscita PWM si accenda completamente. Vi faccio un esempio:

Valore potenziometro 0 - 511 = valore PWM 0 -255

Per fare questa operazione ho provato ad usare la funzione Map, e poi a selezionare i valori del potenziometro con le funzioni If e Else, ma vuoi per ignoranza o forse per non aver provato abbastanza, non ci sono ancora riuscito.

Alla fine i valori per i tre led dovrebbero essere questi

R = 0 - 511
G = 255 - 765
B = 765 - 1023

In maniera che si accendano i tre led in sequenza, accavallandosi e cambiando così il colore di illuminazione.

Magari la risposta e molto semplice, ma che volete farci, non sono riuscito ancora ad arrivarci.
Possiedo buone conoscenze di elettrotecnica ed elettronica, ma poche di programmazione ed informatica.

Ciao, le soluzioni possono essere le più varie io utilizzerei tre if per valutare lo stato del potenziometro e all’interno degli if poi userei la map
Es.

pot=analogRead(A?);
if(pot<511){
   out1 = map(pot, 0, 511, 0, 255);
}
if(pot>255 && pot<765){
   out2 = map(pot, 255, 765, 0, 255);
}

Il codice non l’ho provato

P.S. = Leggi il regolamento, presentati nell’apposita sezione

Ok Grazie mille per lo Start che mi hai dato. Proverò subito e poi darò il riscontro.

Ed eccomi ancora, dopo qualche tempo a fare prove ed a cercare di fare il possibile con le mie forze. Sono riuscito ad ottenere più o meno quello che volevo. Usando le funzioni che mi erano state consigliate da Fabpolli.

Il tutto sembra funzionare in via teorica, il problema sorge quando si va a mettere il tutto in pratica.
Allego il codice intanto:

int ValorePot = 0;
int MappaturaUno = 0;
int MappaturaDue = 0;
int MappaturaTre = 0;
int MappaturaUnoD = 0;
int MappaturaDueD = 0;
int MappaturaTreD = 0;
int ledUno = 9;
int ledDue = 10;
int ledTre = 11;
void setup()
{
  Serial.begin(9600);
  pinMode (ledUno, OUTPUT);
  pinMode (ledDue, OUTPUT);
  pinMode (ledTre, OUTPUT);
}
 
void loop()
{

  
  //Lettura del pin analogico zero
  ValorePot = analogRead(0);
 
  
  //Accensione dell primo led, sulla lettura da 0 a 256 ascendente
  if (ValorePot <256){
  MappaturaUno = map(ValorePot, 0, 256, 0, 256);
  analogWrite(ledUno, MappaturaUno);
  }
  //Accensione del primo led, sulla lettura da 256 a 512 discendente
  if (ValorePot >256 && ValorePot <512){
  MappaturaUnoD = map(ValorePot, 255, 0, 256, 512);
  analogWrite(ledUno, MappaturaUnoD);
  }
  // Spegnimento del primo led quando si è fuori scala
  if (ValorePot >512){analogWrite (ledUno, 0 );}
  
  
  
  
  //Accensione del secondo led, sulla lettua da 256 a 512 ascendente
  if (ValorePot >256 && ValorePot <512){
  MappaturaDue = map(ValorePot, 0, 255, 256, 512);
  analogWrite(ledDue, MappaturaDue);
  }
  //Accensione del secondo led, sulla lettura da 512 a 768 discendente
  if (ValorePot >512 && ValorePot <768){
  MappaturaDueD = map(ValorePot, 255, 0, 512, 768);
  analogWrite(ledDue, MappaturaDueD);
  }
  // Spegnimento del secondo led quando si è fuori scala
  if (ValorePot <256){analogWrite (ledDue, LOW);}
  if (ValorePot >768){analogWrite (ledDue, LOW);}
  
  
  
  
  
  
  
  // Accensione del terzo led, sulla lettura da 512 a 768 ascendente
  if (ValorePot >511 &&  ValorePot <768){
  MappaturaTre = map(ValorePot, 0, 255, 512, 767);
  analogWrite(ledTre, MappaturaTre);
  }
  //Accensione terzo primo led, sulla lettura da 768 a 1020 discendente
  if (ValorePot >768 && ValorePot <1020){
  MappaturaTreD = map(ValorePot, 255, 0, 768, 1020);
  analogWrite(ledTre, MappaturaTreD);
  }
  // Spegnimento del terzo led quando si è fuori scala
  if (ValorePot <512){analogWrite (ledTre, 0 );}
  if (ValorePot >1020){analogWrite (ledTre, 0 );}
  
  Serial.print("Valore Originale ");
  Serial.println(ValorePot);
  Serial.print("Valore Uno Positivo ");
  Serial.println(MappaturaUno);
  Serial.print("Valore Uno Negativo ");
  Serial.println(MappaturaUnoD);
  Serial.print("Valore Due Positivo ");
  Serial.println(MappaturaDue);
  Serial.print("Valore Due Negativo ");
  Serial.println(MappaturaDueD);
  Serial.print("Valore Tre Rimappato ");
  Serial.println(MappaturaTre);
  Serial.print("Valore Tre Rimappato ");
  Serial.println(MappaturaTreD);
  Serial.println();
  delay(50);
 
 }

Il codice è abbastanza semplice, ora il problema è quando si va nella pratica.
Quando si arriva al punto in cui il Led1 è completamente acceso, mentre il secondo sta iniziando ad accendersi, si notano degli sfarfallii strani. Entrambi i led tendono a spegnersi e riaccendersi poco dopo. Stessa cosa accade quando si passa dal secondo led completamente acceso all’accensione del terzo.

Da cosa potrebbe dipendere questo sfarfallio?

Mie ipotesi:
-Il variatore che ho usato fino ad adesso, ne ha viste davvero tante, forse troppe, quindi risulta essere non proprio lineare nella variazione. Ho avvalorato questa ipotesi con il fatto che sostituendo il variatore, si vedono delle migliorie. In ogni modo il risultato non è propriamente dei migliori.
-Ci sono degli errori nel codice, ma sfortunatamente non sono riuscito a trovare i possibili problemi e quindi sono costretto a rimettermi nelle vostre mani.

In ogni modo grazie per l’aiuto che vorrete darmi.

ciao
Un primo errore: sbagli a usare Map invertendo i valori letti con quelli “mappati”

  MappaturaUnoD = map(ValorePot, 255, 0, 256, 512);

qui penso volessi scrivere

  MappaturaUnoD = map(ValorePot, 256,512, 255, 0);

ovvero quando la lettura va da 256 a 512 il valore di MappaturaUnoD va da 255 a 0.
Se ho visto bene questo errore lo hai fatto su tutti i map. :fearful: :fearful:
Un altro errore:

MappaturaUno = map(ValorePot, 0, 256, 0, 256);
  analogWrite(ledUno, MappaturaUno);

scritto così con lettura 256 dai un valore PWM di 256
no, ti sei salvato con quelif (ValorePot <256){

Altra cosa: non ha senso ( o non ho capito perchè lo fai) duplicare le variabili di mappatura (MappaturaUno e MappaturaUnoD ecc.) visto che già usi i vari if()

Volendo stringere il codice questo

//Accensione dell primo led, sulla lettura da 0 a 256 ascendente
  if (ValorePot <256){
  MappaturaUno = map(ValorePot, 0, 256, 0, 256);
  analogWrite(ledUno, MappaturaUno);
  }

diventa:

//Accensione dell primo led, sulla lettura da 0 a 256 ascendente
  if (ValorePot <256){
    analogWrite(ledUno, MappaturaUno);
  }

infatti quel map non ha proprio senso.

ciao
pippo72

Vediamo di capire.
Concordo sul fatto di aver invertito i valori madre con i valori rimappati. Provvedo a rivedere il codice e sistemare quello che ho sbagliato. Evidentemente avevo frainteso quanto detto sopra da una utente del forum che mi aveva dato un consiglio.

Ma non capisco la seconda parte del discorso che fai.
Ho la necessità di accendere e spegnere tre led, in maniera “soft” a seconda del valore ricavato dalla lettura analogica di un potenziometro.
Questo potenziometro restituisce un valore che va da 0 a 1023, ed io a seconda di dove si posiziona questo valore, devo “rimapparlo” in formato PWM, che va da 0 a 255 se non erro.

Il programma come lo hai scritto tu:

//Accensione dell primo led, sulla lettura da 0 a 256 ascendente
  if (ValorePot <256){
    analogWrite(ledUno, MappaturaUno);
  }

Va bene per il primo led, che ha un valore positivo, presumibilmente simile a quello del PWM. Il potenziometro in quel caso parte da 0 fino a 256, mentre il valore va da 0 a 255.
Ma questo comportamento non va più bene per i passaggi successivi, che in ogni caso necessitano di una rimappatura dei valori. Per esempio, gia allo spegnimento del primo led, con il valore del potenziometro che va da 256 a 512, non è possibile trasferire questo valore o sbaglio?

In ogni modo nel codice che hai scritto tu:

//Accensione dell primo led, sulla lettura da 0 a 256 ascendente
  if (ValorePot <256){
    analogWrite(ledUno, MappaturaUno);
  }

Non capisco dove prendi il valore “MappaturaUno” da scrivere sul pin analogico.

Le mie sono supposizioni basate su quello che ho trovato da leggere, ma se ci sono soluzioni migliori sono sempre ben accette. Poi se tutto quello che voglio fare si potesse realizzare senza l’uso della mappatura, sarei ben contento di sapere come. Sono qui per imparare.

Grazie per i consigli.

ciao

diego_nocioni:
Non capisco dove prendi il valore “MappaturaUno” da scrivere sul pin analogico.

Accidenti, troppi copia-incolla :kissing: :kissing:
Volevo scrivere:

//Accensione dell primo led, sulla lettura da 0 a 256 ascendente
  if (ValorePot <256){
    analogWrite(ledUno, ValorePot);
  }

diego_nocioni:
Ma questo comportamento non va più bene per i passaggi successivi, che in ogni caso necessitano di una rimappatura dei valori. Per esempio, gia allo spegnimento del primo led, con il valore del potenziometro che va da 256 a 512, non è possibile trasferire questo valore o sbaglio?

Non sbagli, mi sono spiegato male: quella abbreviazione va bene solo nel caso ValorePot <256.
Gli altri if sono corretti come erano (a parte i valori di map invertiti)

//Accensione del secondo led, sulla lettua da 256 a 512 ascendente
  if (ValorePot >256 && ValorePot <512){
  MappaturaDue = map(ValorePot,256, 512, 0, 255);
  analogWrite(ledDue, MappaturaDue);
  }

Prendi questo spezzone di codice come esempio
ciao
pippo72

Grazie ai vostri consigli, sono riuscito a portare a termine il mio piccolo progetto. Sono alle basi, ma posso dire che sto avendo parecchie soddisfazioni. Adesso che ho finito di correggere il codice, non mi rimane altro che aggiungere una scheda e qualche transistor per poter così pilotare le mie strisce a led RGB. Fortunatamente me la cavo abbastanza bene in elettronica.

Grazie ancora a tutti

Perdonate se continuo a postare in questo progetto. Ma come sempre, evolvendo ed aggiungendo pezzi, mi sono accorto che qualcosa con porta. Questa volta, al progetto del controllo della striscia a led, ho aggiunto ance un display con l’idea di visualizzare i valori correnti del PWM delle varie uscire di Arduino.

Premetto che:

  • Il variatore, per comodità è stato sostituito con un sistema automatico che lo simula. Andando da 0 fino a 1020 senza bisogno di stare sempre a “giocare” i cacciaviti
  • Il display è collegato come nell’esempio “Hello Word”. Tranne che per i due piedini RS ed RW che per comodità li ho spostati ai pin 5 e 6

Allego il codice, poi vi spiego il problema.

#include <LiquidCrystal.h>
int ValorePot = 0;    //Regolazione automatica variatore
int fadeAmount = 5;    // how many points to fade the LED by
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);   // Settaggio pin lcd
int MappaturaUno = 0;                  // Set Led 1 Ascendente
int MappaturaDue = 0;                  // Set Led 2 Ascendente
int MappaturaTre = 0;                  // Set Led 3 Ascendente
int MappaturaUnoD = 0;                 // Set Led 1 Dicendente
int MappaturaDueD = 0;                 // Set Led 2 Dicendente
int MappaturaTreD = 0;                 // Set Led 3 Dicendente
int ledUno = 9;                        // Set pin led 1
int ledDue = 10;                       // Set pin led 2
int ledTre = 11;                       // Set pin led 3


void setup() {
  
  lcd.begin(16, 2);                    // Inizializazione LCD
  lcd.print("Val: RGB");               // Scritta riga di presentazione
  Serial.begin(9600);                  // Inizializazione porta seriale
  pinMode (ledUno, OUTPUT);            // Impostazione pin come uscita RED
  pinMode (ledDue, OUTPUT);            // Impostazione pin come uscita led 2
  pinMode (ledTre, OUTPUT);            // Impostazione pin come uscita led 3
  
}




void loop() {
 
  ValorePot = ValorePot + fadeAmount;
  if (ValorePot == 0 || ValorePot == 1020) {
    fadeAmount = -fadeAmount ;
  }
  delay(100);
  
   
  if (ValorePot <256){
  MappaturaUno = map(ValorePot, 0, 256, 0, 255);
  analogWrite(ledUno, MappaturaUno);
  }
  if (ValorePot >256 && ValorePot <512){
  MappaturaUnoD = map(ValorePot, 256, 512, 255, 0);
  analogWrite(ledUno, MappaturaUnoD);
  }
  if (ValorePot >512){analogWrite (ledUno, LOW );}
  
  
  if (ValorePot >256 && ValorePot <512){
  MappaturaDue = map(ValorePot, 256, 512, 0, 255);
  analogWrite(ledDue, MappaturaDue);
  }
  if (ValorePot >512 && ValorePot <768){
  MappaturaDueD = map(ValorePot, 512, 768, 255, 0);
  analogWrite(ledDue, MappaturaDueD);
  }
  if (ValorePot <256){analogWrite (ledDue, LOW);}
  if (ValorePot >768){analogWrite (ledDue, LOW);}
  
  
  
  if (ValorePot >511 &&  ValorePot <768){
  MappaturaTre = map(ValorePot, 512, 767, 0, 255);
  analogWrite(ledTre, MappaturaTre);
  }
  if (ValorePot >768 && ValorePot <1020){
  MappaturaTreD = map(ValorePot, 768, 1020, 255, 0);
  analogWrite(ledTre, MappaturaTreD);
  }
  if (ValorePot <512){analogWrite (ledTre, LOW );}
  if (ValorePot >1020){analogWrite (ledTre, LOW );}
  
  
  Serial.println(MappaturaUno);
  Serial.print("Valore Uno Negativo ");
  Serial.println(MappaturaUnoD);
  Serial.print("Valore Due Positivo ");
  Serial.println(MappaturaDue);
  Serial.print("Valore Due Negativo ");
  Serial.println(MappaturaDueD);
  Serial.print("Valore Tre Positivo ");
  Serial.println(MappaturaTre);
  Serial.print("Valore Tre Negativo ");
  Serial.println(MappaturaTreD);
  
  // Sezione display LCD
  
  lcd.setCursor(0, 1);
  
  if (ValorePot <512){
 
  if (ValorePot <512)                    {lcd.print("RD");}
  if (ValorePot <256)                    {lcd.print(MappaturaUno);}
  if (ValorePot >256 && ValorePot <512)  {lcd.print(MappaturaUnoD);} 
  if (ValorePot <512)                    {lcd.print(" ");}
  
  if (ValorePot >256 && ValorePot <765)  {lcd.print("GR");}
  if (ValorePot >256 && ValorePot <512)  {lcd.print(MappaturaDue);}
  if (ValorePot >513 && ValorePot <768)  {lcd.print(MappaturaDueD);}
  if (ValorePot >256 && ValorePot <768)  {lcd.print("  ");}
  }
  
  if (ValorePot >512){

  if (ValorePot >511 && ValorePot <1020)  {lcd.print("BL");}
  if (ValorePot >511 && ValorePot <768)  {lcd.print(MappaturaTre);}
  if (ValorePot >768 && ValorePot <1020) {lcd.print(MappaturaTreD);}
  if (ValorePot >511 && ValorePot <1020)  {lcd.print("  ");}
  
  if (ValorePot >256 && ValorePot <765)  {lcd.print("GR");}
  if (ValorePot >256 && ValorePot <512)  {lcd.print(MappaturaDue);}
  if (ValorePot >513 && ValorePot <768)  {lcd.print(MappaturaDueD);}
  if (ValorePot >256 && ValorePot <768)  {lcd.print("  ");}

  }
  }

Ora, il problema principale è che il display continua a dare dei valori anche se il loro range di visualizzazione è oramai passato. Il valore del led GR, rimane impresso a display anche quando non dovrebbe esserci, bloccato su un valore di GR3 oppure anche solo 3

Oltre a questo, come posso dare ad ogni valore un posto sul display? Senza che di volta in volta questi valori si spostino a seconda di quante cifre li compongono.

Secondo me leggi dei valori che sembrano sempre i soliti perché aggiorni troppo spesso il display e non riesce a stare dietro al clock di Arduino. Se provi a rallentare l’esecuzione del codice i valori saranno corretti, come prima prova anche se poco ortodossa e quasi mi vergogno a dirlo è piazzare un bel delay alla fine del loop in modo che l’esecuzione rallenti di molto e controllare la mia ipotesi che se verificata di costringerà a modificare il codice in modo da effettuare gli aggiornamenti del display a intervalli tali da poter leggere valori decenti anche se “poco” aggiornati. Ma se alla fine la variazione non sarà automatica magari non serve neppure, questo dipende dalla destinazione del progetto.
Per la questione del posizionamento credo che l’unica soluzione sia di verificare il valore da scrivere e effettuare una set cursor in moda che i valori restino in posizione Es.

lcd.setCursor(0, val<10?2:1)

Oppure

if(val<10){
  lcd.setCursor(0, 2);
}
else{
  lcd.setCursor(0, 1);
}

Ed ecco che alla fine sono riuscito a fare quello che volevo. Mi ci è voluto un po, dato lo scarso tempo che posso impiegare in questi progetti. Ma ecco il risultato.

// Sezione display LCD
  
  lcd.setCursor(8, 0);
  lcd.print ("Pot");
  lcd.print (ValorePot);
  lcd.print ("  ");
  
  lcd.setCursor(0, 1);
  lcd.print("R");
  
    if (ValorePot >0 && ValorePot < 512) {
    if (ValorePot < 256)  { 
      if (MappaturaUno< 10) {lcd.print("  ");}
      if (MappaturaUno< 100) {lcd.print(" ");}
      lcd.print (MappaturaUno);}
    
    if (ValorePot > 256 && ValorePot < 512) {
      if (MappaturaUnoD< 10) {lcd.print("  ");}
      if (MappaturaUnoD< 100) {lcd.print(" ");}
      lcd.print (MappaturaUnoD);}
      }
    else {lcd.print ("   ");}
  lcd.print (" ");
  lcd.print ("G");
    if (ValorePot > 256 && ValorePot <768){
    if (ValorePot > 256 && ValorePot < 512)  { 
      if (MappaturaDue< 10) {lcd.print("  ");}
      if (MappaturaDue< 100) {lcd.print(" ");}
      lcd.print (MappaturaDue);}
    
    if (ValorePot > 512 && ValorePot < 768) {
      if (MappaturaDueD< 10) {lcd.print("  ");}
      if (MappaturaDueD< 100) {lcd.print(" ");}
      lcd.print (MappaturaDueD);}
    }
    else {lcd.print ("   ");}
    
    
    lcd.print (" ");
    lcd.print ("B");
    if (ValorePot > 512 && ValorePot <1020){
    if (ValorePot > 512 && ValorePot < 768)  { 
      if (MappaturaTre< 10) {lcd.print("  ");}
      if (MappaturaTre< 100) {lcd.print(" ");}
      lcd.print (MappaturaTre);}
    
    if (ValorePot > 768 && ValorePot < 1020) {
      if (MappaturaTreD< 10) {lcd.print("  ");}
      if (MappaturaTreD< 100) {lcd.print(" ");}
      lcd.print (MappaturaTreD);}
    }
    else {lcd.print ("   ");}
    
    lcd.print ("  ");

Grazie mille a tutti.
Cercare un progetto e realizzarlo passo per passo, espanderlo ed aggiungere sempre nuove parti, penso sia un ottimo sistema per poter imparare. Passo per passo sto prendendo familiarità con il codice e capisco sempre meglio come fare quello che voglio.
Spero inoltre che le mie domande ed i vostri aiuti, possano essere utili anche ad altri.

Un saluto e buona Pasquetta a tutto il forum