Enviando información desde python a avr-c

0

está bien, entonces mi situación es que estoy trabajando en un chip avr que es el atmega 328p y lo que quiero hacer es que quiero decir una entrada de usuario en python, digamos los tipos de usuario en una cadena y desde ahí Quiero que mi código avr para interpretar el código.

La razón por la que estoy haciendo esto es porque estoy creando una gui cnc básica para que el usuario ingrese un eje de un motor paso a paso como x y o z, luego la dirección "-" o "+".

Luego, una distancia que es un número en python y luego desde python quiero enviar esta información al código avr-c, que luego utilizará la información para controlar a los steppers.

Quiero evitar el uso de la comunicación serie predeterminada en avr c porque será más difícil de hacer ya que el usuario ingresará cadenas como "x-20 y + 10" y etc.

Es mucho más fácil usar python para interpretar el texto que para usar avr-c. Entonces, ¿cómo voy a hacer esto? //////// DESPUÉS DE ALGUNA VEZ //////////////////////////// Bueno, después de mucha confusión e investigación, se me ocurrió un código basado en la sintaxis de pyserial y en los módulos de estructura, aquí está el código:

            import serial
            import struct 
            import binascii 

            #Function to Initialize the Serial Port
            def init_serial():

                global ser       #Must be declared in Each Function
                ser = serial.Serial()
                ser.baudrate = 9600

                ser.port = '/dev/ttyACM0' #com port of avr 

                ser.timeout = 10
                ser.open()          #Opens SerialPort
                # print port open or closed
                if ser.isOpen():
                    print 'Open: ' + ser.portstr

                    init_serial() 
                    values = (1)
                    s = struct.Struct('I')  
                    packed_data = s.pack(*values)

            ser.write(packed_data)    #Writes to the SerialPort

            while 1:    

                bytes = ser.readline()  #Read from Serial Port
                packed_data = binascii.unhexlify(bytes)
                s = struct.Struct('I') 
                unpacked_data = s.unpack(packed_data)
                print 'You sent: ', unpacked_data      #Print What is Read from Port

            #Ctrl+C to Close Python Window

Por favor, infórmeme si estoy haciendo algo incorrecto o correcto, o si este código funciona realmente, si es así, este es el lado de Python de la transmisión de datos de python a avr-c. ¿Cómo manejaría el avr? ¿El lado C de esta comunicación con python sobre comunicación serial?

    
pregunta Redrachet2

1 respuesta

5

Una opción es analizar la cadena en python y luego enviar algún tipo de formato binario al microcontrolador. Esto sería más eficiente en cuanto a ancho de banda y el código MCU será mucho más simple. El enlace al microcontrolador aún sería serial, pero no estaría limitado a enviar caracteres imprimibles. Es bastante fácil abrir un puerto serie con pyserial en modo binario y luego hacer port.write (struct.pack (....)) para enviar datos binarios a través del enlace.

En su código C, puede declarar una estructura y luego convertir un puntero a los datos recibidos en un puntero a la estructura y luego leer directamente los elementos de datos, sin necesidad de análisis.

En realidad tengo un montón de código de procesamiento de paquetes que escribí hace unos años para un proyecto AVR aquí: enlace . No está diseñado para ser utilizado con el entorno Arduino, pero debería poder ejecutarse en el 328. Hay un montón de otras cosas que son específicas de este proyecto en particular, pero eche un vistazo a send_raw_packet, try_read_packet y try_parse_packet para tener una idea de cómo puede transferir datos binarios estructurados a través del puerto serie.

Actualización:

Parece que estás mirando las bibliotecas correctas para enviar datos al AVR, pero todavía hay algunas cosas que debes mirar. Primero, la idea detrás de los protocolos binarios es enviar bloques de datos binarios que están definidos por estructuras. Por ejemplo, es posible que deba enviar un objeto puntual que tenga una X y una coordenada Y. Definirías esto en C como

struct point {
    int16_t x;
    int16_t y;
};

En C, puede crear una instancia de la estructura, inicializarla con los datos necesarios, crearle un puntero, y convertirla en un puntero de caracteres, y enviarla al puerto serie:

struct point p;
p.x = 1;
p.y = 2;
uart.write((char *)&p, sizeof(point));

Luego, en Python, harías algo como

(x, y) = struct.unpack("hh", ser.read(4))

Para ir al otro lado, puedes invertir todo el proceso de la siguiente manera:

ser.write(struct.pack("hh", x, y))

Y luego en tu microcontrolador:

struct point p;
usart.read((char *)&p, sizeof(point));
x = p.x;
y = p.y;

Ahora, tendrá que hacer más trabajo que solo esto para admitir cosas como el encuadre y la identificación de objetos (algún tipo de campo de tipo de paquete), pero esto debería ser suficiente para comenzar.

Lo dije antes y lo repetiré: mira la implementación de try_read_packet aquí: enlace . Esto gestiona la extracción atómica de paquetes de la cola de recepción de UART de forma no bloqueada: no hará nada y devolverá 0 si el paquete completo no está en el búfer, de lo contrario leerá el paquete y lo analizará. Los paquetes se construyen a partir de un identificador fijo byte 0x5A seguido de una longitud de 2 bytes seguida de los datos de carga útil. Especie de. Los paquetes utilizados en ese proyecto en realidad tienen un montón de otros campos estándar, pero los primeros 3 bytes se manejan de manera diferente en el paquete try_read, ya que tiene que leerlos para saber qué tan grande es el paquete, y el resto se trata como datos de carga útil. La implementación de try_read_packet es bastante simple. Deja caer los caracteres hasta que ve 0x5A. Luego usa peek para obtener la longitud sin quitar los bytes. Si el paquete completo está disponible, lo lee en un búfer y lo pasa a try_parse_packet, que convierte el puntero del búfer en un puntero de estructura y lee los campos del encabezado. La idea es que puede llamar a esta rutina en un bucle y procesar paquetes a medida que llegan. El lado de transmisión es muy simple, solo establezca todos los campos correctos en la estructura, obtenga un puntero de caracteres, y páselo al módulo UART para la transmisión.

    
respondido por el alex.forencich

Lea otras preguntas en las etiquetas