工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduino超音波センサーとProcessingで作るリアルタイム距離測定ソナー

必要な部品と材料

部品数量備考
Arduino UNO1メインマイコン
SG90 マイクロサーボモーター1超音波センサー回転用
超音波センサー HC-SR041距離測定用(2cm-400cm)
ジャンパーワイヤー1セット配線用
フルサイズ ブレッドボード1配線用

必要な工具

使用ソフトウェア

プロジェクト概要

障害物回避ロボットの要素(サーボ+超音波センサー)を応用し、180度回転スキャンするソナーシステムを構築しました。TFT LCDが手元になかったため、PC上でProcessing IDEを使ってリアルタイムにレーダー風表示を実現しています。

仕組み

  1. グルーガンでHC-SR04をSG90サーボのホーンに固定
  2. サーボが0°→180°→0°と往復スキャン(30ms/ステップ)
  3. 各角度で超音波距離測定し、「角度,距離.」形式でシリアル送信
  4. Processing側で受信し、レーダー画面(半円スキャンライン+検出点プロット)に描画
  5. 距離・角度を数値表示、40cm以内の物体を赤線でハイライト

Arduinoコード(C/C++)

#include <Servo.h>

const int trigPin = 12;
const int echoPin = 11;
long duration;
int distance;
Servo s1;

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  s1.attach(9);
}

void loop() {
  // 0度→180度 スキャン
  for (int i = 0; i < 180; i++) {
    s1.write(i);
    delay(30);
    distance = calDist();
    Serial.print(i);
    Serial.print(",");
    Serial.print(distance);
    Serial.print(".");
  }
  // 180度→0度 復路スキャン
  for (int i = 180; i > 0; i--) {
    s1.write(i);
    delay(30);
    distance = calDist();
    Serial.print(i);
    Serial.print(",");
    Serial.print(distance);
    Serial.print(".");
  }
}

int calDist() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2; // 音速340m/sで片道距離計算
  return distance;
}

Processingコード(Java)

import processing.serial.*;

Serial myPort;
String ang = "";
String distance = "";
String data = "";
int angle, dist;

void setup() {
  size(2000, 800);
  myPort = new Serial(this, "COM3", 9600); // ポート名は環境に合わせて変更
  myPort.bufferUntil('.');
  background(0);
}

void draw() {
  // 残像効果付き背景クリア
  fill(0, 5);
  noStroke();
  rect(0, 0, width, height * 0.93);
  noStroke();
  fill(0, 255);
  rect(0, height * 0.93, width, height);
  
  drawRadar();   // レーダー背景(同心円・角度線)
  drawLine();    // 現在のスキャンライン
  drawObject();  // 検出物体のプロット
  drawText();    // 目盛り・数値表示
}

void serialEvent(Serial myPort) {
  data = myPort.readStringUntil('.');
  data = data.substring(0, data.length() - 1);
  int index1 = data.indexOf(",");
  ang = data.substring(0, index1);
  distance = data.substring(index1 + 1, data.length());
  angle = int(ang);
  dist = int(distance);
  System.out.println(angle);
}

void drawRadar() {
  pushMatrix();
  noFill();
  strokeWeight(0.5);
  stroke(10, 255, 10);
  translate(width/2, height - height*0.06);
  
  // 基準線
  line(-width/2, 0, width/2, 0);
  // 同心円(距離目盛り)
  arc(0, 0, width*0.5, width*0.5, PI, TWO_PI);
  arc(0, 0, width*0.25, width*0.25, PI, TWO_PI);
  arc(0, 0, width*0.75, width*0.75, PI, TWO_PI);
  arc(0, 0, width*0.95, width*0.95, PI, TWO_PI);
  
  // 30度刻み主目盛線
  for (int a = 30; a <= 150; a += 30) {
    line(0, 0, (-width/2)*cos(radians(a)), (-width/2)*sin(radians(a)));
  }
  // 15度刻み補助線
  stroke(175, 255, 175);
  for (int a = 15; a <= 165; a += 30) {
    line(0, 0, (-width/2)*cos(radians(a)), (-width/2)*sin(radians(a)));
  }
  popMatrix();
}

void drawLine() {
  pushMatrix();
  strokeWeight(9);
  stroke(0, 255, 0);
  translate(width/2, height - height*0.06);
  line(0, 0, (width/2)*cos(radians(angle)), (-width/2)*sin(radians(angle)));
  popMatrix();
}

void drawObject() {
  pushMatrix();
  strokeWeight(9);
  stroke(255, 0, 0);
  translate(width/2, height - height*0.06);
  
  // 距離をピクセルに変換(40cmを最大半径とする)
  float pixleDist = (dist / 40.0) * (width / 2.0);
  float pd = (width/2) - pixleDist;
  float x = -pixleDist * cos(radians(angle));
  float y = -pixleDist * sin(radians(angle));
  
  if (dist <= 40) {
    line(-x, y, -x + (pd*cos(radians(angle))), y - (pd*sin(radians(angle))));
  }
  popMatrix();
}

void drawText() {
  pushMatrix();
  fill(100, 200, 255);
  textSize(25);
  // 距離目盛りラベル
  text("10cm", (width/2)+(width*0.115), height*0.93);
  text("20cm", (width/2)+(width*0.24), height*0.93);
  text("30cm", (width/2)+(width*0.365), height*0.93);
  text("40cm", (width/2)+(width*0.45), height*0.93);
  
  if (dist <= 40) {
    text("Distance: " + dist, width*0.7, height*0.99);
  }
  
  translate(width/2, height - height*0.06);
  textSize(25);
  // 角度ラベル
  text(" 30", (width/2)*cos(radians(30)), (-width/2)*sin(radians(30)));
  text(" 60", (width/2)*cos(radians(60)), (-width/2)*sin(radians(60)));
  text("90", (width/2)*cos(radians(91)), (-width/2)*sin(radians(90)));
  text("120", (width/2)*cos(radians(123)), (-width/2)*sin(radians(118)));
  text("150", (width/2)*cos(radians(160)), (-width/2)*sin(radians(150)));
  popMatrix();
}

回路図

配線図を参照:HC-SR04のTrig→D12, Echo→D11, VCC/GND→5V/GND。サーボ信号線→D9, VCC/GND→5V/GND。

動作確認のポイント

製造プロセス

  1. TinyML言語検出器:Edge ImpulseとArduino Nano 33 BLE Senseで「はい」を多言語判別
  2. Arduino NanoとMPU-6050で作るリアルタイムジャイロスコープゲーム
  3. Arduinoデジタルダイス: LCD表示の乱数ジェネレーター自作
  4. Arduinoで超音波レベーション(浮遊)装置を自作:ステップバイステップガイド
  5. Arduinoとスマホで作るスマート電圧計 – 簡単DIYプロジェクト
  6. Arduinoで温湿度ロガーを作る – DHT11とEthernetシールドでSDカード記録
  7. ESP8266・Arduino・超音波センサーで作るスマートIoTジャー:リアルタイム中身監視
  8. スマート駐車場カウンター:Arduino、Processing、PHPでリアルタイム車両管理
  9. Bolt IoTとArduino UNOでLED輝度をシームレス制御
  10. Arduino IoT CloudとAlexaでテレビを音声操作:ステップバイステップガイド
  11. ArduinoとProcessingで作るリアルタイムデジタルコンパス