GX-TXT-v3: dal segnale analogico al protocollo di un telecomando IR
Il GX-TXT-v3 è nato come ProvaTelecomando: uno strumento relativamente semplice pensato per verificare rapidamente se un telecomando a infrarossi sta effettivamente trasmettendo.
L’idea iniziale era molto semplice. Non volevo limitarmi a vedere il LED lampeggiare seguendo direttamente gli impulsi ricevuti dal telecomando. Sapevo soltanto che il segnale IR era modulato su una portante dell’ordine dei 38 kHz e volevo sfruttare quegli impulsi per caricare progressivamente una rete di HOLD, in modo da mantenere acceso il LED per un tempo sufficientemente lungo da renderlo chiaramente visibile.
Da qui è nata anche l’idea di introdurre uno stadio di preamplificazione e una regolazione della soglia, così da ottenere non soltanto un’indicazione del tipo “trasmette / non trasmette”, ma anche una forma molto semplice di valutazione dell’intensità del segnale ricevuto. Non volevo utilizzare né un galvanometro né una barra di LED: mi interessava invece provare a ricavare questa informazione dal tempo di accensione del LED.
In quel momento, però, la mia conoscenza pratica del segnale di un telecomando IR finiva praticamente lì: sapevo che era presente una portante attorno ai 38 kHz, ma non avevo ancora approfondito davvero il modo in cui il comando veniva strutturato sopra quella portante.
È stato durante le misure che la cosa ha iniziato a incuriosirmi. Osservando le forme d’onda nei diversi punti del circuito, mi sono reso conto che dietro quel semplice lampeggio c’era una struttura temporale molto più interessante. Da lì è nata la voglia di andare più a fondo e usare il ProvaTelecomando non soltanto per verificare un trasmettitore IR, ma anche per capire meglio che cosa stesse realmente trasmettendo.
Il ProvaTelecomando inizia quindi a diventare anche un piccolo front-end sperimentale per lo studio dei telecomandi IR. Questa non era la funzione principale prevista all’inizio del progetto, ma è una possibilità emersa naturalmente durante le misure.
In questa prova non voglio quindi limitarmi a verificare che il telecomando funzioni. Voglio usare le forme d’onda acquisite per mettere in ordine e comprendere meglio alcuni concetti fondamentali dei protocolli IR: portante, MARK, SPACE, header e codifica dei bit.
Partiamo dal segnale ricevuto
Per cercare di capire meglio che cosa trasmette realmente un telecomando IR, il punto di partenza più naturale è osservare direttamente il segnale ricevuto dal circuito.
La prima acquisizione che considero è quella del nodo VIR, cioè il segnale proveniente dal front-end collegato al fotodiodo. Guardando l’intero comando su una scala temporale relativamente ampia, la forma d’onda appare inizialmente piuttosto complessa: si distinguono gruppi di oscillazioni separati da intervalli nei quali il segnale torna verso il livello di riposo.
Uno zoom sull’inizio del comando permette già di riconoscere una struttura. È presente un primo gruppo di impulsi molto più lungo, seguito da una pausa anch’essa relativamente lunga; successivamente compaiono gruppi più brevi separati da intervalli di durata differente.

Per il momento non do un significato a queste durate. La cosa importante è osservare che il comando non è costituito da una sequenza continua di impulsi a frequenza costante: la portante viene trasmessa a gruppi, intervallati da pause. È proprio nella durata e nella successione di questi intervalli che comincia a comparire l’informazione trasmessa dal telecomando, ed è proprio questo schema che ha acceso la mia curiosità: una sequenza di gruppi di segnali modulati su una frequenza base di circa 38 kHz.
Per capire meglio ho quindi cambiato scala temporale e guardato più da vicino uno di questi gruppi di impulsi.
Leggere il comando direttamente sull’oscilloscopio
Quando ho fatto le prime acquisizioni, il mio approccio era molto più diretto: prima di passare a qualsiasi elaborazione numerica cercavo di ricavare il più possibile semplicemente guardando la forma d’onda sul monitor dell’oscilloscopio.
La prima cosa che mi aveva colpito era una sequenza iniziale di impulsi molto ravvicinati, fitti ma ancora distinguibili. Subito dopo compariva un intervallo vuoto abbastanza netto e poi una sequenza che appariva già chiaramente organizzata, con gruppi di impulsi separati da pause di durata differente. Anche senza conoscere ancora in dettaglio la struttura del protocollo, era difficile non leggere quella forma d’onda come una qualche forma di codifica dell’informazione.
La sequenza iniziale sembrava avere una funzione diversa rispetto a ciò che seguiva: una parte iniziale che appariva destinata a preparare o sincronizzare la ricezione, poi una pausa e infine la parte contenente il comando vero e proprio. Ancora più a destra si intravedeva inoltre una nuova sequenza, segno che il telecomando stava ripetendo la trasmissione.
In quel periodo mi ero già documentato e sapevo che, nei protocolli IR, gli intervalli nei quali la portante è presente vengono chiamati MARK, mentre quelli nei quali la portante è assente vengono chiamati SPACE. Un conto, però, è leggere questi termini in una descrizione teorica; un altro è iniziare a riconoscerli nella forma d’onda reale visualizzata sul proprio oscilloscopio.
Da quelle prime osservazioni è poi partito tutto il lavoro successivo. Ho acquisito i segnali, scritto gli script necessari a individuare la portante, ricostruire la successione dei burst, separare MARK e SPACE, misurarne le durate e arrivare infine a un tentativo di identificazione del protocollo.
Oggi, mentre scrivo questo articolo, quel segnale non mi è più nuovo: l’ho osservato e analizzato molte volte. Proprio per questo credo sia arrivato il momento di fermarmi e fare bene il punto, tornando alla forma d’onda originale e mettendo insieme in modo ordinato quello che ho imparato durante il lavoro.
Quello che voglio fare qui è quindi raccontare con calma com’è fatto questo segnale, partendo da ciò che si vede direttamente sullo strumento e arrivando progressivamente alla sua struttura: portante, MARK, SPACE, temporizzazioni e infine codifica del comando.
Due scale temporali nello stesso segnale
Nello stesso oscillogramma vedo subito due scale temporali diverse.
La prima è veloce: è la successione ravvicinata degli impulsi della portante.
La seconda è molto più lenta: è formata dalla durata dei gruppi di impulsi e delle pause che li separano. È questa struttura più lenta che trasporta il comando.
In altre parole, la portante è il ritmo veloce su cui il segnale viene modulato; l’informazione è invece contenuta nel modo in cui quella portante viene fatta comparire e scomparire nel tempo.
MARK e SPACE
Gli intervalli in cui la portante è presente vengono chiamati MARK.
Gli intervalli in cui la portante è assente vengono chiamati SPACE.
Guardando il segnale in questo modo, la forma d’onda diventa molto più semplice da leggere: non devo più seguire ogni singolo impulso della portante, ma posso concentrarmi sulla durata dei MARK e degli SPACE.
È proprio nella successione di questi intervalli, e soprattutto nelle loro durate, che viene costruita l’informazione del comando.

Dai MARK e SPACE ai bit
Una volta separati MARK e SPACE, il passo successivo è capire dove si trova l’informazione.
Nel segnale che sto analizzando i MARK che compongono i dati hanno una durata quasi costante. A cambiare in modo evidente è invece la durata dello SPACE che segue ogni MARK.
Qui però devo distinguere quello che posso capire guardando l’oscillogramma da quello che posso realmente misurare.
La base dei tempi dell’acquisizione è di 10 ms per divisione. A questa scala l’header si legge abbastanza bene: il MARK iniziale dura circa 9 ms e occupa quasi una divisione, mentre lo SPACE successivo dura circa 4,5 ms.
I simboli che compongono i dati sono invece molto più piccoli. Le misure successive mostrano MARK di circa 568 µs: sull’oscillogramma generale corrispondono ad appena 0,057 divisioni. Anche lo SPACE corto, circa 590 µs, ha praticamente la stessa scala. Lo SPACE lungo, circa 1,70 ms, arriva soltanto a circa 0,17 divisioni.
Quindi, guardando l’immagine, posso intuire immediatamente che esistono pause di durata diversa; per assegnare loro un valore preciso devo però ingrandire il segnale oppure lavorare sui dati acquisiti.
Ed è proprio da queste misure che emerge la struttura della codifica: i MARK dati hanno durata quasi costante, mentre gli SPACE si raggruppano soprattutto attorno a due valori, uno corto e uno lungo. Nel segnale che sto analizzando sono circa 590 µs e 1,70 ms.
È questa differenza temporale a codificare i bit: uno SPACE corto rappresenta un valore, uno SPACE lungo rappresenta l’altro. Nel caso della codifica che sto osservando, lo SPACE corto corrisponde a 0 e quello lungo a 1.
Il bit, quindi, non è rappresentato da una tensione alta o bassa come in una normale linea digitale. È rappresentato soprattutto da una durata.
Le misure sul segnale reale
Dopo aver ricavato la struttura generale del comando direttamente dall’oscillogramma, passo alle misure eseguite sui dati acquisiti.
Ho osservato il segnale in diversi punti del circuito. Il nodo VIR è molto utile perché rappresenta bene il segnale ricevuto, ma è anche un nodo sensibile e ad alta impedenza. Non volevo quindi dipendere sempre da una misura diretta proprio in quel punto.
Una parte del circuito è stata pensata anche per portare il segnale verso nodi più robusti, dove posso osservarlo e acquisirlo con maggiore tranquillità. Questo mi permette inoltre di vedere come la forma d’onda cambia attraversando i diversi stadi.
Nelle sezioni seguenti prendo quindi i grafici uno alla volta. Non come una galleria di risultati, ma per capire che cosa mostra ciascuna misura e quale informazione posso ricavarne.
Il comando visto attraverso massimi e minimi locali
Per iniziare l’analisi quantitativa parto da una rappresentazione più compatta del segnale sul nodo VIR. In questo grafico non sto mostrando direttamente tutta la forma d’onda campione per campione, ma l’andamento dei massimi locali e dei minimi locali nel tempo.
Il significato è semplice. La traccia Local maximum rappresenta, in ciascun piccolo intervallo di analisi, il valore massimo raggiunto dal segnale. La traccia Local minimum rappresenta invece il valore minimo raggiunto nello stesso intervallo.
Quando la portante è presente, il segnale oscilla con una certa ampiezza e le due curve si separano nettamente. Quando invece la portante scompare, il segnale si richiude attorno al proprio livello medio e la distanza tra massimo e minimo si riduce molto. In questo modo la struttura del comando diventa leggibile anche su una scala temporale di alcuni millisecondi.

Sulla destra non sto ancora osservando l’intero comando, ma soltanto l’inizio della sequenza dati. Dopo il lungo MARK e lo SPACE dell’header compaiono i primi MARK e SPACE associati ai bit: nel tratto visualizzato si distinguono due coppie complete MARK–SPACE e l’inizio del MARK successivo.
Questo ingrandimento è quindi particolarmente utile perché mette nello stesso grafico le due scale temporali che avevo riconosciuto sull’oscilloscopio: da una parte il lungo header, dall’altra i primi intervalli molto più brevi che iniziano a costruire i dati del comando.
Associato all’oscillogramma precedente, questo ingrandimento rende ancora più chiaro il significato di MARK e SPACE. Nel segnale originale li riconoscevo soprattutto dalla forma generale; qui invece diventano intervalli temporali ben separati e molto più facili da leggere.
Si vede anche bene un punto importante della codifica: nel tratto dati il MARK resta sostanzialmente della stessa durata, mentre è lo SPACE successivo a cambiare. È quindi soprattutto la durata dello SPACE a determinare il valore del bit.
In questa rappresentazione la differenza tra SPACE corto e SPACE lungo è molto più evidente rispetto all’oscillogramma generale. È proprio questa differenza temporale che permette di distinguere i due valori logici.
Dentro un MARK: il dettaglio della portante

Se ingrandisco ulteriormente il segnale sul nodo VIR, la struttura interna di un MARK diventa visibile. Quello che alla scala dei millisecondi appariva come un unico intervallo occupato dalla portante è in realtà formato da una successione regolare di oscillazioni.
Il grafico mostra circa 200 µs di segnale e quindi soltanto pochi cicli. La periodicità è già evidente e permette di passare dalla scala dei MARK e degli SPACE alla scala molto più veloce della portante.
Il valore di 62,5 kHz riportato automaticamente nel titolo del grafico è errato e va considerato un artefatto dell’elaborazione. Il controllo visivo lo mostra subito: nell’intervallo di circa 200 µs si osservano circa sette cicli principali, quindi la frequenza è già chiaramente dell’ordine di alcune decine di kilohertz, non 62,5 kHz.
Misurando meglio la distanza tra due picchi principali consecutivi si ottiene un periodo di circa 26 µs, corrispondente a una frequenza di circa 38 kHz. È quindi probabile che l’algoritmo abbia contato alcune irregolarità o piccoli disturbi del segnale come ulteriori transizioni, falsando la stima automatica.
In questo caso il grafico è utile anche come controllo del risultato numerico: la forma d’onda reale permette di riconoscere immediatamente che il valore indicato nel titolo non è compatibile con la periodicità effettivamente visibile.
La ricostruzione MARK / SPACE del comando

A questo punto posso eliminare dalla rappresentazione i singoli cicli della portante e conservare soltanto l’informazione che mi interessa: portante presente oppure portante assente.
Nel grafico il livello 1 indica quindi un MARK, mentre il livello 0 indica uno SPACE. Il segnale IR diventa così una sequenza temporale estremamente semplice da leggere.
All’inizio compare immediatamente il lungo MARK dell’header, seguito dal relativo SPACE. Dopo l’header comincia la parte dati: i MARK diventano molto più brevi e mantengono una durata pressoché costante, mentre gli SPACE che li separano possono avere due durate nettamente differenti.
Qui diventa particolarmente evidente ciò che avevo già intuito osservando l’oscillogramma: nel tratto dati è soprattutto la durata dello SPACE a codificare il bit. Non serve nemmeno contare uno per uno gli intervalli per vedere la struttura: gli SPACE corti e quelli lunghi si distinguono immediatamente.
Questa rappresentazione è quindi una sorta di ponte tra la forma d’onda analogica reale e la struttura logica del comando. La portante è scomparsa dal grafico, ma sono rimasti esattamente i tempi che trasportano l’informazione.
Durata dei MARK e degli SPACE successivi

Questo grafico mette in relazione, posizione per posizione, la durata di ciascun MARK con quella dello SPACE che lo segue. In ascissa ho l’ordine degli intervalli nella sequenza; in ordinata la loro durata, espressa in microsecondi.
Il primo punto si distingue subito da tutti gli altri: è il MARK di header, molto lungo, seguito dal relativo SPACE di header, anch’esso molto più lungo rispetto agli intervalli successivi. Già questo conferma in modo quantitativo ciò che sull’oscillogramma si vedeva solo come una struttura iniziale più estesa.
Dopo l’header la situazione cambia nettamente. I MARK della parte dati restano tutti concentrati attorno a una durata simile, mentre gli SPACE che li seguono si dividono chiaramente in due gruppi. Alcuni hanno una durata dello stesso ordine del MARK corrispondente; altri sono invece molto più lunghi.
È proprio qui che la codifica diventa evidente: il MARK resta quasi costante, mentre è lo SPACE successivo a portare l’informazione. In altre parole, il bit non viene riconosciuto tanto dalla durata del burst di portante, quanto dalla pausa che viene subito dopo.
Questo grafico mi piace particolarmente perché traduce in numeri una cosa che ormai si intuiva già bene nelle immagini precedenti: esistono MARK quasi tutti uguali e SPACE di due tipi distinti, uno corto e uno lungo. La struttura del comando emerge quindi in modo molto pulito, senza più dover inseguire i dettagli della forma d’onda analogica.
Dal segnale IR ai punti di misura del circuito
Con questi due grafici cambio leggermente prospettiva. Finora ho usato soprattutto il nodo VIR per capire come è fatto il comando IR. Adesso non sto più studiando il protocollo, ma il modo in cui posso osservare e misurare quel segnale attraverso il circuito.
VIR è il punto più diretto e informativo, ma è anche un nodo ad alta impedenza e particolarmente sensibile. Nel GX-TXT-v3 ho quindi interesse a seguire lo stesso segnale anche nei punti successivi della catena, dove posso disporre di condizioni di misura più favorevoli. Lo schema completo, il PCB, i Gerber e gli altri dettagli costruttivi sono disponibili negli articoli e nei file del progetto; qui mi interessa soltanto vedere che cosa succede al segnale durante il suo attraversamento.
Il primo grafico mostra simultaneamente VIR, QIN, PRE e SENS, mantenendo la stessa base dei tempi. La cosa importante non è confrontare direttamente le tensioni assolute, perché ogni stadio lavora con la propria polarizzazione, ma osservare la struttura temporale.
Il lungo burst iniziale e la successiva sequenza di MARK e SPACE rimangono riconoscibili lungo tutta la catena. La forma elettrica cambia, come è naturale passando attraverso stadi differenti, ma la struttura temporale del comando viene conservata. Questo significa che non sono obbligato a ricavare tutte le informazioni direttamente dal delicato nodo VIR: posso seguirle anche più avanti nel circuito.

Il secondo grafico confronta invece l’escursione rispetto al livello di base misurata nei quattro punti. Sul VIR ottengo circa 3,8 V, su QIN circa 2,8 V, su PRE circa 3,4 V e su SENS circa 1,44 V.
Questi valori non devono essere interpretati semplicemente come guadagni dei singoli stadi: i nodi hanno polarizzazioni, funzioni e forme d’onda differenti. Il confronto serve piuttosto a mostrare quanto segnale utile rimane disponibile nei diversi punti della catena.

I due grafici, letti insieme, mostrano quindi due cose diverse ma complementari: il primo verifica che l’informazione temporale del comando sopravvive lungo il circuito; il secondo mostra con quale escursione elettrica posso ritrovarla nei diversi punti di misura.
Condizioni sperimentali e valori principali
Prima di riportare i risultati è importante fissare le condizioni della prova. Le ampiezze osservate nei diversi nodi, e più in generale la risposta del circuito, hanno significato soltanto se associate alla configurazione con cui è stata effettuata l’acquisizione.
| Manifesto della prova | |
|---|---|
| Progetto | GX-TXT |
| Scheda / revisione | GX-TXT-v3 |
| Tipo di prova | catena_veloce |
| Data | 2026-09-02 |
| Telecomando | Scheda Android TV |
| Tasto | OFF |
| Distanza | 20 cm |
| P_GAIN | 540 Ω |
| P_SENS | 4980 Ω |
| Alimentazione | 8,962 V |
L’acquisizione contiene 3.000.000 di campioni, registrati a 25 MSa/s, per una durata complessiva di circa 120 ms.
| Grandezza | Valore |
|---|---|
| Durata del comando analizzato | circa 63,95 ms |
| MARK individuati | 34 |
| Header MARK | circa 9,02 ms |
| Header SPACE | circa 4,54 ms |
| MARK dati, valore mediano | circa 568 µs |
| SPACE corto, valore mediano | circa 590 µs |
| SPACE lungo, valore mediano | circa 1,70 ms |
| Portante osservata | circa 38 kHz |
| Escursione VIR | circa 3,8 V |
| Escursione QIN | circa 2,8 V |
| Escursione PRE | circa 3,4 V |
| Escursione SENS | circa 1,44 V |
Nota: i valori riportati descrivono questa specifica prova e devono essere letti insieme al relativo manifesto sperimentale. In particolare, le ampiezze nei nodi dipendono dalla distanza dal telecomando, dalla regolazione di P_GAIN e P_SENS, dalla tensione di alimentazione e dalle condizioni di trasmissione.
Per il significato elettrico dei nodi VIR, QIN, PRE e SENS, per lo schema del circuito, il PCB, i Gerber e gli altri dettagli costruttivi rimando agli articoli e ai file del progetto GX-TXT. Per la struttura generale dei protocolli IR rimando invece alle fonti tecniche raccolte nel progetto.
Che protocollo sto osservando?
Dai tempi misurati e dalla struttura del frame, il candidato migliore risulta appartenere alla famiglia NEC. Il comando contiene 32 bit e, interpretando i byte in ordine LSB-first, restituisce 0x08 0x16 0x87 0x78. L’ultimo byte è il complemento del comando, mentre la coppia relativa all’indirizzo non segue la forma complementare del NEC classico. Per questo l’identificazione più plausibile è NEC extended, oppure comunque una variante compatibile della famiglia NEC.
Non approfondisco qui le differenze tra le varie versioni del protocollo: per questo rimando alle fonti tecniche raccolte nel progetto. In questa pagina mi interessa soprattutto mostrare come, partendo da un oscillogramma reale, si possa arrivare fino alla struttura temporale e a una ragionevole identificazione del comando.
Conclusioni
Se ripercorro tutto dall’inizio, il cammino è stato molto più semplice di quanto sembrasse quando ho cominciato.
Sono partito da una forma d’onda che, vista tutta insieme sullo schermo, non diceva quasi nulla: un groviglio di oscillazioni con dei vuoti in mezzo. Il primo passo è stato accorgermi che lì dentro c’erano due velocità diverse. Una veloce, fatta dai singoli impulsi della portante attorno ai 38 kHz, e una lenta, fatta dai gruppi di impulsi e dalle pause che li separano. Da quel momento ho potuto smettere di guardare la portante: serve a trasportare il segnale, non a raccontarlo.
Restando sulla scala lenta, tutto si è ridotto a due sole condizioni: la portante c’è, oppure la portante non c’è. Il MARK e lo SPACE. Il segnale è diventato una successione di intervalli pieni e vuoti, e a quel punto l’unica cosa che restava da guardare era quanto duravano.
Ed è qui che il comando è venuto fuori da solo. Il primo intervallo è lungo, circa 9 ms, seguito da una pausa di circa 4,5 ms: è l’header, il segnale che avverte il ricevitore che sta per arrivare qualcosa. Dopo l’header i MARK diventano tutti uguali, circa 568 µs l’uno, e smettono di portare informazione: fanno solo da battito. A cambiare è la pausa che segue ciascuno di essi, che può essere di circa 590 µs oppure di circa 1,70 ms. Pausa corta, zero. Pausa lunga, uno.
Contando gli intervalli il conto torna in modo pulito: 34 MARK in tutto, cioè quello dell’header, i 32 dei dati e un ultimo MARK di chiusura che serve soltanto a delimitare la pausa dell’ultimo bit. Trentadue bit, quindi quattro byte, che in questo comando risultano 0x08, 0x16, 0x87 e 0x78. Gli ultimi due sono uno il complemento dell’altro, ed è un dettaglio che vale la pena notare: è il modo con cui il ricevitore verifica di aver letto bene, perché se i due byte non si corrispondono il comando viene semplicemente scartato.
Quello che mi ha colpito di più, arrivato in fondo, è che non c’è nessun passaggio difficile. Non ho dovuto decifrare niente: ho solo continuato a guardare la stessa forma d’onda cambiando ogni volta la domanda. Prima quanto è veloce, poi quando c’è e quando non c’è, poi quanto dura. Ogni volta che ho tolto un livello di dettaglio è comparsa un po’ di struttura in più.
Ed è per questo che, se sei arrivato fin qui, il risultato che mi interessa non è che tu abbia imparato che cosa trasmetteva il mio telecomando. È che la prossima volta che ti capita sotto gli occhi un oscillogramma di questo tipo, tuo o di chiunque altro, tu possa cominciare a leggerlo con le stesse domande: dov’è la portante, dove sono i MARK e gli SPACE, quali durate si ripetono. Da lì in poi il protocollo si racconta praticamente da solo.
Era esattamente questo lo scopo: prendere un ProvaTelecomando nato per far lampeggiare un LED e usarlo come scusa per guardare davvero dentro il segnale di un telecomando a infrarossi.