Controllo fari apertura/chiusura auto, errore codice? help!

Salve a tutti!
Sono un nuovo utente del forum e del mondo Arduino! XD

Sono due giorni che ho cominciato ad occuparmi della scrittura C++ e tutto cio' che ne ruota intorno.
Mi serviva un arduino per due progetti, di cui uno sono gia' riuscito egregiamente a cavarmela con qualche centinaio di prove XD

Pero' su questo mi sono impicciato:
Vi spiego.

Sto cercando di creare un programma che mi permetta, all'apertura e alla chiusura della macchina, di accendere per 30 secondi i fari.
In generale avevo in mente questo:

La macchina ha i canonici due fili per le centralizzate a comando di massa, uno è a massa a macchina aperta, uno a macchina chiusa.
Cercando per ore per il web, mescolando e cercando di capire il funzionamento di vari codici, sono arrivato a pensare a un programma che, riassumendo:

Al ricevimento della massa sul pin digitale 12 (chiusura), resetta a 0 la variabile di apertura, e fa passare la variabile di chiusura a 1, attivando il caso 1 della chiusura (accendere il pin 2 ossia rele' 1 (ancora devo arrivare alla temporizzazione per 30 secondi)).
Al ricevimento della massa di apertura, resetta a 0 la variabile di chiusura e fa passare la variabile di apertura a 1, attivando il caso 1 dell'apertura (sempre accensione per 30 secondi che ancora devo scrivere pero' del pin 4 alias rele' 2), in entrambi i casi, la variabile 0 attiva il caso 0, ossia lascia spento il rele'.

Il problema è che in questo modo, dando il contatto al pin 12, si attiva il rele1, ma dando contatto al pin 11, si spenge il rele1 come da programma, ma non si accende il rele2.

Ora, vi incollo il codice che ho scritto, SICURAMENTE sara' una ca*ata, sara' complicato, fatto male e pieno di errori, non potra' SICURAMENTE mai funzionare, ne sono cosciente e piano con le parole quindi, sto imparando! :slight_smile:
Ditemi dove sto sbagliando! =(

const int chiusura = 12;     // Numero pin dedicato alla ricezione della chiusura
const int apertura = 11;     // Numero pin dedicato alla ricezione dell'apertura
const int rele1 = 2;         // Numero pin dedicato all'attuazione del rele comando fari
const int rele2 = 4;         // Numero pin dedicato all'attuazione del rele comando fari

int countChiusura = 0;       // Variabile per la memorizzazione della chiusura
int countApertura = 0;       // Variabile per la memorizzazione dell'apertura


void setup() {
  pinMode(rele1, OUTPUT);    // Setta il pin "rele1" come output    
  pinMode(chiusura, INPUT);  // Setta il pin "chiusura" come input
  pinMode(apertura, INPUT);  // Setta il pin "apertura" come input
}

void loop(){
  
  if(digitalRead(chiusura))                                // Se è presente il segnale di chiusura
  {
    delay(400);                                            // Aspetta 0,4 secondi poi:
    
    if(countChiusura<=0) countChiusura=countChiusura+1;    // Se cCh è uguale o minore a 0, portalo a 1
    if(countApertura=1) countApertura=countApertura-1;     // Se cAp è uguale a 1, portalo a 0
  }  
  

     
  switch (countChiusura)                                   // Switcha tra i due casi:
{
  case 1:                                                  // Caso 1:
     digitalWrite(rele1, LOW);                             // Accendi rele1
     break;                                                // Fine caso 1
  
  case 0:                                                  // Caso 0:
     digitalWrite(rele1, HIGH);                            // Spengi rele1
     break;                                                // Fine caso 0
}

  if(digitalRead(apertura))                                // Se è presente il segnale di apertura
  {
 
  delay(400);                                              // Aspetta 0,4 secondi poi:
  
  if(countApertura<=0) countApertura=countApertura+1;      // Se cAp è uguale o minore di 0, portalo a 1
  if(countChiusura=1) countChiusura=countChiusura-1;       // Se cCh è uguale a 1, portalo a 0
}
  switch (countApertura)                                   // Switcha tra i due casi:
{
  case 1:                                                  // Caso 1:
     digitalWrite(rele2, LOW);                             // Accendi rele2
     break;                                                // Fine caso 1
  
  case 0:                                                  // Caso 0:
     digitalWrite(rele2, HIGH);                            // Spengi rele2
     break;                                                // Fine caso 0
}


}

Ok, primo errore trovato! :smiley:

Dimenticato un pinMode del rele2, per quello non funzionava :smiley:

Ora pensavo per farlo accendere 30 secondi e poi spengerlo e "bloccare" il loop, di fare una ulteriore variabile che dopo 30 secondi di accensione cambi lo stato a 1, sempre con i due casi switch!

Vorrei usare millis(), ma ancora ne ignoro il funzionamento, quindi pensavo a delay(), consigli?

Se in quei 30 secondi di attesa non devi fare altro, puoi usare anche delay. Millis si usa quando durante un'attesa l'Arduino deve eseguire altri compiti.

Allora, tecnicamente non deve far nulla, ma se ci fosse un repentino cambio di stato (aperto/chiuso entro i 30 secondi), il programma con delay sarebbe freezato e leggerebbe il cambiamento di stato solo allo scoccare dei 30 secondi.
Ma potrebbe essere un problema circoscritto, non mi darebbe molto fastidio.
Pero', usando delay, come posso evitare che il loop continui? ossia che allo scoccare dei 30 secondi riparta il case 1 dall'inizio riaccendendo il rele'?

P.S: Come definiresti la costruzione del codice? :smiley:

Se può capitare che la portiera e/o chiusura possa essere riattivata in quei 30 secondi, allora usa direttamente la millis.

Il loop non lo fermi a meno che non infili il codice in un... loop infinito (while(1), ad esempio), ma in questo caso ti servirebbe un reset per sbloccare la scheda.

Meglio allora prevedere 2 stati: macchina chiusa, macchina aperta.
Nello stato "macchina chiusa" la chiusura centralizzata è chiusa e l'Arduino legge il filo che dà il segnale per l'apertura della centralizzata, e passa a "macchina aperta". In questo nuovo stato, l'Arduino legge il filo per la chiusura.

mmmh..
se non erro li ho gia' i due stadi..

Aperta ho un rele' eccitato, Chiusa ho l'altro eccitato, pero' a livello di temporizzazione sinceramente non sono riuscito a trovare soluzioni..

Possibile non esista un modo per temporizzare un'uscita al rilevamento di un segnale comandato?
Non so', una variabilina, una funzioncina, datemi un indirizzamento su :slight_smile:
E' l'unica cosa che mi sta bloccando!

Ho provato con delay, ho provato con goto (che sinceramente non sono riuscito neanche a far fungere, ma vabeh, sara' l'ora tarda, ci sto sopra da oggi alle 14..), millis() non mi si calcola neanche (devo ancora capire bene il posizionamento e la funzione delle stringhe), ma anche se mi si calcolasse ci sarebbe sempre il problema dall'inizio del loop, l'unica era fare un goto ad una funzione che lasci il tutto in stallo finche' non ci sia un cambio di stato... argh! :roll_eyes:

Sì, quello che ti ho descritto è la logica (mi pare) del tuo attuale programma.

Alfa03:
Possibile non esista un modo per temporizzare un'uscita al rilevamento di un segnale comandato?
Non so', una variabilina, una funzioncina, datemi un indirizzamento su :slight_smile:
E' l'unica cosa che mi sta bloccando!

Hai 2 stati differenti. A seconda dello stato, cambi il pin da monitorare.
Durante il loop del programma leggi continuamente il pin che devi tracciare. Nel momento in cui cambia di stato, avvii un conto alla rovescia usando millis ed attendi 30 secondi (è un semplice while da cui esci quando millis>inizio_conteggio+30sec). Se durante quei 30 secondi il proprietario dell'auto riattiva la centralizzata, annulli tutto (o fai quel che devi). Altrimenti passi al nuovo stato, chiudendo o aprendo prima la vettura.

Ho provato con delay, ho provato con goto (che sinceramente non sono riuscito neanche a far fungere, ma vabeh, sara' l'ora tarda, ci sto sopra da oggi alle 14..), millis() non mi si calcola neanche (devo ancora capire bene il posizionamento e la funzione delle stringhe), ma anche se mi si calcolasse ci sarebbe sempre il problema dall'inizio del loop, l'unica era fare un goto ad una funzione che lasci il tutto in stallo finche' non ci sia un cambio di stato... argh! :roll_eyes:

No, il goto no...

Ok, ci sono riuscito! :smiley:

Forse non è proprio come hai scritto tu, ma mi hai dato l'idea!
Posto sotto il codice!

Ora devo solamente trovare la corretta scrittura di un IF che, se è presente un HIGH sul pin 8, fa' saltare tutto il programma, hai qualche consiglio su questo stupido punto? :smiley:

// Scritto da: Alessio A. Pannone
// Ultima modifica: 25/02/2013
// Consente di attivare per un tempo X alternativamente uno alla volta il pin 2 o il pin 4, al momento della 
// ricezione del segnale di apertura o chiusura portiere sul pin 11 e 12.



const int chiusura = 12;     // Numero pin dedicato alla ricezione della chiusura
const int apertura = 11;     // Numero pin dedicato alla ricezione dell'apertura
const int rele1 = 2;         // Numero pin dedicato all'attuazione del rele comando fari
const int rele2 = 4;         // Numero pin dedicato all'attuazione del rele comando fari

int countChiusura = 0;       // Variabile per la memorizzazione della chiusura
int countApertura = 0;       // Variabile per la memorizzazione dell'apertura


void setup() {
  pinMode(rele1, OUTPUT);    // Setta il pin "rele1" come output    
  pinMode(rele2, OUTPUT);    // Setta il pin "rele2" come output
  pinMode(chiusura, INPUT);  // Setta il pin "chiusura" come input
  pinMode(apertura, INPUT);  // Setta il pin "apertura" come input
}

void loop(){
  
  if(digitalRead(chiusura))                                // Se è presente il segnale di chiusura
  {
    delay(400);                                            // Aspetta X secondi poi:
    
    if(countChiusura<=0) countChiusura=countChiusura+1;    // Se cCh è uguale a 0, portalo a 1
    if(countApertura=2) countApertura=countApertura-2;     // Se cAp è uguale a 2, portalo a 0
  }  
  

     
  switch (countChiusura)                                   // Switcha tra i tre casi:
{
  case 1:                                                  // Caso 1:
     digitalWrite(rele1, LOW);                             // Accendi rele1
     delay(2000);                                          // Aspetta X secondi
     if(countChiusura=1) countChiusura=countChiusura+1;    // Se cCh è uguale a 1, portalo a 2
     break;                                                // Fine caso 1
     
  case 2:                                                  // Caso 2:
     digitalWrite(rele1, HIGH);                            // Spengi rele1 (mantenimento spento)
     break;                                                // Fine caso 2
  
  case 0:                                                  // Caso 0:
     digitalWrite(rele1, HIGH);                            // Spengi rele1
     break;                                                // Fine caso 0
}

  if(digitalRead(apertura))                                // Se è presente il segnale di apertura
  {
 
  delay(400);                                              // Aspetta X secondi poi:
  
  if(countApertura<=0) countApertura=countApertura+1;      // Se cAp è uguale a 0, portalo a 1
  if(countChiusura=2) countChiusura=countChiusura-2;       // Se cCh è uguale a 2, portalo a 0
}
  switch (countApertura)                                   // Switcha tra i tre casi:
{
  case 1:                                                  // Caso 1:
     digitalWrite(rele2, LOW);                             // Accendi rele2
     delay(2000);                                          // Aspetta X secondi
     if(countApertura=1) countApertura=countApertura+1;    // Se cAp è uguale a 1, portalo a 2
     break;                                                // Fine caso 1
      
  case 2:                                                  // Caso 2:
     digitalWrite(rele2, HIGH);                            // Spengi rele2 (mantenimento spento)
     break;                                                // Fine caso 2
  
  case 0:                                                  // Caso 0:
     digitalWrite(rele2, HIGH);                            // Spengi rele2
     break;                                                // Fine caso 0
}


}

Alfa03:
Ok, ci sono riuscito! :smiley:

Forse non è proprio come hai scritto tu, ma mi hai dato l'idea!

L'importante è che tu lo abbia scritto da solo!
Bravo! :wink:

Ora devo solamente trovare la corretta scrittura di un IF che, se è presente un HIGH sul pin 8, fa' saltare tutto il programma, hai qualche consiglio su questo stupido punto? :smiley:

Spiega meglio

Sostanzialmente, mi serve che se è presente il sottoquadro sul PIN 8 (HIGH), il programma non venga eseguito cosi' come deve funzionare normalmente, ma "loopare" su un generico "rele1 HIGH" (non so perche' ma i rele' scattano col comando LOW, forse sono a comando di massa), evitando in questo modo di accendere i fari se qualcuno all'interno chiude le chiusure manualmente (solo col quadro acceso).

Sto provando ad effettuare una cosa del genere (posto solo le relative parti del codice):

const int sottoQuadro = 8;
int sottoQ = 0;

void setup() 
{
pinMode(sottoQuadro, INPUT);
}

void loop(){
  
sottoQ = digitalRead(sottoQuadro);
  
     if(sottoQ == HIGH)
  
     switch (sottoQ)                                       
{
  case HIGH:                                               
     digitalWrite(rele1, HIGH);                            
     break;                                                
 }

Lo legge (se metto digitalWrite LOW mi accende il rele quando do il +5v all'8), ma non mi chiude il loop su digitalWrite(rele1, HIGH) evitando cosi' il resto del programma finche' non viene a mancare il sottoquadro.
Dove erro?

Il loop() contiene uno switch all'interno di un if che è del tutto inutile:

void loop(){
  
sottoQ = digitalRead(sottoQuadro);
  
     if(sottoQ == HIGH)
  
     switch (sottoQ)                                       
{
  case HIGH:                                               
     digitalWrite(rele1, HIGH);                            
     break;                                                
 }

Per fare quello che vuoi, al verificarsi del segnale sul pin 8 devi fare una lettura continua finché quel pin non torna low.

void loop() {
    if (digitalRead(sottoQuadro) == HIGH) {
        digitalWrite(rele1, HIGH); //basta una volta, il pin non torna su low da solo
        while (digitalRead(sottoQuadro) == HIGH)); //così fermi il loop finché il pin non torna a low
        digitalWrite(rele1, LOW); //non so se va rimesso basso - levalo tu
    }
}

Hai ragione! :smiley:

Cosi' funziona perfettamente come dico io!

mi mancava lo "while"!

Ora voglio giusto fare qualche prova per vedere se riesco a gestire tutto con un rele' solo! Ma gia' cosi' è perfetto! :smiley:
Per ora grazie! :wink:

posto il codice completo:

// Scritto da: Alessio A. Pannone
// Ultima modifica: 26/02/2013
// Consente di attivare per un tempo X alternativamente uno alla volta il pin 2 o il pin 4, al momento della 
// ricezione del segnale di apertura o chiusura portiere sul pin 11 e 12.



const int chiusura = 12;     // Numero pin dedicato alla ricezione della chiusura
const int apertura = 11;     // Numero pin dedicato alla ricezione dell'apertura
const int rele1 = 2;         // Numero pin dedicato all'attuazione del rele comando fari
const int rele2 = 4;         // Numero pin dedicato all'attuazione del rele comando fari

int sottoQuadro = 8;
int countChiusura = 0;       // Variabile per la memorizzazione della chiusura
int countApertura = 0;       // Variabile per la memorizzazione dell'apertura


void setup() {
  pinMode(rele1, OUTPUT);    // Setta il pin "rele1" come output    
  pinMode(rele2, OUTPUT);    // Setta il pin "rele2" come output
  pinMode(chiusura, INPUT);  // Setta il pin "chiusura" come input
  pinMode(apertura, INPUT);  // Setta il pin "apertura" come input
}

void loop(){
  
      if (digitalRead(sottoQuadro) == HIGH) {              // Se è presente sottoQuadro
        digitalWrite(rele1, HIGH);                         // Spengi rele1 (blocco programma)
        while (digitalRead(sottoQuadro) == HIGH);          // Mentre è presente sottoQuadro, spengi rele1
        digitalWrite(rele1, HIGH);                         // Spengi rele1 (blocco programma)
    }
  
  if(digitalRead(chiusura))                                // Se è presente il segnale di chiusura
  {
    delay(400);                                            // Aspetta X secondi poi:
    
    if(countChiusura<=0) countChiusura=countChiusura+1;    // Se cCh è uguale a 0, portalo a 1
    if(countApertura=2) countApertura=countApertura-2;     // Se cAp è uguale a 2, portalo a 0
  }  
  

     
  switch (countChiusura)                                   // Switcha tra i tre casi:
{
  case 1:                                                  // Caso 1:
     digitalWrite(rele1, LOW);                             // Accendi rele1
     delay(2000);                                          // Aspetta X secondi
     if(countChiusura=1) countChiusura=countChiusura+1;    // Se cCh è uguale a 1, portalo a 2
     break;                                                // Fine caso 1
     
  case 2:                                                  // Caso 2:
     digitalWrite(rele1, HIGH);                            // Spengi rele1 (mantenimento spento)
     break;                                                // Fine caso 2
  
  case 0:                                                  // Caso 0:
     digitalWrite(rele1, HIGH);                            // Spengi rele1
     break;                                                // Fine caso 0
}

  if(digitalRead(apertura))                                // Se è presente il segnale di apertura
  {
 
  delay(400);                                              // Aspetta X secondi poi:
  
  if(countApertura<=0) countApertura=countApertura+1;      // Se cAp è uguale a 0, portalo a 1
  if(countChiusura=2) countChiusura=countChiusura-2;       // Se cCh è uguale a 2, portalo a 0
}
  switch (countApertura)                                   // Switcha tra i tre casi:
{
  case 1:                                                  // Caso 1:
     digitalWrite(rele2, LOW);                             // Accendi rele2
     delay(2000);                                          // Aspetta X secondi
     if(countApertura=1) countApertura=countApertura+1;    // Se cAp è uguale a 1, portalo a 2
     break;                                                // Fine caso 1
      
  case 2:                                                  // Caso 2:
     digitalWrite(rele2, HIGH);                            // Spengi rele2 (mantenimento spento)
     break;                                                // Fine caso 2
  
  case 0:                                                  // Caso 0:
     digitalWrite(rele2, HIGH);                            // Spengi rele2
     break;                                                // Fine caso 0
}


}

Leggendo sulle caratteristiche tecniche noto che i li,iti di alimentazione tramite porta diretta sono 6-20v..
Collegando un Arduino Duemilanove alla 14.2v di un autoveicolo, si rischia o lo sopporta? altrimenti modifico un alimentatore usb da accendisigari..

Alfa03:
Leggendo sulle caratteristiche tecniche noto che i li,iti di alimentazione tramite porta diretta sono 6-20v..
Collegando un Arduino Duemilanove alla 14.2v di un autoveicolo, si rischia o lo sopporta? altrimenti modifico un alimentatore usb da accendisigari..

c'è un intero topic sull'alimentazione di arduino in macchina ti conviene leggerlo, ci sono troppi disturbi sulle alimentazioni delle auto :smiley:

nella sezione Hardware? vado a vedere XD

Alfa03:
Leggendo sulle caratteristiche tecniche noto che i li,iti di alimentazione tramite porta diretta sono 6-20v..

Questi sono limiti massimi.
I limiti per far lavorare in sicurezza il regolatore su scheda sono 7-12V.

Input Voltage (recommended) 7-12V

Questo perché il regolatore ed il diodo a protezione introducono un calo di tensione di circa 2V per cui con 6V saresti a 4V in uscita. Sopra ai 12V invece il regolatore potrebbe scaldare troppo.

ok, provvedero' allora all'adozione di un alimentatore 5v per USB!
Fine OT :smiley:

Comunque ho sostituito nel secondo switch rele2 con rele1, e ora gestisce tutto tramite un rele' unico! :smiley:

Dai, come provo vi posto un video! ahahahaha

Allora!

Il tutto funziona perfettamente!

Ora, vorrei riuscire a sostituire il delay con millis()!

Pero' sinceramente snazzicando in rete e sul forum non ho capito molto come implementarla..

O meglio, ho fatto qualche prova, ma senza risultati.

Ho provato, copiando una porzione di codice da un'altro post, tutte le variabili necessarie e la parte " if (millis() - previousMillis > interval) {
previousMillis = millis();" in varie parti del codice, prima, dopo, in mezzo, al punto di fermo, ma sinceramente ne ignoro il funzionamento, e non riesco a trovare nulla di chiaro.
Ho capito che sostanzialmente "conta" i millisecondi dall'avvio di Arduino, ed esegue l'istruzione che gli viene assegnata ogni volta che ricapiti, ad esempio, l'aumento di 1000ms.

Ma praticamente parlando, come funziona questa millis? blocca il programma? esegue l'istruzione per x secondi?
Datemi chiarezzaaaa =( XD

Millis() è una funzione che restituisce i millisecondi dall'avvio dell'Arduino.
Per capire come usarlo guarda lo sketch "BlinkWithoutDelay" allegato all'IDE, che ti mostra come eseguire un comando temporizzato senza bloccare l'Arduino in un delay.