Arduinoを使ってレーダーを作成しているのをYouTubeで見つけ、早速作ってみました。構造そのものは簡単で、 Arduinoからシリアルポートを通してProcessingにデータを送り、そのデータを使ってProcessingでレーダーを描画したものです。
Arduino Nanoをブレッドボードにセットし、サーボモーターの上に超音波センサーHC-SR04を載せてある簡単な構造です。
それが以下の写真です。
超音波センサーHC-SR04をArduino Nanoのピン番号10(trig)と11(echo)に接続し、
そしてサーボモーターをピン番号12に接続してあります。
レーダー本体(超音波センサーHC-SR04)から20cmの所に障害物を置いてあります。
Arduinoのプログラムは、以下の通りです。
#include <Servo.h> const int trigPin = 10; const int echoPin = 11; long duration; int distance; Servo myServo; void setup() { pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); Serial.begin(9600); myServo.attach(12); //12ピンにサーボモーターを取り付ける } void loop() { //サーボモータを15から165度回転させる for(int i=15;i<=165;i++){ myServo.write(i); delay(30); distance = calculateDistance();//超音波センサーによって測定された距離を度ごとに計算 するための関数を呼び出します Serial.print(i); //現在の角度をシリアルポートに送信します Serial.print(","); //インデックス作成のためにProcessing IDEで、後で必要とされる前の 値のすぐ隣に追加文字を送信する Serial.print(distance); //シリアルポートに距離の値を送ります Serial.print("."); //インデックス作成のためにProcessing IDEで、後で必要とされる前の 値のすぐ隣に追加文字を送信する(データの終わりを示すための文字) } //前の行を165度から15度まで繰り返す for(int i=165;i>15;i--){ myServo.write(i); delay(30); distance = calculateDistance(); Serial.print(i); Serial.print(","); Serial.print(distance); Serial.print("."); } } //超音波センサーによって測定された距離を計算するための関数 int calculateDistance(){ digitalWrite(trigPin, LOW); delayMicroseconds(2); // trigPinを10マイクロ秒間HIGH状態に設定します digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); // echoPinを読み込み、音波の伝搬時間をマイクロ秒で返します distance= duration*0.034/2; return distance; }
void setup()のsize (width,heigh);でディスプレイのサイズに合したwidth,heighを変更してください。
また、myPort = new Serial(this,"COM3", 9600);でポート名を変更してください。
(プログラムの番号は、説明のため付けていますので実際は必要ありません。)
1. /* Arduino Radar */ 2. 3. import processing.serial.*; 4. import java.awt.event.KeyEvent; 5. import java.io.IOException; 6. 7. Serial myPort; 8. String angle=""; 9. String distance=""; 10. String data=""; 11. String noObject; 12. float pixsDistance; 13. int iAngle, iDistance; 14. int index1=0; 15. PFont orcFont; 16. 17. void setup() { 18. size (1280, 1024); 19. smooth(); 20. myPort = new Serial(this,"COM3", 9600); 21. myPort.bufferUntil('.'); 22. orcFont = loadFont("OCRAExtended-30.vlw"); 23. } 24. 25. void draw() { 26. fill(98,245,31); 27. textFont(orcFont); 28. noStroke(); 29. fill(0,4); 30. rect(0, 0, width, height-height*0.065); 31. 32. fill(98,245,31); 33. 34. drawRadar(); 35. drawLine(); 36. drawObject(); 37. drawText(); 38. } 39. 40. void serialEvent (Serial myPort) { 41. data = myPort.readStringUntil('.'); 42. data = data.substring(0,data.length()-1); 43. index1 = data.indexOf(","); 44. angle= data.substring(0, index1); 45. distance= data.substring(index1+1, data.length()); 46. 47. iAngle = int(angle); 48. iDistance = int(distance); 49. } 50. 51. void drawRadar() { 52. pushMatrix(); 53. translate(width/2,height-height*0.074); 54. noFill(); 55. strokeWeight(2); 56. stroke(98,245,31); 57. 58. arc(0,0,(width-width*0.0625),(width-width*0.0625),PI,TWO_PI); 59. arc(0,0,(width-width*0.297),(width-width*0.297),PI,TWO_PI); 60. arc(0,0,(width-width*0.531),(width-width*0.531),PI,TWO_PI); 61. arc(0,0,(width-width*0.765),(width-width*0.765),PI,TWO_PI); 62. 63. line(-width/2,0,width/2,0); 64. line(0,0,(-width/2)*cos(radians(30)),(-width/2)*sin(radians(30))); 65. line(0,0,(-width/2)*cos(radians(60)),(-width/2)*sin(radians(60))); 66. line(0,0,(-width/2)*cos(radians(90)),(-width/2)*sin(radians(90))); 67. line(0,0,(-width/2)*cos(radians(120)),(-width/2)*sin(radians(120))); 68. line(0,0,(-width/2)*cos(radians(150)),(-width/2)*sin(radians(150))); 69. line((-width/2)*cos(radians(30)),0,width/2,0); 70. popMatrix(); 71. } 72. 73. void drawObject() { 74. pushMatrix(); 75. translate(width/2,height-height*0.074); 76. strokeWeight(9); 77. stroke(255,10,10); 78. pixsDistance = iDistance*width*0.469*0.025); 79. 80. if(iDistance < 40){ 81. line(pixsDistance*cos(radians(iAngle)),-pixsDistance*sin(radians(iAngle)), (width-width*0.505)*cos(radians(iAngle)),-(width-width*0.505)*sin(radians(iAngle))); 82. } 83. popMatrix(); 84. } 85. 86. void drawLine() { 87. pushMatrix(); 89. strokeWeight(9); 90. stroke(30,250,60); 91. translate(width/2,height-height*0.074); 92. line(0,0,(width-width*0.505)*cos(radians(iAngle)),-(width-idth*0.505)*sin(radians(iAngle))); 93. popMatrix(); 94. } 95. 96. void drawText() { 97. pushMatrix(); 98. if(iDistance > 40) { 99. noObject = "Out of Range"; 100. } 101. else { 102. noObject = "In Range"; 103. } 104. fill(0,0,0); 105. noStroke(); 106. rect(0, height-height*0.0648, width, height); 107. fill(98,245,31); 108. textSize(20); 109. 110. text("10cm",width-width*0.433,height-height*0.0833); 111. text("20cm",width-width*0.316,height-height*0.0833); 112. text("30cm",width-width*0.199,height-height*0.0833); 113. text("40cm",width-width*0.082,height-height*0.0833); 114. textSize(30); 115. text("Object: " + noObject, width-width*0.875, height-height*0.035); 116. text("Angle: " + iAngle +" °", width-width*0.48, height-height*0.035); 117. text("Distance: ", width-width*0.26, height-height*0.035); 118. 119. if(iDistance < 40) { 120. text(" " + iDistance +" cm", width-width*0.109, height-height*0.035); 121. } 122. textSize(20); 123. fill(98,245,60); 124. translate((width-width*0.4994)+width/2*cos(radians(30)),(height-height*0.0907)-width/2*sin(radians(30))); 125. rotate(-radians(-60)); 126. text("30°",0,0); 127. resetMatrix(); 128. translate((width-width*0.503)+width/2*cos(radians(60)),(height-height*0.0888)-width/2*sin(radians(60))); 129. rotate(-radians(-30)); 130. text("60°",0,0); 131. resetMatrix(); 132. translate((width-width*0.507)+width/2*cos(radians(90)),(height-height*0.0833)-width/2*sin(radians(90))); 133. rotate(radians(0)); 134. text("90°",0,0); 135. resetMatrix(); 136. translate(width-width*0.513+width/2*cos(radians(120)),(height-height*0.07129)-width/2*sin(radians(120))); 137. rotate(radians(-30)); 138. text("120°",0,0); 139. resetMatrix(); 140. translate((width-width*0.5104)+width/2*cos(radians(150)),(height-height*0.0574)-width/2*sin(radians(150))); 141. rotate(radians(-60)); 142. text("150°",0,0); 143. popMatrix(); 144. }
1.インポートについて(*数字は上記プログラム番号)
*3. import processing.serial.*;
これは、Processingでシリアル通信を行うライブラリーをインポートします。
*4. import java.awt.event.KeyEvent;
シリアルポートからデータを読み込むためのライブラリーをインポートします。
*5. import java.io.IOException;
javaコードの入出力操作に関連する例外をインポートします。この例外はファイル等の操作の読み取りや
書き込み中に障害が発生した場合に発生します。
2.void setup()について
*18. size (1280, 1024);
自分のディスプレイのサイズに合わせて、縦横のサイズを変更します。
*20. myPort = new Serial(this,"COM3", 9600);
使用しているポートと希望する速度でシリアル通信をするための設定です。ポート名が違っていると
エラーとなりますので注意してください。
ポート名が分からない場合は、最後に記述してある「ポート名の確認」のSerial_Port_Selectionを起動して確認してください。
*21. myPort.bufferUntil('.');
ラインフィールド”.”が来るたびに、serialEvent()を発動させます。
3.void serialEvent()について
*41. data = myPort.readStringUntil('.');
文字列の途中で読み取りを開始した場合に備えて最初の読み取りをスローします。
“.”はデータの終わりを示すための指定した文字です。
*42. data = data.substring(0,data.length()-1);
上記data=[angle , distance . ] から、新たにdata=[angle , distance]とします。
*43. index1 = data.indexOf(",");
","で定義された部分文字列の最初の出現箇所のインデックス位置を返します。
*44. angle= data.substring(0, index1);
*45. distance= data.substring(index1+1, data.length());
data=[angle , distance]のインデックスが0からindex1までをangleとして読み取り、index1+1からdataの長さまでをdistanceとして読み取ります。
4.レーダーの描画
(1)Void draw()で
(2)原点を(0,0)から(width/2,height-height*0.074)に移動する
(3)レーダーを描画する。0cmから40cmまでの間は均等にしています。
図のようにwidth*0.469 pix が40cmになるので、1cmあたりwidth*0.469*0.025 pixとなります。
したがって、void drawObject() のpixsDistanceは、pixsDistance = iDistance*width*0.469*0.025となります。