Lettura di sequenze di bit indefinite

Devo sviluppare un firmware per riuscire a leggere sequenze di bit di codifiche differenti. Per avere una situazione realistica mi sono attrezzato con diversi radiocomandi (apricancello, auto, altro…) e con diversi moduli ricevitori RF (variano per frequenza e tipo di modulazione). A prescindere dalla combinazione TX/RX dispongo sempre di un pin che mi fornisce la sequenza trasmessa in forma di segnali H di duplice durata, a me sembra che i segnali siano genericamente costruiti così:
1 = impulso H breve
0 = impulso H lungo
tra di essi c’è uno stato L di ampiezza fissa molto breve, mentre tra un treno e l’altro c’è uno stato L di ampiezza molto maggiore. Naturalmente le combinazioni 1/0 sono assolutamente variabili.
A me per il momento basta ottenere l’ampiezza di ogni impulso del treno e la durata dell’intervallo tra due treni.
Sono arrivato alla conclusione che devo misurare una serie di impulsi H e la loro durata singola ed il tempo tra un impulso e l’altro; quindi la mia idea è quella di collegare il pin dell’RX ad un interrupt fisico di Arduino e captare i rising e misurare il tempo totale del singolo bit, inteso come fase H breve o lunga più fase L.
Ritengo che con l’uso della normale routine di interrupt ed il millis posso riuscire nell’intento, e l’unico problema sarebbe la misurazione dell’ultimo impulso, visto che conterrebbe anche la pausa lunga; oppure dovrei usare il change e misurare ogni singola variazione di stato.
Avete suggerimenti?
Ho provato ad usare alcune librerie, ma sono incentrate su codifiche ben precise e quindi non mi aiutano per niente con quelle non contemplate, quindi sono costretto ad inventarmi tutto ex-novo.

Scusa se intervengo … io non sono un programmatore, ma se dovessi fare una cosa del genere a livello hardware, partirei da questa parte per avere un riferimento …

Intendo dire, se le sequenze LOW brevi fra i diversi impulsi HIGH sono sempre uguali (anche se diverse per ricevitori e codifiche differenti, suppongo che, ad esempio per lo stesso radiocomando, siano tutte uguali), potresti forse usarle per avere una specie di “riferimento” sia per misurare i differenti intervalli HIGH e riconoscere uno e zero (se i LOW sono tutti uguali potrebbero fornire una specie di “clock” o “base tempi” per discriminare la durata dei vari HIGH), sia per vedere se il treno di impulsi e’ finito (piu del doppio della durata LOW degli impulsi precedenti dovrebbero essere un’indicazione abbastanza valida del fatto che il treno di impulsi sia finito, credo)

Probabilmente renderebbe il software un po piu complicato, ma anche indipendente dal treno di impulsi (anche se fossero treni di impulsi da sorgenti diverse con temporizzazioni diverse, analizzando il primo paio di treni ricevuti il sistema potrebbe “adattarsi” alla codifica ed ai tempi di volta in volta, anche se cambiassero)

Io se dovessi partire da zero, prenderei la libreria di shirriff, solo che sul pin 7 invece di esserci un Tsop ci metto l'uscita del ricevitore RF, hai già una gestione degli interrupt, dei timer e una stampa dei tempi

Al momento non mi serve che venga riconosciuto il codice, nemmeno un send serve, ma che mi stampi dei valori numerici, osserverei il comportamento di questi valori e poi decido se è utile e procedere con le modifiche o buttare tutto, ricominciando da capo

ciao

Proverei con il pulseIn()

Hai ragione ma in realtà la cosa è un tantino più complicata. Astro mi ha fatto notare su alcune immagini che il singolo impulso è in realtà costituito da una terna, in cui il primo è un L fisso e l'ultimo è H fisso, in base allo stato logico del centrale si stabilisce se l'intero impulso è un L o un H, le prime prove mi hanno fatto girare la testa, procedo......

@@Paoli :grinning: finisco questo giro di prove e poi ragiono sui vs suggerimenti. Grazie.

La codifica di un H e un L puó essere molteplice. Il L-H puó essere decodificato nel rapporto di durata H-L del segnale (come nei WS2811).
Visto che nomini anche automobli le cose diventano pißu complicate. In quel caso c'é una comunicazione bidirezionale dove l'auto su richiesta della chiave da alla chiave una stringa casuale che la chiave deve criptare/decriptare e rimandare perché l' auto la considera valida. Senza sapere la chiave e il tipo di criptatura non fai niente.

Ciao Uwe

Ciao UWE, la mia idea iniziale è quella di leggere le sequenze 1/0 e misurare la durata del singolo impulso, per il momento NON devo decodificare ma solo leggere, quindi se anche ogni TX invia ogni volta un codice diverso a me non interessa, quello che mi serve è essere in grado di "descrivere" quel codice, tutto qui.

@ Pablos, ho scaricato la lib IRremote, il pin di ingresso è l'11, purtroppo nessuno dei due DEMO in ricezione reagisce ai mie segnali, chiaro che si aspetta codifiche ben definite ma io non sono in grado di fornire elementi via software, quindi niente da fare.

@ Paulus: mi studio il pulseIn

PulseIn misura la durata dell’impulso H oppure L, il problema è che devo dichiarare prima QUALE voglio misurare; visto che io devo misurare tutto ciò che mi arriva di 1/0 in un lasso di tempo come faccio ad implementare entrambi gli stati?

oppure dovrei usare il change e misurare ogni singola variazione di stato.
Avete suggerimenti?

Questa mi sembra la soluzione più adatta. Ti servono due array (o uno solo di struct) uno conterrà i tempi e l'altro 0 1 0 1 ecc. 0 quando la transizione è da 1 verso 0, 1 viceversa.
Collezionati questi dati esigui in un for.. la sottrazione di tempo[1] - tempo[0] e continui fino a tempo[n] fermando tutto quando n >= Nmax.

Oppure invii i dati delle collezioni al pc e scrivi un programmino sul pc che esegue i calcoli e li mostra graficamente.

PS: Se avessi un oscilloscopio vi tempesterei di immagini oscillografiche.

Ciao.

Ma tu non sai la prima volta se il segnale parte a 0 e da quel momento attendi un 1, poi attenderai da 1 a 0, etc. ?
Se così fosse, la prima volta pulseIn() attende un HIGH (da 0 a 1) , poi attende un LOW (da 1 a 0) e quindi il secondo parametro value potrebbe essere una variabile che passa da HIGH a LOW e poi a HIGH, e via di seguito di continuo.
(Scusa se mi sono spiegato male)

...
duration=pulseIn(pin,stato);
if(stato==HIGH) stato=LOW; else stato=HIGH;
...

E magari lo stato iniziale puoi determinarlo nella setup() leggendo dal pin, se 0 devi attendere HIGH, se 1 devi attendere LOW, quindi nella setup():

if(digitalRead(pin)==HIGH) stato=LOW; else stato=HIGH;

Però non saprei se è un problema la tempistica tra lettura in setup() e quando poi lavora la prima volta nel loop(), visto che la digitalRead() è pure lenta.

Oppure duplichi su due ingressi, con uno misuri HI e con l'altro LOW ...

Io non so nulla della sequenza che vado a leggere, se inizia con 1 o con 0 e poi potrei trovarmi con una serie di 1 o di 0; forse usando entrambi gli interrupt 0 e 1 e leggendo su uno il falling e sull'altro il rising.
Peraltro se nella ISR metto la lettura del tempo in realtà è il tempo dello stato precedente :sweat_smile:
che mal di testa :disappointed_relieved: :disappointed_relieved: :disappointed_relieved:
@ Mauro: l'array lo implementerò dopo per fornire la lettura completa, ma per ora devo cercare di arrivare a riconoscere i singoli bit, altrimenti è lotta inutile.

Scusa Michele, ma di quali frequenze parliamo? Parli di telecomando apricancello, questi lavorano intorno ai 433.92Mhz come fa Arduino a leggere i valori H/L di queste frequenze?

@ Mauro: l'array lo implementerò dopo per fornire la lettura completa, ma per ora devo cercare di arrivare a riconoscere i singoli bit, altrimenti è lotta inutile.

Secondo me vedi il problema più grande di quello che è, forse è meglio che ti svaghi e riprendi dopo a ragionarci su.

Se la ISR viene eseguita ad ogni cambio di stato basta fare un controllo dello stato corrente.
Il pin di ingresso o è con pull-up o con pull-down e questo dipende da come inizia la trasmissione dati, nel tuo caso non può che essere pull-down, se è così la prima transizione sarà 01, la seconda ovviamente 10 e così via.

ISR() {

times[n] = systemCounter

if pin == High
transition 01
else
transition 10
transitions[n] = transition
n++;

}

systemCounter conterà in us o ms.

PS: Io penso sia il caso di usare il codice nudo e crudo senza fare uso di librerie.
PS1: Prima non l'ho esplicitato ora si; ma che ci aspetti a postare delle foto oscillografiche?

Ciao.