Arduinoと処理。 COMポートを介してマイクロコントローラーを制御する方法。 双方向通信

みなさんこんにちは! 自家製の電子機器を使用してコンピューターを制御するには、USB HIDデバイスとして認識できる特別なボードのみが必要であるという誤解がインターネット上にあります。 Arduinoに関しては、誰もがArduino Leanardoについて話すだけです 。 マイクロコントローラを使用してマウスまたはキーボードのエミュレーションを作成できるKeyboardMouseなどの人気のあるライブラリは、Arduino、Leonardoボードのペア用にのみ設計されています。



Arduinoマイクロコントローラー(たとえば、 Arduino Unoを使用 )とその処理プログラムを接続する方法について説明します。 ProcessingのベースとなるJavaの知識を他のすべてに追加すると、独自のアプリケーションだけでなく、コンピューター全体の制御下でプロジェクトを追加できるようになります。 Javaでコンピュータープログラムを制御するトピックは秘密ではありません。グーグルですべてを見つけてください。



開発環境(IDE)をダウンロードする



純粋なCでマイクロコントローラーをプログラミングするための統合開発環境は数多くあります。 これらのうち、最も便利なのはAtollic、Eclipse、Keilです。



ただし、このガイドの簡潔さとアクセシビリティのために、Arduino IDEエディターを使用してArduino Cで記述します。 このようなエディターは、 Arduino公式Webサイトからダウンロードできます。



Procrssingでプログラミングするための開発環境は、 公式Webサイトからダウンロードすることもできます。



IDEエンジンのデータは同じエンジンで作成されているため、見栄えのためにIDEデータは非常に似ていることに注意してください。 そして、Arduinoが作成されたとき、ファウンダーは、Processingエディターで行われていたように、可能な限りコードエディターを簡素化しようとしました。



Arduino 回路を組み立ててコードを書く



この例では、Arduino Unoを使用します。 ボタン、ポテンショメーター、LEDが接続されます。 したがって、論理0または1を出力できます。論理0または1を読み取り、ポテンショメータの位置に応じて0〜1023(Arduino Unoでは10ビットADC)の数値を取得して、 アナログ-デジタル変換 (ADCまたはADC)を実行します。 これらはマイクロコントローラが実行できる主な機能であるため、例ではこれ以上必要ありません。



配線図:







図では、アノードのLEDは、制限抵抗(最小220オーム、好ましくは500オーム)を介して5Vに、カソードによってピンD11に接続されています。 ボタンはアースとピンD2を閉じます。 ポテンショメータは、ピンA1の電位を変化させます。



マイクロコントローラのタスクは次のとおりです。「LED-H」というメッセージがシリアルインターフェイス(シリアルCOMポート)に届くと、LEDが点灯します。 「LED-L」というメッセージが届いたら、LEDを消します。 250msごとに、シリアルポート(この場合はコンピューター画面)にメッセージ「Pot-」とピンA1のアナログ読み取りで受信した番号を送信します。 ボタンが押されたら、「ボタンが押されました!」というメッセージを一度送信します。



この問題を解決するための私の提案は次のとおりです(従う例ではありません)。



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









コメント:LEDはアノードによって電源に接続されています。 これにより、LEDのステータスのロジックが反転し、利点がなくなります。 Arduino Unoには、ピンがINPUT_PULLUPモードに初期化されるときに回路に含まれるプルアップ抵抗が組み込まれているため、経済的な理由から、ボタンはプルアップ抵抗で固定されていません。

また、ファームウェアでは、ポテンショメーターから取得した値に関するメッセージは、ボタンを最初に押した後にのみ送信されます!



ボードのファームウェアを埋めるには、ポートとボードを選択することを忘れないでください。







Arduinoボード用に予約されているCOMポートがわからない場合は、Windowsで

[コントロールパネル]-> [デバイスマネージャー]をクリックし、[COMポート]タブをクリックします







COMポートが私のポートとして署名されていない場合、いつでもArduinoを切断して、どのポートが削除されているかを確認できます。 しかし、誰も姿を消しておらず、Arduinがコンピューターにまったく認識されない場合は、インターネットで解決策を探すときです。 ただし、ドライバーの更新またはボードの変更から始めてください。



すべてがうまくいったら、ポートモニターを開いて「Led-H」、「Led-L」と入力し、ボタンを押してポテンショメーターを回し、画面を見て、すべてが正しく表示されるかどうかを確認します。



十分にプレイした-コードをわずかに変更します。



最後の行をコメントのコードに置き換えます。



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





これで、ポテンショメータからの値は判読できなくなりますが、処理プログラムにはこのような操作が必要です。



処理中。 マイクロコントローラーと対話するプログラムを書いています



処理プログラムとマイクロコントローラー間の通信の本質は非常に簡単です。 このプログラミング言語にはSerialライブラリがあり、 Serial.write();



として送信されたメッセージを受信できますSerial.write();



、およびSerial.print();



としてメッセージを送信することもできますSerial.print();



。 このようなメッセージが送信されると、ポートバッファに書き込まれるため、マイクロコントローラによって読み取られることに注意することが重要です。 したがって、目的のシリアルポートに接続して、メッセージを送受信するだけです。



次のプログラムは、シリアルライブラリを接続し、エディターコンソールに、接続可能なすべてのCOMポートのリストを書き込みます。



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





エディターにコードを記述し、「開始」ボタン(図の矢印1)をクリックすると、アプリケーションウィンドウが表示され(2)、COMポートのリストがコンソールに表示されます(3)。







このようなCOMポートは1つしかなく、シートには、配列のように、番号0になります。これらの理由から、Serialクラスのオブジェクトは次のとおりですSerial port;



作成されると、ポートリストport = new Serial(this, Serial.list()[0], 9600);



の最初の要素が正確に指定されますport = new Serial(this, Serial.list()[0], 9600);







変更して最新のファームウェアをArduinに注ぎます。 次に、このプログラムを作成して実行します。 その中で、500ミリ秒ごとにメッセージがCOMポートに送信され、LEDが消灯または点灯します。 そして、すべてがあなたのために正しく行われている場合、アプリケーションを開始した後、LEDが点滅するはずです。



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





または、ここに別の例があります。 LEDは、マウスボタンでアプリケーションウィンドウ(サイズは800x800px)をクリックすると状態が変わります。



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





処理中。 機能豊富なアプリケーションの例



この基本アプリケーションは、「宇宙での飛行」をシミュレートします。 ポテンショメーターの値は飛行速度を変更し、ボタンを押すと飛行方向が変更されます。 また、アプリケーションウィンドウでマウスボタンをクリックすると、LEDの状態が変わります(はい、私はこれ以上オリジナルを思いつきませんでした)。



私のコードは完璧とはほど遠いです。良い例としてそれを受け取らないでください。 これは機能する単なる例です。 ここにいる。



多機能プログラムの例
 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"); } }
      
      





おわりに



私は、1人のプログラマー-Daniel Shiffmanから最後のプログラムのアイデアを選んだことを書く必要があると思います。DanielShiffmanは 、Processingのプログラミングについて子供たちにも理解できるビデオを撮影します( 140以上の視覚的なタスクが解決されました )。



ProcessingとArduinoの通信を自分で何をどのように行うかを理解しようとしたとき、これらのサイトは本当に役に立ちました。



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



All Articles