Diversi problemi di programmazione per modellino cancello scorrevole.

Salve ragazzi, sto realizzando un modellino di un cancello automatico scorrevole. Il video fa vedere il funzionamento del programma:TEST_CANCELLO
I pulsanti sono solo per prova per poi sostituirli con le fotocellule e i finecorsa.
-1 pulsante apertura cancello
-2 pulsante finecorsa apertura cancello
-3 pulsante finecorsa chiusura cancello
-4 pulsante fotocellula
-5 pulsante chiusura cancello
-led bianco = lampeggiante
-led verde = apertura cancello
-led blu = chiusura cancello
Ora però ci sono diversi problemi nel programma:
-Quando il finecorsa di apertura va a 1 cioè quando il cancello e tutto aperto i relè non scattano subito ma dopo circa mezzo secondo/un secondo. Io vorrei però che appena FCA passa a 1 il relè vada a zero. Come posso risolvere questo problema?
-Quando il cancello si sta chiudendo e la fotocellula FC rileva qualche oggetto il cancello si deve fermare per due secondi per poi aprirsi nuovamente ovviamente con il lampeggiante sempre attivo! Come potrei fare per fargli fare questa cosa?
-Quando si attiva il finecorsa di chiusura (FCC), come in FCA, i relè non scattano istantaneamente.
-Quando il cancello è in fase di chiusura , se si preme il pulsante di apertura(PA) il cancello si arresta per due secondi per poi invertire la marcia e riaprirsi.
-Quando il cancello è nello stato di temporizzazione premendo il pulsante di chiusura il cancello si chiude immediatamente senza aspettare il tempo prestabilito per la chiusura automatica.
Mi potete aiutare con il programma? Consigli su come risolvere questi problemi e implementare le funzioni che ho detto prima? Ah prima che mi dimentico la scheda che ho io è a logica inversa quindi quando l'uscita e HIGH i relè sono LOW e viceversa
Questo è il codice che ho realizzato:

#define F1     2  //pin rele 1 per fase motore avanti
#define F2     3  //pin rele 2 per fase motore indietro
#define F3     4  //pin rele 3 per fase motore comune 
#define H      5  //pin rele 4 per lampada lampeggiante
#define PA     12 //pulsante apertura cancello
#define PC     8  //pulsante chiusura cancello
#define FCA    11 //finecorsa apertura cancello
#define FCC    10 //finecorsa chiusura cancello
#define FC     9  //fotocellula per sicurezza
#define PAT    6  //pulsante apertura telecomando
#define PCT    7  //pulsante chiusura telecomando


int STATOP=0;
int STATOFCA=0;
int STATOFCC=0;
int STATOFC=1;
int STATOP1=0;
int RITARDO=0;
int STATO=0;


void setup() {
  pinMode(F1, OUTPUT);
  pinMode(F2, OUTPUT);
  pinMode(F3, OUTPUT);
  pinMode(H, OUTPUT);
  pinMode(PA, INPUT);
  pinMode(PC, INPUT);
  pinMode(FCA, INPUT);
  pinMode(FCC, INPUT);
  pinMode(FC, INPUT);
  pinMode(PAT, INPUT);
  pinMode(PCT, INPUT);
  digitalWrite(F1,HIGH);
  digitalWrite(F2,HIGH);
  digitalWrite(F3,HIGH);
  digitalWrite(H,HIGH);
}


void loop() {
if(digitalRead(PA)==1 || STATO==1 || digitalRead(PAT)==1)   //TASTO P PREMUTO
 {STATO=1; 
  if(digitalRead(FCA)==0)           //
    {digitalWrite(F1,LOW);
     digitalWrite(F3,LOW);
     digitalWrite(H,LOW);
     delay(500);
     digitalWrite(H,HIGH);
     delay(500);
    }
  else
    {STATO=3;
     digitalWrite(F1,HIGH);
     digitalWrite(F3,HIGH);
     digitalWrite(H,HIGH);
    }
 }

if(digitalRead(PC)==1 || STATO==2 || digitalRead(PCT)==1) //CHIUSURA -----------------------------------------------------
{
STATO=2;
if(digitalRead(FCC)==0) //FCC NON attivato
{
digitalWrite(H,LOW);
delay(500);
digitalWrite(H,HIGH);
delay(500);
digitalWrite(F2,LOW);
digitalWrite(F3,LOW);
if(digitalRead(FC)==1) //Barriera fotocellula attivata
{
digitalWrite(F1,HIGH);
digitalWrite(F2,HIGH);
digitalWrite(F3,HIGH);
delay(2000);
STATO=1;
}
}
else //FCC ATTIVATO
{
STATO=0;
digitalWrite(F1,HIGH);
digitalWrite(F2,HIGH);
digitalWrite(F3,HIGH);
digitalWrite(H,HIGH);
}
}

if(STATO==3) //APERTO-TEMPORIZZAZIONE -------------------------------------------------
{
delay(10000);
STATO=2;

}
   


}

Buongiorno,
essendo il tuo primo post, nel rispetto del regolamento, ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

Buongiorno REbox,

premettendo che... spero di non sparare boiate...e che in ogni caso, quanto scrivo, vale solo per il modellino.

il delay() blocca il programma fino allo scadere del suo valore...con millis() puoi fare un confronto del tempo trascorso mentre il programma continua a "girare".

se vuoi che all'insorgere di un evento il programma "molli" tutto e faccia qualche cosa di specifico devi usare gli interrupts...attenzione che solo alcuni PIN sono selezionabili per l'interrupt (vedi specifica scheda in tuo possesso) e che l'eventuale verifica del tempo durante la funzione chiamata, da esso, non viene verificato.

Nel tuo sketch non vedo interrupt e vedo solo delay()...quindi il programma viene sempre ciclato per intero e se un evento lo verifichi, per esempio, alla riga 20...comunque verranno eseguite le 19 precedenti, con eventuali delay().

Da quanto ho capito i PIN per l'interrupt sono 2 e 3 per arduino uno. Mi potresti spigare bene come si utilizza l'interrupt e come metterlo nel mio programma? E invece la funzione millis non ho capito bene come funziona e cosa cambia dal delay?

REbox:
... E invece la funzione millis non ho capito bene come funziona e cosa cambia dal delay?

Puoi studiarti come si usa la millis(), prima QUI, poi QUI ed infine leggi anche QUI e QUI ... vedrai che ti si chiarirà la cosa.

Guglielmo

REbox:
... Mi potresti spigare bene come si utilizza l'interrupt e come metterlo nel mio programma?

Prova a dare un occhiata QUI ed a fare una ricerca su Google per "Arduino Interrupt"

Guglielmo

Nel mentre studi i link proposti da gpb01, la millis() e la micros() non "fermano" il microcontrollore.

ciao REbox,

per la millis()...prova ad eseguire i due sketch allegati e vedi che differenze vedi (sul monitor seriale)

unsigned long milli;
int num;

void setup() {
  Serial.begin(9600);
  milli = millis();
  num = 0;
}
void loop() {
  if (millis() - milli == 500) {
    Serial.println("ciao");
    Serial.println(num);
    milli = millis();
  }
  num += 1;
}
int num;

void setup() {
  Serial.begin(9600);
  num = 0;
}
void loop() {

  Serial.println("ciao");
  Serial.println(num);
  delay(500);

  num += 1;
}

per l'interrupt guarda l'esempio che trovi alla reference AttachInterrupt()...e che sostanzialmente è:

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
}

ciao

ciao...nei primi due sketch, invece di int, dichiara anche num come unsigned long...forse è più chiaro

Grazie mille per le numerose risposte! Allora per adesso o risolto il problema del ritardo di spegnimento dei relè quando FCA e FCC vanno a 1 utilizzando la l'istruzione millis.

#define F1     2  //pin rele 1 per fase motore avanti
#define F2     3  //pin rele 2 per fase motore indietro
#define F3     4  //pin rele 3 per fase motore comune 
#define H      5  //pin rele 4 per lampada lampeggiante
#define PA     12 //pulsante apertura cancello
#define PC     8  //pulsante chiusura cancello
#define FCA    11 //finecorsa apertura cancello
#define FCC    10 //finecorsa chiusura cancello
#define FC     9  //fotocellula per sicurezza
#define PAT    6  //pulsante apertura telecomando
#define PCT    7  //pulsante chiusura telecomando


int RITARDO=0;
int STATO=0;
int STATOH=0;
unsigned long VALORE_PRECEDENTE_MILLIS=0; //will store last time LED was updated
unsigned long INTERVALLO_LAMPEGGIO=500; //interval at which to blink (milliseconds)


void setup() {
  pinMode(F1, OUTPUT);
  pinMode(F2, OUTPUT);
  pinMode(F3, OUTPUT);
  pinMode(H, OUTPUT);
  pinMode(PA, INPUT);
  pinMode(PC, INPUT);
  pinMode(FCA, INPUT);
  pinMode(FCC, INPUT);
  pinMode(FC, INPUT);
  pinMode(PAT, INPUT);
  pinMode(PCT, INPUT);
  digitalWrite(F1,HIGH);
  digitalWrite(F2,HIGH);
  digitalWrite(F3,HIGH);
  digitalWrite(H,HIGH);
}


void loop() {
if(digitalRead(PA)==1 || STATO==1 || digitalRead(PAT)==1)   //TASTO P PREMUTO
 {STATO=1; 
  if(digitalRead(FCA)==0)           //
    {digitalWrite(F1,LOW);
     digitalWrite(F3,LOW);
     unsigned long VALORE_CORRENTE_MILLIS = millis();
     if(VALORE_CORRENTE_MILLIS - VALORE_PRECEDENTE_MILLIS > INTERVALLO_LAMPEGGIO) 
       {VALORE_PRECEDENTE_MILLIS = VALORE_CORRENTE_MILLIS; 
       STATOH ^= 1;
       digitalWrite(H, STATOH);
       }
    }
  else
    {STATO=3;
     digitalWrite(F1,HIGH);
     digitalWrite(F3,HIGH);
     digitalWrite(H,HIGH);
    }
 }

if(digitalRead(PC)==1 || STATO==2 || digitalRead(PCT)==1) //CHIUSURA -----------------------------------------------------
{
STATO=2;
if(digitalRead(FCC)==0) //FCC NON attivato
{unsigned long VALORE_CORRENTE_MILLIS = millis();
 if(VALORE_CORRENTE_MILLIS - VALORE_PRECEDENTE_MILLIS > INTERVALLO_LAMPEGGIO) 
  {VALORE_PRECEDENTE_MILLIS = VALORE_CORRENTE_MILLIS; 
   STATOH ^= 1;
   digitalWrite(H, STATOH);
  }
digitalWrite(F2,LOW);
digitalWrite(F3,LOW);
if(digitalRead(FC)==1) //Barriera fotocellula attivata
{
digitalWrite(F1,HIGH);
digitalWrite(F2,HIGH);
digitalWrite(F3,HIGH);
digitalWrite(H,LOW);
delay(2000);
STATO=1;
}
}
else //FCC ATTIVATO
{
STATO=0;
digitalWrite(F1,HIGH);
digitalWrite(F2,HIGH);
digitalWrite(F3,HIGH);
digitalWrite(H,HIGH);
}
}

if(STATO==3) //APERTO-TEMPORIZZAZIONE -------------------------------------------------
{delay(5000);
 STATO=2;


}
   


}

Ora per fare queste due cose:
-Quando il cancello è in fase di chiusura , se si preme il pulsante di apertura(PA) il cancello si arresta per due secondi per poi invertire la marcia e riaprirsi.
-Quando il cancello è nello stato di temporizzazione premendo il pulsante di chiusura il cancello si chiude immediatamente senza aspettare il tempo prestabilito per la chiusura automatica.
Devo utilizzare il comando interrupt?

E per fargli fare questa?
-Quando il cancello si sta chiudendo e la fotocellula FC rileva qualche oggetto il cancello si deve fermare per due secondi per poi aprirsi nuovamente ovviamente con il lampeggiante sempre attivo!

Qualcuno che mi può aiutare per sistemare gli ultimi problemi?

ciao REbox,

sicuramente devi usare gli interrupts...quindi occhio ai pin che usi...se hai un Arduino UNO gli interrupts vengono gestiti solo dai pin 2 e 3.
Secondo me, ma è una mia opinione, lavorerei solo ad interrupt...o che abilitino/disabilitino delle flags per delle condizioni esterne (funzioni) e/o che svolgano loro stessi delle funzioni specifiche, magari verificando cos'era successo prima...attenzione che con gli interrupts i delay() non funzionano e nemmeno la millis()..