creare impulso per relè bistabile

Buona sera a tutti,
sto “giocando” con otto relè bistabili, comandati da due ULN2803 che a loro volta vengono pilotati da due mcp23017.
Praticamente tramite codice binario eseguo una sequenza di comandi che mi eccitano i relè in uno stato o nell’altro a seconda del codice generato.
Essendo dei relè bistabilii, non è necessario che l’alimentazione ai capi della bobina sia persistente, basta quindi attivare solo degli impulsi. Durante le prime prove, quando utilizzavo due pulsanti la cosa riusciva perfettamente, mi servivo di due variabili di stato e di una funzione “if”, ma ora che ho l’esigenza di introdurre un encoder non riesco più a creare quanto mi serve.

#include "Wire.h"
int encoderPin1 = 2;
int encoderPin2 = 3;
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
long lastencoderValue =0;
;


void setup(){
  Wire.begin();
  Wire.beginTransmission(0x27);
  Wire.write(0x01);
  Wire.write(0x00);
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x00);
  Wire.write(0x00);
  Wire.endTransmission();
  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);
  digitalWrite(encoderPin1, HIGH);
  digitalWrite(encoderPin2, HIGH);
  attachInterrupt (0, updateEncoder, CHANGE);   
  attachInterrupt (1, updateEncoder, CHANGE); 
}

void loop(){ 
  
 Wire.beginTransmission(0x27);
  Wire.write(0x13);
  Wire.write(encoderValue);
  Wire.endTransmission();
  Wire.beginTransmission(0x20);
  Wire.write(0x12);
  Wire.write(encoderValue);
  Wire.endTransmission();
  delay(100);
}

//****************************************************************
//****************************************************************
//****************************************************************

void updateEncoder(){
  int MSB = digitalRead(encoderPin1);
  int LSB = digitalRead(encoderPin2);
  
  int encoded = (MSB << 1)  |LSB;
  int sum = (lastEncoded << 2)  |encoded;
  
  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
  encoderValue ++;

if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
  encoderValue --;

lastEncoded = encoded;
}

Nel codice che ho postato è evidente che le uscite che si trovano in uno stato alto, rimango in quello stato sino a che un nuovo codice generato le riporta a 0, io invece vorrei che che le uscite non fossero sempre attive, ma siano appunto degli impulsi.
Prima di chiedere aiuto ho eseguito svariati tentativi e ricerche, ma non riesco proprio a trovre la quadra.
Qualcuno potrebbe darmi qualche input??

grazie

Meluino

Vediamo se ho capito. Hai bisogno di mandare 2 impulsi allo stesso relé a distanza di breve tempo: col primo impulso attivi il relé, col secondo impulso riporti il relé nel precedente stato. E' giusto?

Se è così, potresti crearti un array di x celle di tipo unsigned long in cui memorizzare il tempo a cui attivi un relé e poi controllare nel codice se una delle uscite dei relé è a 1 (quindi è attiva). Userai un altro array (non so se già lo fai nel codice, non ho guardato). Se la trovi attiva, controlli che il valore di millis meno il valore memorizzato nell'altro array sia superiore ad un periodo predefinito (il tempo di attivazione): se lo è, disattivi relé e metti il suo stato a 0.

leo72: Vediamo se ho capito. Hai bisogno di mandare 2 impulsi allo stesso relé a distanza di breve tempo: col primo impulso attivi il relé, col secondo impulso riporti il relé nel precedente stato. E' giusto?

Non proprio, ma il problema è che mi sono spiegato decisamente male!! Allora, metto da parte per un attimo i relè, supponiamo che sto comandando solo un mcp23017, due uscite qualsiasi. Utilizzo un pulsante, lo premo e creo sulle due uscite la sequenza 0-1 (0 su un'uscita e uno sull'altra) lo rilascio e le uscite si riportano allo stato di 0-0, dopo ripremo il pulsante e le uscite si portano nella combinazione 1-0, rilascio il pulsante e si riportano 0-0, e così via! Ora utilizzando il pulsante questo tipo di ragionamento riesco a ricrearlo, il problema è che voglio riprodurre la stessa cosa con l'encoder. Giro di uno scatto l'encoder e ottengo la combinazione 0-1, rimane attiva per X ms e le uscite si riportano a livello 0-0. La combinazione 1-0 deve attivarsi solo al secondo scatto dell'encoder, ed anche in questo caso via via sino al limite da me imposto.

Forse sono un po' contorto nella domanda , sicuramente è più facile la soluzione del quesito che capire quello che voglio intendere. :P

Grazie

Meluino

Per l’attivazione/disattivazione usa come detto un temporizzatore basato su millis, per scegliere la sequenza da attivare ad ogni pressione ti basta una variabile in cui memorizzi la combinazione come numero da 0 a x e poi un semplice switch col quale attivi le uscite:
esempio
case 0: 0-1
case 1: 1-0
eccc.

Leo72, grazie per le dritte che dai, come sempre sei di grandissimo aiuto per chi come me non è un programmatore ma vuole comunque provarci! Devo dire che non ho ancora avuto la possibilità di eseguire i suggerimenti quindi spero di evitare pessime figure, come ho fatto nell'ultimo topic!! :P :grin: Per quanto concerne la funzione "switch", non credo possa essermi utile, in quanto il progetto finale prevede l'utilizzo di 8 relè, quindi se non vado errato una combinazione totale di 256 casi, nella struttura che ho postato io faccio eseguire queste combinazioni mettendo il valore di encoderValue in "Wire.write".

Wire.write(encoderValue);

Ora dal punto di vista software non so cosa succede, questo sicuramente me lo potrai spiegare tu, però il risultato è quello desiderato!! Quindi credo che sull'attivazione delle uscite questa sia la strada giusta, sottolineo [u]credo[/u]!! :cold_sweat:

Per quanto concerne "millis" è una funzione che non conosco, o per lo meno ho utilizzato solo se faceva parte di sketch già esistenti, quindi non so bene come possa venirmi utile, se qualcuno vuole darmi qualche dritta non mi offendo mica eh.... :D. Detto questo ho cercato sul Playground e la spiegazione che mi da mi lascia un po' dubbioso: "utilizzata per restituire il numero di millisecondi dall'inizio del programma Arduino. overflow (tornare a zero), dopo circa 50 giorni." :roll_eyes: :roll_eyes: :roll_eyes: Ma questo a cosa mi serve per spegnere delle uscite??????? Il perché l'ho trovato cercando un po' in giro, ora non so se faccio una cosa consentita, però ho trovato alcuni link dove viene spiegato molto bene come utilizzare questa funzione, quidi vorrei postarli credendo di far cosa gradita a tutti coloro che navigano nlle mie stesse condizioni. Uno è sicuramente il blog di Leo72: www.leonardomiliani.com/2013/programmiamo-i-compiti-con-millis/ L'altro è suggerito da Mauro Alfieri ed è di Vittorio Zuccalà: http://zuccala.blogspot.it/2010/01/multitasking-arduino-millis-parte-1.html

Meluino

Edit modificato link

:sweat_smile:

Sono riuscito nell'impresa, però, nonostante ci abbia provato, non ho utilizzato "millis" (non sono stato in grado di ottenere un risultato utile). Ho immesso un'altra variabile che ho comparato con encoderValue ed il risultato è stato quello desiderato:

If (encoderValue -encoderValue1 == 0) {
//metto tutto a 0
} else{
//le uscite prendono il valore di encodeValue e encoderValue1 diventa uguale ad encoderValue
}

Dal punto di vista funzionale "funziona" ma dal punto di vista di programmazione è corretto?

Meluino