Controleras y controleros, en esta entrada aprenderemos como configurar el SIMULINK [Matlab] para que pueda recibir datos o transmitir datos usando una comunicación serial con nuestra placa de desarrollo del Arduino, sin embargo, el procedimiento puede ser aplicado con otro microcontrolador (PIC, ESP, Raspberry Pi Pico, etc), con un PLC, un sensor o cualquier otro instrumento que posea comunicación serial.
Antes de comenzar, te hago la invitación para que veas nuestro CURSO GRATUITO DE ARDUINO.
Y que te suscríbas al canal si te gusta la programación, los microcontroladores, el modelado de sistemas y la teoría del control.
Instrument Control Toolbox Simulink
Para poder realizar la comunicación serial entre Arduino (o cualquier otro instrumento) y Simulink, será necesario tener instalado el instrument control toolbox.
Con Instrument Control Toolbox, es posible generar bien sea en MATLAB o SIMULINK para transmitirlos a un instrumento.
De la misma forma, tambien se pueden leer datos en MATLAB o SIMULINK para su análisis y visualización.
Si no tienes instalado el toolbox, dentro de MATLAB puedes ir a la pestaña HOME y dar Click en Add Ons/Get Add-Ons y buscar por: instrument control toolbox.
Una vez instalada la biblioteca, procedemos a abrir el SIMULINK, y verificamos que efectivamente el BLOCKSET del ToolBox se encuentre instalado y que tenga todos los bloques de comunicación como Comunicación Serial, TCP/IP, UDP, I2C, SPI, y Bluetooth.
Comunicación Serial Arduino Simulink/Matlab
Una vez instalado el toolbox procedemos a efectuar la Comunicación Serial entre Arduino y Simulink/Matlab.
Inicialmente es muy importante que CONECTES tu ARDUINO o INSTRUMENTO al Computador ANTES de Abrir el MATLAB, para que el software consiga detectar adecuadamente el dispositivo.
Antes de comenzar a transmitir o recibir datos, es importante entender que Matlab por defecto trabaja con Números punto flotante precisión doble que ocupan 8 bytes. Sin embargo, el punto flotante de doble precisión de arduino ocupa 4 bytes, lo que es equivalente a un single en Matlab. Por lo tanto deberemos hacer alguna conversión de datos dentro del Simulink con el bloque Data Type Conversion.
Ahora, si deseas aprender SIMULINK DESDE CERO, te invito a que te matricules a mi Curso el cual se encuentra disponible en UDEMY. Basta con darle click al siguiente botón y te volveras un experto manipulando este software:
Con el objetivo de lograr la Comunicación Serial entre Arduino y Simulink vamos a construir el siguiente diagrama (todos los archivos están disponibles para descarga al final del post):
Transmisión de Datos Serial
Los tres primeros bloques de la transmisión de datos son:
- Pulse Generator: Genera un tren de pulsos de periodo 4 segundos con un ancho del 50%
- Zero-Order Hold: Discretiza la señal con un periodo de muestreo de 0.05s
- Data Type Conversion: convierte el double de Matlab (8 bytes) para un single (4 bytes) para que pueda ser interpretado por arduino.
- Serial Send: Configuramos el puerto de comunicación serial [COM] en el cual está conectado nuestro Arduino o instrumento.
Recepción de Datos Serial
En esta etapa también tenemos un Data Type Conversion para transformar el double proveniente de Arduino (4 bytes) para el double de Matlab de (8 bytes)
Tenemos también el bloque Serial Receive en el cual configuraremos la recepción serial.
En este caso, configuramos el puerto de comunicación COM, colocamos el tipo de dato SINGLE, y habilitamos el Data Frame:
En el header colocamos el caracter de inicio con el que indicamos el inicio de la trama de datos. En mi caso, yo coloqué un ‘V’ como caractér de inicio el cual voy a programar en el Arduino. Ustedes pueden colocar cualquier otro caractér o palabra.
En el terminator colocamos el caracter de finalización de la trama de datos. En mi caso coloque el ‘\n’.
Finalmente también colocamos el periodo de muestreo de 0.05s.
Configuración Serial
Con el bloque Serial Configuration, realizamos la configuración serial del dispositivo, por ejemplo la velocidad en Baudios, los bits de paridad, los bits de datos, el bit de parada, el puerto de comunicación, etc.
Programa de Comunicación Serial Arduino Simulink/Matlab
Procedemos a configurar el programa en Arduino (en mi caso estoy empleando un Leonardo, pero puedes emplear cualquier otra placa), el cual va a transmitir y recibir datos por el puerto serial con Simulink.
Para este caso implementaremos el siguiente circuito:
Lista de Materiales
- Placa de Desarrollo de Arduino
- Motor DC con Encoder de 5v o 12v
- Driver de Potencia Puente H (L298)
- Potenciometro 5k (o cualquiera)
- Cables
- Fuente de Alimentción de 5v o 12v dependiendo del motor empleado.
Nota (Comunicación Serial en Arduino)
En el video de YouTube, pueden notar que en el void setup() NO configuré el Serial.begin().
No es estrictamente necesario usar Serial.begin()
en el void setup()
para la comunicación USB CDC en Arduino. La razón es que, en algunas placas de Arduino, como el Leonardo, Micro y Due, la comunicación USB CDC se maneja a través de un chip separado, y no es necesario inicializarla explícitamente con Serial.begin()
.
Sin embargo, en placas como Arduino Uno, Nano y Mega, que utilizan el ATmega328P o ATmega2560 y no tienen un chip separado para la comunicación USB, es necesario usar Serial.begin()
para configurar el UART (Universal Asynchronous Receiver-Transmitter) e iniciar la comunicación serial.
Aunque no sea necesario en algunos casos, es una buena práctica incluir Serial.begin()
en tu código, ya que hace que tu programa sea más compatible con diferentes placas Arduino y permite ajustar la velocidad de transmisión de datos (baud rate) si es necesario.
Funcionamiento
La idea del código es activar y desactivar un Motor DC con Enconder en el Arduino con el cual podremos leer la velocidad del motor en Radianes/s.
La activación y desactivación del motor vendrá dada por el simulink empleando la comunicación serial, para eso fue colocado el generador de pulsos cuadrados.
El Arduino enviará los datos de velocidad hacia el simulink, los cuales son graficados usando un Scope.
Suscríbete a este sitio WEB para estar enterado de las nuevas entradas!
Código
Todos los códigos del Arduino y el Simulink los puedes descargar en el siguiente botón:
A continuación muestro cual sería el código empleado en el Arduino:
//***************************************************// //***************************************************// //***** Recepción y transmición de datos *****// //***** de velocidad de un encoder de un *****// //***** motor DC hacia Simulink para *****// //***** Validación de modelo matematico *****// //***** *****// //***** by: Sergio Andres Castaño Giraldo *****// //***** https://controlautomaticoeducacion.com/ *****// //***** *****// //***************************************************// //***************************************************// // this library includes the ATOMIC_BLOCK macro. #include <util/atomic.h> #define ENCODER_A 2 // Amarillo #define ENCODER_B 3 // Verde // Pines de Control Shield const int E1Pin = 10; const int M1Pin = 12; //Estructura del Motor typedef struct{ byte enPin; byte directionPin; }Motor; //Estructura Union typedef union{ float number; uint8_t bytes[4]; }valor; //Variable Union valor velocidad; //Creo el motor const Motor motor = {E1Pin, M1Pin}; //Constantes de dirección del Motor const int Forward = LOW; const int Backward = HIGH; //Variable global de pulsos compartida con la interrupción volatile int pulsos = 0; unsigned long timeold; float resolution = 374.22; //Variable Global Velocidad int vel = 0; float value; float rpm=0; void setup(){ Serial.begin(9600); // set timer 1 divisor to 1024 for PWM frequency of 30.64 Hz TCCR1B = TCCR1B & B11111000 | B00000101; //Configura Motor pinMode(motor.enPin, OUTPUT); pinMode(motor.directionPin, OUTPUT); //Configurar Interrupción timeold = 0; attachInterrupt(digitalPinToInterrupt(ENCODER_A),leerEncoder,RISING); } void loop(){ //Pregunta si tenemos un dato a recibir if(Serial.available() > 0){ value = recepcion(); } //Transforma el valor del voltaje (0-5) a velocidad vel = map(value,0,5,0,255); //Activa el motor dirección Backward con la velocidad setMotor(motor, vel, true); //Espera un segundo para el calculo de las RPM if (millis() - timeold >= 50) { //Modifica las variables de la interrupción forma atómica ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ rpm = float((60.0 * 1000.0 / resolution ) / (millis() - timeold) * pulsos); timeold = millis(); pulsos = 0; velocidad.number = rpm * 0.10472; //rad/s Serial.write('V'); for(int i=0; i<4; i++){ Serial.write(velocidad.bytes[i]); } Serial.write('\n'); } } } //Función para dirección y velocidad del Motor void setMotor(const Motor motor, int vel, bool dir){ analogWrite(motor.enPin, vel); if(dir) digitalWrite(motor.directionPin, Forward); else digitalWrite(motor.directionPin, Backward); } //Recibir Flotante float recepcion(){ int i; valor buf; for(i=0; i<4; i++) buf.bytes[i] = Serial.read(); return buf.number; } //Función para la lectura del encoder void leerEncoder(){ pulsos++; //Incrementa una revolución }
Eso es todo por la entrada del dia de hoy, espero les haya gustado y hayan aprendido algo nuevo. Si te ha servido el contenido de esta entrada, de los videos y los códigos de implementación y deseas apoyar mi trabajo invitandome a un café super barato, puedes hacerlo en el siguiente link:
👉 Invitar a Sergio a un Café ☕️
Que esten muy bien, nos vemos en la siguiente entrada.
Mi nombre es Sergio Andres Castaño Giraldo, y en este sitio web voy a compartir una de las cosas que mas me gusta en la vida y es sobre la Ingeniería de Control y Automatización. El sitio web estará en constante crecimiento, voy a ir publicando material sobre el asunto desde temas básicos hasta temas un poco más complejos. Suscríbete al sitio web, dale me gusta a la página en Facebook y únete al canal de youtube. Espero de corazón que la información que comparto en este sitio, te pueda ser de utilidad. Y nuevamente te doy las gracias y la bienvenida a control automático educación.