Go Down

Topic: Codice azionamento passerella idraulica imbarcazione. (Read 534 times) previous topic - next topic

vince59

Il thread è a metà tra software ed hardware. La premessa è che sto smanettando con la passerella indraulica della barca. Dalle belle e semplici schede a rele si è passati ai microcontrollori che più spesso danno problemi con la felicità dei costruttori che invece che riparare sostituiscono la scheda a suon di centinaia di euro.
 Avendone aperta più di una ho verificato che spesso si tratta di un semplice PIC e 4 mosfet.
Ora vorrei tornare af una semplice versione a rele pilotati da Arduino. Il concetto oprativo è questo:
- premo tasto alza -> il rele da corrente alla pompa ed all'attuatore di alzata;
- premo tasto abbassa -> un secondo rele da corrente alla pompa ed all'attuatore di abbassamento e cosi via per avanzamento ed arretramento.
Parallelando poi i contatti NA dei rele con un semplice modulo radiocomando a 4 canali (cineseria da 10 euro già utilizzati con successo per illuminazione) vorrei azionarla con telecomando quando scendo a terra e quando rientro.
Il codice non mi sembra complesso...ora la domanda che è più hardware che software...intravedete problemi o particolari attenzioni per la realizzazione pratica?...io non ne vedo.

salvogi

Intanto come hardware potresti usare qualcosa tipo lo schema allegato.
Ciao

vince59

Grazie, pensavo a qualcosa del genere, in fin dei conti quello che la scheda fa è molto semplice...quella su cui sto lavorando ora e che vorrei sostituire con una replica fatta con arduino è esattamente questa in foto. In pratica i mosfet comandano gli attuatori. L alogica è affidata ad un PIC16F...non parte l'impulso e mi sono scocciato.
Voglio provare Arduino e rele!


salvogi

Ovviamente lo schema che ti ho proposto parte dal presupposto che per invertire l'azionamento dell'attuatore è sufficiente invertire la polarità.
Inoltre bisogna vedere se ci sono dei fine corsa oppure se l'azionamento va a tempo o se si deve tenere premuto il pulsante finchè la passerella non è completamente alzata o abbassata.

Datman

Non capisco a che cosa possa servire un microcontrollore...
Metti un relè con autoritenuta (uno scambio che tiene alimentata la bobina) che la abbassa, un interruttore di fine corsa, un altro relè con autoritenuta che la alza e un altro interruttore di fine corsa... :-)
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

vince59

...infatti.  Mi sono posto la stessa domanda. Le ditte sono portate evidentemente a complicare (?) quando invece  serve solo la chiusura del teleruttore della pompa e delle 4 valvole di azionamento.
@salvogi: la pompa non inverte la rotazione (non è un trim) ma pompa solo il fluido che attraverso 4 valvole viene indirizzato verso lo specifico attuatore.
Ora volgio misurare la corrente di attivazione necessaria e provo un circuito terraterra con i pulsanti...se poi la corrente fosse alta utilizzerò dei rele.
L'idea del microcontrollore era per replicare la scheda del produttore e gestire la logica dei componenti in modo più mirato (attivazione pompa e dopo un breve ritardo attivatione valvole movimento).
@ Datman: credo che il rele con autoritenuta non vada bene. Il movimento deve essere comandato dall pressione sul pulsante. Il fine corsa...diciamo è a vista...cmq la passerella raggiunto il fine corsa fisico non si muove più ed il fluido circola nel loop.

PS: nella scheda che sto testando non ho l'impulso che attiva il MOSFET e non so come verificarlo

vince59

...dunque voglio provare un codice.
Mi suggerite di utilizzare diversi cicli "if" per ognuno dei 4 bottoni o cicli "case"?

...sono un pò rico dal caldo ma mi sa che il case non posso utilizzarlo...vero?


Claudio_FF

#7
Jul 07, 2019, 08:23 pm Last Edit: Jul 07, 2019, 08:28 pm by Claudio_FF
...dunque voglio provare un codice.
Mi suggerite di utilizzare diversi cicli "if" per ognuno dei 4 bottoni o cicli "case"?
...sono un pò rico dal caldo ma mi sa che il case non posso utilizzarlo...vero?
Il 'case' è solo un 'if' scritto in altro modo.
Nessuno dei due è un ciclo.

Quello che manca mi sembra essere la descrizione di una sequenza ben precisa di azioni da compiere... che poi si traducono in macchinese usando: sequenze di istruzioni (operazioni su porte e variabili), decisioni (if/switch) e cicli (while/for).
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

vince59

Grazie della precisazione sulla terminologia...ho da imparare ancora.

Ho buttato giù due righe con gli "if", e funziona, però testandolo sul monitor seriale noto un pò di ritardo nella risposta probabilmente dovuto al "delay" ed ho provato con "millis".
Cosa mi suggerisci di utilizzare?
Onestamente,  ho letto poco, ma  non mi è del tutto chiaro come impostare la variabile del "case" affinchè rilevi la variazione di stato di uno dei quattro pulsanti.
...spero di aver descritto in modo appropriato.
Ecco il codice buttati giù con cui azionando un tasto:
- si attiva la pompa;
- dopo un breve ritardo;
- si attiva la valvola;
...ho commesso errori?...suggerimenti?
i tasti hanno tutti resistenza di pull-up.
Considerando che il dispositivo sarà alimentato in maniera più o meno continuativa il millis che problemi potrebbe darmi?

Code: [Select]



const byte btnStateUp = 2;
const byte btnStateDown = 3;
const byte btnStateOut = 4;
const byte btnStateIn = 5;

long previousMillis = 0;
long interval = 100;

//int pausa = 100;                // attendi x durata time

void setup() {
  Serial.begin(9600);

  pinMode(btnStateUp, INPUT);   // pulsante ALZO
  pinMode(btnStateDown, INPUT); // pulsante ABBASSA
  pinMode(btnStateOut, INPUT);  // pulsante ALLUNGA
  pinMode(btnStateIn, INPUT);   // pulsante ACCORCIA

  pinMode(A0, OUTPUT); // valvola POMPA
  pinMode(A1, OUTPUT); // valvola ALZO
  pinMode(A2, OUTPUT); // valvola ABBASSA
  pinMode(A3, OUTPUT); // valvola ALLUNGA
  pinMode(A4, OUTPUT); // valvola ACCORCIA

  digitalWrite(A0, HIGH);
  digitalWrite(A1, HIGH);
  digitalWrite(A2, HIGH);
  digitalWrite(A3, HIGH);
  digitalWrite(A4, HIGH);
}

void loop() {
  {
    if (digitalRead (btnStateUp) == LOW)
    {
      Serial.println ("alzo passerella");
      analogWrite (A0, LOW); // valvola POMPA
      //   delay (pausa);
      //    ---------------- ritardo -----------------

      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
      }
  //    ---------------------------------------------
       analogWrite (A1, LOW); // valvola ALZO
    }
    else
    {
      digitalWrite(A0, HIGH);   //spegne POMPA
      digitalWrite(A1, HIGH);   //spegne ALZO
    }
    {
      if (digitalRead  (btnStateDown) == LOW)
      {
        Serial.println ("abbasso passerella");
        analogWrite (A0, LOW);
        //     delay (pausa);
  //    ---------------- ritardo -----------------

        unsigned long currentMillis = millis();
        if (currentMillis - previousMillis > interval)
        {
          previousMillis = currentMillis;
        }
  //    ---------------------------------------------
        analogWrite (A2, LOW);
      }
      else
      {
        digitalWrite(A0, HIGH);   //spegne POMPA
        digitalWrite(A2, HIGH);   //spegne ALZO
      }
    }
    {
      if (digitalRead  (btnStateOut) == LOW)
        Serial.println ("allungo passerella");
      analogWrite (A0, LOW);
      //  delay (pausa);
  //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
      }
  //    ---------------------------------------------
      analogWrite (A3, LOW);
    }
    {
      if (digitalRead  (btnStateIn) == LOW)
        Serial.println ("accorcio passerella");
      analogWrite (A0, LOW);
     // delay (pausa);
  //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
      }
  //    ---------------------------------------------
      analogWrite (A4, LOW);
    }

    /*
      switch (pushBtn) {
      case (pushBtn == ALZA):
      //do something when var equals 1

      digitalWrite(1, LOW);        // aziona pompa
      delay(pausa);                // ritardo
      digitalWrite(2, LOW);        // aziona valvola
      delay(pausa);                // pausa

      break;
      case 2:
      //do something when var equals 2

      digitalWrite(1, LOW);        // aziona pompa
      delay(pausa);                // ritardo
      digitalWrite(2, LOW);        // aziona valvola
      delay(pausa);                // pausa
      }
      break;

      default:
      // if nothing else matches, do the default
      // default is optional
      break;
      }
    */
  }
}

steve-cr

Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

vince59

..hai ragione Steve. Me ne sono accorto...il caldo fa anche questi effetti. Ora correggo.
Ora funziona ma NON riesco ad ottenre il ritardo...dove sbaglio?

Code: [Select]



const byte btnStateUp = 2;
const byte btnStateDown = 3;
const byte btnStateOut = 4;
const byte btnStateIn = 5;

long previousMillis = 0;
long interval = 500;

// int pausa = 2000;                // attendi x durata time

void setup() {
  Serial.begin(9600);

  pinMode(btnStateUp, INPUT);   // pulsante ALZO
  pinMode(btnStateDown, INPUT); // pulsante ABBASSA
  pinMode(btnStateOut, INPUT);  // pulsante ALLUNGA
  pinMode(btnStateIn, INPUT);   // pulsante ACCORCIA

  pinMode(7, OUTPUT); // valvola POMPA
  pinMode(8, OUTPUT); // valvola ALZO
  pinMode(9, OUTPUT); // valvola ABBASSA
  pinMode(10, OUTPUT); // valvola ALLUNGA
  pinMode(11, OUTPUT); // valvola ACCORCIA

  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
}

void loop() {

  // ------------- ALZO ----------------

  {
    if (digitalRead (btnStateUp) == LOW)
    {
      Serial.println ("alzo");
      digitalWrite (7, LOW); // valvola POMPA
      //  delay (pausa);
      //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
        digitalWrite (8, LOW);
      }
      //    ---------------------------------------------
      //digitalWrite (8, LOW); // valvola ALZO
    }
    else
    {
      digitalWrite(7, HIGH);   //spegne POMPA
      digitalWrite(8, HIGH);   //spegne ALZO
    }
  }
  {

    // ----------- ABBASSO ----------------

    if (digitalRead  (btnStateDown) == LOW)
    {
      Serial.println ("abbasso");
      digitalWrite(7, LOW);
      //     delay (pausa);
      //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
        digitalWrite (8, LOW);
      }
      //    ---------------------------------------------
      digitalWrite (9, LOW);
    }
    else
    {
      digitalWrite(7, HIGH);   //spegne POMPA
      digitalWrite(9, HIGH);   //spegne ALZO
    }
  }
  {

    // ------------ ALLUNGO ------------------

    if (digitalRead  (btnStateOut) == LOW)
    {
      Serial.println ("allungo");
      digitalWrite (7, LOW);
      //  delay (pausa);
      //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
        digitalWrite (10, LOW);
      }
      //    ---------------------------------------------

    }
    else
    {
      digitalWrite(7, HIGH);   //spegne POMPA
      digitalWrite(10, HIGH);   //spegne ALZO
    }
  }
  {

    // ---------------- ACCORCIO --------------------

    if (digitalRead  (btnStateIn) == LOW)
    {
      Serial.println ("accorcio");
      digitalWrite (7, LOW);
      // delay (pausa);
      //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
        digitalWrite (11, LOW);
      }
      //    ---------------------------------------------

    }
    else
    {
      digitalWrite(7, HIGH);   //spegne POMPA
      digitalWrite(11, HIGH);   //spegne ALZO
    }
  }

  /*
    switch (pushBtn) {
    case (pushBtn == ALZA):
    //do something when var equals 1

    digitalWrite(1, LOW);        // aziona pompa
    delay(pausa);                // ritardo
    digitalWrite(2, LOW);        // aziona valvola
    delay(pausa);                // pausa

    break;
    case 2:
    //do something when var equals 2

    digitalWrite(1, LOW);        // aziona pompa
    delay(pausa);                // ritardo
    digitalWrite(2, LOW);        // aziona valvola
    delay(pausa);                // pausa
    }
    break;

    default:
    // if nothing else matches, do the default
    // default is optional
    break;
    }
  */
}




Claudio_FF

#11
Jul 08, 2019, 08:09 pm Last Edit: Jul 08, 2019, 08:17 pm by Claudio_FF
Ora funziona ma NON riesco ad ottenre il ritardo...dove sbaglio?
Bisogna ragionare a fasi di funzionamento:

SE sono fermo E premo alzo:
    on valvola pompa
    annoto tempo attuale
    imposto non fermo
ALTRIMENTI SE non sono fermo E non è premuto alzo:
    off valvole
    imposto fermo
ALTRIMENTI SE non sono fermo E trascorso > intervallo:
    on valvola alzo


Poi i movimenti sono mutuamente esclusivi o si potrebbero attivare in coppia, che so, alzo e ritrai contemporanei?
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

vince59

Claudio, ho cercato di mettere in codice proprio il principio di azionamento in parte da te esposto.
Ovvero:
se premo ALZO (o qualsiasi altro tasto x movimento):
- ON alimentazione pompa;
- annoto tempo (è un ritardo la cui necessità dovrò verificare NON in simulazione);
- trascorso il ritardo prefissato;
- ON valvola attuatore;
se rilascio il pulsante e/o nessun tasto è premuto:
- OFF alimentazione pompa;
- OFF valvola attuatore.

I movimenti sono esclusivi dato che bisogna pigiare dei tasti quindi meglio uno per volta.

Cmq a tavolino sembra andare...il millis era troppo corto e NON realizzavo...messo a due secondi si vede che va.


vince59

Dunque, dopo qualche prova, ancora al banco ho elaborato un codice piuttosto semplice che sembra funzionare.
Praticamente aziono 4 elettrovalvole e la pompa idraulica premendo un tasto. Laddove fossero premuti due tasti in contemporanea la pompa deve bloccarsi. Ho ottenuto ciò con degli if.
Ora dovrei inserire un altra condizione...ovvero, dovendo montare anche un modulo radiocomandato con  cui vorrei attivare i medesimi relé (in parallelo) vorrei escludere la sovrapposizione dei tasti e del radiocomando.
A livello di codice ho pensato di monitorare "semplicemente" la pompa idraulica.
La logica sarebbe questa.
Pigio il pulsante sulla tastiera...se il motore sta già girando (telecomando azionato) NON DEVE accadere nulla.
Diversamente si attiva quello che deve attivarsi.
Stessa cosa per il telecomando...arriva l'impulso ma se il motore sta già girando (TASTO pigiato) NON deve accadere nulla.
Vi sembra relaizzabile?
Cmq ecco il codice attuale.

Code: [Select]



const byte btnStateUp = 2;
const byte btnStateDown = 3;
const byte btnStateOut = 4;
const byte btnStateIn = 5;

long previousMillis = 0;
long interval = 0;

// int pausa = 500;                // attendi x durata time

void setup() {
  Serial.begin(9600);

  pinMode(btnStateUp, INPUT);   // pulsante ALZO
  pinMode(btnStateDown, INPUT); // pulsante ABBASSA
  pinMode(btnStateOut, INPUT);  // pulsante ALLUNGA
  pinMode(btnStateIn, INPUT);   // pulsante ACCORCIA

  pinMode(7, OUTPUT); // valvola POMPA
  pinMode(8, OUTPUT); // valvola ALZO
  pinMode(9, OUTPUT); // valvola ABBASSA
  pinMode(10, OUTPUT); // valvola ALLUNGA
  pinMode(11, OUTPUT); // valvola ACCORCIA

  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
}

void loop() {

// ------------- ALZO ----------------
  {
    if (digitalRead (btnStateUp) == LOW && digitalRead (btnStateDown) == HIGH && digitalRead (btnStateOut) == HIGH && digitalRead (btnStateIn) == HIGH)
    {
      digitalWrite (7, LOW); // aziono POMPA
      // delay (pausa);
      //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
        digitalWrite (8, LOW); // aziono valvo
        Serial.println ("alzo");
      }
//    ---------------------------------------------
      //digitalWrite (8, LOW); // aziono valvola ALZO
    }
    else
    {
      digitalWrite(7, HIGH);   //spegne POMPA
      digitalWrite(8, HIGH);   //spegne ALZO
    }
  }
  {
// ----------- ABBASSO ----------------
    if (digitalRead  (btnStateDown) == LOW && digitalRead (btnStateUp) == HIGH && digitalRead (btnStateOut) == HIGH && digitalRead (btnStateIn) == HIGH)
    {

      digitalWrite(7, LOW);  // aziona POMPA
      //    delay (pausa);
      //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
        digitalWrite (9, LOW);
        Serial.println ("abbasso");
      }
//    ---------------------------------------------
      //  digitalWrite (9, LOW);
    }
    else
    {
      digitalWrite(7, HIGH);   //spegne POMPA
      digitalWrite(9, HIGH);   //spegne ABBASSO
    }
  }
  {
// ------------ ALLUNGO ------------------
    if (digitalRead  (btnStateOut) == LOW && digitalRead (btnStateUp) == HIGH && digitalRead (btnStateDown) == HIGH && digitalRead (btnStateIn) == HIGH)
    {

      digitalWrite (7, LOW);
      //  delay (pausa);
      //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
        digitalWrite (10, LOW);
        Serial.println ("allungo");
      }
//    ---------------------------------------------
    }
    else
    {
      digitalWrite(7, HIGH);   //spegne POMPA
      digitalWrite(10, HIGH);   //spegne ALLUNGO
    }
  }
  {
// ---------------- ACCORCIO --------------------
    if (digitalRead  (btnStateIn) == LOW && digitalRead (btnStateUp) == HIGH && digitalRead (btnStateDown) == HIGH && digitalRead (btnStateOut) == HIGH)
    {
      digitalWrite (7, LOW);
      // delay (pausa);
      //    ---------------- ritardo -----------------
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis > interval)
      {
        previousMillis = currentMillis;
        digitalWrite (11, LOW);
        Serial.println ("accorcio");
      }
//    ---------------------------------------------
    }
    else
    {
      digitalWrite(7, HIGH);   //spegne POMPA
      digitalWrite(11, HIGH);   //spegne ACCORCIO
    }
  }
}
  /*
    switch (pushBtn) {
    case (pushBtn == ALZA):
    //do something when var equals 1

    digitalWrite(1, LOW);        // aziona pompa
    delay(pausa);                // ritardo
    digitalWrite(2, LOW);        // aziona valvola
    delay(pausa);                // pausa

    break;
    case 2:
    //do something when var equals 2

    digitalWrite(1, LOW);        // aziona pompa
    delay(pausa);                // ritardo
    digitalWrite(2, LOW);        // aziona valvola
    delay(pausa);                // pausa
    }
    break;

    default:
    // if nothing else matches, do the default
    // default is optional
    break;
    }
  */

Claudio_FF

#14
Jul 17, 2019, 07:01 pm Last Edit: Jul 18, 2019, 06:53 am by Claudio_FF
Stai usando una logica combinatoria priva di stato, cioè i soli ingressi opportunamente valutati decidono l'uscita. Comportamenti più complessi è più semplice descriverli usando una logica a a stati.

Ma comunque in questo caso la cosa più semplice mi sembra parallelare dal punto di vista logico i comandi pulsante locale e pulsante remoto, in maniera che risultino un unico comando:

Code: [Select]
bool comandoAlzo = (   digitalRead(btnStateUp) == LOW
                    || digitalRead(...intelecomando...) == ....  );


e quindi si andranno a valutare i comandi combinati invece dei singoli ingressi:

Code: [Select]
if (comandoAlzo && !comandoAbbasso && !comandoEstendi && !comandoRitrai)
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

Go Up