Buona sera a tutti,
come faccio a memorizzare un segnale acquisito da un pin ?
Mi spiego meglio, io ho il pin 8 digitale di Arduino, devo fargli memorizzare un segnale quando abilito il pin 9. quando porto a livello logico alto il pin 10 lui deve riprodurmelo su il pin 11.
Grazie in anticipo per chiunque mi sarà d'aiuto!
Di che segnale stiamo parlando?
digitalRead() e digitalWrite() ti sono chiare?
Si è un segnale di tipo digitale
Ciao,
intanto credo sia il caso che tu ci dica come è fatto il segnale. Se è un treno di impulsi di durata variabile, immagino tu debba memorizzare ogni durata (eventualmente in microsecondi) dello stato 1 e dello stato 0. Per quanto riguarda la memoria tutto dipende dal numero di campioni che devi memorizzare e da quanto spesso vuoi cambiare i campioni memorizzati.
Se non devi cambiarli troppo spesso puoi usare una EEPROM (che ha un numero di cicli di scrittura limitato, piuttosto alto ma limitato). Se si tratta di meno di 1024 campioni, puoi utilizzare la EEPROM interna del ATmega328 (o una MCU dotata di una EEPROM più grande). Oppure puoi utilizzare una EEPROM esterna. Ne esistono di I2C.
Ciao.
Vittorio
Io innanzitutto non capisco questo: una volta appurato che è digitale, per "segnale" intendi UN SINGOLO VALORE alto/basso, o una sequenza di valori nel tempo?
Mi scuso per non essermi spiegato bene,
sto cercando di copiare un protocollo per poi farlo replicare ad Arduino. Questo è composto da una serie di 10 bit. Io vorrei cercare di far acquisire alla scheda il segnale sul pin 8 quando il 9 è abilitato, quando io lo disabilito lui smette di leggere. Nel momento in cui io vado a portare a livello logico alto il pin 10 lui deve riprodurmelo su il pin 11.
Sarebbe possibile realizzare il seguente codice solo con Arduino senza l'ausilio di una EEPROM?
Potete scrivermi il codice?
Grazie mille, buona serata.
Il codice non te lo scriverà nessuno, ma possiamo spiegarti più o meno come fare: con un ciclo, leggi il segnale ad una frequenza appropriata e salva i valori in un array in RAM, almeno inizialmente.
Questa è la logica, poi bisogna vedere se Arduino è abbastanza rapido per campionare il tuo segnale. Se non lo è puoi provare a sfruttare il meccanismo degli interrupt, ma non è banale.
Oltre a questo bisogna vedere se in RAM sta tutto il segnale. In verità basta un bit per campione, ma inizia con un byte, è più semplice da gestire.
Poi questo presuppone che puoi ricampionare il segnale ad ogni riaccensione di Arduino. Se non è così dovrai salvarlo in EEPROM, ma questa è ancora più lenta e piccola della RAM, con conseguenti complicazioni.
Mi aiutereste a scrivere a scrivere solo le prime righe del codice,
con digitalRead e con delay leggo lo stato del pin, come faccio a salvare il risultato nella array in RAM ?
Di solito usi variabile=digitalRead(pin)
Per non fare cose complicate, variabile invece di una singola variabile di tipo byte può essere una cella di un array di byte. Devi anche avere un indicatore/variabile che conta quanti elementi hai già inserito di tipo int.
Memorizzare in un byte lo stato di 1 bit è uno spreco ma non complichiamo le cose.
byte vet[50]; // vettore
int indice=0;
...
void loop()
{ ...
vet[indice]=digitalRead(pinX);
indice=indice+1;
if(indice>=50) indice=0; // se proprio non bastano 50 elementi riparto dal primo
...
}
Ciao,
non sapendo come è fatto il tuo segnale non so dirti come capire, durante l'acquisizione, quando questo inizia e quando finisce. Devi darci più informazioni a questo riguardo.
Tralasciando per un attimo questo aspetto, in generale io farei in questo modo. Bada bene che si tratta solo di pseudo codice non testato... Prendilo solo come punto di partenza. In particolare è necessario aggiungere il codice che individua l'inizio del segnale quando il pin 9 va alto ed il codice che individua la fine del segnale e chiama la detachInterrupt.
int signalPin = 2;
int enablePin = 9;
volatile int state = LOW;
long lastMicros;
byte bitValue;
long bitDuration;
void setup()
{
pinMode(enablePin, INPUT);
}
void loop()
{
if (digitalRead(enablePin) == HIGH)
{
lastMicros = micros();
bitValue = digitalRead(signalPin);
attachInterrupt(digitalPinToInterrupt(signalPin), changed, CHANGE);
}
if (state == HIGH)
{
long m = micros();
bitDuration = lastMicros - m;
// qui memorizza in EEPROM bitvalue e bitDuration
bitValue = digitalRead(signalPin);
lastMicros = m;
state = LOW;
}
}
void changed()
{
state = HIGH;
}
La micros restituisce un long, quindi 4 byte cui devi aggiungere il byte per memorizzare il valore del segnale. Essendo un segnale a 10 bit userai al massimo 50 bytes che riesci a memorizzare tranquillamente nella EEPROM del ATmega328 (1024 bytes).
Rimane infine da verificare che il segnale non sia troppo veloce da eccedere la capacità di Arduino ed eventualmente che la tolleranza sui valori memorizzati non infici la qualità del segnale riprodotto.
Ciao
Ciao ragazzi grazie per le risposte tempestive,
dopo un analisi effettuata con un'analizzatore di stati logici sono riuscito a fotografare il segnale.
è un segnale a 24 volt che tramite delle resistenze ho abbassato fino a 5 tenendo come riferimento 10 kohm di impedenza di ingresso di arduino.
Tramite un buffere unl2003 vado poi a pilotare il segnale, nella foto i segnali sono due ma essendo il 2 il not del primo combino con una porta logica o semplicemente con due buffer.
Ciao!!
forse è colpa mia... ma guardando un solo segnale non riesco a capire come questo cambia...
Mi spiego meglio. Dalla tua richiesta intuisco che tu hai un dispositivo che emette un segnale variabile che vuoi memorizzare e poi riprodurre a piacimento, immagino per emulare il dispositivo originale.
Un tipico esempio potrebbe essere un telecomando ad infrarossi che emette treni di impulsi diversi a seconda del testo premuto. In questo caso tu vuoi memorizzare i diversi treni per poi riprodurli emulando il telecomando originale.
Ora, quello che ci hai mostrato è un segnale di esempio che sembrerebbe composto (su CH01) da 8 impulsi HIGH da 1ms intervallati da 8 spazi LOW da 2ms ed infine 1 impulso HIGH da 2ms seguito da uno spazio LOW da 1 ms.
Bene, un'altra versione del segnale, come cambia? Ci sono un diverso numero di impulsi HIGH? Gli impulsi HIGH o LOW hanno durata diversa?
Scusami, magari qualcuno con più esperienza di me riesce ad intuire lo scenario anche dalle informazioni che hai già postato.
Il segnale non so come cambia nel tempo ma io vorrei solo capire come fare per memorizzarlo e riprodurlo. Per tentativi forse posso riuscire a capire come varia.
Hai inteso alla perfezione sto cercando di emulare il dispositivo originale, si tratta di un plc per building automition, non posso entrare nei dettagli per problemi di copyright, comunque è per scopo puramente didattico non di tipo professionale.
Riuscireste a scrivermi il codice o a dirmi come fare ?
vittorio68 Mi contatteresti via messaggio privato se sai qualcosa in più?
Grazie mille!!!
Certo che sembra di fare un interrogatorio... ci dici le cose solo con la luce puntata in faccia!!!
Queste nuove informazioni mi fanno pensare ad un bus RS485 dove i due segnali A e B sono appunto in contrapposizione di fase. Immagino quindi che hai collegato i due canali dell'analizzatore appunto alle linee A e B.
In questo caso credo che la strada più semplice per fare quello che vuoi è di utilizzare uno shield RS485 da comprare già fatto oppure di costruirne uno con un MAX485 o un SN75176 (qui trovi uno schema).
Se colleghi lo shield al tuo bus, ricevi direttamente in arduino lo stream di bytes che transita sul bus. A questo punto è davvero banale memorizzare questi bytes e riprodurli sul bus attraverso lo stesso shield semplicemente in trasmissione.
Due considerazioni.
Primo. Fai attenzione a collegare al bus un dispositivo costruito da te perché potresti danneggiare i dispositivi originali. Ma suppongo che questo lo hai già messo in conto in quanto varrebbe anche per l'altro approccio che intendevi seguire.
Secondo. Una comunicazione RS485 può essere sia molto banale sia più articolata. Potresti avere banalmente un sensore che periodicamente invia un valore letto ad una centralina che lo elabora. Oppure potresti avere una centralina che periodicamente effettua richieste ai dispositivi connessi alla rete ed attende le relative risposte. Nel primo caso costruire un oggetto che stupidamente si limita a ripetere a "pappagallo" quello che ha appreso potrebbe effettivamente funzionare. Nel secondo caso invece la questione è più complessa e l'approccio potrebbe non funzionare in quanto il tuo oggetto dovrebbe attendere una richiesta e rispondere con coerenza.