Comunicación serial python-arduino

Estoy haciendo una práctica para mi clase de microprocesadores, me piden que desde python, usando tkinter, con un slider controle un motor, el sentido del motor y el encendido y apagado de 8 leds con botones de tkinter. Estos datos los mando a Arduino, mi problema es que en la ventana generada en tkinter tengo que presionar varias veces un botón para que el led de prefs o apague y hay veces en donde deslizando el slider y mandando el giro se queda quieto el motor hasta que vuelvo a mover un poco el slider y volver a indicar el giro, apreciaría mucho si me ayudan, les adjunto ambos programas:
Programa de python:

#llamado a comunicacion serial y puerto
from tkinter import *
import serial
import time

arduino= serial.Serial("COM6",115200,timeout=1)

#funciones de encendido
def ON1 ():
    arduino.write(b'J')
    
def ON2 ():
    arduino.write(b'K')
    
def ON3 ():
    arduino.write(b'L')
    
def ON4 ():
    arduino.write(b'M')

def ON5 ():
    arduino.write(b'N')
    
def ON6 ():
    arduino.write(b'O')
    
def ON7 ():
    arduino.write(b'P')
    
def ON8 ():
    arduino.write(b'Q')
    
#funciones de apagado
def off1():
    arduino.write(b'A')
    
def off2():
    arduino.write(b'B')
    
def off3():
    arduino.write(b'C')

def off4():
    arduino.write(b'Z')

def off5():
    arduino.write(b'E')

def off6():
    arduino.write(b'F')
    
def off7():
    arduino.write(b'G')
    
def off8():
    arduino.write(b'H')
    
#control del motor

def controlMotor(valor):
    
     time.sleep(0.01)
     valor=str(Barra.get())
     arduino.write((valor +'\n').encode())
     print(valor)
    
def izquierda():
    arduino.write(b'I')
    
def derecha():
    arduino.write(b'D')
    
def kill():
   arduino.close()
   raiz.destroy()
    
#control de LEDS
raiz=Tk()
raiz.geometry("600x700")#ventana principal
raiz.title("Control de leds")
titulo1=Label(raiz,fg="blue", font=("Arial",30),text="Encendido y apagado")
titulo1.place(x=100,y=50)
Cancel=Button(raiz,text="cerrar comunicacion",command=kill)
Cancel.place(x=300,y=150)

#led1
Boton1=Button(raiz,text="Encender led 1",command=ON1)
Boton1.place(x=50,y=150)
BotonA=Button(raiz,text="Apagar led 1",command=off1)
BotonA.place(x=50,y=175)

#led2
Boton2=Button(raiz,text="Encender led 2",command=ON2)
Boton2.place(x=150,y=150)
BotonB=Button(raiz,text="Apagar led 2",command=off2)
BotonB.place(x=150,y=175)
#led3

Boton3=Button(raiz,text="Encender led 3",command=ON3)
Boton3.place(x=50,y=220)
BotonC=Button(raiz,text="Apagar led 3",command=off3)
BotonC.place(x=50,y=245)
#led4

Boton4=Button(raiz,text="Encender led 4",command=ON4)
Boton4.place(x=150,y=220)
BotonD=Button(raiz,text="Apagar led 4",command=off4)
BotonD.place(x=150,y=245)
#led5

Boton5=Button(raiz,text="Encender led 5",command=ON5)
Boton5.place(x=50,y=300)
BotonE=Button(raiz,text="Apagar led 5",command=off5)
BotonE.place(x=50,y=325)
#led6

Boton6=Button(raiz,text="Encender led 6",command=ON6)
Boton6.place(x=150,y=300)
BotonF=Button(raiz,text="Apagar led 6",command=off6)
BotonF.place(x=150,y=325)
#led7

Boton7=Button(raiz,text="Encender led 7",command=ON7)
Boton7.place(x=50,y=390)
BotonG=Button(raiz,text="Apagar led 7",command=off7)
BotonG.place(x=50,y=415)
#led8

Boton8=Button(raiz,text="Encender led 8",command=ON8)
Boton8.place(x=150,y=390)
BotonH=Button(raiz,text="Apagar led 8",command=off8)
BotonH.place(x=150,y=415)

#Control de motor 
titulo2=Label(raiz,fg="Blue", font=("Arial",30),text="Control del motor")
titulo2.place(x=100,y=500)
Barra=Scale(raiz,from_=0,to=255,orient=HORIZONTAL,length=200, command=controlMotor)
Barra.place(x=50,y=550)
BotonGD=Button(raiz,text="Giro derecha",command=derecha)
BotonGD.place(x=50,y=590)
BotonGI=Button(raiz,text="Giro izquierda",command=izquierda)
BotonGI.place(x=50,y=620)
raiz.mainloop()

Programa de Arduino:

#define led1 9
 #define led2 8
 #define led3 7
 #define led4 6
 #define led5 5
 #define led6 4
 #define led7 3
 #define led8 2
 #define m1 10
 #define m2 11
String mensaje="";
bool terminado=false;
char caracter;
char caracter2;
int vel;
void leer_puerto()
{
if(Serial.available()>0){    //lee el valor de la barra de python
   caracter=Serial.read();
    mensaje+=caracter;//concatena las letras para formar una palabra
    if(caracter=='\n'){ // determina el cambio de linea 
      terminado=true;//Termina el mensaje 
   }
}
}

void setup() 
{
Serial.begin(115200);
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(led4,OUTPUT);
pinMode(led5,OUTPUT);
pinMode(led6,OUTPUT);
pinMode(led7,OUTPUT);
pinMode(led8,OUTPUT);
pinMode(m1,OUTPUT);
pinMode(m2,OUTPUT);
}

void loop()
{
   leer_puerto();//llamo a la función
   while(terminado)
   {//si se termina el mensaje, convierto mis valores de str de py en INT
    vel=mensaje.toInt();//conversión de valores str a INT
    mensaje="";//limpia el mensaje
    terminado=false; //evita volver a leer el mismo dato anterior y se prepara para uno nuevo
  }

if(Serial.available()>0 && terminado==false)
{
//Control de leds
    caracter2=Serial.read();
   
    if (caracter2=='J'){//Led_1
      digitalWrite(led1,HIGH);
      
    }
    else if(caracter2=='A'){
      digitalWrite(led1,LOW);
      
    }
    else if(caracter2=='K'){//led_2
      digitalWrite(led2,HIGH);
     
    }
    else if(caracter2=='B'){
      digitalWrite(led2,LOW);
      
    }
    else if(caracter2=='L'){//led_3
      digitalWrite(led3,HIGH);
     
    }
    else if(caracter2=='C'){
      digitalWrite(led3,LOW);
      
    }
    else if(caracter2=='M'){//led4
      digitalWrite(led4,HIGH);
      
    }
    else if(caracter2=='Z'){
      digitalWrite(led4,LOW);
    }
    else if(caracter2=='N'){//led5
      digitalWrite(led5,HIGH);
     
    }
    else if(caracter2=='E'){
      digitalWrite(led5,LOW);
      
    } 
    else if(caracter2=='O'){//led6
      digitalWrite(led6,HIGH);
     
    }
    else if(caracter2=='F'){
      digitalWrite(led6,LOW);
      
    }
    else if(caracter2=='P'){//led7
      digitalWrite(led7,HIGH);
      
    }
    else if(caracter2=='G'){
      digitalWrite(led7,LOW);
      
    }
    else if(caracter2=='Q'){//led8
      digitalWrite(led8,HIGH);
      
    }
    else if(caracter2=='H'){
      digitalWrite(led8,LOW);
    }
    else if(caracter2=='I'){
      analogWrite(m2,vel);
      digitalWrite(m1,LOW);
    }
    else if(caracter2=='D'){
      analogWrite(m1,vel);
      digitalWrite(m2,LOW);
    }
  }
}

Desde mi punto de vista el código de arduino no es correcto para tratar los datos que envía python.

Veamos, por un lado envía caracteres según el estado de los botones y por otro una cadena si es el valor de un slider.
¿Cómo discrimina el código de arduino cuál tipo de datos recibe?

Tu código primero lee el puerto esperando una cadena con final de línea mediante la función leer_puerto() pero sin saber si lo que está recibiendo es solo un caracter o varios.


Al margen

while (terminado) {

debería ser

if (terminado) {

Porque no es necesario un lazo para un bloque de sentencias que solo se ejecutará una vez.


Volviendo a tu secuencia de lecturas, leer_puerto() lee y quita un byte del buffer serie así que si ese byte es un caracter correspondiente a un botón ya no va a ser leído por el bloque que controla los LED.

Te convendría enviar un caracter previo al valor (por ej. 'V') así solo cuando recibe ese caracter lee los caracteres siguientes como una cadena (podrías usar readStringUntil())

También sería conveniente que utilices switch() en lugar de tantos else if(), el código quedaría más "prolijo".

Moderador:
Una pregunta de software no transforma un hilo en Proyecto.
Lo será para ti pero no para este foro
Lee en la sección Proyectos los 2 primeros hilos y encontrarás que requicitios debe reunir un hilo para estar ahí.
Movido a software

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.