V
Visla Hardware
Portal R&D
🧩 Moduli & Shield ✓ Verified · 2026-06-05 ⚡ Low power cheap ✓ In stock

EBYTE E07-M1101D-SMA (CC1101 module)

EBYTE (chip TI CC1101)
🏭 Chip @ 1k pcs
€4.50
production BOM
📦 Dev board
€3.29
EBYTE E07-M1101D-SMA
0.2µA sleep!Wake-on-radioSMA antenna connector
📑 Indice sezioni

Curiosity

Breakout EBYTE da €3.29 (Amazon Business, IVA inclusa) per il chip TI CC1101 sub-GHz transceiver. Stessa categoria del RXB6 dell’attuale Visla Prototype 1 ma 10× meglio in battery life (wake-on-radio 0.2 µA sleep, sensibilità -116 dBm). Form factor DIP 15×28mm con connettore SMA per antenna esterna. Cert CE/FCC/RoHS già ottenute (sollevato Visla dalla cert chip-level). Per Visla v2 è il candidato n.1 come ricevitore 433 MHz keyfob (EV1527 / arm-disarm) + come possibile TX bidirezionale per ACK affidabile.

📐 Dimensioni e pinout ufficiale

EBYTE E07-M1101D-SMA — dimensioni e pinout ufficiale

Form factor: DIP 15×28mm (PCB) + SMA antenna stub. Pin pitch standard 2.54mm. Vista da sopra (component side): pin 7-5-3-1 in alto, 8-6-4-2 in basso. Sul bottom (solder side) è mirrored: 1-3-5-7 in alto, 2-4-6-8 in basso. Pad 9 e 10 sono ground/RF aggiuntivi.

⚠️ Gotcha critico: la sequenza pin SPI non è quella che ti aspetti dal CC1101 raw. EBYTE ha rimappato l’ordine — verifica sempre col datasheet ufficiale (incluso sotto), MAI assumere.

Specs tecniche (datasheet EBYTE)

ParametroValore
ChipTI CC1101 (sub-GHz transceiver SPI)
Frequenza387–464 MHz (default 433 MHz EU ISM)
Potenza TX max10 dBm (10 mW)
Sensibilità RX-116 dBm @ 0.6 kbps · -110 dBm @ 1.2 kbps
Distanza tipica0.6 km LOS, ~50 m indoor
ModulazioniOOK · ASK · GFSK · 2-FSK · 4-FSK · MSK
Voltage VCC1.8–3.6V DC (3.3V tipico)
Standby (wake-on-radio)0.2 µA
RX active14.7 mA
TX active @ +10 dBm30 mA
InterfaceSPI 4-wire + 2× GDO (digital output programmabili)
Antenna connectorSMA female (variant SMA) o IPEX (variant IPEX)
Dimensioni PCB15.0 × 28.0 mm + SMA stub
Peso3.4 g
Operating temp-40 to +85°C (industrial)
CertificazioniCE · FCC · RoHS (sollevati dalla cert chip-level)
Cristallo26 MHz industrial grade
BufferRX FIFO + TX FIFO (64 byte each)
CompatibilitàFlipper Zero, ESP32, Arduino, Raspberry Pi
Prezzo Amazon Business IT€3.29 (singolo) → €2.49 a 100pz

🔌 Pinout ufficiale + cablaggio XIAO

⚠️ Sequenza pin ufficiale EBYTE (corretta — verificata dal datasheet manual v1.40):

PinFunzioneDirezioneCablaggio XIAO Expansion Board
1GNDXIAO GND (strip superiore, 2° pin “G”)
2VCCinput 1.8-3.6V DCXIAO 3V3 (strip superiore, 3° pin “3V3”) ⚠️ MAI 5V
3GDO0outputXIAO D0 (bottom strip, 1° pin a sinistra) — interrupt RX
4CSNinputXIAO D2 (bottom strip, 3° pin) — chip select SPI
5SCKinputXIAO D8 (top strip, label “8”) — SPI clock
6MOSIinputXIAO D10 (top strip, label “10”) — SPI data IN al modulo
7MISO / GDO1outputXIAO D9 (top strip, label “9”) — SPI data OUT dal modulo
8GDO2outputnon collegato (interrupt secondario opzionale)

🎓 Cosa fa ciascun pin (spiegato semplice)

1) GND — Massa / ground Lo “zero” elettrico del circuito. Tutti i voltaggi (3.3V, segnali SPI) sono misurati rispetto a GND. Senza GND condiviso col MCU, anche se i fili dati arrivano, non c’è un riferimento comune e i bit risultano random. Pensa a 2 persone che parlano lingue diverse senza vocabolario condiviso.

2) VCC — Power input L’alimentazione del chip. Range 1.8–3.6V, optimal 3.3V. Da qui parte la corrente che alimenta tutto: oscillatore 26 MHz, amplificatori RF, logica SPI. ⚠️ MAI 5V — brucia il chip in pochi secondi.

3) GDO0 — General Digital Output 0 Pin programmabile: il CC1101 può configurarlo in molti modi. Nel nostro setup è settato come “raw bit stream RX” — il pin sputa fuori i bit decodificati dall’aria man mano che arrivano, e l’MCU li legge via attachInterrupt() + libreria rc-switch per decodificare keyfob/garage. Altre funzioni possibili: “pacchetto ricevuto” (modalità FIFO), RSSI threshold, wake-on-radio.

4) CSN — Chip Select Not (active LOW) Il “telecomando attenzione” del CC1101. Quando l’MCU mette CSN a LOW = “stai zitto e ascolta SPI”. Quando torna HIGH = “ignora SPI”. Serve perché lo stesso bus SPI può collegare più device in parallelo (es. col microSD dell’Expansion), e CSN separa chi parla con chi.

5) SCK — Serial Clock SPI Il metronomo del bus SPI. L’MCU (master) batte il tempo, il CC1101 (slave) ascolta. Ogni “tic” del clock = 1 bit trasferito. Più veloce il clock, più rapida la comunicazione. CC1101 supporta fino a 6.5 MHz, noi siamo a 1 MHz per sicurezza.

6) MOSI — Master Out, Slave In Il canale dati MCU → CC1101. Quando l’MCU vuole dire “configura te stesso a 433 MHz”, manda i byte sul filo MOSI mentre batte SCK. Il CC1101 li legge bit per bit ad ogni tic del clock.

7) MISO / GDO1 — Master In, Slave Out Il canale dati CC1101 → MCU (la risposta). Quando l’MCU chiede “che versione di chip sei?”, il CC1101 risponde con 0x14 sul filo MISO. La doppia etichetta “/GDO1” significa che quando SPI è inattivo (CSN HIGH), CC1101 può usare questo pin come terzo output programmabile.

8) GDO2 — General Digital Output 2 Gemello del GDO0, secondo pin programmabile. Tipici usi: secondo interrupt (“FIFO RX pieno”), carrier detect (segnale 433 MHz presente), output del clock interno per debug. Non lo usiamo, resta scollegato. Se in futuro vuoi dual-channel RX lo cabli su un altro GPIO MCU.

Pad extra 9 e 10

Visibili nel drawing dimensionale sotto le 2 file di pin SPI: sono pad aggiuntivi GND/RF per stabilità meccanica (saldatura SMD) e schermatura RF. Non li devi cablare al XIAO.

// Arduino — SmartRC-CC1101-Driver-Lib pin setup per XIAO ESP32-S3
ELECHOUSE_cc1101.setSpiPin(D8, D9, D10, D2);  // SCK, MISO, MOSI, CSN
ELECHOUSE_cc1101.setGDO(D0, 0);               // GDO0=D0, GDO2=non usato

🧪 Note dal bench Visla

  • Prezzo €3.29 Amazon Business — il sub-GHz transceiver più economico con cert CE
  • Cert CE/FCC/RoHS ottenute — Visla non rifà cert se cambia solo firmware applicativo
  • Wake-on-radio 0.2 µA = 75× meglio del RXB6 (~5 mA always-on) → battery life 75× su scenari arm-disarm da telecomando
  • Bidirezionale = ACK + retry possibili per arm/disarm reliable, vs RXB6 one-way → comando affidabile anche con noise EU SRD 433.92 MHz
  • SMA antenna esterna → range outdoor reale 100-200m con antenna stilo 5dBi, vs ~30m antenna spirale RXB6
  • Compatibile Flipper Zero (review Amazon menziona caso d’uso identico) — utile per debug protocolli + capture-replay
  • SPI a 5-10 MHz condiviso con microSD dell’Expansion Board (no conflict se microSD non inserita)
  • ⚠️ Pinout NON-standard CC1101 raw: EBYTE ha rimappato l’ordine pin — primo errore comune. Vedi tabella sopra
  • ⚠️ VCC 1.8-3.6V solo: i 5V bruciano il chip immediatamente, non ci sono protezioni a bordo
  • ⚠️ Antenna SMA obbligatoria: senza antenna il range è 1-2m (inutilizzabile)
  • ⚠️ FW più complesso del RXB6: configurazione registri CC1101 + decode protocolli (EV1527, PT2240, ecc) richiede ~3KB firmware Arduino vs 200 byte del RXB6

⚠️ Gotchas

  • Pin 1 identifica con punto/quadratino bianco sul silkscreen — se confuso con pin 4 corto-circuito VCC-GND
  • CSN active LOW — pull-up esterna non serve (CC1101 interno gestisce), ma se floating durante boot il chip ignora SPI
  • GDO0 default = sync word detect — per RX raw OOK serve riconfigurare via iocfg0
  • Crystal 26 MHz interno: drift di ~30 ppm → per protocolli low-baud OK, per 100+ kbps verifica calibration WORCTRL.WOR_RES
  • 2 versioni: -SMA (con connettore antenna) vs -TH (solo pad antenna, da saldare a filo). Variant SMA = €3.29, TH = €3.09

🧬 Bench Visla 2026-06-09 — config registri SmartRC ESATTA (funzionante)

Dopo 4 ore di debug col bench (diymore ESP32-S3 + CC1101 EBYTE + telecomandi vari), troviamo che la libreria SmartRC-CC1101-Driver-Lib si blocca in Init() su ESP32-S3 (loop infinito wait MISO low). Soluzione: bypass library + scrittura registri raw via SPIClass.

Inoltre i miei valori AGC iniziali erano sbagliati — il chip vedeva solo noise floor a -92 dBm. La config corretta è copiata 1:1 dai default di SmartRC source:

RegistroValore correcto OOK 433.92Cosa controlla
IOCFG00x0DGDO0 = async serial baseband demod out
IOCFG20x29GDO2 = CHIP_RDY (default)
PKTCTRL00x32async serial + infinite length (bit 6:4 = 0b011)
FSCTRL10x06IF freq
FREQ2/1/00x10 0xB0 0x71433.92 MHz (= MHz × 65536 / 26)
MDMCFG40xC7RX BW 270 kHz + drate_e (larga per OOK noisy)
MDMCFG30x83drate_m
MDMCFG20x30ASK/OOK + NO sync word
MDMCFG10x02 ⚠️preamble 2 byte (NON 0x22 = 4 byte)
MDMCFG00xF8
DEVIATN0x47 ⚠️valore critico (NON 0x35)
MCSM10x30resta in RX dopo pkt
MCSM00x18auto-calibrate
FOCCFG0x16
BSCFG0x1C ⚠️valore SmartRC (NON 0x6C)
AGCCTRL20xC7 ⚠️⚠️CRITICO: MAX_DVGA_GAIN + MAGN_TARGET_7 (NON 0x03!)
AGCCTRL10x00
AGCCTRL00xB2 ⚠️⚠️CRITICO: OOK decision boundary 8dB (NON 0x91)
FREND10x56 ⚠️front-end SmartRC (NON 0xB6)
FREND00x11OOK PA table index = 1
FSCAL3/2/1/00xE9 0x2A 0x00 0x1Fcalibrazione VCO
TEST2/1/00x81 0x35 0x09OOK test values
PATABLE[0x00, 0xC0]PA: index 0=OFF, index 1=+10dBm

Per cambiare frequenza dinamicamente (315/433/868/915): SCAL strobe + riscrivi FREQ2/1/0 + SRX strobe. Calibration VCO necessaria solo cross-band.

Sketch raw SPI funzionante (Visla bench 2026-06-09)

#include <SPI.h>
SPIClass spi(FSPI);
#define CC_SCK 12   // diymore screw IO12
#define CC_MISO 13  // IO13
#define CC_MOSI 11  // IO11
#define CC_CSN 10   // IO10
#define CC_GDO0 4   // IO4

void waitMiso() { uint32_t t=millis()+50; while(digitalRead(CC_MISO)&&millis()<t){} }
byte strobe(byte c) { digitalWrite(CC_CSN,LOW); waitMiso(); byte s=spi.transfer(c); digitalWrite(CC_CSN,HIGH); return s; }
void wReg(byte a,byte v) { digitalWrite(CC_CSN,LOW); waitMiso(); spi.transfer(a&0x3F); spi.transfer(v); digitalWrite(CC_CSN,HIGH); }
byte rStat(byte a) { digitalWrite(CC_CSN,LOW); waitMiso(); spi.transfer(0xC0|(a&0x3F)); byte v=spi.transfer(0); digitalWrite(CC_CSN,HIGH); return v; }

void initCC() {
  pinMode(CC_CSN,OUTPUT); digitalWrite(CC_CSN,HIGH);
  spi.begin(CC_SCK,CC_MISO,CC_MOSI,CC_CSN);
  spi.setFrequency(1000000); spi.setDataMode(SPI_MODE0);
  digitalWrite(CC_CSN,LOW); delayMicroseconds(40);
  digitalWrite(CC_CSN,HIGH); delayMicroseconds(40);
  digitalWrite(CC_CSN,LOW); delayMicroseconds(40);
  spi.transfer(0x30);  // SRES
  digitalWrite(CC_CSN,HIGH); delay(10);
  // Tutti i registri (vedi tabella sopra)
  wReg(0x02,0x0D); wReg(0x00,0x29); wReg(0x08,0x32); wReg(0x0B,0x06);
  wReg(0x0D,0x10); wReg(0x0E,0xB0); wReg(0x0F,0x71);
  wReg(0x10,0xC7); wReg(0x11,0x83); wReg(0x12,0x30); wReg(0x13,0x02); wReg(0x14,0xF8);
  wReg(0x15,0x47); wReg(0x17,0x30); wReg(0x18,0x18); wReg(0x19,0x16); wReg(0x1A,0x1C);
  wReg(0x1B,0xC7); wReg(0x1C,0x00); wReg(0x1D,0xB2);
  wReg(0x21,0x56); wReg(0x22,0x11);
  wReg(0x23,0xE9); wReg(0x24,0x2A); wReg(0x25,0x00); wReg(0x26,0x1F);
  wReg(0x2C,0x81); wReg(0x2D,0x35); wReg(0x2E,0x09);
  strobe(0x33); delay(5);   // SCAL
  strobe(0x36); delay(2);   // SIDLE
  strobe(0x3A); delay(2);   // SFRX
  strobe(0x34); delay(50);  // SRX
}

Sorgente completa (Visla repo): test-moduli/diymore-esp32-s3-cc1101/cc1101-wifi-webserver/

Risultati live monitor (bench 2026-06-09 00:26 — CSV salvato)

Con sketch corretto + Python dashboard 10 Hz:

Statoedges/100msRSSINote
Idle (chip silente)0-91 dBmnoise floor del front-end
Telecomando #1 a 30 cm100-160-34/-45 dBmpulsi OOK chiari
Telecomando #2 a 10 cm500-790-25/-30 dBmsegnale fortissimo

Verdetto: la config OOK funziona, l’antenna funziona (anche graffetta nel pin SMA), il front-end vede +65 dB di dinamica tra idle e segnale forte. Era solo questione di registri corretti SmartRC + library bypass su ESP32-S3.

Gotcha ESP32-S3 trovati nel bench

  1. SmartRC-CC1101-Driver-Lib Init() freeza su ESP32-S3 (timing wait MISO low non rispettato). Workaround: scrittura registri raw via SPIClass.
  2. USBMode/CDCOnBoot in FQBN cambia dove va Serial:
    • USBMode=default,CDCOnBoot=default → Serial sulla UART0 (CH9102 = wchusbserial)
    • USBMode=hwcdc,CDCOnBoot=cdc → Serial sul USB nativo S3 (usbmodem)
  3. WiFi + CC1101 init order: prima cc1101_init(), poi WiFi.begin() non-bloccante. Se WiFi fallisce il setup precoce blocca tutto.
  4. PKTCTRL0 = 0x32 è async serial NON sync (bit 6:4 = 0b011, non 0b001). Errore comune nei tutorial.
  5. Test loopback TX→RX sullo stesso modulo (TX continuous + leggi edges su GDO0 durante RX dopo) = test definitivo per validare front-end RF senza dover validare l’antenna.

🧬 Bench Visla 2026-06-09 — Decodifica completa rolling-code

Continuando il bench del 2026-06-09, una volta superato il problema “RCSwitch non decodifica nulla” abbiamo dimostrato che il CC1101 EBYTE su ESP32-S3 è in grado di decodificare protocolli OOK custom oltre EV1527 — incluso il rolling code di un telecomando auto/cancello commerciale.

Pulse-width sniffer — la tecnica che funziona

Quando RCSwitch fa 0 codici ma vediamo edges in OOK, la strategia che ha sbloccato tutto:

  1. Sketch ESP32-S3 con ISR attachInterrupt(GDO0, CHANGE) che spinge (level, dt_µs) in buffer circolare
  2. Loop drena il buffer su Serial.printf("P,%u,%u\n", level, dt)
  3. Script Python ccwidths.py legge il flusso, fa istogramma dei pulse widths
  4. Script Python ccdecode.py legge il CSV, splitta in frame su gap >5 ms, decodifica PWM per ogni frame, conta ripetizioni

Il vantaggio: non assumiamo nulla sul protocollo — l’istogramma ti dice il bit time reale, il frame splitter ti dice quanto è lunga ogni ripetizione del codice, il counter ti dice qual è il pattern stabile.

Risultato test telecomando ignoto (433.92 MHz)

Dump istogramma su ~16 secondi tenendo premuto un tasto:

Top pulse widths (carrier ON):
    50-  99 µs : 2599  (noise floor / glitch filtrato)
   850- 899 µs : 1846  (LONG mark)
   400- 449 µs : 1705  (SHORT mark)
   450- 499 µs : 1156  (SHORT mark variant)
 14450-14499 µs:   51  (frame inter-gap)
  4650- 4699 µs:   45  (SYNC header)

Top pulse widths (carrier OFF):
   950- 999 µs : 3521  (LONG gap)
   400- 449 µs : 2272  (SHORT gap)
   800- 849 µs : 1827
  1950-1999 µs :  965

Rapporto long/short: 2.29 (NON Manchester puro, NON EV1527 standard)
Frame gap mediano: 14.5 ms tra ripetizioni

Parametri protocollo dedotti dal solo istogramma:

ParametroValoreNote
ModulazioneOOK/ASK PWMconfermato (no FSK)
Bit short (T)~425 µsil “0” PWM
Bit long (2T)~875 µsil “1” PWM
Sync header~4650 µspulse di wake-up
Frame gap14.5 mstra ripetizioni della stessa pressione
Bits per frame66–67 utili (+ 10 zero preamble)

Decodifica codici — firma rolling-code

Catturando ~100 frame stesso tasto:

A (39×): 11000000100001010011101011010011010100 1100011001010011110101001100
B (13×): 11011001110100000110010110011111010100 1100011001010011110101001100
C  (3×): 10100111010101110110100100110000010100 1100011001010011110101001100
         └────────CRYPTO BLOCK (varia)─────────┘ └────FIXED SERIAL + button─────┘

I 28 bit finali sono identici in tutti i frame: serial number del telecomando + button code = firma fissa di quel telecomando specifico.

I 38 bit iniziali (post-preamble) variano ad ogni press = rolling code crittografato, classica firma Microchip HCS200/HCS300/HCS301 KeeLoq o clone (Holtek HT6P20D, ecc).

Implicazioni per Visla anti-furto

Identificazione device-specific possibile — il serial fisso ci permette di:

  • Whitelist telecomandi autorizzati per un veicolo
  • Detection “telecomando ignoto nel raggio” (anti-relay attack)
  • Log accessi per audit / forense

Replay attack non funziona — counter crittografico anti-replay sul transponder.

Decifratura cifrato richiede chiave del produttore (KeeLoq Manufacturer Key) o brute force su ~2-3 codici (attacchi accademici noti contro KeeLoq classico).

Sketch sniffer + decoder

  • Sketch ESP32-S3: pulse-width logger (commit dopo bench)
  • Python istogramma: ccwidths.py
  • Python decoder PWM + frame splitter: ccdecode.py

Verdetto chiave: il CC1101 EBYTE su ESP32-S3 è in grado di sniffare e decodificare protocolli OOK custom non-standard purché si bypassi RCSwitch e si lavori sui pulse width grezzi. Per Visla v2 questo apre la porta a feature tipo “telecomando trovato vicino al device” senza richiedere SDR specializzati.

🧬 Bench Visla 2026-06-09 — Lezione: NON tutti i telecomandi 433 sono OOK

Continuando il bench, abbiamo testato il telecomando del kit LHD-Tech C003E (4G car alarm cinese) sul CC1101 EBYTE. Inizialmente in OOK mode vedevamo solo artefatti (pulse 50-75 µs + gap 950 µs, rapporto 13:1, nessun bit decodificabile).

La svolta: cambio modulation a 2-FSK

Sospettando un problema di modulation, abbiamo riconfigurato CC1101 in 2-FSK:

// PRIMA: OOK (errato per LHD)
wReg(0x12, 0x30);  // MDMCFG2 - OOK/ASK
wReg(0x22, 0x11);  // FREND0 - PATABLE[1]

// DOPO: 2-FSK (corretto)
wReg(0x12, 0x00);  // MDMCFG2 - 2-FSK
wReg(0x22, 0x10);  // FREND0 - PATABLE[0]
wReg(0x10, 0x88);  // MDMCFG4 - RXBW 203 kHz + DRATE_E=8
wReg(0x15, 0x47);  // DEVIATN - ~47 kHz frequency deviation
wReg(0x1B, 0x43);  // AGCCTRL2 - standard FSK gain

Risultato: rapporto pulse passa da 13:1 (artefatto OOK) a 3:1 (EV1527 standard valido). Il telecomando trasmette EV1527 PWM ma su carrier 2-FSK invece di OOK puro — scelta inusuale tra fixed-code commerciali 433 ma sensata per ambiente automotive rumoroso.

Cosa abbiamo imparato

  1. CC1101 OOK mode falsa il segnale FSK in un pattern PDM-like che sembra “custom” ma non lo è — è artefatto del slicer OOK che cerca di demodulare carrier FSK costante.
  2. Test sistematico modulation è cruciale prima di concludere “protocollo custom”. Lo sketch modulation sweep cycla 5 modulation in 25 sec — se vedi attività in 2-FSK + RSSI alto in OOK = probabilmente è FSK, non OOK.
  3. Decoder universale (ccdecode_ev1527.py) con noise filter > 400 µs filtra gli artefatti FSK demod e isola i bit reali EV1527 PWM 1:3.
  4. CC1101 è radio universale 433 — copre fixed-code OOK (cancelli base), rolling-code KeeLoq (auto), fixed-code FSK (alarm car). Il modulino è correttamente “il coltellino svizzero sub-1GHz” che speravamo.

Workflow Visla per protocollo ignoto 433 MHz

1. Modulation sweep (5 sec per modulation)
   → Identifica quale demoda con edges/sec > 1000 e pattern stabile
2. Cattura raw pulses in modulation winner
   → ccwidths.py → istogramma → rapporto long/short
3. Se ratio 3:1 → EV1527 → ccdecode_ev1527.py
   Se ratio 2:1 → Manchester → ccdecode_manchester.py
   Se ratio 2.3:1 + 28-bit serial fisso → KeeLoq rolling → ccdecode_keeloq.py
4. Whitelist serial ID per Visla

Tutto questo con €3.29 di CC1101 EBYTE + ESP32-S3 + Python. Niente SDR, niente bench costoso.

🔗 Risorse