spiegazione sketch (risolto)

Salve a tutti, ho trovato questo listato in rete, e ho cercato di studiarlo ma sinceramente non ne capisco il funzionamento, qualcuno puo’ aiutarmi?

grazie

//LED Flasher Relay with hazard lights combination v1.0 for motorcycles with Arduino or ATTiny85 - by Fedaceag Ionut ( Youtube - Think small, build big! )
//input pins for arduino
const int leftSignalInPin = 2; 
const int rightSignalInPin = 3;
const int leftSignalOutPin = 4; 
const int rightSignalOutPin = 5;
const int buzzer = 6;

//input pins for attiny85
/*const int leftSignalInPin = 1; 
const int rightSignalInPin = 2;
const int leftSignalOutPin = 3; 
const int rightSignalOutPin = 4;*/

int leftSignalVal = 0;
int leftSignalState = 0;
int rightSignalVal = 0;
int rightSignalState = 0;

int delayForHazard = 500; // delay in milliseconds for hazard light combination
unsigned long currentMillis = 0; 
unsigned long previousMillis = 0;

int delayForSignal = 400; // signal frequency in milliseconds
unsigned long signalMillis = 0;
int signalBlink = 0;

int relayLowOrHighTriggering = 0; // 0 - for relays with low level triggering | 1 - for relays with hight level triggering

void setup() {
  Serial.begin(9600);
  pinMode(leftSignalInPin, INPUT);
  pinMode(rightSignalInPin, INPUT);
  pinMode(leftSignalOutPin, OUTPUT);
  pinMode(rightSignalOutPin, OUTPUT);
  pinMode(buzzer, OUTPUT);

  // setting the pins to the correct state
 if(relayLowOrHighTriggering == 0){
    digitalWrite(leftSignalOutPin,HIGH);
    digitalWrite(rightSignalOutPin,HIGH);
    noTone(buzzer);
  }else{
    digitalWrite(leftSignalOutPin,LOW);
    digitalWrite(rightSignalOutPin,LOW);
    noTone(buzzer);
  }
}

void loop() {
  Serial.print(relayLowOrHighTriggering, DEC);
  //Serial.println(leftSignalOutPin, DEC);
  leftSignalVal = digitalRead(leftSignalInPin);
  rightSignalVal = digitalRead(rightSignalInPin);
  currentMillis = millis();

  if(leftSignalVal == 1){
    leftSignalState = 1;
    previousMillis = currentMillis;
  }else{
    if(currentMillis-previousMillis >= delayForHazard && signalBlink == 0){
      leftSignalState = 0; 
    }
  }

  if(rightSignalVal == 1){
    rightSignalState = 1;
    previousMillis = currentMillis;
  }else{
    if(currentMillis-previousMillis >= delayForHazard && signalBlink == 0){
      rightSignalState = 0;
    }
  }

  if(leftSignalState == 1){
    if(signalBlink == 1){ 
      if(relayLowOrHighTriggering == 0){ digitalWrite(leftSignalOutPin,LOW); }else{ digitalWrite(leftSignalOutPin,HIGH); }
    }else{
      if(relayLowOrHighTriggering == 0){ digitalWrite(leftSignalOutPin,HIGH); }else{ digitalWrite(leftSignalOutPin,LOW); }
    }   
  }else{
    if(relayLowOrHighTriggering == 0){ digitalWrite(leftSignalOutPin,LOW); }else{ digitalWrite(leftSignalOutPin,HIGH); }
  }

  if(rightSignalState == 1){
    if(signalBlink == 1){
      if(relayLowOrHighTriggering == 0){ digitalWrite(rightSignalOutPin,LOW);}else{ digitalWrite(rightSignalOutPin,HIGH); }
    }else{
      if(relayLowOrHighTriggering == 0){ digitalWrite(rightSignalOutPin,HIGH); }else{ digitalWrite(rightSignalOutPin,LOW); }
    }
  }else{
    if(relayLowOrHighTriggering == 0){ digitalWrite(rightSignalOutPin,LOW); }else{ digitalWrite(rightSignalOutPin,HIGH); }
  }

  if(leftSignalState == 1 || rightSignalState == 1){
    if(signalMillis+delayForSignal > currentMillis){     
      signalBlink = 1;
    }else{
      signalBlink = 0;
      if(signalMillis+delayForSignal+delayForSignal < currentMillis){
        signalMillis = currentMillis;
      }
    }
  }
  
}

L'autore si è complicato la vita non poco :o

In sostanza con i valori letti dai pin 'leftSignalInPin' e 'rightSignalInPin' comanda due temporizzatori di tipo TOFF, le cui uscite (le variabili 'leftSignalState' e 'rightSignalState') restano alte per 'delayForHazard' millisecondi dopo la cessazione dei comandi in ingresso.
I temporizzatori si potevano scrivere così:

if(leftSignalVal == 1){
    leftSignalState = 1;
    inizio = adesso;
}else if(adesso-inizio >= delayForHazard   &&   signalBlink == 0){
    leftSignalState = 0;
}

if(rightSignalVal == 1){
    rightSignalState = 1;
    inizio = adesso;
}else if(adesso-inizio >= delayForHazard   &&   signalBlink == 0){
    rightSignalState = 0;
}

Quando una qualsiasi di queste uscite è alta il blinker genera un'uscita (la variabile 'signalBlink
') alternata 'delayForSignal' millisecondi on e 'delayForSignal
' millisecondi off.

L'AND tra signalState (destro e sinistro) e signalBlink comanda le uscite (destra e sinistra).
Si poteva scrivere così:

if(leftSignalState == 1  &&  signalBlink == 1){
    digitalWrite(leftSignalOutPin, ONLEVEL);
}else{
    digitalWrite(leftSignalOutPin, OFFLEVEL); 
}

if(rightSignalState == 1  &&  signalBlink == 1){
    digitalWrite(rightSignalOutPin, ONLEVEL);  
}else{
    digitalWrite(rightSignalOutPin, OFFLEVEL);
}

Il codice è abbastanza contorto, il blinker non sono sicuro sia scritto giusto, l'insieme funziona in un modo che non so se è giusto così o se sia un errore (non conoscendo come sia il comportamento giusto).

Tra l'altro, tutte le cose di questo genere:
   if (relayLowOrHighTriggering==0) {digitalWrite(leftSignalOutPin,LOW);}
   else {digitalWrite(leftSignalOutPin,HIGH);}

sono semplificabili in:
   digitalWrite (leftSignalOutPin, relayLowOrHighTriggering);
o simili.

in effetti io ho provato a collegarlo elettricamente, e funziona.
quello che non capisco è dove, nel programma, fa partire il tempo di lampeggio singolo e dove fa partire il lampeggio doppio

nel frattempo ho tolto " relayLowOrHighTriggering " perchè non mi era logico e poi inutile....

grazie

Inezia, ma per il numero di un pin basta un byte
const byte leftSignalInPin = 2;

hai ragione , ma non credo sia qui il caso di cercare di risparmiare.
quello che non capisco è come faccia in poche righe a fare una cosa molto utile,ma allo stesso tempo poco chiara per un neofita…

grazie

anche perchè stavo cercando di capire come fare per inserire, un buzzer che suona solo con le attivazioni singole,
mentre quando c'è l'attivazione doppia stia muto......studio!!!

grazie
p.s. se capissi come inserire quei due " ONLEVEL, OFFLEVEL" forse potri inserire quella negazione del buzzer???

Dalla lettura non capisco esattamente come devono essere i segnali in ogni momento. Per cui magari posta il codice attuale ridotto che dici funzionare. Forse è difficile capire dove fa una cosa e dove l’altra perché l’uscita è la combinazione di più segnali che cambiano in parallelo, e in più è scritto in un modo “contorto”, credo di averlo anche inteso/“tradotto” male.

Dopo un tentativo di operazione dimagrante viene una cosa del genere, ma per ora ho esaurito le energie :slight_smile:

// LED Flasher Relay with hazard lights combination v1.0 for motorcycles with Arduino or ATTiny85
// by Fedaceag Ionut (Youtube - Think small, build big!)

// I/O pins for arduino:
const byte S=2;
const byte D=3;
const byte lampS=4;
const byte lampD=5;
const byte buzzer=6;

/*
I/O pins for attiny85:
const byte S=1;
const byte D=2;
const byte lampS=3;
const byte lampD=4;*/

byte statoLampS=0;
byte statoLampD=0;

int delayForHazard=500; // delay in milliseconds for hazard light combination
unsigned long previousMillis=0;

int delayForSignal=400; // signal frequency in milliseconds
unsigned long signalMillis=0;
byte signalBlink=0;

void setup()
{
pinMode(S, INPUT);
pinMode(D, INPUT);
pinMode(lampS, OUTPUT);
pinMode(lampD, OUTPUT);
pinMode(buzzer, OUTPUT);
}

void loop()
{
if(digitalRead(S)==1) {statoLampS=1; previousMillis=millis();}
else
  {
  if(millis()-previousMillis>=delayForHazard && signalBlink==0) {statoLampS=0;}
  }

if(digitalRead(D)==1) {statoLampD=1; previousMillis=millis();}
else
  {
  if(millis()-previousMillis>=delayForHazard && signalBlink==0) {statoLampD=0;}
  }

if(statoLampS==1)
  {
  if(signalBlink==1) {digitalWrite(lampS,HIGH);}
  else {digitalWrite(lampS,LOW);}   
  }
else {digitalWrite(lampS,HIGH);}

if(statoLampD==1)
  {
  if(signalBlink==1) {digitalWrite(lampD,HIGH);}
  else {digitalWrite(lampD,LOW);}
  }
else {digitalWrite(lampD,HIGH);}

if(statoLampS==1 || statoLampD==1)
  {
  if(signalMillis+delayForSignal>millis()) {signalBlink=1;}
  else
    {
    signalBlink=0;
    if(signalMillis+delayForSignal+delayForSignal<millis())
      {signalMillis=millis();}
    }
  }
}

Si Datman, è lo stessa modifica che ho fatto io, solo che non ho cambiato il nome delle variabili.

Rispondendo a Claudio,
Si usa un interruttore a tre posizioni fisse con zero al centro.
1: metto l'interruttore a sinistra e lampeggiano le luci di sinistra
2:metto in centro spengo
3: metto a destra e lampeggiano le luci di destra
4: metto al centro si spengono
5: metto l'interruttore indifferentemente a sinistra o a destra, e velocemente lo metto nella direzione opposta(
passando ma non fermandomi al centro)e si accendono sia destra che sinistra insieme
6: metto al centro e spengo tutto.

in effetti io l'ho collegato e funziona, volevo solo capirne la logica, per poter aggiungere un cicalino che suonasse solo se lo metto a sinistra o a destra, ma non quando sono accese contemporaneamente.

come ben sa Claudio, non vorrei soluzioni ma spiegazioni per arrivare alla soluzione

grazie

Scusa Datman, ma ho provato la tua modifica, e bisogna invertire tutti gli HIGH e i LOW , altrimenti i due rele restano sempre eccitati e funzionano al contrario.
nel senso che se restano sempre in tensione scaricano l'eventuale batteria.....

sbaglio?
grazie

Allora puoi fare così:

// LED Flasher Relay with hazard lights combination v1.0 for motorcycles with Arduino or ATTiny85
// by Fedaceag Ionut (Youtube - Think small, build big!)

// I/O pins for arduino:
const byte S=2;
const byte D=3;
const byte lampS=4;
const byte lampD=5;
const byte buzzer=6;


/*
I/O pins for attiny85:
const byte S=1;
const byte D=2;
const byte lampS=3;
const byte lampD=4;
*/

const bool ON=LOW;
byte statoLampS=0;
byte statoLampD=0;

int delayForHazard=500; // delay in milliseconds for hazard light combination
unsigned long previousMillis=0;

int delayForSignal=400; // signal frequency in milliseconds
unsigned long signalMillis=0;
byte signalBlink=0;

void setup()
{
pinMode(S, INPUT);
pinMode(D, INPUT);
pinMode(lampS, OUTPUT);
pinMode(lampD, OUTPUT);
pinMode(buzzer, OUTPUT);
digitalWrite(lampS, !ON);
digitalWrite(lampD, !ON);
}

void loop()
{
if(digitalRead(S)==1)
  {
  statoLampS=1;
  previousMillis=millis();
  }
else
  {
  if(millis()-previousMillis>=delayForHazard && signalBlink==0)
    {statoLampS=0;}
  }

if(digitalRead(D)==1)
  {
  statoLampD=1;
  previousMillis=millis();
  }
else
  {
  if(millis()-previousMillis>=delayForHazard && signalBlink==0)
    {statoLampD=0;}
  }

if(statoLampS==1)
  {
  if(signalBlink==1)
    {
    digitalWrite(lampS,ON);
    }
  else{digitalWrite(lampS,!ON);}   
  }
else
  {digitalWrite(lampS,ON);}

if(statoLampD==1)
  {
  if(signalBlink==1)
    {digitalWrite(lampD,ON);}
  else
    {digitalWrite(lampD,!ON);}
  }
else
  {digitalWrite(lampD,ON);}

if(statoLampS==1 || statoLampD==1)
  {
  if(signalMillis+delayForSignal>millis())
    {signalBlink=1;}
  else
    {
    signalBlink=0;
    if(signalMillis+delayForSignal+delayForSignal<millis())
      {signalMillis=millis();}
    }
  }
}

io avevo adottato questa soluzione che è praticamente uguale…

adesso pero vorrei capire come fare per il buzzer, qualche idea?

grazie

// LED Flasher Relay with hazard lights combination v1.0 for motorcycles with Arduino or ATTiny85
// by Fedaceag Ionut (Youtube - Think small, build big!)

// I/O pins for arduino:
const byte S=2;
const byte D=3;
const byte lampS=4;
const byte lampD=5;
const byte buzzer=6;



byte statoLampS=0;
byte statoLampD=0;

int delayForHazard=500; // delay in milliseconds for hazard light combination
unsigned long previousMillis=0;

int delayForSignal=400; // signal frequency in milliseconds
unsigned long signalMillis=0;
byte signalBlink=0;

void setup()
{
pinMode(S, INPUT);
pinMode(D, INPUT);
pinMode(lampS, OUTPUT);
pinMode(lampD, OUTPUT);
pinMode(buzzer, OUTPUT);
}

void loop()
{
if(digitalRead(S)==1) {statoLampS=1; previousMillis=millis();}
else
  {
  if(millis()-previousMillis>=delayForHazard && signalBlink==0) {statoLampS=0;}
  }

if(digitalRead(D)==1) {statoLampD=1; previousMillis=millis();}
else
  {
  if(millis()-previousMillis>=delayForHazard && signalBlink==0) {statoLampD=0;}
  }

if(statoLampS==1)
  {
  if(signalBlink==1) {digitalWrite(lampS,LOW);}
  else {digitalWrite(lampS,HIGH);}   
  }
else {digitalWrite(lampS,LOW);}

if(statoLampD==1)
  {
  if(signalBlink==1) {digitalWrite(lampD,LOW);}
  else {digitalWrite(lampD,HIGH);}
  }
else {digitalWrite(lampD,LOW);}

if(statoLampS==1 || statoLampD==1)
  {
  if(signalMillis+delayForSignal>millis()) {signalBlink=1;}
  else
    {
    signalBlink=0;
    if(signalMillis+delayForSignal+delayForSignal<millis())
      {signalMillis=millis();}
    }
  }
}

Deve suonare solo se digitalRead(lampS)!=digitalRead(lampD)

esatto, sto cercando di capire come inserirlo, ma con le prove che faccio anche se aggiungo un altro if per negare il suono con i due stati degli interruttori, giustamente emette un brutto suono, visto che uno gli dice di suonare e l'altro no

spero di farmi capire, vorrei capirne le logica di come posso fare

grazie
p.s. scusa ma ho visto una cosa strana....

  if(signalBlink==1) {digitalWrite(lampD,LOW);}
  else {digitalWrite(lampD,HIGH);}
  }
else {digitalWrite(lampD,LOW);}

come è possibile che quei due " else" non mi diano errore????

rigrazie

Se leggi tutto, vedi che va bene... :slight_smile:

if(statoLampD==1)
  {
  if(signalBlink==1) {digitalWrite(lampD,LOW);}
  else {digitalWrite(lampD,HIGH);}
  }
else {digitalWrite(lampD,LOW);}

Io non ho ancora capito se digitalWrite(lampS,LOW); accende la lampada o la spegne >:(

Basterebbe un semplice commento:

const byte S=2;        // ingresso, livello 1 quando premuto
const byte D=3;
const byte lampS=4;    // uscita, livello ... per accendere
const byte lampD=5;
const byte buzzer=6;

Riscriverei il tutto in modo più compatto, e soprattutto riscriverei quel cavolo di blinker, contorto all’inverosimile per risparmiare UNA variabile :stuck_out_tongue:

void loop()
{
    // tempo ciclo attuale
    unsigned long now = millis();

    // timer sinistro
    if      (digitalRead(S) == PRESSLEVEL)   { statoLampS=1; t0=now; }
    else if (now-t0 >= 500  && !signalBlink) { statoLampS=0;         }

    // timer destro
    if      (digitalRead(D) == PRESSLEVEL)   { statoLampD=1; t0=now; }
    else if (now-t0 >= 500  && !signalBlink) { statoLampD=0;         }

    // comando uscite
    digitalWrite (lampS, (statoLampS && signalBlink) ? ONLEVEL : OFFLEVEL);
    digitalWrite (lampD, (statoLampD && signalBlink) ? ONLEVEL : OFFLEVEL);

    // blinker
    if (!conta  && (statoLampS | statoLampD))
    {
        signalBlink = !signalBlink;
        t1 = now;
        conta = 1; 
    }
    else if (conta  && (now-t1 >= 400)) { conta = 0; }
}

Prima si definiranno le costanti PRESSLEVEL ONLEVEL OFFLEVEL in base ai propri collegamenti hardware:

#define PRESSLEVEL ...  <- livello letto a contatto premuto
#define ONLEVEL    ...  <- livello che accende le luci
#define OFFLEVEL   ...  <- livello che spegne le luci

I timer sinistro e destro usano la stessa variabile temporale ‘t0’, questo permette di attivare un lato e poi passare all’altro entro mezzo secondo mantenendoli entrambi attivi.

Le uscite lampeggiano per l’AND tra il segnale di attivazione continuo proveniente dai timer, e quello alternato proveniente dal blinker.

Il blinker si trova normalmente a 0 nello stato “non conta”. Commuta appena diventa alto il segnale destro o sinistro, fa una pausa di 400ms usando la variabile temporale ‘t1’, e ricommuta. Il segnale ‘signalBlink’ finisce sempre per tornare a 0 in quanto solo con questo valore i due timer iniziali ricommutano a zero quando non c’è più un comando in ingresso (commutatore su centrale).

Ora è compattato e ripulito.

Rimane solo il buzzer, che sarà da accendere (tone) o spegnere (noTone) in concomitanza con la commutazione della variabile signalBlink, ma non sarà da accendere nel caso in cui entrambi i segnali sinistro e destro siano attivi contemporaneamente.

Io non ho ancora capito se digitalWrite(lampS,LOW); accende la lampada o la spegne >:(

A quanto pare, i relè si attivano con le uscite a livello basso. Per questo, nel programma che ho pubblicato nel mio messaggio #11 ho usato ON e OFF anziché HIGH e LOW e all'inizio ho scritto:

const bool ON=LOW;

Datman:
A quanto pare, i relè si attivano con le uscite a livello basso.

Il che vorrebbe dire normalmente sempre accesi, ho riscritto la logica in modo che non ci siano simili ambiguità ::slight_smile: :wink:

allora il digitalWrite(lampS,LOW) è per tenere spenti i rele che comandano le luci

ok apportate le correzioni, grazie come al solito Claudio.
Adesso studio per la modifica del buzzer.

grazie, appena fatto vi faccio sapere

// LED Flasher Relay with hazard lights combination v1.0 for motorcycles with Arduino or ATTiny85
// by Fedaceag Ionut (Youtube - Think small, build big!)

// I/O pins for arduino:
const byte S=2;
const byte D=3;
const byte lampS=4;
const byte lampD=5;
const byte buzzer=6;



byte statoLampS=0;
byte statoLampD=0;

int delayForHazard=500; // delay in milliseconds for hazard light combination
unsigned long previousMillis=0;

int delayForSignal=400; // signal frequency in milliseconds
unsigned long signalMillis=0;
unsigned long t0=0;
unsigned long t1=0;
byte signalBlink=0;

#define PRESSLEVEL HIGH  //...  <- livello letto a contatto premuto
#define ONLEVEL    HIGH //...  <- livello che accende le luci
#define OFFLEVEL   LOW //...  <- livello che spegne le luci
bool conta=1;
void setup()
{
pinMode(S, INPUT);
pinMode(D, INPUT);
pinMode(lampS, OUTPUT);
pinMode(lampD, OUTPUT);
pinMode(buzzer, OUTPUT);
}
void loop()
{
    // tempo ciclo attuale
    unsigned long now = millis();

    // timer sinistro
    if      (digitalRead(S) == PRESSLEVEL)   { statoLampS=1; t0=now; }
    else if (now-t0 >= 500  && !signalBlink) { statoLampS=0;         }

    // timer destro
    if      (digitalRead(D) == PRESSLEVEL)   { statoLampD=1; t0=now; }
    else if (now-t0 >= 500  && !signalBlink) { statoLampD=0;         }

    // comando uscite
    digitalWrite (lampS, (statoLampS && signalBlink) ? ONLEVEL : OFFLEVEL);
    digitalWrite (lampD, (statoLampD && signalBlink) ? ONLEVEL : OFFLEVEL);

    // blinker
    if (!conta  && (statoLampS | statoLampD))
    {
        signalBlink = !signalBlink;
        t1 = now;
        conta = 1;
    }
    else if (conta  && (now-t1 >= 400)) { conta = 0; }
}