Arduino y Procesamiento. Cómo controlar un microcontrolador a través de un puerto COM. Comunicación bidireccional

Hola a todos! Existe una idea errónea en Internet de que para controlar una computadora utilizando dispositivos electrónicos caseros, solo se necesitan placas especiales que puedan reconocerse como dispositivos USB HID. Y con respecto a Arduino, todos solo hablan de Arduino Leanardo . Bibliotecas tan populares como Keyboard and Mouse , que le permiten crear una emulación del mouse o del teclado usando el microcontrolador, están destinadas solo a un par de placas Arduino, Leonardo, entre ellas.

Hablaré sobre cómo conectar cualquier microcontrolador Arduino (por ejemplo, tomado Arduino Uno ) y su programa de procesamiento. Habiendo agregado a todo lo demás el conocimiento de Java, en el que se basa el procesamiento, será posible agregar un proyecto bajo el control de toda la computadora, y no solo su propia aplicación. El tema de controlar un programa de computadora en Java no es algo secreto, google y encontrarás todo, te lo aseguro.

Descargar Development Environment (IDE)


Existen muchos entornos de desarrollo integrados para programar microcontroladores en puro C. De estos, se puede observar el más conveniente: Atollic, Eclipse, Keil.

Sin embargo, por la simplicidad y accesibilidad de esta guía, usaré el editor Arduino IDE y escribiré en Arduino C. Puede descargar dicho editor desde el sitio web oficial de Arduino .

El entorno de desarrollo para la programación en Procrssing también se puede descargar desde el sitio web oficial .

Vale la pena señalar, en aras de la decencia, que los datos IDE son muy similares, porque están escritos en el mismo motor. Y cuando se creó Arduino, los fundadores intentaron simplificar su editor de código lo más posible, como se hizo en el editor de Procesamiento.

Arduino Montamos el circuito y escribimos el código


En este ejemplo, usaré Arduino Uno. Se le conectará un botón, un potenciómetro y un LED. En consecuencia, puedo generar un 0 o 1. lógico. Leer un 0 o 1. lógico y realizar una conversión analógico-digital (ADC o ADC), obteniendo números del 0 al 1023 (en el Arduino Uno, un ADC de 10 bits), dependiendo de la posición del potenciómetro. No necesita mucho más como ejemplo, ya que estas son las funciones principales que puede hacer un microcontrolador.

Diagrama de cableado:



En el diagrama, el LED del ánodo está conectado a 5V a través de una resistencia limitadora (al menos 220 ohmios, preferiblemente 500 ohmios), por el cátodo al pin D11. El botón cierra el suelo y el pin D2. El potenciómetro cambia el potencial en el pin A1.

La tarea del microcontrolador es la siguiente: si el mensaje "LED - H" llega a la interfaz en serie (puerto COM serie), encienda el LED. Si llega el mensaje "LED - L", apague el LED. Cada 250 ms envía un mensaje al puerto serie (en este caso, a la pantalla de la computadora) el mensaje "Pot -" y el número recibido por lectura analógica del pin A1. Cuando se presiona un botón, envíe un mensaje "¡Se presiona el botón!" Una vez.

Aquí está mi sugerencia para resolver este problema (no es un ejemplo a seguir):

Firmware para Arduino Uno
 #define pinPot A1 #define pinLed 11 #define pinBtn 2 void setup() { pinMode(pinPot, INPUT); pinMode(pinLed, OUTPUT); pinMode(pinBtn, INPUT_PULLUP); Serial.begin(9600); Serial.println("The program starts.\n\n"); } void loop() { /* INITIAL VARIABLES. Segment 1 */ static char potMes[] = "Pot - "; static char btnMes[] = "Button is pressed!"; static char passLight[] = "Led - "; static int passLength = sizeof(passLight) - 1; static int sizepm = sizeof(potMes) - 1; static int sizebtn = sizeof(btnMes) - 1; static bool flagLedState = LOW; static bool flagBtnPress = false; static long int curTime = 0; static const int period = 200; static bool flagEnableRead = false; /* INITIAL VARIABLES. Segment 1 */ /* FUNCTIONS CALL. Segment 2 */ /* * Led is attached to HIGH voltage from one side * And to pin on the other side * By that the inverting logic */ ReadSerialForLed(passLight, passLength, &flagLedState); digitalWrite(pinLed, !flagLedState); /* * Button pin always is pulled to the HIGH voltage * And only when button is pressed - Voltage on pin goes to GROUND * So it is need to invert logic when read pins */ if(!Bounce(pinBtn) && flagBtnPress == false){ for(int i = 0; i < sizebtn; i++){ Serial.write(btnMes[i]); } Serial.print("\n"); flagBtnPress = true; if(!flagEnableRead){ curTime = millis(); flagEnableRead = true; } }else if(Bounce(pinBtn)){ flagBtnPress = false; } /* * Read and send Info "Pot - " + var Only after first press on button * Every 'period'ms */ if(millis() - curTime > period && flagEnableRead){ SendData(pinPot, potMes, sizepm); curTime = millis(); } /* FUNCTIONS CALL. Segment 2 */ } /* * Pot - pin with potentiometer * pMes - Array with message before Pot value * sp - size of potentiometer message */ void SendData(int Pot, char* pMes, int sp){ static int varP[2]; varP[0] = analogRead(Pot); varP[1] = varP[0]/256; // 0 - 3 (256 - 1024) varP[0] = varP[0]%256; // 0 - 255 //Send Message for(int i = 0; i < sp; i++){ Serial.write(char(pMes[i])); } //Send 2 bits of data //Serial.write(varP[0]); //Serial.write(varP[1]); Serial.print(analogRead(Pot)); Serial.print("\n"); } /* * Function, which is reads button pin with the bounce */ bool Bounce(int btn){ if(digitalRead(btn) == true){ delay(15); if(digitalRead(btn) == true){ return true; }else{ return false; } }else{ return false; } } /* * If Message from Serial port, which you read will be the same to passLight * So look at the next symbol after Pass Message. If it is symbol 'H' - make LED to light * If it is 'L' - make LED off. */ void ReadSerialForLed(char *passLight_f, int passLength_f, bool* flagLedState_f){ static char sym; static int cntPass = 0; static bool readyGetLed = LOW; while (Serial.available() > 0) { sym = Serial.read(); if(sym == passLight_f[cntPass] && !readyGetLed){ cntPass++; }else if (!readyGetLed){ cntPass = 0; }else if(readyGetLed){ if(sym == 'H'){ *flagLedState_f = HIGH; }else if(sym == 'L'){ *flagLedState_f = LOW; } } if(cntPass == passLength_f){ readyGetLed = HIGH; } } } 

Comentario: el LED está conectado a la fuente de alimentación por el ánodo. Esto invierte la lógica del estado del LED y ya no se beneficia. El botón no está atado con una resistencia pull-up por razones de economía, ya que Arduino Uno tiene resistencias pull-up incorporadas que se incluyen en el circuito cuando el pin se inicializa al modo INPUT_PULLUP.
¡También en el firmware, los mensajes sobre el valor tomado del potenciómetro se envían solo después de presionar un botón por primera vez!

Para llenar el firmware en la placa, no olvide seleccionar el puerto y la placa.



Si no sabe qué puerto COM tiene para la placa Arduino, en Windows, vaya a
Panel de control -> Administrador de dispositivos y haga clic en la pestaña "Puertos COM"



Si su puerto COM no está firmado como mío, siempre puede desconectar el Arduino y ver qué puerto se ha ido. Pero si nadie ha desaparecido y Arduin no es reconocido por la computadora, entonces es hora de buscar una solución en Internet. Pero comience actualizando los controladores o cambiando la placa.

Cuando todo salga bien, intente abrir el monitor de puerto e ingrese "Led-H", "Led-L", presione el botón, gire el potenciómetro y mire la pantalla para ver si todo se muestra correctamente.

Han jugado lo suficiente, cambien ligeramente el código.

Reemplace la última línea con el código del comentario.

  //Send 2 bits of data //Serial.write(varP[0]); //Serial.write(varP[1]); Serial.print(analogRead(Pot)); 

Ahora los valores del potenciómetro no se verán legibles, pero se requiere tal maniobra para el programa de procesamiento.

Procesamiento Estamos escribiendo un programa que interactúa con un microcontrolador.


La esencia de la comunicación entre el programa de procesamiento y el microcontrolador es muy simple. Hay una biblioteca en serie para este lenguaje de programación, que le permite recibir mensajes enviados como Serial.write(); , y también le permite enviar mensajes como Serial.print(); . Es importante tener en cuenta que con tal mensaje enviado, se escribirá en el búfer del puerto, lo que significa que será leído por el microcontrolador. Por lo tanto, solo tenemos que conectarnos al puerto serie deseado y recibir / enviar mensajes.

El siguiente programa conectará la biblioteca en serie y escribirá en la consola del editor una lista de todos los puertos COM a los que puede conectarse.

 import processing.serial.*; void setup() { String[] port = Serial.list(); for(int i = 0; i < port.length; i++){ print("Port number #" + i + " "); println(Serial.list()[0]); } } void draw() {} 

Cuando escriba el código en el editor y haga clic en el botón "Inicio" (flecha 1 en la imagen), aparecerá la ventana de la aplicación (2) y la lista de puertos COM se mostrará en la consola (3).



Solo tengo uno de esos puertos COM y en la hoja, como en la matriz, estará en el número 0. Por estas razones, el objeto de la clase Serial port; : Serial port; cuando se crea, se especificará el primer elemento de la lista de port = new Serial(this, Serial.list()[0], 9600);

Vierta Arduin nuestro último firmware con un cambio. Luego escribe este programa y ejecútalo. En él Cada 500 milisegundos se envía un mensaje al puerto COM para apagar o encender el LED. Y si todo se hace correctamente, luego de iniciar la aplicación, el LED debería parpadear.

 import processing.serial.*; Serial port; // Create object from Serial class void setup(){ port = new Serial(this, Serial.list()[0], 9600); } void draw(){ delay(500); port.write("Led - H"); delay(500); port.write("Led - L"); } 

O aquí hay otro ejemplo. El LED cambiará su estado después de hacer clic en la ventana de la aplicación (cuyas dimensiones son 800x800px) con el botón del mouse.

 import processing.serial.*; Serial port; // Create object from Serial class int cnt = 0; void setup(){ size(800, 800); port = new Serial(this, Serial.list()[0], 9600); } void draw(){} void mousePressed() { cnt++; if(cnt % 2 == 1){ port.write("Led - H"); }else{ port.write("Led - L"); } } 

Procesamiento Ejemplo de aplicación rica en funciones


Esta aplicación primaria simula un "vuelo en el espacio", si puede llamarlo así. El valor del potenciómetro cambia la velocidad de vuelo, al presionar el botón cambia la dirección de vuelo. Y cualquier clic del botón del mouse en la ventana de la aplicación cambia el estado del LED (sí, no se me ocurrió nada más original).

Mi código está lejos de ser perfecto, no lo tome como un buen ejemplo. Este es solo un ejemplo que funciona. Aquí está

Programa multifuncional de ejemplo
 import processing.serial.*; Serial port; // Create object from Serial class int val; // Data received from the serial port (symbol) int pot; // Data from potentiometer String potMes = "Pot - "; String btnMes = "Button is pressed!"; int cntPM = 0; // Counter Potentiometer Message. // When it equals to length of Pot Mess - get value. int cntBM = 0; int cntBtnPress = 0; int cntMousePress = 0; Star[] stars = new Star[1000]; float speed; int dir = 1; void setup(){ size(800, 800); for(int i = 0; i < stars.length; i++){ stars[i] = new Star(); } frameRate(60); // 60 Frames per second port = new Serial(this, Serial.list()[0], 9600); // Wait for first message from Arduino delay(2000); while (port.available() > 0) { val = port.read(); print(char(val)); } } void draw(){ if (port.available() > 0) { val = port.read(); cntPM = CheckSymbol(potMes, cntPM, char(val), cntPM); cntBM = CheckSymbol(btnMes, cntBM, char(val), cntBM); } DrawRain(pot, 0, 1023); } void DrawRain(int speed_f, int min, int max){ background(0); translate(width/2,height/2); speed = dir*map(speed_f, min, max, 0, 50); for(int i = 0; i < stars.length; i++){ stars[i].go(); stars[i].update(); stars[i].show(); } } int CheckSymbol(String mes, int index, char sym, int ret_val){ if(mes.charAt(index) == sym && ret_val < (mes.length() - 1)){ return (ret_val + 1); }else if( ret_val == (mes.length() - 1) && mes.equals(potMes) ){ if(port.available() > 0){ pot = port.read(); // First 0-255 value } if(port.available() > 0){ pot += 256*port.read(); // Last 2 bits 256 - 1024 } }else if( ret_val == (mes.length() - 1) && mes.equals(btnMes) ){ cntBtnPress++; dir = -dir; } return 0; } void mousePressed() { cntMousePress++; if(cntMousePress % 2 == 1){ port.write("Led - H"); }else{ port.write("Led - L"); } } 

Conclusión


Creo que es necesario escribir que tomé la idea del último programa de un programador: Daniel Shiffman , quien graba videos que son comprensibles incluso para los niños sobre la programación en Procesamiento ( se han resuelto más de 140 tareas visuales ).

Cuando traté de averiguar qué y cómo hacer las comunicaciones de Processing y Arduino, estos sitios realmente me ayudaron:

  1. developer.alexanderklimov.ru/arduino/processing.php
  2. arduino-diy.com/arduino-processing-osnovi

Source: https://habr.com/ru/post/450518/


All Articles