Python modulo Tkinter Inviare dati seriali da PC ad Arduino

Premessa:

Questa guida nasce soprattutto per le molteplici richieste fatte dai nostri visitatori riguardo l’argomento di invio dati tra dispositivi via seriale. Molto spesso in rete troviamo solo tutorial su come inviare dati da arduino a dispositivi come PC, Smartphone e Schede embedded come la Raspberry. In questo articolo invece ci concentreremo su come si può inviare dati da un PC ad un Arduino e far si che il microcontrollore compie delle azioni come muovere stepper o servi oppure accendere led o cambiare stati degli ingressi. Abbiamo pensato per rendere il contenuto più interessante di aggiungere un interfaccia grafica come software di gestione di invio dati utilizzando tkinter, un modulo di python che permette di realizzare delle finestre con dei semplici button, menu e altri widget interessanti.

PythonTkinterPySerialDaPcAdArduino

Procedimento:

Prima di cominciare vi mostreremo cosa si può fare con python, il modulo di interfaccia grafica tkinter,il modulo pyserial e arduino che gestisce ad esempio degli stepper:

EsempioPythonTkinterInterfacciaGrafica

Quello che vedete illustrato nell’immagine non è altro che il software che andremo a realizzare in grandi linee in questa guida. Noi ci limiteremo nella realizzazione di un pulsante che invierà un certo dato seriale alla sua pressione. Questa è una intro di quello che si può fare con questa combo di software e hardware noi alla Critics Corporation nel 2010 abbiamo realizzato la nostra prima cnc comandata da PC.

Per prima cosa per chi ancora non lo avesse installato su windows , a differenza degli utenti linux che lo hanno già, andremo a scaricare python da qui preferibile la versione 2.7.9, poi successivamente una volta installato bisognerà scaricare il modulo per la seriale:

  • Pyserial che serve per installare i moduli necessari per la seriale. Scaricare la versione con scritto pyserial-2.7.win32.exe (md5).

INVIO DI UN CARATTERE ASCII DA PC AD ARDUINO

Una volta scaricato il tutto non resta che aprire un semplice documento di testo che chiameremo seriale.py. Editate il file dove andremo a inserire questo codice:

#!/usr/bin/env python

#include le librerie necessarie
from Tkinter import *
import serial
import time
ser = serial.Serial('COM4',9600) #dichiara la porta seriale
#la porta seriale va impostata controllare da arduino IDE
#quale porta ha assegnato il pc

def Premuto(): #funzione pressione pulsante
     print "Invio" #stampa a video un messaggio
     valore="120" #valore ASCII da inviare via seriale
     # il numero 120 corrisponde a una x
     ser.write(valore) #invia il valore
     time.sleep(1) #sleep per un secondo
     valoreletto=ser.read() 
     #arduino rispedisce il valore nella variabile
     print valoreletto #stampa 120 in ascii cioè x

def main():
     finestra = Tk() #crea la finestra
     finestra.title("Critics Corporation")
     #Diamo un title alla finestra creata
     riquadro1= Frame(finestra)
     riquadro1.pack()
     #crea il riquadro dove inserire il nostro pulsante
     x=Label(riquadro1, text="Invio Dato Seriale Ascii X = 120").pack(side="top", anchor=S)
     #crea la nostra etichetta
     puls1 = Button(riquadro1, command = Premuto)
     puls1["borderwidth"] = 1
     puls1["text"] = " Invia ad Arduino "
     puls1["background"] = "grey" #colore
     puls1.pack(side="left", padx=40, pady=10)#cordinate posizione
     #crea il pulsante
     finestra.mainloop()#fine del loop finestra
main()#chiamata alla funzione main

Il codice python è molto semplice ed intuibile. Spendiamo due parole su questa riga:

puls1 = Button(riquadro1, command = Premuto)

come possiamo vedere viene passato alla variabile puls1 la funzione che crea il bottone, che ha come parametri riquadro1 cioè dove deve essere collocato il pulsante e come secondo parametro l’istruzione command. Passando il parametro:

command = Premuto 

Verrà richiamata la nostra funzione:

def Premuto(): #funzione pressione pulsante
     print "Invio" #stampa a video un messaggio
     valore="120" #valore ASCII da inviare via seriale
     # il numero 120 corrisponde a una x
     ser.write(valore) #invia il valore
     time.sleep(1) #sleep per un secondo
     valoreletto=ser.read() 
     #arduino rispedisce il valore nella variabile
     print valoreletto #stampa 120 in ascii cioè x

che penserà ad inviare il valore ASCII 120 che corrisponde alla x minuscola ad Arduino con un delay di un secondo che permetterà ad arduino di rinviare il valore ricevuto e successivamente leggerlo di nuo con il python con la funzione:

valoreletto=ser.read()

CODICE ARDUINO RINVIO DATO SERIALE:

void setup(){

  Serial.begin(9600);

}
void loop(){
  
if (Serial.available() > 0) {
        int valore=Serial.parseInt();
       
        Serial.write(valore);

}
}

Il compito di Arduino in questo skatch e di aspettare che un certo dato viene inviato alla porta seriale e il controllo viene effettuato dalla istruzione Serial.available() > 0, successivamente passa il valore ricevuto alla variabile valore per poi rispedirlo con Serial.write(valore).

INVIO DI NUMERI O STRINGHE ALFANUMERICHE DA PC AD ARDUINO

Qualora volessimo ricevere su arduino numeri (es. 453) oppure caratteri (CF34D) ed avere maggiori valori da passare, bisogna fare una piccola modifica al codice arduino e python nelle istruzioni READ sostituendole con:

ARDUINO:

int valore=Serial.read();

PYTHON:

valoreletto=ser.read(3)

In pratica cambiando parseInt() di arduino con read() non passerà più la codifica di 120 in ASCII cioè la lettera X, ma bensì leggerà il valore numerico che lo passerà alla variabile valore.  Mentre in python nella istruzione ser.read(3) abbiamo aggiunto il parametro 3 che equivale al numero di cifre alfanumeriche che vogliamo stampare a schermo, cioè nell’interfaccia software realizzata con tkinter. nel nostro esempio sarà 120 il numero visualizzato, che è composto da  tre cifre, se scrivevamo al posto di valore=120:

valore="453B"

Su Python alla istruzione ser.read dovevamo aggiungere una cifra essendo composta da 4 caratteri (4-5-3-B) quindi:

valoreletto=ser.read(4)

con la funzione print valoreletto leggeremo il valore passato 453B.

In conclusione non vi resta che utilizzare i dati ricevuti da pc per muovere stepper accendere le o altro dal vostro microcontrollore Arduino. Questo progetto funziona anche con la Raspberry Pi unica cosa che deve essere cambiata la porta seriale di comunicazione che non sarà COM ma bensì dev/tty.

Buon Progetto