Se mai avete avuto necessità di scambiare dei dati in seriale fra la nostra board Arduino e il noto linguaggio di programmazione, Python. Ecco un esempio che chiarirà molti dubbi.

Inviare e ricevere numeri interi in Seriale

L’invio di interi è forse una delle operazioni basilari più utili e meno trattate in rete. Io stesso ho dovuto perderci un pò di tempo per venire a capo ad alcuni problemi che insorgevano irremediabilmente quando si desidera inviare dei valori interi composti da cifre decimali. Da e verso Arduino.

Per questo esempio ho usato le libreria pyserial di Python 3.4 e la funzione Serial.parseInt() di Arduino.

Nativamente l’installazione di Python non include la libreria pyserial, motivo per cui, bisogna installarla. Per farlo, è sufficiente recarsi (da linea di comando) nella cartella d’installazione di Pyhon, nel mio caso: C:\Python34 e lanciare il comando python -m pip install pyserial. Questo avvierà il download e l’installazione automatica della libreria che ci serve.

Serial.parseInt() invece, è una funzione di arduino per restituire il primo numero intero valido dal buffer seriale. I caratteri che non sono interi vengono ignorati. La funzione viene terminata dal primo carattere che non è un numero.

Dunque passiamo al codice operativo per Arduino, ben commentato:

void setup() {
  // apriamo la porta seriale:
Serial.begin(9600);
 
}
 
void loop() {
  // controlliamo eventuali dati in arrivo sulla seriale:
  if (Serial.available() > 0) {
    // leggiamo l'intero in arrivo:
    int inDigit = Serial.parseInt();
    // Spediamo indietro il valore ricevuto:
    Serial.write(inDigit);
  }  
}

E qui invece il codice per Python 3.4, anch’esso commentato:

import serial #Per installare la libreria in python 3.4:  C:\Python34>python -m pip install pyserial
import sys
import time
 
port = "COM5" # porta seriale, se non specificata viene selezionata la prima disponibile
 
def scan():
    """scan for available ports. return a list of tuples (num, name)"""
    available = []
    for i in range(256):
        try:
            s = serial.Serial(i)
            available.append( (i, s.portstr))
            s.close()   # explicit close 'cause of delayed GC in java
        except serial.SerialException:
            pass
    return available
 
def connessione_seriale(port):
    """ funzione per connessione alla porta seriale """
    try:
        return serial.Serial(port, 9600)
    except serial.SerialException:
        print("verificatosi ERRORE...")
 
 
porte = scan()
 
if len(porte) or len(port): # porte seriali libere
       porta = porte[0][1] # ci connettiamo alla prima porta disponibile
       if len(port) > 1:
           porta = port # se gia' conoscete la porta e' sempre meglio inserirla manualmente
       print("Porta Seriale usata: " + porta)
 
       ser = connessione_seriale(porta)
 
       def invia_num(valore):
           if valore.isdigit() and int(valore) in range(0, 101):
 
               # gli sleep qua sotto sono necessari per evitare che arduino vada in reset, passa troppo poco tempo fra la connessione e l'invio del comando in seriale altrimenti
               time.sleep(1) #  attesa
               ser.setDTR(level=0)
               time.sleep(1) #tempo di attesa di un secondo dovrebbe essere sufficiente
 
               #cmd = sys.argv[1] # cmd ricevuto da linea di comando
 
               ser.write(bytes(valore, 'UTF-8')) #inviamo il valore in seriale
               time.sleep(1)
               #ser.write(comando.encode("latin1"))
 
               print("Valore inviato!")
 
               time.sleep(0.5)
               #ser.close()
           else:
               print("Prego inserire un valore intero compreso fra 0 e 100.")
 
else:
       print("Nessun dispositivo seriale connesso oppure porta seriale occupata!")
 
'''
print("Found ports:")
for n,s in scan():
   print("(%d) %s" % (n,s))
'''
 
 
if __name__ == "__main__":
  inp = ""
  while inp != "stop":
    if inp == "stop":
        break
    else:
        inp = input()
        print("Invio valore: "+inp)
 
        invia_num(inp)
        out = b""
        while ser.inWaiting() > 0:
            out += ser.read(1)
 
        if out != '':
            print("risposta: " + str(ord(out.decode('utf-8')))) # la funzione ord() traduce un carattere con il corrispondente numero nella tabella ascii
              #print(type(out.decode('utf-8')))

I valori accettati dallo script in python, sono interi compresi fra 0 e 100.
Una precisazione va fatta per quanto riguarda la porta seriale a cui è connesso il nostro arduino. Nel codice è presente una funzione che automaticamente ci connette alla prima porta seriale disponibile, che può non essere quella giusta. Questo perchè per poter effettivamente rilevare a quale porta è connesso arduino, bisognerebbe implementare un protocollo di handshake. Quest’ultimo non è lo scopo di questa guida, quindi tralasciamo e limitatevi a inserire la porta corretta manualmente nel codice Python.

Per qualsiasi dubbio o eventuali miglioramenti, commentate.