Primo programma accensioni luci

Salve a tutti sono nuovo del forum e ho appena acquistato arduino uno.
Siccome faccio l' elettricista il primo programma che mi è venuto in mente è stato di fare l' accensione di un carico con un pulsante replicando un relè passo-passo.
Questo è il programma

const int Pulsantepin = 2;
const int Utilizzatorepin = 3;

int Statopulsante;
int Statoutilizzatore;

void setup ()
{
  
  Serial.begin(9600);
  pinMode (Pulsantepin, INPUT);
  pinMode (Utilizzatorepin, OUTPUT);
}
  
void loop ()
{
  
  Statopulsante = digitalRead (Pulsantepin);
  Statoutilizzatore = digitalRead (Utilizzatorepin);
 
  if (Statopulsante==HIGH)
    if (Statoutilizzatore==HIGH)
    {
      Statoutilizzatore=LOW;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
      delay(500);
    }
    else
    {
      Statoutilizzatore=HIGH;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
      delay(500);
    }
}

Per risolvere il problema del pulsante ho dovuto aggiungere i delay (500). Il problema è se io aggingo molte accensioni tutti questi delay mi farebbero funzionare male il programma.
Lo stesso problema lo avrei se dovessi temporizzare una accensione per replicare un relè luci scale che stà acceso per esempio 3 minuti. Durante questi 3 minuti il programa è fermo e non accetta nessun comando per esempio l' accensione di un altro punto luce.
Per risolvere ho scritto questo altro programma ma non funziona il led non risponde bene ai comandi e si accende con poca illuminazione.

const int Pulsantepin = 2;
const int Utilizzatorepin = 3;

int Statopulsante;
int Statoutilizzatore;

unsigned long int Tempo;
unsigned long int Tempopulsante;
unsigned long int Tempoutilizzatore;

void setup ()
{
  Tempo=millis ();
  Tempopulsante=millis();
  Tempoutilizzatore=millis();
  Serial.begin(9600);
  pinMode (Pulsantepin, INPUT);
  pinMode (Utilizzatorepin, OUTPUT);
}  
void loop ()
{
  Tempo=millis ();
  if (Tempo>Tempopulsante+20)
  {
    Statopulsante = digitalRead (Pulsantepin);
    Tempopulsante=millis();
  }
  if (Tempo>Tempoutilizzatore+20)
  {
    Statoutilizzatore = digitalRead (Utilizzatorepin); 
    Tempoutilizzatore=millis ();
  }  


  if (Statopulsante==HIGH)
    if (Statoutilizzatore==HIGH)
    {
      Statoutilizzatore=LOW;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
    }
    else
    {
      Statoutilizzatore=HIGH;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);

    }
}

c' è qualcuno che può aiutarmi? Grazie in anticipo.

Il codice deve essere racchiuso negli appositi tag [ code] e [/ code] (senza spazi, li ho messi per farli vedere)
come da regolamento. Altrimenti, 1) l'admin ti cazzia ]:), 2) alcune parti del codice potrebbero essere in parte mancanti :fearful:

grazie ho modificato :cold_sweat:

Perche a
hai messo:
Serial.begin(9600);

con chi devi comunicare?

Prova così:

const int Pulsantepin = 2;
const int Utilizzatorepin = 3;

int Statopulsante;
int Statoutilizzatore;

void setup ()
{
  
  Serial.begin(9600);
  pinMode (Pulsantepin, INPUT);
  pinMode (Utilizzatorepin, OUTPUT);
}
  
void loop ()
{
  
  Statopulsante = digitalRead (Pulsantepin);
  Statoutilizzatore = digitalRead (Utilizzatorepin);
 const int Pulsantepin = 2;
const int Utilizzatorepin = 3;

int Statopulsante;
int Statoutilizzatore;

void setup ()
{
  
  Serial.begin(9600);
  pinMode (Pulsantepin, INPUT);
  pinMode (Utilizzatorepin, OUTPUT);
}
  
void loop ()
{
  
  Statopulsante = digitalRead (Pulsantepin);
  Statoutilizzatore = digitalRead (Utilizzatorepin);
  delay(500);

  if (Statopulsante==HIGH)
    if (Statoutilizzatore==HIGH)
    {
      Statoutilizzatore=LOW;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
      
    }
    else
    {
      Statoutilizzatore=HIGH;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
      
    }
}
  if (Statopulsante==HIGH)
    if (Statoutilizzatore==HIGH)
    {
      Statoutilizzatore=LOW;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
     
    }
    else
    {
      Statoutilizzatore=HIGH;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
    
    }
}

non puoi bloccare il programma con delay . per inserire o disinserire delle accensioni in base ai pulsanti
premuti devi memorizzare lo stato dei pulsanti o la loro commutazione ed in base al loro stato
commutare lo stato delle lampade .

Grazie per le risposte.
Il Serial.begin l' ho messo perchè in un futuro la scheda dovrà comunicare con altre schede, in questo momento non serve ma in un futuro si.
Lo stato del pulsante l' ho memorizzato in una variabile il delay che ho messo serve per eliminare il problema dei rimbalsi del pulsante.
Adesso provo il codice che mi hai inviato.
Se volessi aggiungere al programma, che adesso accende e spegne un led come un relè passo-passo, anche una accensione temporizzata per esempio spingo un altro pulsante che accende un altro led per 3 minuti non posso utilizzare delay perchè bloccherebbe tutto il programma. Penso che dovrei utilizzare millis() ma non ho capito bene come funziona.

Ti passo un link ad un articoletto che ho scritto in cui spiego come programmare i compiti usando milis:
http://www.leonardomiliani.com/2013/programmiamo-i-compiti-con-millis/

Affronto il problema di 1 compito, e poi il problema di 2 compiti.
Per cose più impegnative ho fatto anche un paio di scheduler, uno basato su millis (looper), ed uno un pò più complesso basato sugli interrupt (leOS).

Grazie leo il tuo articolo sembra chiaro.
Adesso faccio un pò di prove.

Hai provato con il mio codice?

Si grazie ho provato ho copiato il codice con copia e incolla ma mi d' ha un errore quando faccio la verifica ma non ho avuto il tempo di capire qualè l' errore.

Manca la graffa aperta dopo:
if (Statopulsante==HIGH) {

errore corretto, comunque il delay antirimbalso lo devi mettere solo sotto la lettura del pin digitalRead e non ogni volta che chiedi lo stato del pin sul programma, tanto la lettura avviene una volta sola ad ogni ciclo e viene memorizzata.
così l'errore non cè piu:

const int Pulsantepin = 2;
const int Utilizzatorepin = 3;

int Statopulsante;
int Statoutilizzatore;

void setup ()
{
  
  Serial.begin(9600);
  pinMode (Pulsantepin, INPUT);
  pinMode (Utilizzatorepin, OUTPUT);
}
  
void loop ()
{
  
  Statopulsante = digitalRead (Pulsantepin);
  Statoutilizzatore = digitalRead (Utilizzatorepin);
  delay(500);
 
  if (Statopulsante==HIGH)
    if (Statoutilizzatore==HIGH)
    {
      Statoutilizzatore=LOW;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
    }
    else
    {
      Statoutilizzatore=HIGH;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
    }
}

Adesso provo il codice che mi hai mandato.

Bastano anche 30 millisecondi.

Penso di avere risolto in questo modo i due programmi il primo con delay e il secondo con millis funzionano perfettamente uguali.
Praticamente nel programma con delay ho ad un certo punto del programma:

delay (500); //faccio fermare il programma per mezzo secondo.

Con millis delay (500); è stato sostituito con:

if (currentMillis - previousMillis > interva1) //Se lo Stato attuale - Stato precedente > intervallo
      {
        previousMillis = currentMillis; // Stato precedente = Stato attuale

delay (500); va espresso dopo il digitalWrite mentre il programma con millis() va espresso prima del digitalWrite.
Programma delay

const int Pulsantepin = 2;
const int Utilizzatorepin = 3;

int Statopulsante;
int Statoutilizzatore;

void setup ()
{

  Serial.begin(9600);
  pinMode (Pulsantepin, INPUT);  
  pinMode (Utilizzatorepin, OUTPUT);
}  
void loop ()
{  
  Statopulsante = digitalRead (Pulsantepin);  
  Statoutilizzatore = digitalRead (Utilizzatorepin);  
  if (Statopulsante==HIGH)
    if (Statoutilizzatore==HIGH)
    {
      Statoutilizzatore=LOW;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
      delay(500); //aspetta mezzo secondo
    }
    else
    {
      Statoutilizzatore=HIGH;
      digitalWrite (Utilizzatorepin, Statoutilizzatore);
      delay(500); //aspetta mezzo secondo
    }
}

Programma con millis()

const int Pulsantepin = 2;
const int Utilizzatorepin = 3;
unsigned long previousMillis = 0; //Variabile globale Precedente millis
unsigned long interva1 = 500; // Variabile globale intervallo posto a mezzo secondo

int Statopulsante;
int Statoutilizzatore;

void setup ()
{
  Serial.begin(9600); 
  pinMode (Pulsantepin, INPUT);
  pinMode (Utilizzatorepin, OUTPUT);
}  
void loop ()
{
  unsigned long currentMillis = millis ();  //Variabile Stato attuale di millis
  Statopulsante = digitalRead (Pulsantepin);
  Statoutilizzatore = digitalRead (Utilizzatorepin);
  if (Statopulsante==HIGH)
    if (Statoutilizzatore==HIGH)
    {
      if (currentMillis - previousMillis > interva1) //Se lo Stato attuale - Stato precedente > intervallo
      {
        previousMillis = currentMillis; // Stato precedente = Stato attuale 
        Statoutilizzatore=LOW;
        digitalWrite (Utilizzatorepin, Statoutilizzatore);
      }
    }
    else
    {
      if (currentMillis - previousMillis > interva1) //Se lo Stato attuale - Stato precedente > intervallo
      {
        previousMillis = currentMillis; // Stato precedente = Stato attuale
        Statoutilizzatore=HIGH;
        digitalWrite (Utilizzatorepin, Statoutilizzatore);  
      }  
    } 
}

La prima cosa che ho notato facendo la verifica è che il programma con delay è più pesante di quello con milli() ed avrei pensato al contrario.
Mi sembrava di avere letto che millis() è più pesante.

Domande

  1. Millis salva in una variabile dei dati dopo tanto tempo posso avere problemi di spazio ed in particolare se uso millis per molte accensioni?
  2. Millis salva i dati per 50 gg mi sembra di avere letto e poi si azzera. Quando si azzera cosa succede? Nel momento che si azzera l' utente dell' impianto che vuole accendere e spegnere le sue luci cosa nota un mal funzionamento? Si trova tutte le luci spente per esempio?

Ho provato l' ultimo programma che mi hai mandato con delay sotto la lettura del pin digitalRead.
Mi sembra meno reattivo di quello che ho scritto cioè il led non si accende perfettamente ad ogno pressione del pulsante.
Prova anche tu. Carica il programma con delay che ti ho postato. Subito dopo prova quello che hai postato tu e guarda la differenza.
Il prossimo programma sarà una accensione temporizzata di 10 secondi e una accensione passo-passo normale per vedere se millis mi ha risolto il problema.
Ciao.

Domande

  1. Millis salva in una variabile dei dati dopo tanto tempo posso avere problemi di spazio ed in particolare se uso millis per molte accensioni?
  2. Millis salva i dati per 50 gg mi sembra di avere letto e poi si azzera. Quando si azzera cosa succede? Nel momento che si azzera l' utente

evidentemente non hai letto il Reply #7 di Leo

Nicola88:
La prima cosa che ho notato facendo la verifica è che il programma con delay è più pesante di quello con milli() ed avrei pensato al contrario.
Mi sembrava di avere letto che millis() è più pesante.

Delay è una funzione un pò più complessa di millis: millis restituisce solo il valore di un contatore, delay esegue un ciclo di attesa.
Probabilmente i byte in più stanno qui.

Domande

  1. Millis salva in una variabile dei dati dopo tanto tempo posso avere problemi di spazio ed in particolare se uso millis per molte accensioni?

No, millis è una funzione che legge una variabile interna e che ne restituisce il valore. Il problema di "spazio" è solo legato alla memoria Flash che contiene il tuo programma (nel caso di millis).

  1. Millis salva i dati per 50 gg mi sembra di avere letto e poi si azzera. Quando si azzera cosa succede? Nel momento che si azzera l' utente dell' impianto che vuole accendere e spegnere le sue luci cosa nota un mal funzionamento? Si trova tutte le luci spente per esempio?

Stai usando il secondo metodo del mio articolo, quel metodo è esente dall'overflow di millis per cui non devi preoccupartente. L'overflow è gestito senza problemi per cui a te non interessa se il contatore che millis legge riparte da zero, il controllo per come l'hai usato non soffre di questo problema.

500 ms sono tanti, troppi per un debounce.
Ne bastano 50.

pablos:
evidentemente non hai letto il Reply #7 di Leo

Avevo scritto un poema, quando ho visto il tuo reply l'ho spedito lo stesso :stuck_out_tongue:

Con 50 ms il programma non funziona cioè il led non si accende bene con la pressione del pulsante.
Ho eseguito il programma con una accensione temporizzata e una accensione a relè passo-passo senza l' uso di delay funziona tutto bene.

const int Pulsantepin1 = 2;
const int Pulsantepin2 = 3;
const int Utilizzatorepin1 = 4;
const int Utilizzatorepin2 = 5;
unsigned long previousMillis1 = 0; //Variabile globale Precedente millis
unsigned long interva1 = 10000; // Variabile globale intervallo posto a mezzo secondo
unsigned long previousMillis2 = 0; //Variabile globale Precedente millis
unsigned long interva2 = 200;
unsigned int counter = 0;

int Statopulsante1;
int Statopulsante2;
int Statoutilizzatore1;
int Statoutilizzatore2;

void setup ()
{
  Serial.begin(9600); 
  pinMode (Pulsantepin1, INPUT);
  pinMode (Pulsantepin2, INPUT);
  pinMode (Utilizzatorepin1, OUTPUT);
  pinMode (Utilizzatorepin2, OUTPUT);
}  
void loop ()
{
  unsigned long currentMillis = millis ();
  Statopulsante1 = digitalRead (Pulsantepin1);
  Statopulsante2 = digitalRead (Pulsantepin2);
  Statoutilizzatore1 = digitalRead (Utilizzatorepin1);
  Statoutilizzatore2 = digitalRead (Utilizzatorepin2);
  // ACCENSIONE 1 TEMPORIZZATA
  if (Statopulsante1==HIGH)
  {
    Statoutilizzatore1=HIGH;
    digitalWrite (Utilizzatorepin1, Statoutilizzatore1);
  }  
  else if (Statopulsante1==LOW)
  {
    if (currentMillis - previousMillis1 > interva1)
    {
      previousMillis1 = currentMillis; 
      Statoutilizzatore1=LOW;
      digitalWrite (Utilizzatorepin1, Statoutilizzatore1);  
    }
  }
  // ACCENSIONE 2 
  if (Statopulsante2==HIGH)
    if (Statoutilizzatore2==HIGH)
    {
      if (currentMillis - previousMillis2 > interva2)
      {
        previousMillis2 = currentMillis;
        Statoutilizzatore2=LOW;
        digitalWrite (Utilizzatorepin2, Statoutilizzatore2);
      }
    }
    else
    {
      if (currentMillis - previousMillis2 > interva2)
      {
        previousMillis2 = currentMillis;
        Statoutilizzatore2=HIGH;
        digitalWrite (Utilizzatorepin2, Statoutilizzatore2);
      }
    }
}

Se avete consigli e suggerimenti sul programma sono tutto orecchie.