目的
I2Cだと約20cmから約30cmと伝送距離が短いので
シリアルを使い伝送距離(約2mから3m)を延ばす。
STM32L010のスレーブ
//ser_slave_HC_SR04_010_1
#include "mbed.h"
//10の割り算 0から1028までは、正しい。主に0から999
#define DIV10(n) ((n*205)>>11)
DigitalOut TX(PA_2);
DigitalIn RX(PA_3);
#define UART_DELAY 101 // 1/9600 98-105
//仮想シリアルへの一文字出力 9600bps
int pc_putc(char ch)
{
TX=1;
TX=0;//Start
wait_us(UART_DELAY);
for(int ii=0; ii<8; ii++) { //Data x 8
TX=(ch>>ii)&1;
wait_us(UART_DELAY);
}; //for
TX=1;//Stop
wait_us(UART_DELAY);
return(0);
} //pc_putc
#define HIGH 1
DigitalOut TRIG(PA_6);
DigitalIn ECHO(PA_5);
//タイマーの設定
Timer t;
unsigned long times; //測定時間
int distance; //長さ
//PA_5のオン時間をusで測る 今のところ引数は、無効
int pulseIn(int pin1,int pu1,int timeout1)
{
t.reset();//タイマーの開始
//timeout1 = 32000000;
timeout1 = 100000; //28ms
//timeout1 = 1000; //degbu
//while(PA_5 == 0) {}
loop_s1:
timeout1--;
// 5432109876543210
if ( (~(GPIOA->IDR)) & 0b0000000000100000 ) {
if ( timeout1 ) {
goto loop_s1;
}
}
int sd = t.read_us();//測定開始
//timeout1 = 32000000;
timeout1 = 100000; //28ms
//timeout1 = 1000; //degbu
//while(PA_5 != 0) {}
loop_in1:
timeout1--;
// 5432109876543210
if ( (GPIOA->IDR) & 0b0000000000100000 ) {
if( timeout1 ) {
goto loop_in1;
}
}
return(t.read_us()-sd);//測定終了
}//pulseIn
unsigned char b=200; //マスターに返す値
//プロトタイプ宣言
void rx_Event();
//メインルーチン
int main()
{
//タイマーの開始
t.start();
TX=1; //ポートの初期化
//GPIOの初期化
TRIG = 0;
int input_bk;
int input;
//無限ループ
while(1) {
//開始信号の入力
input = RX;
//エッジ検出 信号が変わる
//立ち上がり、立下りの検出
if (input != input_bk) {
//立下り
if ( input == 0 ) {
wait_ms(2); //空読み時間
//b = '0';
//putcNS(b);
rx_Event();
}//end if
}//end if
//信号の保存
input_bk = input;
//0.5秒の待ち
//wait_ms(500);
}//while
}//main
void rx_Event()
{
//ソフトウェアシリアルから距離を出力
pc_putc(b);
/*
//I2Cスレーブの送信データの表示 num debug
int d = b; //buf[0];
//int d = b; //+ 60;
//int d = ir_length;
char data_read[4]; //バッファーの定義
data_read[3] = 0;
data_read[2] = '0' + ( d - (DIV10(d) * 10) ); // '0'+(d%10)
d = DIV10(d);
data_read[1] = '0' + ( d - (DIV10(d) * 10) ); // '0'+(d%10)
data_read[0] = '0' + DIV10(d); // '0'+(d/10)
pc_putc(data_read[0]);
pc_putc(data_read[1]);
pc_putc(data_read[2]);
pc_putc('\r');
pc_putc('\n');
*/
// 超音波を発生させる
TRIG=1;
wait_us(10);
TRIG=0;
// 超音波を受け取る
times = pulseIn( 5, HIGH,2000000);
//times = (unsigned long)7700/2; //debug
//times = 1177;//debug 1ms 20.0cm
//times = 942;//debug 1ms 16.0cm
//distance = (int)(times * 0.017);
distance = (int)((times * ((unsigned long)(17))) / 100);
//レンジ圧縮をして8ビット(256)に収める
//60mm から 200mmまでは、1mm単位
//60mm = 0 , 200mm = 140
//200mm から 800mmまでは、1cm単位
//200mm =140 , 800mm = 200
if ( distance <= 199 ) {
b = distance - 60;
} else {
b = (unsigned char)( DIV10(distance)-20+140 );
}//endif
//0.5秒の待ち
//wait_ms(500);
}//rx_Event
//容量削減
void error(const char* format, ...) {}
Arduino UNOのマスター
#include <Arduino.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
//初期化
void setup()
{
//シリアルポートの初期化
Serial.begin(9600);
//ソフトウェアシリアルの初期化
mySerial.begin(9600);
} //setup
//メインループ
void loop()
{
int l; //距離
unsigned char b = 200;
//読み込み
mySerial.print("S");delay(5); //トリガーを投げる
while( mySerial.available() ){
//Serial.println( mySerial.available() );//debug
b = mySerial.read();//受信
//Serial.println( b );//debug
}//while
if( b <= 0 ) b=0;
if( b >= 200 ) b=200;
//レンジ圧縮 140までは、mm 140からは、cm
if( b <= 139 ) {
l = b + 60;
} else {
l = ((int)(b - 140 + 20)) * 10;
}
Serial.print("800,");
Serial.print( l ); //UNO
Serial.print(",0");
Serial.println(" ");
delay(500); // 0.5秒の待ち
} //loop