Nella serie di articoli attuale mi rivolgo ai miei colleghi del gruppo di fisica. I prossimi episodi tratteranno di un dinamometro senza molla a spirale, naturalmente non senza l'uso di un sensore elastico. Tuttavia, la sua elasticità è praticamente impercettibile. Tuttavia, la risoluzione non è ridotta dall'aspetto visivo appena percettibile, ma piuttosto migliorata. Vi svelerò come ciò sia possibile nei nuovi episodi della serie.
MicroPython su ESP32, ESP8266 e Raspberry Pi Pico
oggi
Un dinamometro con MicroPython – Parte 1
1. Nella prima parte ci occuperemo del principio di misurazione e della struttura dell'hardware.
2. Nella seconda parte aggiungiamo un display di grandi dimensioni al laptop, controllato tramite USB.
3. Nella parte 3 sostituiamo il cavo dati USB con la trasmissione radio.
4. La parte 4 comprende un'unità di visualizzazione con 8 pannelli LED, anch'essa collegata tramite WLAN.
5. Un tablet Android come unità di visualizzazione viene presentato nella parte 5.
Il sensore di forza
Qualche tempo fa ho già utilizzato altrove un componente della stessa famiglia di quello che sto utilizzando ora. bilancia . In entrambi i casi si tratta in definitiva della misurazione di forze. Ciò significa che anche nella determinazione della massa con la bilancia si trattava della misurazione di una forza, ovvero la forza di gravità F.g. Questa è collegata alla massa m dei pesi tramite il fattore locale g = 9,81 N/kg: Fg = g • m. Ciò consentiva di calibrare la bilancia con pesi. La figura 1 mostra una bilancia a bracci. Il lato destro della bilancia è fissato saldamente al supporto, mentre il piatto di pesatura è fissato sul lato sinistro.

Figura 1: Cella di carico dal lato
Nel caso specifico, occorre misurare direttamente le forze. Ciò è possibile grazie alla deformazione elastica di un bilanciere in alluminio su cui sono applicati degli estensimetri. Questi componenti sono costituiti da circuiti conduttori sottilissimi che, a seconda della loro posizione, vengono allungati o compressi dalla flessione dei punti assottigliati del bilanciere, modificando così la loro resistenza elettrica.

Figura 2: Estensimetro schematico
Allungando i conduttori, questi diventano più lunghi e sottili, mentre comprimendoli si ottiene l'effetto opposto. La lunghezza e la sezione trasversale del conduttore influiscono entrambe sul calcolo della resistenza elettrica di un conduttore. Sia l'allungamento che la riduzione della sezione trasversale provocano un aumento del valore di resistenza. ρ è la resistenza specifica, una costante del materiale.

Figura 3: Formula di resistenza
Affinché anche le più piccole variazioni del valore di resistenza portino a un risultato di misurazione riproducibile con un'elevata risoluzione, le strisce di misurazione sono raggruppate in un circuito a ponte, la cui tensione di uscita viene inviata a un amplificatore di precisione. La tensione di uscita di quest'ultimo deve ora essere solo digitalizzata per l'elaborazione in un microcontrollore.

Figura 4: Estensimetri sull'HX711
Il modulo HX711 contiene entrambi i componenti e consente inoltre di scegliere l'amplificazione, 128x o 64x sull'ingresso differenziale A e 32x sull'ingresso B. La trasmissione del segnale a 24 bitADC-Valore (ADC = Analog Digital Converter) al microcontrollore avviene tramite la Dati-linea, che tramite 24 impulsi a Orologio viene sincronizzato. Fino a tre ulteriori impulsi influenzano l'impostazione dell'amplificazione del PGA (Programmable Gain Amplifier) per la misurazione successiva. La barra di pesatura qui utilizzata può sopportare un carico fino a 5 kg, che corrisponde a una forza massima di circa 50 N. Insieme all'ingresso A e al guadagno = 128, otteniamo una risoluzione di 1 mN, corrispondente a circa 0,1 grammi di massa. Poiché questo è già il punto incerto, ci accontentiamo di 10 mN come valore di misura minimo e otteniamo in cambio una visualizzazione stabile del valore misurato. 0,01 N è anche molto più di quanto si possa ottenere con i dinamometri a molla elicoidale.

Figura 5: Regolazione dell'amplificazione tramite impulsi di clock aggiuntivi
L'interfaccia software per l'HX711 è la classe HX711 del modulo MicroPython hx711.py. Ne parleremo più avanti.
Hardware
Come controller sono adatti sia i modelli ESP8266 che ESP32 con almeno quattro GPIO liberi. Il valore misurato viene inizialmente visualizzato su un display OLED. Naturalmente è possibile utilizzare anche un altro modello come cella di carico. Sono disponibili modelli con capacità di pesatura da 100 g fino a 100 kg e oltre.
Per motivi di spazio, in questo progetto ho optato per un D1 Mini NodeMcu con modulo WLAN ESP8266-12F Deciso. L'alimentazione elettrica dell'elettronica di misurazione avviene per il momento tramite USB.
Il circuito per l'ESP8266 D1 Mini

Figura 6: Dinamometro - Cambio
Il software
Per il flashing e la programmazione dell'ESP32:
Thonny o
Creazione di set di caratteri personalizzati
zeichensatz.rar Ambiente di lavoro per la creazione di set di caratteri personalizzati
Per la rappresentazione dei segnali bus
SALEAE – Software Logic Analyzer (64 bit) per Windows 8, 10, 11
Firmware utilizzato per l'ESP32:
Firmware utilizzato per l'ESP8266:
Firmware utilizzato per il Raspberry Pi Pico (W):
RPI_PICO_W-20240602-v1.23.0.uf2
I programmi MicroPython relativi al progetto:
ssd1306.py Driver hardware per il display OLED
oled.py API per il display OLED
geometer_30.py ampio set di caratteri per la visualizzazione dei numeri
hx711.py API per AX711
newtonmeter.py Il programma operativo
MicroPython - Linguaggio - Moduli e programmi
Per l'installazione di Thonny, clicca qui istruzioni dettagliate (versione inglese). Qui si trova anche una descrizione di come Firmware Micropython (aggiornato al 25/01/2024) sul chip ESP bruciato sarà. Per sapere come preparare il Raspberry Pi Pico all'uso, consultare qui.
MicroPython è un linguaggio interpretato. La differenza principale rispetto all'IDE Arduino, dove si eseguono sempre e solo programmi completi, è che il firmware MicroPython deve essere eseguito solo una volta all'inizio sull'ESP32 affinché il controller comprenda le istruzioni MicroPython. A tal fine è possibile utilizzare Thonny, µPyCraft o esptool.py. Per Thonny ho descritto la procedura qui descritto.
Una volta aggiornato il firmware, è possibile comunicare liberamente con il controller, testare singoli comandi e vedere immediatamente la risposta, senza dover prima compilare e trasferire un intero programma. È proprio questo che mi disturba dell'IDE Arduino. Si risparmia un sacco di tempo se si possono verificare in anticipo semplici test della sintassi e dell'hardware, fino a provare e perfezionare funzioni e intere parti del programma tramite la riga di comando, prima di creare un programma. A questo scopo, mi piace creare piccoli programmi di prova. Come una sorta di macro, raggruppano i comandi ricorrenti. Da tali frammenti di programma si sviluppano talvolta intere applicazioni.
Avvio automatico
Se desiderate che il programma si avvii automaticamente all'accensione del controller, copiate il testo del programma in un nuovo file vuoto. Salvate questo file con il nome main.py nell'area di lavoro e caricatelo sul chip ESP. Al successivo reset o all'accensione, il programma si avvierà automaticamente.
Testare i programmi
I programmi vengono avviati manualmente dalla finestra corrente dell'editor nell'IDE Thonny premendo il tasto F5. È più veloce che cliccare con il mouse sul pulsante di avvio o dal menu. Corsa. Solo i moduli utilizzati nel programma devono trovarsi nella memoria flash dell'ESP32.
Di tanto in tanto ancora Arduino IDE?
Se in seguito desiderate utilizzare nuovamente il controller con l'IDE Arduino, è sufficiente eseguire il flashing del programma come di consueto. Tuttavia, l'ESP32/ESP8266 avrà dimenticato di aver mai parlato MicroPython. Al contrario, ogni chip Espressif che contiene un programma compilato dall'IDE Arduino o il firmware AT o LUA o ... può essere facilmente dotato del firmware MicroPython. La procedura è sempre la stessa, come qui descritto.
Struttura dell'apparecchiatura di misurazione
Per il fissaggio della barra di pesatura da 12 mm x 12 mm x 75 mm occorrono altri due profili in alluminio delle stesse dimensioni, oltre a due lamiere di alluminio da 21 mm x 12 mm x 2,5 mm come distanziatori. Sono necessarie due guide a U in alluminio per alloggiare le schede su cui sono inseriti il controller e l'HX711. Ecco lo schizzo dei componenti, disponibile anche come Documento PDF scaricato . Esso contiene il layout delle schede e il loro schema di assemblaggio.
Ho acquistato i profili in alluminio in un negozio di bricolage. Nel profilo superiore devono essere tagliati dei filetti M3 per il fissaggio delle guide a U. Anche il fissaggio delle schede nelle guide a U avviene tramite filetti M3 e distanziatori in plexiglas (12 mm x 10 mm x 2 mm). I filetti da 3 mm sui lati esterni delle guide a U servono per il fissaggio di una copertura opzionale.

Figura 7: Struttura meccanica del dinamometro

Figura 8: Unità sensore dall'alto

Figura 9: Dinamometro in uso
La figura 8 mostra il montaggio dei componenti elettronici. Due schede, dotate di connettori femmina per l'alloggiamento del microcontrollore e dell'HX711, fungono da supporto. Ecco il layout e lo schema di montaggio. Tre collegamenti via cavo sono indicati in verde.

Figura 10: Layout delle due schede
Per un primo approccio ho realizzato un setup di prova con un NodeMCU Lua Lolin Modulo V3 ESP8266che avevo a portata di mano. Ho collegato il bilanciere al circuito con i miei cavi di prova.

Figura 11: Configurazione di prova con una scheda ESP8266 Node MCU
Questi cavi di prova possono essere facilmente ricavati da un cavo in silicone e uno morsetto di prova in qualsiasi lunghezza. Una presa a un polo consente il collegamento alla breadboard. Un pezzo di guaina termorestringente contrario.
Figura 12: Pratico morsetto di prova con cavo in silicone
Un ampio set di caratteri per il display OLED
I numeri grandi facilitano notevolmente la lettura della misurazione. Invece dei consueti otto pixel, utilizziamo 30 pixel come altezza dei caratteri. Il file geometer_30.py contiene le informazioni relative.
Per creare un proprio set di caratteri per il display OLED, abbiamo bisogno di alcuni ingredienti.
1. Python per Windows
2. freetype-py
Se Python non è ancora installato sul tuo PC, devi farlo ora. Scarica il pacchetto aggiornato Python 3.13.3 e installarlo eseguendo il file python-3.13.3-amd64.exe Avviare il programma nella cartella dei download e seguire le istruzioni della procedura guidata.
freetype-py è uno strumento necessario per la conversione di un set di caratteri TTF di Windows. Con Python è stato creato anche uno strumento chiamato pip3 installato. Lo utilizziamo per freetype-py da installare.
Aprire il prompt dei comandi e digitare la seguente riga.
pip3 install freetype-py
Ecco come creare un proprio set di caratteri dall'archivio TTF di Windows.
Scarica l'archivio zeichensatz.rar e decomprimere il contenuto in una directory a scelta. Per risparmiare tempo nella digitazione, consiglio di utilizzare una directory con un nome breve nel percorso root del disco rigido o di una chiavetta USB. Nel mio caso è F:\font.
Da Explorer, apri una finestra Powershell in questa directory tenendo premuto tasto Maiusc uno clic destro sul menu. Quindi clicca con il tasto sinistro del mouse su Apri finestra PowerShell qui.

Figura 13: Aprire la finestra Powershell
Digitare la seguente riga al prompt e premere Invio.
.\makecharset.bat geometer 30 """0123456789,-+N""" "F:\fonts\quellen\"

Figura 14: Il set di caratteri è pronto
Nella directory è ora presente un file geometer_30.py con i dati pixel del nuovo estratto del set di caratteri. Sono stati convertiti solo i caratteri in """0123456789,-+N""", risparmiando così spazio di memoria. È possibile scaricare ulteriori set di caratteri dal font-Directory di Windows nella directory fonti copiare e convertire come indicato sopra. Si prega di notare che il nome del file deve essere specificato senza l'estensione .TTF.
Ora copiamo il set di caratteri generato nella directory di lavoro del nostro nuovo progetto MicroPython.
Primi test
Il LED di segnalazione
A questo punto possiamo iniziare a eseguire alcuni primi test. Come presupposto possiamo utilizzare il circuito di prova della figura 11, al quale viene collegata la bilancia a bracci come illustrato nello schema elettrico della figura 6.
Come LED di segnalazione ho utilizzato un LED Neopixel proveniente da una striscia LED avanzata dalla costruzione dell'orologio Abacus. Il vantaggio è che con un LED è possibile rappresentare qualsiasi colore tramite un unico cavo di comando.
Figura 15: LED Neopixel
Perché il NodeMCU Lua Lolin Modulo V3 ESP8266 Poiché il pin Vin non trasmette i 5 V dall'USB, ho collegato i +5 V del cavo all'uscita da 3,3 V della scheda del controller, il che funziona senza problemi con un LED. Il ESP8266 D1 Miniche installiamo nel sensore di forza fornisce effettivamente i 5 V dall'USB al pin da 5 V. Din continuiamo D4 = GPIO2 acceso.
Di seguito vengono riportati i dati inseriti in REPL grasso formattato, spese corsivo.
>>> da neopixel importare NeoPixel
L'oggetto Neopixel è costituito da un LED su GPIO2.
>>> led=Pin(2, Pin.OUT, value=0) # D4
>>> np=NeoPixel(led,1)
Definiamo alcuni colori...
>>> rosso=(4,0,0)
>>> blu=(0,0,4)
>>> giallo=(16,8,0)
>>> off=(0,0,0)
E ne verificano l'efficacia.
>>> np[0]=rosso
>>> np.write()
>>> np[0]=off
>>> np.write()
La scelta dei colori e la scrittura dei LED sono riassunte nella funzione segnale() insieme.
>>> def segnale(col):
np[0]=col
np.write()
>>> segnale (giallo)
>>> segnale (spento)
Misurazione delle forze
Per l'utilizzo del HX711 Esiste una classe nel modulo hx711.py vive. Se si parte hx711.py in una finestra dell'editor Thonny, il blocco if alla fine dell'elenco crea un oggetto HX711 con l'identificatore hx.
if __name__ == "__main__":
da macchina importare Pin
hx=HX711(Pin(14),Pin(12,Pin.IN)) # D5, D6
Questo ci permette di fare i primi passi con il sensore di forza. Recuperiamo un valore di misurazione, così come determinato dall'HX711, tramite la linea seriale. In base al suo cablaggio, otteniamo 10 valori al secondo (velocità di connessione = GND).
>>> %Run -c $EDITOR_CONTENT
HX711 pronto sul canale A con guadagno 128
>>> hx.getRaw()
-502747
Questo valore si ottiene per la bilancia senza carico. Nel nostro caso, il punto di riferimento non è il supporto inferiore della bilancia, ma il gancio nella parte superiore. Quando l'unità di misura è sospesa, tra le parti del sensore soggette a carico rientrano anche i profili montati sotto la bilancia a braccio. Questo valore deve essere considerato come tara per le misurazioni successive. Il valore della tara viene determinato come media di più misurazioni. Il numero di misurazioni viene specificato al momento della richiesta, in questo caso 2.
>>> hx.tara(2)
-502631

Figura 16: Registrare Tara
Successivamente è necessario calibrare il sensore. Ciò significa che il valore di misura grezzo per una determinata forza, corretto in base al valore di tara, deve essere convertito in una forza espressa in Newton. Fissiamo quindi saldamente la barra di pesatura o appendiamo la nostra unità di misura, avviamo hx711.py e richiamiamo hx.tara(2) . Il valore tara viene quindi memorizzato nell'attributo hx.tare memorizzati e restituiti.
Ora dobbiamo determinare il fattore di calibrazione per la conversione in Newton. Questo viene fatto dal metodo hx.calibrateF(), al quale trasferiamo la massa di 102 g. Nel campo gravitazionale terrestre, su questa massa agisce, a seconda del luogo di misurazione, una forza di peso di circa 1 Newton.

Figura 17: Calibrare a 1 N con una massa di 102 g.
Anche questo valore viene utilizzato come attributo hx.fcal dell'oggetto HX711. Da questo momento in poi possiamo misurare direttamente le forze utilizzando il metodo hx.kraft(n). Il parametro n indica nuovamente il numero di misurazioni da eseguire, dalle quali viene calcolato il valore medio. Ogni singola misurazione dura circa 100 ms.
>>> hx.calibrateF(102)
44098.7
>>> hx.potenza(2)
1.00366
Il fattore di calibrazione può essere richiamato in qualsiasi momento e, se necessario, regolato manualmente. Per semplificare la procedura, si consiglia di inserire il fattore di calibrazione trovato nella classe HX711 nell'attributo di classe KFattoreForza . In alternativa, potremmo anche scrivere il valore in un file che leggiamo ogni volta all'avvio.
>>> hx.fcalFaktor(44098.1)
>>> hx.potenza(2)
1.00045
>>> hx.potenza(2)
1.00288
Ci rendiamo conto che un risultato utilizzabile può essere indicato solo con due cifre decimali, perché la terza cifra decimale è già chiaramente instabile. Ma questo è sufficiente, perché nessun dinamometro convenzionale con molla a spirale può risolvere a 0,01 N. In futuro, quindi, per la visualizzazione trimmeremo i nostri risultati di misurazione su sei posizioni con due cifre decimali e li visualizzeremo allineati a destra (>) con una "N" come denominazione.
>>> "{:>6.2f} N".format(hx.kraft(2))
' 1,00 N'
Caratteri più grandi nel display OLED
Il modulo geometer_30.py ha la seguente struttura. Dopo un'intestazione, in cui sono elencati i caratteri contenuti, l'altezza e la larghezza massima dei caratteri, nella lista seguono numero Tupel, il cui primo componente indica l'attuale larghezza del carattere. Segue poi il modello di pixel del carattere sotto forma di byte-Oggetti in rappresentazione binaria. Tramite la posizione del carattere nella stringa chars abbiamo accesso alla voce in numero. È possibile generare caratteri personalizzati creando manualmente il modello di bit e inserendo un carattere puntatore in chars registrare.
Il modulo deve essere caricato nella memoria flash del controller affinché possa essere attivato.
>>> import geometer_30 come cs
Importato in questo modo, possiamo utilizzare il modulo con il prefisso geometer_30 molto breve con il prefisso cs affrontare.
chars="0123456789,-"
altezza=31
width=29
numero=[
(17, # Segno: 0
0b00000000000000000,
0b00000000000000000,
0b00000000000000000,
0b00000011111000000,
0b00001111111110000,
0b00011111111111000,
0b00011111111111000,
0b00111110001111100,
0b00111110001111100,
0b01111100000111110,
0b01111100000111110,
0b01111100000111110,
0b01111100000111110,
0b01111100000111110,
0b01111100000111110,
0b01111100000111110,
0b01111100000111110,
0b01111100000111110,
0b00111110001111100,
0b00111110001111100,
0b00011111111111000,
0b00011111111111000,
0b00001111111110000,
0b00000011111000000,
0b00000000000000000,
0b00000000000000000,
0b00000000000000000,
0b00000000000000000,
0b00000000000000000,
0b00000000000000000,
0b00000000000000000,
),
Per la rappresentazione, dobbiamo semplicemente inserire un pixel nel display a partire dalla posizione iniziale (= angolo superiore sinistro della matrice di caratteri) in tutti i punti in cui nel modello è presente un 1. Questo è ciò che fa la funzione putNumber(). Il numero del modello nell'elenco è riportato nella riga seguente. z è il segno da rappresentare, il metodo indice() determina la posizione in chars.
>>> n=cs.chars.index(z)
def putNumber(n,xpos,ypos,show=True):
larghezza=cs.number[n][0]
for row in range(1,cs.height):
for col in range(larghezza-1,-1,-1):
c=cs.number[n][row] & 1<
d.setPixel(xpos+larghezza+3-col,ypos+row,c,False)
if show:
d.show()
restituisci xpos+larghezza+2
Recuperiamo la larghezza del carattere e scansioniamo il modello riga per riga e colonna per colonna. Leggiamo il codice colore c, 0 o 1, e impostiamo nascosto (False) il pixel sul colore di sfondo o di primo piano, 0 o 1. Sono previsti due pixel come distanza tra i caratteri. La funzione restituisce la posizione x per il carattere successivo, in modo che i caratteri possano essere visualizzati in modalità proporzionale.
Per i prossimi test, i file devono essere oled.py e ssh1306.py caricati nella memoria flash del controller.
>>> import geometer_30 come cs
>>> da machine import Pin,freq,SoftI2C
>>> da oled importare OLED
>>> import geometer_30 come cs
>>> def putNumber(n,xpos,ypos,show=True):
larghezza=cs.number[n][0]
for row in range(1,cs.height):
for col in range(larghezza-1,-1,-1):
c=cs.number[n][row] & 1<
d.setPixel(xpos+larghezza+3-col,ypos+row,c,False)
if show:
d.show()
restituisci xpos+larghezza+2
>>> n=cs.chars.index("5")
>>> n
5
>>> n=cs.chars.index("N")
>>> n
13
>>> d.clearAll(False)
>>> pos=putNumber(5,0,0, False)
>>> pos=putNumber(13,pos,0, True)
Ora abbiamo tutti i requisiti necessari per programmare il nostro misuratore di forza. La realizzazione avverrà nel prossimo articolo.
Restate sintonizzati! A presto!






