Arduino und Verarbeitung. So steuern Sie einen Mikrocontroller über einen COM-Port. Zwei-Wege-Kommunikation

Hallo allerseits! Im Internet gibt es ein Missverständnis, dass zur Steuerung eines Computers mit hausgemachter Elektronik nur spezielle Karten benötigt werden, die als USB-HID-Geräte erkannt werden können. Und in Bezug auf Arduino sprechen alle nur über Arduino Leanardo . Beliebte Bibliotheken wie Tastatur und Maus , mit denen Sie mithilfe des Mikrocontrollers eine Emulation der Maus oder Tastatur erstellen können, sind nur für ein Paar Arduino-Leonardo-Boards vorgesehen.

Ich werde darüber sprechen, wie ein Arduino-Mikrocontroller (z. B. Arduino Uno ) und sein Verarbeitungsprogramm angeschlossen werden. Nachdem Sie das Wissen über Java, auf dem Processing basiert, zu allem anderen hinzugefügt haben, können Sie ein Projekt unter der Kontrolle des gesamten Computers und nicht nur seiner eigenen Anwendung hinzufügen. Das Thema der Steuerung eines Computerprogramms in Java ist kein Geheimnis, Google und Sie werden alles finden, das versichere ich Ihnen.

Download Entwicklungsumgebung (IDE)


Es gibt viele integrierte Entwicklungsumgebungen zum Programmieren von Mikrocontrollern in reinem C. Von diesen kann das bequemste festgestellt werden: Atollic, Eclipse, Keil.

Zur Vereinfachung und Zugänglichkeit dieses Handbuchs werde ich jedoch den Arduino IDE-Editor verwenden und in Arduino C schreiben. Sie können einen solchen Editor von der offiziellen Arduino-Website herunterladen .

Die Entwicklungsumgebung für die Programmierung auf Procrssing kann auch von der offiziellen Website heruntergeladen werden .

Aus Gründen des Anstands ist anzumerken, dass die IDE-Daten sehr ähnlich sind, da sie auf derselben Engine geschrieben sind. Und als Arduino erstellt wurde, versuchten die Gründer, ihren Code-Editor so weit wie möglich zu vereinfachen, wie dies im Verarbeitungs-Editor der Fall war.

Arduino Wir bauen die Schaltung zusammen und schreiben den Code


In diesem Beispiel werde ich Arduino Uno verwenden. Eine Taste, ein Potentiometer und eine LED werden daran angeschlossen. Dementsprechend kann ich eine logische 0 oder 1 ausgeben. Lesen Sie eine logische 0 oder 1. Und führen Sie eine Analog-Digital-Wandlung (ADC oder ADC) durch, wobei Sie abhängig von der Position des Potentiometers Zahlen von 0 bis 1023 (im Arduino Uno einen 10-Bit-ADC) erhalten. Für ein Beispiel brauchen Sie nicht viel mehr, da dies die Hauptfunktionen sind, die ein Mikrocontroller ausführen kann.

Schaltplan:



In dem Diagramm ist die Anoden-LED über einen Begrenzungswiderstand (mindestens 220 Ohm, vorzugsweise 500 Ohm) über die Kathode an Pin D11 mit 5 V verbunden. Der Knopf schließt den Boden und Pin D2. Potentiometer ändert Potential an Pin A1.

Der Mikrocontroller hat folgende Aufgabe: Wenn die Meldung „LED - H“ an der seriellen Schnittstelle (serieller COM-Anschluss) ankommt, leuchtet die LED auf. Wenn die Meldung „LED - L“ eintrifft, löschen Sie die LED. Alle 250 ms senden Sie eine Nachricht an die serielle Schnittstelle (in diesem Fall an den Computerbildschirm), die Nachricht „Pot -“ und die Nummer, die durch analoges Lesen von Pin A1 empfangen wurde. Wenn eine Taste gedrückt wird, senden Sie einmal die Nachricht „Taste wird gedrückt!“.

Hier ist mein Vorschlag zur Lösung dieses Problems (kein Beispiel, dem ich folgen soll):

Firmware für 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; } } } 

Kommentar: Die LED ist über die Anode mit der Stromversorgung verbunden. Dies kehrt die Logik des LED-Zustands um und profitiert nicht mehr. Der Knopf ist aus wirtschaftlichen Gründen nicht mit einem Pull-up-Widerstand verbunden, da Arduino Uno eingebaute Pull-up-Widerstände enthält, die in der Schaltung enthalten sind, wenn der Pin in den INPUT_PULLUP-Modus initialisiert wird.
Auch in der Firmware werden Meldungen über den vom Potentiometer übernommenen Wert erst nach dem ersten Knopfdruck gesendet!

Vergessen Sie nicht, den Port und die Karte auszuwählen, um die Firmware in die Karte zu füllen.



Wenn Sie nicht wissen, welchen COM-Anschluss Sie für das Arduino-Board haben, gehen Sie unter Windows zu
Systemsteuerung -> Geräte-Manager und klicken Sie auf die Registerkarte „COM-Anschlüsse“



Wenn Ihr COM-Port nicht als meiner signiert ist, können Sie das Arduino jederzeit trennen und sehen, welcher Port weg ist. Aber wenn niemand verschwunden ist und Arduin vom Computer überhaupt nicht erkannt wird, ist es Zeit, im Internet nach einer Lösung zu suchen. Beginnen Sie jedoch mit der Aktualisierung der Treiber oder dem Wechsel der Karte.

Wenn alles funktioniert, öffnen Sie den Anschlussmonitor und geben Sie „Led-H“, „Led-L“ ein, drücken Sie die Taste, drehen Sie das Potentiometer und schauen Sie auf den Bildschirm, um festzustellen, ob alles korrekt angezeigt wird.

Habe genug gespielt - ändere den Code leicht.

Ersetzen Sie die letzte Zeile durch den Code aus dem Kommentar.

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

Jetzt sehen die Werte vom Potentiometer nicht mehr lesbar aus, aber ein solches Manöver ist für das Verarbeitungsprogramm erforderlich.

Verarbeitung. Wir schreiben ein Programm, das mit einem Mikrocontroller interagiert


Das Wesen der Kommunikation zwischen dem Verarbeitungsprogramm und dem Mikrocontroller ist sehr einfach. Für diese Programmiersprache gibt es eine serielle Bibliothek, mit der Sie Nachrichten empfangen können, die als Serial.write(); gesendet werden Serial.write(); und ermöglicht es Ihnen auch, Nachrichten als Serial.print(); zu senden Serial.print(); . Es ist wichtig zu beachten, dass eine solche gesendete Nachricht in den Portpuffer geschrieben wird, was bedeutet, dass sie vom Mikrocontroller gelesen wird. Wir müssen uns also nur mit dem gewünschten seriellen Port verbinden und Nachrichten empfangen / senden.

Das folgende Programm verbindet die serielle Bibliothek und schreibt in die Editor-Konsole eine Liste aller COM-Ports, mit denen Sie eine Verbindung herstellen können.

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

Wenn Sie den Code in den Editor schreiben und auf die Schaltfläche „Start“ klicken (Pfeil 1 im Bild), wird das Anwendungsfenster angezeigt (2) und die Liste der COM-Anschlüsse in der Konsole angezeigt (3).



Ich habe nur einen solchen COM-Port und im Blatt, wie im Array, wird es die Nummer 0 sein. Aus diesen Gründen ist das Objekt der seriellen Klasse: Serial port; Wenn es erstellt wird, wird das erste Element der port = new Serial(this, Serial.list()[0], 9600); angegeben. port = new Serial(this, Serial.list()[0], 9600);

Gießen Sie mit einer Änderung unsere neueste Firmware in Arduin ein. Dann schreiben Sie dieses Programm und führen es aus. Darin Alle 500 Millisekunden wird eine Nachricht an den COM-Port gesendet, um die LED zu löschen oder zu leuchten. Und wenn alles richtig gemacht ist, sollte die LED nach dem Start der Anwendung blinken.

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

Oder hier ist ein anderes Beispiel. Die LED ändert ihren Status nach jedem Klick auf das Anwendungsfenster (mit den Abmessungen 800 x 800 Pixel) mit der Maustaste.

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

Verarbeitung. Funktionsreiches Anwendungsbeispiel


Diese elementare Anwendung simuliert einen "Flug im Weltraum", wenn man es so nennen kann. Der Wert vom Potentiometer ändert die Fluggeschwindigkeit, durch Drücken der Taste wird die Flugrichtung geändert. Und jeder Mausklick im Anwendungsfenster ändert den Status der LED (ja, ich habe mir nichts Originelleres ausgedacht).

Mein Code ist alles andere als perfekt. Nehmen Sie ihn nicht als gutes Beispiel. Dies ist nur ein Beispiel, das funktioniert. Hier ist er.

Beispiel für ein multifunktionales Programm
 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"); } } 

Fazit


Ich denke, es ist notwendig zu schreiben, dass ich die Idee des letzten Programms von einem Programmierer aufgegriffen habe - Daniel Shiffman , der Videos dreht, die selbst für Kinder über das Programmieren in der Verarbeitung verständlich sind ( mehr als 140 visuelle Aufgaben wurden gelöst ).

Als ich versuchte herauszufinden, was und wie die Verarbeitung und die Arduino-Kommunikation selbst durchgeführt werden sollen, haben mir diese Websites wirklich geholfen:

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

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


All Articles