Go Down

Topic: Tre condizioni (Read 240 times) previous topic - next topic

stefano71

Ciao a tutti.

Ho creato due condizioni (vero e falso) che mi permettono di gestire due servo motori per scambio treno lego

Code: [Select]
void loop()
{
  if ( digitalRead(swClose) == LOW ) { statoPL = true;  }
  if ( digitalRead(swOpen) == LOW )  { statoPL = false; }



Avrei pero bisogno di crearne una successiva legata al tempo. Vale a dire dopo 20 sec oltre a quello che succede nello stato vero deve attivarsi anche un rele. Come definisco la terza condizione?

Grazie

fabpolli

Supponendo che nel frattempo tu voglia fare altre cose la soluzione risiede nell'uso di millis, ovvero quando entri in uno dei due if prendi il valore di millis da usare come riferimento iniziale e poi con un if apposito trascorso il tempo fai ciò che devi (nel tuo caso attivare il relé), per capire le basi con cui si usa millis() consiglio prima la lettura di QUESTO post esplicativo, dopo di che lo studio di come si usa la funzione millis(), prima QUI, poi QUI e QUI e QUI e tutti gli articoli che sono in QUESTA pagina ... alla fine il tutto dovrebbe essere più chiaro :)

ORSO2001

ciao...pseudo codice

se (lettura = LOW)
   statoPL = LOW
   se (tempo >= 20000)
       faccio altro...
diversamente
   tempo = millis()
   altro...

stefano71

Grazie

Questo è quello che ho inserito oggi

Code: [Select]
void loop()
{
  if ( digitalRead(swClose) == LOW ) { statoPL = true;  }
  if ( digitalRead(swOpen) == LOW )  { statoPL = false; }
 
  if ( statoPL == true && currentGrad > posMin) {
     digitalWrite( ledSemaf,HIGH );
     while (currentGrad > posMin) {
        currentGrad--;
        servo1.write(currentGrad);
        servo2.write(currentGrad);
        delay(timePL);
   }
 }
  if ( statoPL == false  && currentGrad < posMax) {
     while (currentGrad < posMax) {
        currentGrad++;
        servo1.write(currentGrad);
        servo2.write(currentGrad);
        delay(timePL);
     }
     digitalWrite( ledSemaf,LOW );
   }
 }


Quindi devo creare un altro if?

Datman

#4
Apr 16, 2019, 02:00 pm Last Edit: Apr 16, 2019, 02:03 pm by Datman
Intanto, se non devi modificare le variabili indipendentemente dallo stato dei sensori, puoi semplificare così (n.b.: c'era anche qualche errore nell'indentazione):
Code: [Select]
void loop()
{
  if (digitalRead(swClose) == LOW && currentGrad > posMin) {
     digitalWrite(ledSemaf,HIGH);
     while (currentGrad > posMin) {
        currentGrad--;
        servo1.write(currentGrad);
        servo2.write(currentGrad);
        delay(timePL);
     }
  }
  if (digitalRead(swOpen) == LOW  && currentGrad < posMax) {
     while (currentGrad < posMax) {
        currentGrad++;
        servo1.write(currentGrad);
        servo2.write(currentGrad);
        delay(timePL);
     }
     digitalWrite(ledSemaf,LOW);
  }
}
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

fabpolli

Quindi devo creare un altro if?
Dopo il secondo if al loro stesso "livello" ovvero dentro il loop ma fuori da entrambe gli if che già hai fatto.
Dentro i due if dovrai mettere la variabile di "inizio conteggio" del millis e nell'if che andrai ad aggiungere confronterai tale variabile con il valore attuale ecc. ecc. ma per quello ti rimando nuovamente alla documentazione che ti ho linkato nel post precedente

stefano71

Ci sto provando ma sbaglio qualcosa:

Code: [Select]
#include <Servo.h>

#define swClose  2
#define swOpen   3
#define ledSemaf 4
#define relay_1 13

#define posMin 0
#define posMax 50
#define timePL 10

unsigned long T0;
int stato;

boolean statoPL=false;
int currentGrad=posMax;
 
Servo servo1;
Servo servo2;
 
void setup()
{
  pinMode( swClose,INPUT );
  pinMode( swOpen,INPUT );
  pinMode( ledSemaf,OUTPUT );
  pinMode(relay_1,OUTPUT);
  T0= millis();
  stato=0 ;
 
  servo1.attach(5);
  servo2.attach(6);
  servo1.write(currentGrad);
  servo2.write(currentGrad);
  digitalWrite( ledSemaf,LOW );
  digitalWrite(relay_1,LOW);
}
 
void loop()
{
  if ( digitalRead(swClose) == LOW ) { statoPL = true;  }
  if ( digitalRead(swOpen) == LOW )  { statoPL = false; }
 
 
  if ( statoPL == true && currentGrad > posMin) {
     digitalWrite( ledSemaf,HIGH );
     while (currentGrad > posMin) {
        currentGrad--;
        servo1.write(currentGrad);
        servo2.write(currentGrad);
        delay(timePL);
     }
  }

  if (statoPL == true){
     millis() - T0 > 20000 ;
     digitalWrite( relay_1,HIGH);
     }   

       
  if ( statoPL == false  && currentGrad < posMax) {
     while (currentGrad < posMax) {
        currentGrad++;
        servo1.write(currentGrad);
        servo2.write(currentGrad);
        delay(timePL);
     }
     digitalWrite( ledSemaf,LOW );
   }
 }

maubarzi

Non sono mica riuscito a capire cosa vuoi fare.
Ti spiace descrivere esattamente cosa vuoi ottenere?
Ho capito che hai una pista lego con, immagino, un treno che ci corre sopra.
Ho letto semaforo, quindi presumo tu voglia gestire il semaforo per segnalare il passaggio del treno.
I 2 servo muovono la leva dello scambio? Dovresti averne due se hai una diramazione che poi si ricongiunge. Li gestisci separatamente? Oppure hai 3 strade possibili? Gli scambi dovrebbero funzionare solo in un senso, nell'altro il percorso è obbligato per cui, o fai tornare indietro il treno, o hai 3 strade, giusto?
C'è altro?
Poi definiti i vari elementi, prova a descrivere il comportamento dell'intero sistema.
Una cosa del tipo, il treno parte, dopo 10s il semaforo deve scattare, quando il treno passa davanti al sensore X faccio scattare lo scambio Y, ecc. In modo che si capiscano esattamente tutti i movimenti che servono e le tempistiche (più o meno, poi i secondi precisi si sistemeranno)
Nessuna buona azione resterà impunita!

Preistoria -> medioevo -> rinascimento -> risorgimento -> rincoglionimento!

stefano71

#8
Apr 16, 2019, 07:47 pm Last Edit: Apr 16, 2019, 08:12 pm by stefano71
Ciao Maubarzi ..ora mi spiego meglio.

In effetti è un treno lego che percorre una piccola pista che si dirama in due per poi riunirsi.
Il treno percorre i binari sempre verso la stessa direzione.
Al semaforo non farci caso toglierò tutto dallo sketch, perchè viene gestito, insieme al passaggio a livello da un altro arduino.

Tutto funzionava cosi':


Code: [Select]
#include <Servo.h>

#define swClose  2
#define swOpen   3
#define ledSemaf 4


#define posMin 0
#define posMax 50
#define timePL 10



boolean statoPL=false;
int currentGrad=posMax;

Servo servo1;
Servo servo2;

void setup()
{
pinMode( swClose,INPUT );
pinMode( swOpen,INPUT );
pinMode( ledSemaf,OUTPUT );

servo1.attach(5);
servo2.attach(6);
servo1.write(currentGrad);
servo2.write(currentGrad);
digitalWrite( ledSemaf,LOW );

}

void loop()
{
if ( digitalRead(swClose) == LOW ) { statoPL = true;  }
if ( digitalRead(swOpen) == LOW )  { statoPL = false; }


if ( statoPL == true && currentGrad > posMin) {
  digitalWrite( ledSemaf,HIGH );
  while (currentGrad > posMin) {
     currentGrad--;
     servo1.write(currentGrad);
     servo2.write(currentGrad);
     delay(timePL);
  }
}

    
if ( statoPL == false  && currentGrad < posMax) {
  while (currentGrad < posMax) {
     currentGrad++;
     servo1.write(currentGrad);
     servo2.write(currentGrad);
     delay(timePL);
  }
  digitalWrite( ledSemaf,LOW );
}



Praticamente il treno passa su un sensore e attiva i servo motori per predisporre lo scambio in modo tale da far passare il treno sul secondo tratto dove si trova un nuovo sensore che riporta lo scambio nelle condizioni iniziali che fanno si di riportare il treno sulla prima traccia.
Il treno si avvia in automatico ad una certa ora per poi interrompersi dopo qualche minuto.
Il tutto avviene dando alimentazione e togliendola dopo qualche minuto.
Cosi' facendo il treno può trovarsi in una condizione particolare (treno in parte sugli scambi) che al riavvio rischio che parte dei vagoni si stacchino o deraglino.

Ho pensato cosi di obbligare il treno a fermarsi in un punto particolare, sfruttando i sensori che ho già.

Quindi, tutto parte normalmente ma dopo un tot di tempo ( che si aggira intorno a 100 sec) un sensore deve attivarmi un rele che toglierà l'alimentazione e mi fermerà il tutto.


Spero di essere stato chiaro.

Datman

[comicMode] Shrek sui scrive con la maiuscola!
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

stefano71


maubarzi

#11
Apr 16, 2019, 08:40 pm Last Edit: Apr 16, 2019, 08:46 pm by maubarzi
Ok, quindi ad ogni giro muovi lo scambio per alternare sui due percorsi.
Da quando si avvia, gira per 100 secondi e poi deve scattare il relè per spegnere tutto, giusto?
I due sensori sono normalmente HIGH e quando rilevano il treno vanno a LOW?
Quindi l'unica cosa che ti servirebbe è gestire il relè dopo 100 secondi dall'avvio.
Quindi una cosa del tipo (metto solo la roba nuova)

Code: [Select]

#define DURATA 100000 // 100 * 1000 mS = 100s
#define TEMPO_ARRESTO 5000 // Assumo 5s come tempo di arresto sicuro dopo il passaggio su uno dei due sensori in modo da non fermare il treno in mezzo ad uno scambio.
unsigned long startTime = 0;
boolean arresto = false;
unsigned long arrestoTime = 0;

void setup() {
  ...
  startTime = millis();
}

void loop() {
  if ( digitalRead(swClose) == LOW ) {
    statoPL = true;
    if (arresto) {
      // Qui ci arriva solo quando è iniziata la procedura di arresto e imposta il tempo di riferimento per lo stop effettivo.
      arrestoTime = millis();
    }
  }
  if ( digitalRead(swOpen) == LOW ) {
    statoPL = false;
    if (arresto) {
      // Qui ci arriva solo quando è iniziata la procedura di arresto e imposta il tempo di riferimento per lo stop effettivo.
      arrestoTime = millis();
    }
  }
  // Della parte sopra non ho toccato nulla perchè ti funziona già
  ...
  if (millis() - startTime > DURATA) {
    // Attivare il relè. Oppure attiviamo la procedura di arreto.
    arresto = true;
  }
  // arrestoTime è sempre zero tranne quando è iniziata la procedura di arresto e il treno è passato per un sensore.
  if (arrestoTime > 0 && millis() - arrestoTime > TEMPO_ARRESTO) {
    // E' passato il tempo di arresto sicuro, arrestiamo il treno attivando il relè.
    digitalWrite...
  }
}

Ho fatto in modo che dopo che è passato il tempo previsto, aspetti il passaggio per un sensore e poi
aspetti il tempo di arresto che dovrebbe garantire al treno di passare completamente lo scambio così da non rischiare di fermarsi nel mezzo.

Ho scritto a cappella, quindi potrei aver fatto vari errori, verifica se è quello che ti serve e se capisci tutto e poi, se serve, riadattalo ai tuoi scopi.
Nessuna buona azione resterà impunita!

Preistoria -> medioevo -> rinascimento -> risorgimento -> rincoglionimento!

Go Up