ArduinoとHC-SR04を使用して距離計算機を作ってみた

プログラミング
スポンサーリンク

はじめに

こんにちは。少し前にArduinoHC-SR04を利用して距離計算機を作りました。そのときのメモとなります。

ちなみに、動作しているときの雰囲気はこんな感じ。(デバッグ中で距離はでない・・・)

流れ

HC-SR04という超音波で距離を測定する装置を購入します。

あとは、こんな感じに繋げました。
ちなみにArduinoや液晶、圧電スピーカーは、このArduinoセットを購入したときについてたものを利用。

ボタンを押すと圧電スピーカーからピッと音が出て距離が出ます。

モバイルバッテリーと繋げることで、持ち運びもできます。

ソースコード

以下のようなソースコードを記述しました。

#include <Metro.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <stdio.h>

volatile static unsigned int i = 0;

// シリアル接続
const int SERIAL_BITRATE = 9600;

// LCD
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
char strLcdBuffer[33] = { 0 };

//--------------------------------------------

// 圧電スピーカー
const int SOUND_PIN	= 12;
const int SOUND_HZ	= (440 * 4);
const int SOUND_MS	= 100;

void beep() {
	tone(SOUND_PIN, SOUND_HZ, SOUND_MS);
}

//--------------------------------------------

// 距離センサ―

#define PORT_DISTANCE_SENSOR1_TRIG		4
#define PORT_DISTANCE_SENSOR1_ECHO		3

const int DISTANCE_SENSOR2			= 1;
const int DISTANCE_SENSOR1			= 0;

void setupDistanceSensor() {
	pinMode( PORT_DISTANCE_SENSOR1_TRIG, OUTPUT );
	pinMode( PORT_DISTANCE_SENSOR1_ECHO, INPUT );
}

int getOneDistanceXCm(int trig_pin, int echo_pin) {
	int interval = 0;
	float distance = 0;
	digitalWrite( trig_pin, LOW );
	delayMicroseconds( 2 );
	digitalWrite( trig_pin, HIGH );
	delayMicroseconds( 10 );
	digitalWrite( trig_pin, LOW );
	interval = pulseIn( echo_pin, HIGH );
	distance = interval * 0.017;
	return (int)distance;
}

int compare_int(const void *a, const void *b) {
	return *(int*)a - *(int*)b;
}

int getDistanceCm(int sensor_number) {
	int i = 0, count = 0;
	int buffer[7] = { 0 };
	int max_count = sizeof(buffer) / sizeof(int);
	int trig_pin, echo_pin;
	
	if(sensor_number == DISTANCE_SENSOR1) {
		trig_pin = PORT_DISTANCE_SENSOR1_TRIG;
		echo_pin = PORT_DISTANCE_SENSOR1_ECHO;
	}
	else {
		return -1;
	}
	
	for(i = 0; i < max_count; i++) {
		int distance = getOneDistanceXCm(trig_pin, echo_pin);
		if(distance > 0) {
			buffer[count++] = distance;
		}
	}
	qsort(buffer, count, sizeof(int), compare_int);
	return buffer[count - (count / 2)];
}


//-------------------------------------------

// 押しボタン

#define INPUT_BUTTON_INTERVAL_MS	100
#define BUTTON_CHATTERING_SIZE		1

#define BUTTON_LENGTH				1
#define BUTTON1						0
#define PORT_BUTTON1				2

// 入力ピン
Metro intervalButtonTimer = Metro(INPUT_BUTTON_INTERVAL_MS);

unsigned char ucButtonPortArray[BUTTON_LENGTH] = { PORT_BUTTON1 };
unsigned char ucButtonChattering[BUTTON_LENGTH][BUTTON_CHATTERING_SIZE];
bool isBufferPushed[BUTTON_LENGTH];
bool isBufferPushReaded[BUTTON_LENGTH];

void setupButton() {
	pinMode( PORT_BUTTON1, INPUT_PULLUP);
	memset(&ucButtonChattering, 0, sizeof(ucButtonChattering));
	memset(&isBufferPushed, false, sizeof(isBufferPushed));
	memset(&isBufferPushReaded, false, sizeof(isBufferPushReaded));
}

void pushInputBuffer(int button_num, bool ispush) {
	int num = button_num;
	int x = ispush ? 1 : 0;
	unsigned int i = 0;
	
	// push
	for(i = BUTTON_CHATTERING_SIZE - 1; i >= 1; i--) {
		ucButtonChattering[num][i] = ucButtonChattering[num][i - 1];
	}
	ucButtonChattering[num][0] = x;
	
	// check
	{
		unsigned int sum = 0;
		for(i = 0; i < BUTTON_CHATTERING_SIZE; i++) {
			sum += ucButtonChattering[num][i];
		}
		if(sum == BUTTON_CHATTERING_SIZE) {
			isBufferPushed[num] = true;
		}
		else if((isBufferPushReaded[num]) && (sum < BUTTON_CHATTERING_SIZE)) {
			isBufferPushed[num] = false;
			isBufferPushReaded[num] = false;
			memset(ucButtonChattering[num], 0, BUTTON_CHATTERING_SIZE);
		}
	}
}

void intervalButtonCheck() {
	if (intervalButtonTimer.check()) {
		unsigned int i = 0;
		for(i = 0; i < BUTTON_LENGTH;i++) {
			int buttonState	= digitalRead(ucButtonPortArray[i]);
			int buttonNum	= i;
			pushInputBuffer(buttonNum, buttonState == LOW);
		}
	}
}

bool isPushed(int button_num) {
	if(isBufferPushReaded[button_num]) {
		return false;
	}
	else if(isBufferPushed[button_num]) {
		isBufferPushReaded[button_num] = true;
		return true;
	}
	return false;
}

//-------------------------------------------

void setup() {
	Serial.begin(SERIAL_BITRATE);	 // パソコンとシリアル通信の準備を行う
	setupButton();
	setupDistanceSensor();
	lcd.begin(16,2);
	lcd.backlight();
//	lcd.noBacklight();
	lcd.clear();
	lcd.setCursor(0,0);
	lcd.print("start");
}

void printMessage(int x, int distance) {
	if(distance < 0) {
		distance = 0;
	}
	lcd.clear();
	lcd.setCursor(0,0);
	sprintf(strLcdBuffer, "[%d]", x);
	lcd.print(strLcdBuffer);
	lcd.setCursor(0,1);
	sprintf(strLcdBuffer, "%d cm", distance);
	lcd.print(strLcdBuffer);
}

void loop() {
	
	intervalButtonCheck();
	
	if (isPushed(BUTTON1)) {
		i++;
		beep();
		printMessage(i, getDistanceCm(DISTANCE_SENSOR1));
	}
}

以下のライブラリを使用しました。

おわりに

Arduinoは、ライブラリも豊富で内部の仕様をそんなに把握しなくても簡単にプログラムが作れて、とてもよいことが分かりました。

Raspberry Pi もいいですが、Arduinoでしか動作しない外部装置もあるので、部分的にArduinoを使って連携させてみるといいかもしれませんね。

コメント

タイトルとURLをコピーしました