Arduino et traitement. Comment contrôler un microcontrôleur via un port COM. Communication bidirectionnelle

Bonjour à tous! Il existe une idée fausse sur Internet selon laquelle pour contrôler un ordinateur à l'aide d'appareils électroniques faits maison, seules des cartes spéciales sont nécessaires et peuvent être reconnues comme des périphériques USB HID. Et en ce qui concerne Arduino, tout le monde parle d' Arduino Leanardo . Des bibliothèques populaires telles que Clavier et souris , qui vous permettent de créer une émulation de la souris ou du clavier à l'aide du microcontrôleur, ne sont destinées qu'à une paire de cartes Arduino, Leonardo, parmi elles.

Je vais parler de la façon de connecter n'importe quel microcontrôleur Arduino (par exemple, pris Arduino Uno ) et son programme de traitement. Après avoir ajouté à tout le reste la connaissance de Java, sur laquelle le traitement est basé, il sera possible d'ajouter un projet sous le contrôle de l'ordinateur entier, et pas seulement de sa propre application. Le sujet du contrôle d'un programme informatique en Java n'est pas quelque chose de secret, google et vous trouverez tout, je vous assure.

Télécharger l'environnement de développement (IDE)


Il existe de nombreux environnements de développement intégrés pour la programmation de microcontrôleurs en pur C. Parmi ceux-ci, le plus pratique peut être noté: Atollic, Eclipse, Keil.

Cependant, pour la simplicité et l'accessibilité de ce guide, je vais utiliser l'éditeur Arduino IDE et écrire en Arduino C. Vous pouvez télécharger un tel éditeur sur le site officiel d'Arduino .

L'environnement de développement pour la programmation sur Procrssing peut également être téléchargé sur le site officiel .

Il convient de noter, par souci de décence, que les données IDE sont très similaires, car elles sont écrites sur le même moteur. Et quand Arduino a été créé, les fondateurs ont essayé de simplifier leur éditeur de code autant que possible, comme cela a été fait dans l'éditeur de traitement.

Arduino Nous assemblons le circuit et écrivons le code


Dans cet exemple, j'utiliserai Arduino Uno. Un bouton, un potentiomètre et une LED y seront connectés. En conséquence, je peux sortir un 0 ou 1. logique Lire un 0 ou 1. logique et effectuer une conversion analogique-numérique (ADC ou ADC), en obtenant des nombres de 0 à 1023 (dans l'Arduino Uno un ADC 10 bits), en fonction de la position du potentiomètre. Vous n'avez pas besoin de beaucoup plus pour un exemple, car ce sont les principales fonctions qu'un microcontrôleur peut faire.

Schéma de câblage:



Dans le schéma, la LED d'anode est connectée à 5V via une résistance de limitation (au moins 220 Ohms, de préférence 500 Ohms), par la cathode à la broche D11. Le bouton ferme la masse et la broche D2. Le potentiomètre change le potentiel sur la broche A1.

La tâche du microcontrôleur est la suivante: Si le message «LED - H» arrive sur l'interface série (port COM série) - allumez la LED. Si le message «LED - L» arrive, éteignez la LED. Toutes les 250 ms, envoyez un message au port série (dans ce cas, à l'écran de l'ordinateur) le message «Pot -» et le numéro reçu par lecture analogique de la broche A1. Lorsqu'un bouton est enfoncé, envoyez un message «Le bouton est enfoncé!» Une fois.

Voici ma suggestion pour résoudre ce problème (pas un exemple à suivre):

Micrologiciel pour 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; } } } 

Remarque: la LED est connectée à l'alimentation par l'anode. Cela inverse la logique de l'état de la LED et n'en profite plus. Le bouton n'est pas lié à une résistance de pull-up pour des raisons d'économie, car Arduino Uno a des résistances de pull-up intégrées qui sont incluses dans le circuit lorsque la broche est initialisée en mode INPUT_PULLUP.
Toujours dans le firmware, les messages sur la valeur prise par le potentiomètre ne sont envoyés qu'après la première pression sur un bouton!

Pour remplir le firmware de la carte, n'oubliez pas de sélectionner le port et la carte.



Si vous ne savez pas quel port COM vous avez pour la carte Arduino, alors sous Windows, allez à
Panneau de configuration -> Gestionnaire de périphériques et cliquez sur l'onglet "Ports COM"



Si votre port COM n'est pas signé comme le mien, vous pouvez toujours déconnecter l'Arduino et voir quel port a disparu. Mais si personne n'a disparu et Arduin n'est pas du tout reconnu par l'ordinateur, alors il est temps de chercher une solution sur Internet. Mais commencez par mettre à jour les pilotes ou changer la carte.

Lorsque tout fonctionne, essayez d'ouvrir le moniteur de port et entrez «Led-H», «Led-L», appuyez sur le bouton, tournez le potentiomètre et regardez l'écran pour voir si tout s'affiche correctement.

J'ai assez joué - modifiez légèrement le code.

Remplacez la dernière ligne par le code du commentaire.

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

Maintenant, les valeurs du potentiomètre ne sembleront pas lisibles, mais une telle manœuvre est requise pour le programme de traitement.

Traitement. Nous écrivons un programme qui interagit avec un microcontrôleur


L'essence de la communication entre le programme de traitement et le microcontrôleur est très simple. Il existe une bibliothèque Serial pour ce langage de programmation, qui vous permet de recevoir des messages envoyés en tant que Serial.write(); , et vous permet également d'envoyer des messages en tant que Serial.print(); . Il est important de noter qu'avec un tel message envoyé, il sera écrit dans la mémoire tampon du port, ce qui signifie qu'il sera lu par le microcontrôleur. Il nous suffit donc de nous connecter au port série souhaité et d'y recevoir / envoyer des messages.

Le programme suivant connecte la bibliothèque série et écrit dans la console de l'éditeur une liste de tous les ports COM auxquels vous pouvez vous connecter.

 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() {} 

Lorsque vous écrivez le code dans l'éditeur et cliquez sur le bouton «Démarrer» (flèche 1 dans l'image), la fenêtre de l'application apparaît (2) et la liste des ports COM s'affiche dans la console (3).



Je n'ai qu'un tel port COM et dans la feuille, comme dans le tableau, il sera au numéro 0. Pour ces raisons, l'objet de la classe Serial port; : Serial port; lors de sa création, il sera spécifié le premier élément de la liste des port = new Serial(this, Serial.list()[0], 9600);

Versez Arduin notre dernier firmware avec un changement. Ensuite, écrivez ce programme et exécutez-le. Toutes les 500 millisecondes, un message est envoyé au port COM pour éteindre ou allumer la LED. Et si tout est fait correctement, après avoir démarré l'application, la LED devrait clignoter.

 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"); } 

Ou voici un autre exemple. La LED changera d'état après tout clic sur la fenêtre de l'application (dont les dimensions sont 800x800px) avec le bouton de la souris.

 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"); } } 

Traitement. Exemple d'application riche en fonctionnalités


Cette application élémentaire simule un "vol dans l'espace", si vous pouvez l'appeler ainsi. La valeur du potentiomètre change la vitesse de vol, une pression sur le bouton change la direction du vol. Et chaque clic du bouton de la souris sur la fenêtre de l'application change l'état de la LED (oui, je n'ai rien trouvé de plus original).

Mon code est loin d'être parfait, ne le prenez pas comme un bon exemple. Ceci est juste un exemple qui fonctionne. Le voici.

Exemple de programme multifonctionnel
 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"); } } 

Conclusion


Je pense qu'il est nécessaire d'écrire que j'ai repris l'idée du dernier programme d'un programmeur - Daniel Shiffman , qui tourne des vidéos compréhensibles même aux enfants sur la programmation sur Processing ( plus de 140 tâches visuelles ont été résolues ).

Lorsque j'ai essayé de comprendre quoi et comment faire les communications de traitement et Arduino moi-même, ces sites m'ont vraiment aidé:

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

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


All Articles