Go Down

Topic: Aggiunta comando manuale alzata discesa (Read 495 times) previous topic - next topic

marcosilve95

Salve a tutti,
avrei bisogno di inserire un selettore ON OFF ON per comandare i due relè, mantenendo ovviamente il comando da tastierino numerico. Come posso fare? Volevo inserire l'ingresso 22 e 24 per il selettore a 2 posizioni

Questo è il mio codice programma:

Code: [Select]

#include <Keypad.h>

const byte ROWS = 4; // quattro righe
const byte COLS = 4; // quattro colonne
// Definizione del Keymap
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'#', '0', '*', 'D'}
};
// Connessione Keypad ROW0, ROW1, ROW2 e ROW3 ai pin Arduino
byte rowPins[ROWS] = { 2, 3, 4, 5};
// Connessione Kaypad COL0, COL1 e COL2 ai pin Arduino
byte colPins[COLS] = { 6, 7, 8, 9 };

// Creazione del Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

#define pin_rele_su 12 // relè salita
#define pin_rele_giu 11 // relè discesa

byte statoRele_su = 1 ;
byte statoRele_giu = 1 ;
unsigned long prevMillis ;
int int_key ;
int old_key ;

void setup() {
  delay(1000);
  pinMode(pin_rele_su, OUTPUT);
  pinMode(pin_rele_giu, OUTPUT);
  digitalWrite(pin_rele_su, statoRele_su );
  digitalWrite(pin_rele_giu, statoRele_giu );
  Serial.begin(9600);
}

void loop() {
  char key = kpd.getKey();
  if (key) {
    Serial.println(key);
    int_key = key - '0'; // converte in intero e lo usa come moltiplicatore
    if ( int_key  >= 0 && int_key <= 9 ) { // controlla se è un numero
      prevMillis = millis();
      if ( int_key == 0 ) {
        statoRele_giu = 0 ;
      }
      else {
        statoRele_su = 0 ;
        old_key = int_key ; // memorizza il tasto premuto
      }
    }
  }

  if (statoRele_su == 0)  {
    // c'è da disabilitare prima il relè discesa, come interblocco
    digitalWrite(pin_rele_giu, HIGH ); // disabilita rele discesa
    if ( millis() - prevMillis > ( int_key * 1550 ) ) {
      statoRele_su = 1;  // disattivare relè e conteggio
    }
    digitalWrite(pin_rele_su, statoRele_su);
  }
  if (statoRele_giu == 0)  {
    // c'è da disabilitare prima il relè salita, come interblocco
    digitalWrite(pin_rele_su, HIGH ); // disabilita rele salita
    if ( millis() - prevMillis > (old_key * 1600 ) ) {
      statoRele_giu = 1;  // disattivare relè e conteggio
    }
    digitalWrite(pin_rele_giu, statoRele_giu);
  }

}

ORSO2001

ciao marcosilve95,

cioè tu vorresti poter comandare i relè sia con il tastierino che con il selettore!?
se così nelle tue if() ti basta aggiungere un "or" con digitalRead() od il suo negato "!"...dipende se imposti i pin come INPUT od INPUT_PULLUP.

marcosilve95

Si esatto. E  come esattamente?

Grazie

ORSO2001

Code: [Select]
if(condizioneEsistente || digitalRead(pinX)){
    quello che devi fare;
}


oppure:

Code: [Select]
if(condizioneEsistente || !digitalRead(pinX)){
    quello che devi fare;
}


fino a che una delle due condizioni è "vera" verrà eseguito il codice all'interno delle if()

marcosilve95

Potresti cortesemente inserirlo nel codice che ho postato io? Perchè non riesco a capire come fare (scusa ma sono io che son duro!)

marcosilve95

Code: [Select]
if(condizioneEsistente || digitalRead(pinX)){
    quello che devi fare;
}


oppure:

Code: [Select]
if(condizioneEsistente || !digitalRead(pinX)){
    quello che devi fare;
}


fino a che una delle due condizioni è "vera" verrà eseguito il codice all'interno delle if()
Mi potresti aiutare? Grazie

ORSO2001

ciao...sta sera ci do un occhio meglio...

Claudio_FF

#7
Dec 08, 2017, 09:15 pm Last Edit: Dec 08, 2017, 10:14 pm by Claudio_FF
Il programma è terribilmente difficile, forse impossibile, da modificare in modo semplice.

Intanto logica di stato e valori di comando delle uscite sono mescolati assieme.
Quando leggo:
Code: [Select]
digitalWrite(pin_rele_giu,statoRele_giu);
devo andare andare in cerca di cosa sia statoRele_giu, quale valore deve assumere e quando, quale
sia livello di attivazione del relé, tutte cose che distraggono dall'operazione che mi interessa (sto accendendo o spegnendo?)

Anche cose come:
Code: [Select]
digitalWrite(pin_rele_su, statoRele_su );
digitalWrite(pin_rele_giu, statoRele_giu );

confondono abbastanza le idee.

Invece leggere:
Code: [Select]
digitalWrite(PIN_RELE_GIU, OFF_LEVEL);
digitalWrite(PIN_RELE_GIU, ON_LEVEL);

è immediatamente chiaro, in un caso sto spegnendo, nell'altro accendendo. E non mi interessa neppure sapere se il relé si accende con HIGH o LOW perché avrò definito all'inizio i valori di OFF_LEVEL e ON_LEVEL coerentemente con le necessità/collegamenti hardware.

Se gli stati sono solo due, è più chiaro usare variabili booleane con nomi autodocumentanti come 'inSalita' e 'inDiscesa'. Non serve neppure aggiungere commenti per capire cosa sta facendo il programma, e non serve ricordarsi 1, 0 HIGH, LOW ecc:
Code: [Select]
 if (in_salita)  {
        digitalWrite(PIN_RELE_GIU, OFF_LEVEL);    // interblocco
        if (millis() - prevMillis > durata_up) {  // se timeout
            in_salita = false;                    // fine salita
            digitalWrite(PIN_RELE_SU, OFF_LEVEL);
        }
        else
            digitalWrite(PIN_RELE_SU, ON_LEVEL);
    }


Poi quando si chiede una "modifica" bisognerebbe almeno spiegare come funziona il codice (cosa dovrebbe fare e come), e non lasciare che gli altri faticosamente cerchino di capirlo da soli.

Diciamo che dopo un po' si capisce che vuoi alzare con tempi diversi a seconda del numero premuto (1..9), e poi abbassare grosso modo con lo stesso tempo premendo 0.

Ma ci sono molte situazioni di contorno non gestite, e noi non sappiamo se volutamente o per errore.

Ad esempio:
  • Cosa succede se dopo una salita si preme un'altra salita?
  • Cosa succede se dopo una discesa si preme un'altra discesa?
  • Cosa succede se la prima volta si preme discesa visto che la variabile old_key in quel caso non è ancora inizializzata?
  • Cosa succede se durante una salita o discesa si preme un pulsante opposto, visto che non ci sono pause tra la disattivazione di un relé e l'attivazione dell'altro?
  • Cosa succede se durante una salita o discesa si ripreme la stessa salita o discesa, visto che il conteggio del tempo riparte dall'inizio?

E di conseguenza:
  • Come dovrebbe funzionare il selettore manuale?
  • Comando continuo come un interruttore o impulsivo come un click?
  • Cosa succede se lo si gira su discesa mentre è attiva la salita e viceversa?
  • Cosa succede se si preme un pulsante salita con il selettore girato su discesa e viceversa?

Go Up