Modulazione luce led IR a 38kHz (arduino uno)

Salve a tutti.
Avrei bisogno di trasmettere tramite led IR gli 8 bit di un intero, con una carrier frequency di 38kHz con arduino uno.
Ho letto moltissimi post a riguardo, ma continuo ad avere dubbi circa l’implementazione.
Non mi è necessario l’utilizzo dei Timer interni di arduino, mi è sufficiente modulare le pulsazioni con delle delay.
Vi posto il testo del problema:

Il rivelatore richiede una luce modulata a 38kHz:

  • I periodi a zero sono realizzati tenendo il led spento
  • Quelli a uno sono realizzati con 38 o 76 impulsi della durata di ~26µs ciascuno
  • Il bit di start consiste di almeno 19 impulsi di ~26µs

Potreste aiutarmi in qualche modo con il codice?
Vi ringrazio moltissimo in anticipo.

Allego anche il codice che ho per ora:

const int PIN_LED = 3;
const int CUBE_ID = 1;

void emitID(int ID) {
  int i = 8;
  while(i > 0) {
    i--;
    if(ID & (1 << i)) {
      // se il bit i è 1 faccio lampeggiare il led per tot millis e lo tengo spento per tot -> trasmetto 1
      pinMode(PIN_LED, OUTPUT);
      digitalWrite(PIN_LED, HIGH);
      delay(xxx); // non so che valore mettere
      pinMode(PIN_LED, INPUT);
      delay(xxx); // non so che valore mettere
    } else {
      // se il bit i è 0 faccio lampeggiare il led per tot millis e lo tengo spento per tot -> trasmetto 0
      pinMode(PIN_LED, OUTPUT);
      digitalWrite(PIN_LED, HIGH);
      delay(xxx); // non so che valore mettere
      pinMode(PIN_LED, INPUT);
      delay(xxx); // non so che valore mettere
    }
  }
}

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
  //TODO: bit di start
  
  emitID(CUBE_ID);
  delay(3000); // trasmetti l'ID ogni 3 secondi

}

E’ il mio primo post sul forum, siate clementi :smiley:
Grazie ancora.

Buongiorno,
essendo il tuo primo post, nel rispetto del regolamento (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

P.S.: Qui una serie di link utili, NON necessariamente inerenti alla tua domanda:
- serie di schede by xxxPighi per i collegamenti elettronici vari: ABC - Arduino Basic Connections
- pinout delle varie schede by xxxPighi: Pinout
- link generali utili: Link Utili

Buonasera Guglielmo,
mi scuso molto per non essermi presentata, tuttavia ho rimediato rispondendo sul thread delle presentazioni da lei indicatomi. Avevo letto il regolamento, ma data l'ora tarda in cui ho scritto questo post non ho pensato di presentarmi, interpretando la presentazione solo come buona norma consigliata. Comunque grazie a lei ho rimediato.
Ora che sono entrata ufficialmente nel forum spero che qualcuno mi saprà aiutare :smiley:

Buona serata!
Matilde

NON puoi usare la delay() … la risoluzione minima è di 1 msec … se devi lavorare con la delayMicroseconds() in cui specifichi il tempo in μsec. con un MINIMO di 3 μsec.

Guglielmo

Se invece ti vuoi affidare ad una libreria fatta apposta per trasmissioni IR ... puoi usare la IRremote (la installi attraverso il library manager del IDE) e trasmettere i tuoi bytes come se fossero dei codici RAW.

Guglielmo

Avevo già provato ad utilizzare la libreria IRremote, il problema è che la funzione decode() in ricezione, se non sbaglio, è bloccante e dovendo usare 3 ricevitori ir (VS1838b) che ricevono in contemporanea non andava bene. Quindi dovrei implementare un protocollo ad hoc che trasmetta bit a bit un intero, seguendo le indicazioni del testo del “problema”, soprariportate.

gpb01:
NON puoi usare la delay() … la risoluzione minima è di 1 msec … se devi lavorare con la delayMicroseconds() in cui specifichi il tempo in μsec. con un MINIMO di 3 μsec.

Guglielmo

Riguardo a questo, grazie, in effetti mi sono confusa, intendevo delayMicroseconds().
Il mio problema è che non so che valori mettere per trasmettere a 38kHz e modulare il segnale secondo i parametri dati dal problema → (

  • I periodi a zero sono realizzati tenendo il led spento
  • Quelli a uno sono realizzati con 38 o 76 impulsi della durata di ~26µs ciascuno
  • Il bit di start consiste di almeno 19 impulsi di ~26µs )

Il periodo è T=1/38kHz, quindi 26 μsec, e fin qui ci sono. Purtroppo però non riesco ad andare avanti.

Grazie mille.
Matilde

mugolini4:
Il periodo è T=1/38kHz, quindi 26 μsec, e fin qui ci sono.

Se il periodo è 26µs il LED va commutato ogni 13µs. Per quante volte? Per il tempo che dura un bit (se si parla di 76 periodi, cioè 1.976ms, va commutato 152 volte).

Nel caso di bit zero invece non si commuta niente, si aspettano solo 1976µs.

Sono tempi che, realizzati in C e con gli interrupt abilitati, saranno affetti da qualche µs di jitter dei fronti d'onda (per non parlare dei 5µs richiesti da una digitalWrite standard). L'ideale sarebbe realizzarli in assembly (e sicuramente con scrittura diretta sulle porte).

In ogni caso non mi pare risolvano il problema del programma "bloccante", anzi, una trasmissione realizzata in bit-bang come questa è altrettanto bloccante.

Un semplice oscillatore esterno con NE555 comandato on/off con un pin sarebbe decisamente più semplice.

Grazie mille per il chiarimento sui valori da impostare, appena riesco provo a testare il tutto!

Claudio_FF:
Sono tempi che, realizzati in C e con gli interrupt abilitati, saranno affetti da qualche µs di jitter dei fronti d'onda (per non parlare dei 5µs richiesti da una digitalWrite standard). L'ideale sarebbe realizzarli in assembly (e sicuramente con scrittura diretta sulle porte).

Sono d'accordo, tuttavia non conosco bene assembly, e non saprei da dove iniziare. Secondo te questi µs di ritardi vari potrebbero compromettere completamente il protocollo di comunicazione, o solo renderlo un po' meno affidabile? Perchè comunque l'intero verrà ri-inviato frequentemente da 3 led (pilotati da un transistor).

Claudio_FF:
In ogni caso non mi pare risolvano il problema del programma "bloccante", anzi, una trasmissione realizzata in bit-bang come questa è altrettanto bloccante.

Il problema della decode() della libreria IRremote è che non credo supporti multi-ricezione, e invece io avrei bisogno di avere 3 ricevitori ir che ricevano indipendentemente nello stesso momento. (opportunamente "schermati" e direzionati diversamente). In effetti forse bloccante non era la parola più adatta, ma comunque era riferita a lato ricezione ir.

Claudio_FF:
Un semplice oscillatore esterno con NE555 comandato on/off con un pin sarebbe decisamente più semplice.

E per quanto riguarda l'utilizzo di NE555, facendo ricerche sull'argomento ne ho sentito parlare molto come possibile soluzione al mio problema, tuttavia non ho molto controllo sulla scelta dei componenti anche perchè dobbiamo mantenere l'elettronica del prototipo al minimo. Inoltre da quello che ho visto il modulo ne555 richiede una Vcc in input troppo grande rispetto alle batterie che andremo ad usare purtroppo.

Grazie ancora!

mugolini4:
Avevo già provato ad utilizzare la libreria IRremote, il problema è che la funzione decode() in ricezione, se non sbaglio, è bloccante e dovendo usare 3 ricevitori ir (VS1838b) che ricevono in contemporanea non andava bene.

Ma se fino ad adesso hai parlato di "trasmissione" .. che c'entra la decode() ? :o :o :o

Guglielmo

mugolini4:
...dobbiamo mantenere l'elettronica del prototipo al minimo. Inoltre da quello che ho visto il modulo ne555 richiede una Vcc in input troppo grande...

La versione CMOS funziona anche a 1.5V, l'oscillatore sono tre componenti in tutto compreso il 555 (il pin di controllo è il 4).

non ti va bene la lib IR classica ?

ora e' in versione 2 compatibile con molte mcu

gpb01:
Ma se fino ad adesso hai parlato di "trasmissione" .. che c'entra la decode() ? :o :o :o

Stessa domanda che stavo per fare anche io. La trasmissione la risolve sicuramente con la IRremote e quindi anche la ricezione, a meno che non debba per forza implementare un protocollo totalmente "strano" (ma la libreria permette anche di creare nuovi protocolli, anche se significa studiare non solo l'interno della libreria ma anche come si traduce nella relativa codifica).

Ma soprattutto non ho capito, cosa intende dire con "in contemporanea"???

Se c'è un solo MCU che trasmette il segnale IR e ci sono 3 MCU separate che lo ricevono (quindi la stessa comunicazione ma per MCU separate) non vedo il problema, è come se ognuno fosse l'unico ricevitore.

Se invece c'è un solo MCU ricevente che ha 3 sensori IR e deve poter ricevere contemporaneamente 3 segnali diversi da 3 sorgenti diverse, i problemi sono due, ma molto gravi:

  1. se trasmettono con la stessa modulazione (o anche adiacente) si sovrappongono quindi non riceverai mai nulla di buono/affidabile;
  2. Se anche fosse (diciamo che vanno su 3 frequenze distanti tra loro e provenienti da direzioni diverse per cui i fasci non si sovrappongono) ricordiamo che Arduino non ha "thread" o "multitasking", per cui non esiste la parola "contemporaneamente". Può solo verificare in sequenza (più o meno rapida) se ognuno dei 3 ricevitori sta ricevendo "qualcosa" quindi interpretarlo ed agire di conseguenza.

Claudio_FF:
La versione CMOS funziona anche a 1.5V, l’oscillatore sono tre componenti in tutto compreso il 555 (il pin di controllo è il 4).

Beh sarebbero comunque 3 componenti in più per ogni oggetto creato (dovremo produrne in quantità elevate) e purtroppo come ho già detto l’elettronica scelta non dipende troppo da me, ma comunque grazie, lo farò presente :slight_smile:

testato:
non ti va bene la lib IR classica ?

ora e’ in versione 2 compatibile con molte mcu
https://github.com/cyborg5/IRLib2

Alla fine di test e settings vari dovremo usare la nodemCU (ESP8266) e non mi sembrava fosse supportata da questa libreria, grazie comunque!

docdoc:
Se invece c’è un solo MCU ricevente che ha 3 sensori IR e deve poter ricevere contemporaneamente 3 segnali diversi da 3 sorgenti diverse, i problemi sono due, ma molto gravi:

  1. se trasmettono con la stessa modulazione (o anche adiacente) si sovrappongono quindi non riceverai mai nulla di buono/affidabile;
  2. Se anche fosse (diciamo che vanno su 3 frequenze distanti tra loro e provenienti da direzioni diverse per cui i fasci non si sovrappongono) ricordiamo che Arduino non ha “thread” o “multitasking”, per cui non esiste la parola “contemporaneamente”. Può solo verificare in sequenza (più o meno rapida) se ognuno dei 3 ricevitori sta ricevendo “qualcosa” quindi interpretarlo ed agire di conseguenza.

E’ esattamente così che dovrà funzionare il nostro prototipo, 3 ricevitori che possono ricevere anche 3 segnali diversi “in contemporanea” (passami il termine :smiley: ), per questo sto avendo un po’ di difficoltà a farli comunicare. Mi rendo conto che rischia di farsi complicata la comunicazione, ma come dicevo sopra purtroppo dobbiamo limitare al minimo sia come quantità che prezzo l’elettronica, di conseguenza posso utilizzare solo 3 vs1838b ricevitori che ricevano da 3 led ir trasmettitori.
Per ora per creare simultaneità nella ricezione ho implementato delle ISR che sono triggerate con gli interrupt interni pin-change (PCINT0_vect, PCINT1_vect e PCINT2_vect) su 3 pin diversi che lavorano sui fronti di discesa.
In linea teorica comunque dovrebbero essere schermati bene gli uni dagli altri, anche perchè la comunicazione tra ricevitori e led non avverrà a distanza, ma saranno “attaccati” grazie a magneti forati e il fascio luminoso del led sarà estremamente direzionale e limitato.
Qualsiasi consiglio è ovviamente ben accetto :slight_smile:

Grazie a tutti!
Matilde

mugolini4:
Alla fine di test e settings vari dovremo usare la nodemCU (ESP8266) e non mi sembrava fosse supportata da questa libreria, grazie comunque!

Quella no, ma guarda che esiste la "IRremoteESP8266" ossia la versione proprio per gli ESP!
Io la uso per il mio ripetitore di telecomando, con una WeMos D1, quindi fidati, funziona.

docdoc:
Quella no, ma guarda che esiste la "IRremoteESP8266" ossia la versione proprio per gli ESP!
Io la uso per il mio ripetitore di telecomando, con una WeMos D1, quindi fidati, funziona.

Che tu sappia IRremoteESP8266 supporta ricevitori multipli?
Perchè volendo anche la libreria IRremote, che avevo testato un po', è compatibile con la nodemCU, solo che non permette ricezione su più pin. Al massimo avevo trovato una versione modificata sempre di IRremote, ma da quel che avevo letto dava comunque un po' di errori.

Per caso conosci una libreria un minimo ottimizzata che implementi questa funzione di multi-receiver?
Cercando su internet non ho trovato nulla a parte la libreria modificata sopra citata (che però ammetto devo ancora testare, ma pare che con 3 receivers dia problemi).

Buona giornata!

mugolini4:
Che tu sappia IRremoteESP8266 supporta ricevitori multipli?

Non lo so, ma se le condizioni sono quelle che hai scritto, il problema non è che la decode() blocca il processo (che è che si mette in attesa e non esce se non c'è nulla in ingresso, ma torna subito false), e neanche è una questione di libreria: per me semmai è che se tu devi ricevere contemporaneamente 3 segnali, è la MCU che non è in grado di gestirli essenzialmente perché non ha thread/multitasking!

In pratica, tu potresti pure fare 3 istanze della stessa classe ed assegnando ognuna ad un diverso pin, esempio:

IRrecv irrecv1(RECV_PIN_1);
IRrecv irrecv2(RECV_PIN_2);
IRrecv irrecv3(RECV_PIN_3);

e quindi nel loop() leggere in sequenza i tre:

if (irrecv1.decode(&results)) {

  • // ricevuto dato sulla IR 1*
    }
    if (irrecv2.decode(&results)) {
  • // ricevuto dato sulla IR 2*
    }
    if (irrecv3.decode(&results)) {
  • // ricevuto dato sulla IR 3*
    }

Ma se sta ricevendo un segnale su un IR la CPU è impegnata ad interpretare e decodificare, quindi fino alla fine del decode() non può "sentire" nulla dagli altri ingressi (in questo senso la decode() "blocca" la ricezione) per cui rischia di "perdersi" pacchetti!

Quindi a parte un eventuale completo cambio di architettura (Raspberry Pi 3), posso solo consigliarti di usare più MCU ossia una, diciamo la "master", con un ricevitore IR, e due "slave" (es. due Arduino Nano) ognuno dedicato solamente a gestire gli altri due ingressi IR, messi in comunicazione con il master ad esempio tramite bus I2C (usando la libreria Wire, vedi ad esempio QUI e QUI).
Chiaramente a quel punto i due slave potrebbero "predigerire" i dati ricevuti e mandare via I2C semplicemente una codifica del comando che hanno ricevuto (ad esempio nel mio ripetitore di telecomando non mando tutto il treno di bit ricevuto dal telecomando di una stanza, ma una volta decodificato mando al suo master semplicemente un byte che rappresenta il tasto premuto!).

docdoc:
Non lo so, ma se le condizioni sono quelle che hai scritto, il problema non è che la decode() blocca il processo (che è che si mette in attesa e non esce se non c'è nulla in ingresso, ma torna subito false), e neanche è una questione di libreria: per me semmai è che se tu devi ricevere contemporaneamente 3 segnali, è la MCU che non è in grado di gestirli essenzialmente perché non ha thread/multitasking!

In pratica, tu potresti pure fare 3 istanze della stessa classe ed assegnando ognuna ad un diverso pin, esempio:

IRrecv irrecv1(RECV_PIN_1);
IRrecv irrecv2(RECV_PIN_2);
IRrecv irrecv3(RECV_PIN_3);

Grazie, in effetti non sapevo/avevo pensato si potessero fare più istanze. Allo stato attuale quello che posso provare e proverò a fare è fare 3 decode() diverse e a metterle nelle ISR degli interrupt pin-change, e vedere come si comporta Arduino, anche se non prevedo nulla di buono :sob:

docdoc:
Quindi a parte un eventuale completo cambio di architettura (Raspberry Pi 3), posso solo consigliarti di usare più MCU ossia una, diciamo la "master", con un ricevitore IR, e due "slave" (es. due Arduino Nano) ognuno dedicato solamente a gestire gli altri due ingressi IR, messi in comunicazione con il master ad esempio tramite bus I2C (usando la libreria Wire, vedi ad esempio QUI e QUI).

Sarebbe sicuramente intelligente e funzionale, ma purtroppo temo che per il progetto che stiamo sviluppando non sia fattibile :slightly_frowning_face:
Grazie mille comunque, gentilissimo e chiarissimo :slight_smile:

Non potrà mai funzionare :wink:

Un elemento fondamentale da capire è se i tre segnali IR usano la stessa portante. Se è così non c'è soluzione, perché capisci che mettiamo io prema il tasto di un telecomando e lo prema per due secondi, questo segnale arriva su tutti e tre i ricevitori IR, nel frattempo dopo un secondo, quindi mentre il primo telecomando è ancora premuto, premo un altro telecomando che va sempre su tutti e tre gli IR, che succede ? Badapumpt :slight_smile:

Hai una sola strada possibile, che i tre telecomandi (permettimi di chiamarli così) usino tre portanti diverse il più distante possibile una dall'altra.

Tu puoi decidere queste cose ? Se non puoi mettere mano alla parte di trasmissione, e i tre segnali sono sulla stessa frequenza, non c'è soluzione

Leggendo ad inizio topic sembra che invece tu debba progettare sia la parte trasmittente che ricevente, allora in quel caso in trasmissione usa appunto 3 portanti diverse e se non trasmetti mai in contemporanea non avrai problemi anche su un unico thread sia in tx che in rx

testato:
Un elemento fondamentale da capire è se i tre segnali IR usano la stessa portante. Se è così non c’è soluzione, perché capisci che mettiamo io prema il tasto di un telecomando e lo prema per due secondi, questo segnale arriva su tutti e tre i ricevitori IR

La stessa cosa che dicevo io, ma lui ha scritto che i tre ricevitori puntano in direzioni diverse e sono schermati tra loro. Immagino/spero che significhi che nessun segnale possa in alcun modo giungere al ricevitore sbagliato, anche se nutro forti dubbi che si possano isolare in questo modo, a meno che i trasmettitori non siano estremamente direzionali (ma sappiamo che gli infrarossi non lo sono molto…).
Per cui per ora mi fido di quello che dice, ma anche io ho grossi dubbi. Soprattutto, se anche fossero totalmente separati i fasci, per il discorso della ricezione contemporanea dei segnali da parte di una MCU mono-task.

testato:
... usa appunto 3 portanti diverse ...

Il problema e' che la portante e' proprio il flusso a 38KHz, ed a meno che non usi anche tre ricevitori NON identici, ognuno con la sua specifica frequenza da usare come portante, c'e' poco da fare ...

Inoltre su un sito che ha fatto dei test comparativi avevo letto che i VS si comportano "male" quando e' presente luce solare, al contrario dei TSOP della Vishay (del resto se i VS costano 14 centesimi l'uno ed i TSOP un dollaro e venti l'uno, "forse" una qualche differenza di qualita' c'e' anche ... :D) ... peraltro i TSOP sono disponibili con discriminazione della portante per diverse frequenze, il che risolverebbe anche questo problema, o almeno contribuirebbe a risolverlo ...