Sommario:

Arduino UNO Logic Sniffer: 8 passaggi (con immagini)
Arduino UNO Logic Sniffer: 8 passaggi (con immagini)

Video: Arduino UNO Logic Sniffer: 8 passaggi (con immagini)

Video: Arduino UNO Logic Sniffer: 8 passaggi (con immagini)
Video: DIY Radar With Ultrasonic Sensor And Chat-GPT Generated Arduino Code | Coders Cafe 2024, Luglio
Anonim
Arduino UNO Logic Sniffer
Arduino UNO Logic Sniffer

Questo progetto è iniziato come un semplice esperimento. Durante la mia ricerca sulla scheda tecnica dell'ATMEGA328P per un altro progetto, ho trovato qualcosa di piuttosto interessante. L'unità di acquisizione dell'ingresso Timer1. Consente al microcontrollore del nostro Arduino UNO di rilevare un fronte di segnale, memorizzare un timestamp e attivare un'interruzione, il tutto nell'hardware.

Mi sono quindi chiesto in quale applicazione potesse essere utile e come testarlo. Dato che voglio ottenere un analizzatore logico da un po' di tempo, ho deciso di provare a implementarne uno nella mia scheda Arduino UNO, solo per testare la funzionalità e vedere se possiamo ottenere buoni risultati.

Non sono l'unico ad aver avuto questa idea e ne troverai molti semplicemente cercando su Google "Arduino Logic Analyzer". All'inizio del progetto, dato che era appena iniziato come un esperimento, non mi ero nemmeno accorto che le persone l'avessero già fatto, e sono rimasto impressionato dai buoni risultati che hanno ottenuto con questo piccolo pezzo di hardware. Tuttavia, non sono riuscito a trovare un altro progetto utilizzando l'unità di acquisizione dell'input, quindi se l'hai già visto, fammi sapere!

Per riassumere, il mio analizzatore logico:

  • Avere un canale,
  • Avere un'interfaccia grafica,
  • Comunicare con l'interfaccia tramite USB,
  • Esegui su una scheda Arduino UNO.

Avrà finalmente una profondità di memoria di 800 campioni ed è stato in grado di catturare con successo un messaggio UART a 115200 baud (non l'ho davvero testato a velocità più elevate).

Questo tutorial contiene sia le parti "come funziona" che "come usarlo" di questo progetto, quindi per coloro che non sono interessati dal lato tecnico, puoi passare direttamente al passaggio 4.

Forniture

Volevo mantenere l'analizzatore il più semplice possibile, richiedendo così pochissimo hardware.

Avrai bisogno:

  • Una scheda Arduino UNO (o equivalente purché si basi sull'MCU ATMEGA328P),
  • Un computer,
  • Qualcosa di cui eseguire il debug (un'altra scheda Arduino UNO funziona bene per eseguire alcuni test).

Il codice sia per Arduino UNO che per l'interfaccia web può essere trovato qui. Avrai anche bisogno del software p5.serialcontrol e PulseView.

Passaggio 1: principio di funzionamento

Principio di funzionamento
Principio di funzionamento

L'idea è semplice. Scegli le impostazioni di acquisizione e fai clic su "acquisisci". L'interfaccia web li invierà al software p5.serialcontrol, che ci permette di utilizzare l'interfaccia seriale da un browser, non potendo accedervi direttamente. Il software p5.serialcontrol quindi inoltra le informazioni alla scheda Arduino UNO, che acquisisce i dati e li rimanda all'interfaccia attraverso lo stesso percorso.

Facile! Beh… Dato che non sono molto bravo con la programmazione dell'interfaccia uomo/macchina o con le tecnologie web, la mia è sicuramente un po' brutta e piena di bug. Ma mi consente di avviare un'acquisizione e recuperare i miei dati, che è ciò per cui è stato progettato, quindi penso che vada bene. Per un lavoro di analisi più serio, importo i miei record in PulseView, che è facile da usare e offre un buon set di funzionalità e decodificatori di protocollo, come vedremo più avanti.

L'unità di acquisizione dell'ingresso di Arduino UNO può essere configurata per utilizzare diverse divisioni di clock, riducendo così la risoluzione, ma aumentando il ritardo prima dell'overflow. Può anche attivarsi in caso di salita, discesa o entrambi i fronti per iniziare a catturare i dati.

Passaggio 2: schizzo Arduino UNO

Arduino UNO Sketch
Arduino UNO Sketch

Ho scritto e compilato lo sketch con l'IDE di Arduino. Ho iniziato impostando il Timer1 in modalità operativa "Normale" scrivendo nei suoi registri TCCR1A e TCCR1B nel setup(). Ho quindi creato alcune funzioni per facilitarne un po' l'utilizzo in futuro, come quella per impostare la divisione dell'orologio denominata "setTim1PSC()". Ho anche scritto funzioni per attivare e disattivare l'unità di acquisizione dell'ingresso Timer1 e gli interrupt di overflow.

Ho aggiunto l'array "campioni", che conterrà i dati acquisiti. È un array globale che ho impostato su "volatile" per impedire al compilatore di fare ottimizzazioni e di metterlo in flash, come faceva durante le mie prime compilazioni. L'ho definito come un array "uint16_t", poiché anche il Timer1 è a 16 bit, con una lunghezza di 810. Smettiamo di catturare a 800 valori, ma poiché il test viene eseguito al di fuori degli interrupt per ovvi motivi di velocità, ho scelto di mantenere 10 più valori per evitare l'overflow. Con alcune variabili extra per il resto del codice, lo sketch utilizza 1313 byte (88%) di memoria, lasciandoci con 235 byte di RAM libera. Abbiamo già un elevato utilizzo della memoria e non volevo aggiungere più capacità di campionamento, in quanto potrebbe causare comportamenti strani a causa dello spazio di memoria insufficiente.

Nella mia ricerca per aumentare sempre la velocità di esecuzione, ho usato i puntatori a funzione invece delle istruzioni if all'interno degli interrupt, per ridurre al minimo il loro tempo di esecuzione. Il pin di cattura sarà sempre il numero 8 di Arduino UNO, in quanto è l'unico collegato all'unità di cattura dell'ingresso del Timer1.

Il processo di acquisizione è mostrato nell'immagine sopra. Si avvia quando Arduino UNO riceve un frame di dati UART valido, contenente le impostazioni di acquisizione desiderate. Quindi elaboriamo tali impostazioni configurando i registri giusti per acquisire sul bordo scelto e utilizzare la divisione di clock corretta. Abilitiamo quindi l'interrupt PCINT0 (cambio pin) per rilevare il primo fronte del segnale. Quando lo otteniamo, resettiamo il valore Timer1, disabilitiamo l'interrupt PCINT0 e abilitiamo l'interrupt ICU (Input Capture Unit). Da quel momento, qualsiasi fronte di salita/discesa del segnale (a seconda della configurazione scelta), attiverà l'unità di cattura dell'ingresso, salvando così un timestamp di questo evento nel registro ICR1 ed eseguendo un interrupt. In questo interrupt inseriamo il valore del registro ICR1 nel nostro array "samples" e incrementiamo l'indice per la cattura successiva. Quando il Timer1 o l'array trabocca, disabilitiamo l'interrupt di acquisizione e reinviamo i dati all'interfaccia Web tramite UART.

Ho deciso di utilizzare un interrupt di cambio pin per attivare l'acquisizione, poiché l'unità di acquisizione dell'input consente di acquisire solo su uno o sull'altro bordo, non su entrambi. Causa anche un problema quando si desidera acquisire entrambi i bordi. La mia soluzione è quindi quella di invertire il bit che controlla la selezione del bordo nel registro di controllo dell'acquisizione dell'ingresso ad ogni campione recuperato. In questo modo perdiamo velocità di esecuzione, ma possiamo comunque utilizzare le funzionalità dell'unità di acquisizione dell'input.

Quindi, come avrai notato, non catturiamo realmente ogni campione a intervalli di tempo fissi, ma catturiamo il momento in cui avviene una transizione del segnale. Se avessimo catturato un campione ad ogni ciclo di clock, anche con la divisione di clock più alta, avremmo riempito il buffer in circa 0,1 secondi, supponendo che stessimo usando il tipo uint8_t, che è il più piccolo in memoria senza usare struct.

Passaggio 3: interfaccia Web e P5.js

Interfaccia Web e P5.js
Interfaccia Web e P5.js

Come suggerisce il titolo, l'interfaccia web è stata realizzata con l'aiuto di p5.js. Per chi ancora non lo conoscesse, consiglio vivamente di andare a dare un'occhiata al sito, perché è davvero un'ottima libreria. Si basa su Processing, è facile da usare, permette di ottenere buoni risultati molto velocemente ed è ben documentato. È per tutti questi motivi che ho scelto questa libreria. Ho anche usato la libreria quicksettings.js per i menu, quella grafica.js per tracciare i miei dati e la libreria p5.serialport per comunicare con Arduino UNO.

Non passerò troppo tempo sull'interfaccia, poiché l'ho appena progettata per l'anteprima dei dati e il controllo delle impostazioni, e anche perché non è stata affatto l'oggetto del mio esperimento. Spiegherò comunque nelle parti successive i diversi passaggi per utilizzare l'intero sistema, spiegando così i vari controlli disponibili.

Passaggio 4: configurazione del sistema

La prima cosa è scaricare Arduino UNO e il codice dell'interfaccia qui se non è già stato fatto. Puoi quindi riprogrammare la tua scheda Arduino UNO con lo sketch "UNO_LS.ino" tramite l'IDE Arduino.

Dovresti aver scaricato il software p5.serialcontrol dal suo repository github. Devi ottenere il file zip corrispondente al tuo sistema operativo (l'ho testato solo su Windows). Estrai lo zip in una cartella, avvia l'eseguibile trovato in esso e lascialo così. Non provare a connetterti a nessuna porta seriale, lascialo in esecuzione in background, verrà utilizzato come relè.

Apri la cartella "Interfaccia". Dovresti trovare un file chiamato "index.html". Aprilo nel tuo browser, è l'interfaccia web.

E questo è tutto! Non è necessario scaricare librerie aggiuntive, tutto dovrebbe essere incluso nel pacchetto che ho fornito.

Passaggio 5: connessione, configurazione e acquisizione

Connessione, Configurazione e Acquisizione
Connessione, Configurazione e Acquisizione

Per connettere l'interfaccia alla scheda Arduino UNO, basta selezionare la porta corrispondente nell'elenco e premere il pulsante "Apri". Se l'operazione è andata a buon fine, il messaggio "stato" dovrebbe visualizzare qualcosa come "COMX aperto".

Ora puoi scegliere le opzioni di acquisizione. Il primo è la selezione del bordo. Ti consiglio di usare sempre "Entrambi", in quanto ti darà la migliore rappresentazione del segnale reale. Se l'impostazione "Entrambi" non riesce a catturare il segnale (se la frequenza del segnale è troppo alta, ad esempio), puoi provare con l'impostazione "Ascendente" o "Discendente", a seconda del segnale che cerchi di vedere.

La seconda impostazione è la divisione dell'orologio. Ti darà la risoluzione alla quale sarai in grado di catturare il segnale. Puoi scegliere di impostare il fattore di divisione per "8", "64", "256" e "1024". La scheda Arduino UNO utilizza un quarzo da 16 MHz per il clock del microcontrollore, quindi la frequenza di campionamento sarà "16 MHz/fattore di divisione". Fai attenzione con questa impostazione, poiché determina anche per quanto tempo sarai in grado di catturare un segnale. Poiché Timer1 è un timer a 16 bit, il tempo di acquisizione consentito prima dell'overflow sarà "(2^16)*(fattore di divisione)/16MHz". A seconda dell'impostazione scelta, sarà compreso tra ~33ms e 4.2s. Tieni a mente la tua scelta, ne avrai bisogno in seguito.

L'ultima impostazione è la cancellazione del rumore. Non ho condotto molti test su di esso e non ne avrai bisogno nel 99% dei casi, quindi lascialo deselezionato. Per chi ne fosse ancora curioso, è possibile cercare il noise canceller nella sezione Timer/Contatore1 della scheda tecnica dell'ATMEGA328P.

Non dimenticare di collegare il pin 8 della scheda Arduino UNO al segnale e di collegare le masse insieme per avere lo stesso riferimento di tensione sia per il circuito di prova che per l'analizzatore logico. Se hai bisogno di isolamento da terra, o hai bisogno di misurare segnali con livelli diversi da 5V, probabilmente dovrai aggiungere un optoisolatore al tuo circuito.

Una volta che tutto è configurato correttamente, puoi premere il pulsante "Acquisisci".

Passaggio 6: acquisizione dei risultati ed esportazione dei dati CSV

Acquisizione dei risultati ed esportazione dei dati CSV
Acquisizione dei risultati ed esportazione dei dati CSV

Una volta che Arduino UNO ha terminato l'acquisizione, invierà automaticamente i dati all'interfaccia web, che li stamperà. Puoi ingrandire o ridurre con il cursore destro e viaggiare attraverso i campioni con quello in basso.

La trama ti dà solo un'anteprima e non ha strumenti di analisi dei dati. Pertanto, per condurre ulteriori analisi sui tuoi dati, dovrai importarli in PulseView.

Il primo passo è esportare un file CSV contenente tutti i tuoi dati. Per fare ciò, è sufficiente fare clic sul pulsante "Esporta" dall'interfaccia web. Salva il file in una posizione nota quando richiesto.

Ora apri PulseView. Nella barra dei menu in alto, fai clic su "Apri" (icona della cartella) e seleziona "Importa valori separati da virgola…". Seleziona il file CSV generato in precedenza contenente i tuoi dati.

Apparirà una piccola finestra. Lascia tutto così com'è, devi solo modificare l'impostazione "Samplerate" in base al fattore di divisione dell'orologio scelto per la cattura. La tua frequenza di campionamento sarà "16MHz/(fattore di divisione)". Quindi fare clic su "Ok", il segnale dovrebbe apparire sullo schermo.

Passaggio 7: analisi del segnale PulseView

Analisi del segnale PulseView
Analisi del segnale PulseView

PulseView dispone di molti decodificatori di protocollo. Per accedervi, fai clic su "Aggiungi decodificatore di protocollo" nella barra dei menu in alto (strumento più a destra). Per il mio esperimento, ho appena inviato un semplice messaggio UART a 9600 baud, quindi ho cercato "UART".

Aggiungerà un canale con un tag alla sua sinistra (proprio come quello per i tuoi dati). Cliccando sul tag è possibile modificare le impostazioni del decoder. Dopo aver scelto quelli giusti, sono riuscito a recuperare lo stesso messaggio inviato dal mio dispositivo di prova. Ciò dimostra che l'intero sistema funziona come previsto.

Passaggio 8: conclusione

Conclusione
Conclusione

Anche se il progetto era, all'inizio, un esperimento, sono contento dei risultati che ho ottenuto. Sono stato in grado di campionare segnali UART fino a 115200 baud in modalità edge "Both" senza alcun problema, e sono persino riuscito a raggiungere 230400 baud in modalità edge "Falling". Puoi vedere la mia configurazione di prova nella foto sopra.

La mia implementazione ha diversi inconvenienti, a cominciare dal fatto che può catturare solo un segnale alla volta, poiché solo il pin 8 di Arduino UNO è "capace di catturare l'input". Se stai cercando un analizzatore logico Arduino con più canali, controlla quello di Catoblepas.

Non puoi aspettarti che un Arduino UNO sia in grado di catturare segnali con alte frequenze (alcuni MHz), poiché ha un clock solo a 16 MHz (se qualcuno lo facesse, sarei interessato a vedere il suo metodo). Tuttavia, sono ancora impressionato dai risultati che possiamo ottenere da questo microcontrollore ATMEGA328P.

Non credo che lavorerò molto sul codice. Ho condotto i miei esperimenti e ho ottenuto i risultati che cercavo. Ma se qualcuno vuole contribuire, si senta libero di modificare e ridistribuire tutto o parte del mio codice.

Questo è stato il mio primo Instructable, e credo sia lungo. Spero che sia stata una lettura interessante per te.

Fammi sapere se trovi errori o se hai qualche domanda!

Consigliato: