STM32G031と超音波距離センサーHC-SR04でソフトウェアシリアルバイナリ通信



x OBでPA0をGPIO がわかる人むけ


目的
I2Cだと約20cmから約30cmと伝送距離が短いので
シリアルを使い伝送距離(約2mから3m)を延ばす。


![o_con384.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5ca48ce2-1dc4-d2ac-7a91-95c00193613b.jpeg)



STM32G031のスレーブ


```c++


//ser_slave_HC_SR04_031_1


//1ピン PB7 Echo
//2ピン Vdd
//3ピン Gnd
//4ピン PA0 TX


//5ピン PA14 SWD-CL
//6ピン PA13 SWD-DA
//7ピン PA12 Trig
//8ピン PA11 RX   

#include <Arduino.h>


#define RX1        PA11   // 8pin


#define TRIG PA12
#define ECHO PB7

unsigned long times; //測定時間
int distance;        //長さ


#define DW   digitalWrite
#define TX1        PA0   // 4pin
#define UART_DELAY 106  // 012-110 9600bps ok 031

//仮想シリアルへの一文字出力 9600bps
void putcNS(char ch)
{
  DW(TX1, HIGH);

  DW(TX1, LOW);//START
  delayMicroseconds(UART_DELAY); //START BIT WAIT

  for (int ii = 0; ii < 8; ii++) {
    DW(TX1, (ch >> ii) & 1  );
    delayMicroseconds(UART_DELAY); //DATA 1-8BIT WAIT
  }//for

  DW(TX1, HIGH);//Stop
  delayMicroseconds(UART_DELAY); //StOP BIT WAIT

}//putcNS


void setup() {

  //TXポートの初期化
  pinMode(TX1, OUTPUT);
  DW(TX1, HIGH);

  //開始、立下りトリガー
  pinMode(RX1, INPUT);

  //超音波距離センサーのポートの設定
  pinMode(TRIG, OUTPUT); digitalWrite(TRIG, LOW);
  pinMode(ECHO, INPUT);

}//setup


//10の割り算 0から1028までは、正しい。主に0から999
#define DIV10(n) ((n*205)>>11)

byte b = 200; // ((s-140)*10)+200 -> 800


void loop() {

//debug
//while(1){
//  rx_Event();
//  delay(500);
//}//while

  int input_bk;
  int input;
  //無限ループ
  while (1) {

    //開始信号の入力
    input = digitalRead(RX1);

    //エッジ検出　信号が変わる
    //立ち上がり、立下りの検出
    if (input != input_bk) {

      //立下り
      if ( input == LOW ) {
        delay(2); //空読み時間

        //b = '0';
        //putcNS(b);
        rx_Event();
      }//end if

    }//end if

    //信号の保存
    input_bk = input;

  }//while

}//loop


void rx_Event() {

  //PB7  入力
  //PA12 出力
  //RX  PA11  11ピン G031
  //TX  PA0    4ピン G031

  //ソフトウェアシリアルから距離を出力
  putcNS(b);

/*
  //debug
  char rt[16];
  rt[2] = '0' + (b - DIV10(b) * 10);
  b = DIV10(b);
  rt[1] = '0' + (b - DIV10(b) * 10);
  rt[0] = '0' + DIV10(b);
  putcNS(rt[0]);
  putcNS(rt[1]);
  putcNS(rt[2]);
  putcNS('\r');
  putcNS('\n');
  //delay(1000);
*/

  // 超音波を発生させる
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);


  // 超音波を受け取る
  times = pulseIn(ECHO, HIGH,2000000);
  //times = (unsigned long)(7700/2); //debug 650cm
  //times = 1177;//debug 1ms 20.0cm
  //times = 942;//debug 1ms 16.0cm

  //distance = (int)(times * 0.017);
  distance = (int)((times * ((unsigned long)(17))) / 100);
  //distance = 321; //debug

  //レンジ圧縮をして8ビット(256)に収める
  //60mm から　200mmまでは、1mm単位
  //60mm = 0 , 200mm = 140
  //200mm から　800mmまでは、1cm単位
  //200mm =140 ,  800mm = 200

  //オーバーの値を丸める
  if( distance >= 800 ){ distance = 800;}
  if( distance <= 60  ){ distance = 60 ;}

  // 200mmより　小さいか?
  if ( distance <= 199 ) {

  b = distance - 60;

  } else {

  b = (byte)( DIV10(distance) -20 + 140 );//DIV10(x)==x/10
  
  }//endif

  //b = 200;//debug
  //b = '0';//debug

}//rx_Event






```

Arduino UNOのマスター


```c++



#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








```