STM32G031でRS-485パケットで赤外線距離センサーの値を読み込みたい(センサー編





x まだ試していない　確認済み2022/5/17 17:32

目的
RS-485で上り下りの実現
複数話になる
どこまで行けるかわからないが作ってみよう


受信のテスト　(成功)


![o_con448.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/537fc1ec-2ad7-a4ca-8e6d-f4291bae861a.jpeg)


マスターでの送受信　(成功)

![o_con449.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/74b764e5-6d86-8325-7bee-44706028aec4.jpeg)




```c++



//ser_500kbps_ir_length_S_031_1


#include <Arduino.h>

// tx PA14(PB6) 8PIN
// rx PC14(PB7) 1PIN

#define  header   0x00
#define  address  0x40
#define  data1    0x00
#define  data2    0x00

#define  data3    0x00
#define  data4    0x00
#define  Checksum 0x00
#define  footer   0xff



#define DW   digitalWrite
#define TX1        PA12   // 6pin
#define UART_DELAY 106  // 002-110 9600bps ok 031

//仮想シリアルへの一文字出力 9600bps
void pc_putc(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

}//pc_putc





//文字列の表示
int pc_printf(char *str1) {

  //文字の中身がゼロか
  while (*str1) {

    //一文字出力
    pc_putc(*str1 ++);

  } //while

  //戻り値
  return (0);
}//pc_printf



void ir_length_reply(char id,char ch){

  int ii;           //カウンター
  char out_buff[8]; //バッファー

  //バケットに値を設定
  // packet move
  out_buff[1 - 1] = 0x00; //header
  out_buff[2 - 1] = 0xc0+id; //address
  out_buff[3 - 1] = 0x00; //data1  zero Fixed
  out_buff[4 - 1] = 0x00; //data2  zero Fixed

  out_buff[5 - 1] = 0x00; //data3  zero Fixed
  out_buff[6 - 1] = ch;   //data4  zero Fixed
  out_buff[7 - 1] = 0x00; //Checksum
  out_buff[8 - 1] = 0xff; //footer

  //チェックサムの計算
  //Checksum
  int chk = 0;
  for (ii = 0; ii < 8; ii++) {
    chk = chk + out_buff[ii];
  }//for
  out_buff[7 - 1] = chk & 0xff;

  //送信処理
  //send 8 byte
  delay(1);
  for (ii = 0; ii < 8; ii++) {
    Serial.write(out_buff[ii]);
  }//for
  delay(1);

} //ultrasound_reply


int u_key;      // 受信データを格納するchar型の変数
int ch_in_key() {

  // 受信データがあった時だけ、処理を行う
  while (!Serial.available()) {}      // 受信データがあるか？
  u_key = Serial.read();            // 1文字だけ読み込む

  return (u_key);
}


//80-20
unsigned char qq[] = {
  80, 78, 77, 76, 75, 75, 74, 73, 72, 71,
  70, 69, 68, 68, 67, 66, 65, 65, 64, 63,
  63, 62, 61, 61, 60, 60, 59, 58, 58, 57,
  57, 56, 56, 55, 55, 54, 54, 53, 53, 52,
  52, 51, 51, 50, 50, 50, 49, 49, 48, 48,
  47, 47, 47, 46, 46, 46, 45, 45, 45, 44,
  44, 44, 43, 43, 43, 42, 42, 42, 41, 41,
  41, 41, 40, 40, 40, 40, 39, 39, 39, 38,
  38, 38, 38, 37, 37, 37, 37, 37, 36, 36,
  36, 36, 35, 35, 35, 35, 35, 34, 34, 34,
  34, 34, 33, 33, 33, 33, 33, 32, 32, 32,
  32, 32, 32, 31, 31, 31, 31, 31, 31, 30,
  30, 30, 30, 30, 30, 30, 29, 29, 29, 29,
  29, 29, 28, 28, 28, 28, 28, 28, 28, 28,
  27, 27, 27, 27, 27, 27, 27, 27, 26, 26,
  26, 26, 26, 26, 26, 26, 25, 25, 25, 25,
  25, 25, 25, 25, 25, 25, 24, 24, 24, 24,
  24, 24, 24, 24, 24, 24, 23, 23, 23, 23,
  23, 23, 23, 23, 23, 23, 22, 22, 22, 22,
  22, 22, 22, 22, 22, 22, 22, 22, 21, 21,
  21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
  21, 20, 20, 20, 20, 20, 20, 20, 20, 20,
  20, 20, 20, 20, 20, 20
};

//20-10
unsigned char pp[] = {
  200, 199, 198, 197, 196, 196, 195, 194, 193, 193,
  192, 191, 190, 190, 189, 188, 187, 187, 186, 185,
  185, 184, 183, 183, 182, 181, 181, 180, 179, 179,
  178, 177, 177, 176, 176, 175, 174, 174, 173, 173,
  172, 171, 171, 170, 170, 169, 168, 168, 167, 167,
  166, 166, 165, 165, 164, 163, 163, 162, 162, 161,
  161, 160, 160, 159, 159, 158, 158, 157, 157, 156,
  156, 155, 155, 154, 154, 153, 153, 152, 152, 151,
  151, 151, 150, 150, 149, 149, 148, 148, 147, 147,
  147, 146, 146, 145, 145, 144, 144, 144, 143, 143,
  142, 142, 142, 141, 141, 140, 140, 140, 139, 139,
  138, 138, 138, 137, 137, 136, 136, 136, 135, 135,
  135, 134, 134, 134, 133, 133, 132, 132, 132, 131,
  131, 131, 130, 130, 130, 129, 129, 129, 128, 128,
  128, 127, 127, 127, 126, 126, 126, 125, 125, 125,
  125, 124, 124, 124, 123, 123, 123, 122, 122, 122,
  121, 121, 121, 121, 120, 120, 120, 119, 119, 119,
  119, 118, 118, 118, 117, 117, 117, 117, 116, 116,
  116, 116, 115, 115, 115, 114, 114, 114, 114, 113,
  113, 113, 113, 112, 112, 112, 112, 111, 111, 111,
  111, 110, 110, 110, 110, 109, 109, 109, 109, 108,
  108, 108, 108, 107, 107, 107, 107, 107, 106, 106,
  106, 106, 105, 105, 105, 105, 105, 104, 104, 104,
  104, 103, 103, 103, 103, 103, 102, 102, 102, 102,
  102, 101, 101, 101, 101, 101, 100, 100, 100, 100,
  100
};

//10-6
unsigned char oo[] = {
  100, 99, 98, 98, 97, 97, 96, 96, 95, 95,
  94, 94, 93, 93, 92, 92, 91, 91, 90, 90,
  90, 89, 89, 88, 88, 87, 87, 86, 86, 86,
  85, 85, 84, 84, 84, 83, 83, 82, 82, 82,
  81, 81, 81, 80, 80, 80, 79, 79, 78, 78,
  77, 77, 76, 76, 75, 75, 74, 74, 74, 73,
  73, 72, 72, 71, 71, 71, 70, 70, 69, 69,
  68, 67, 66, 66, 65, 64, 63, 63, 62, 61,
  61, 60, 60
};

//赤外線距離センサー(GP2Y0A21YK)の電圧から距離を求める。
//Voltage //電圧
int ir_len_i(int Voltage)
{

  int ir_length;   //長さ

  if (Voltage >= 0    && Voltage <= 400 ) {
    return (800);
  }
  if (Voltage >= 3120 && Voltage <= 5000) {
    return (60);
  }

  if        (Voltage >= 400 && Voltage <= 1300 ) { //80-20

    ir_length = (int)qq[(Voltage - 400) >> 2];
    ir_length = ir_length * 10;

  } else if (Voltage >= 1300 && Voltage <= 2300 ) { //20-10

    ir_length = (int)pp[(Voltage - 1300) >> 2];

  } else if (Voltage >= 2300 && Voltage <= 3120  ) { //10-6

    //ir_length = (int)oo[(Voltage - 2300) / 10];
    ir_length = (int)oo[  ((Voltage - 2300) * 205) >> 11 ]; //10の割り算

  }//end if

  //戻り値
  return (ir_length);

} //ir_le_i


//初期化処理
void setup() {

  delay(3000); //not Delete


  Serial.begin( 500000 ); // シリアル通信の速度を500000bpsにする。


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


  pc_printf("<ST>\r\n");


} //setup


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

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


//メインループ
void loop() {

  int ii;           //カウンター
  int pp;           //ポジション
  char out_buff[8]; //バッファー
  int chk;             //チェックサム
  char read_record[8];
  char x;          //一時領域

  char c_hex[] = {
    '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  };

  //b = 200; //debug

  //pc_printf("<ST>");

  while (1) {

    //第一バイト目
    //ヘッダー
    x = (char)ch_in_key();
    read_record[1 - 1] = x;
    //pc_printf("-H-");
    if (x != header ) break;

    //第二バイト目
    //アドレス
    x = (char)ch_in_key();
    read_record[2 - 1] = x;
    //pc_printf("-ADD-");
    if (x != (0x40 + 16) ) break;

    //第三バイト目
    //データの1
    x = (char)ch_in_key();
    read_record[3 - 1] = x;
    //pc_printf("-D1-");
    if (x != data1 ) break;

    //第四バイト目
    //データの2
    x = (char)ch_in_key();
    read_record[4 - 1] = x;
    if (x != data2 ) break;

    //第五バイト目
    //データの3
    x = (char)ch_in_key();
    read_record[5 - 1] = x;
    if (x != data3 ) break;

    //第六バイト目
    //データの4
    x = (char)ch_in_key();
    read_record[6 - 1] = x;
    if (x != data4 ) break;

    //第七バイト目
    //チェックサム
    x = (char)ch_in_key();
    read_record[7 - 1] = x;

    //チェックサムの計算
    //Checksum
    //read_record[1 - 1] = 0x00;
    //read_record[2 - 1] = 0x10;
    //read_record[3 - 1] = 0x00;
    //read_record[4 - 1] = 0x00;

    //read_record[5 - 1] = 0x00;
    //read_record[6 - 1] = 0x12;
    read_record[7 - 1] = 0x00;
    read_record[8 - 1] = 0xff;
    chk = 0;
    for (ii = 0; ii < 8; ii++) {
      chk = chk + read_record[ii];
    }//for
    read_record[7 - 1] = chk & 0xff;

    //チェックサムの処理　八バイト目はFFで固定　チェックサム自身は、00
    if (x != (chk & 0xff) ) break;


    //第八バイト目
    //フッター
    x = (char)ch_in_key();
    read_record[8 - 1] = x;
    if (x !=  footer ) break;



    //オールクリア
    //pc_printf("<OK>");
    //pc_printf("\r\n");


//超音波のデータの送り処理

    //マスターへの返信処理
    ir_length_reply(16,b);


    //デバッグ用出力に送信
    x=b;
    //ヘキサに値を設定
    // packet move
    out_buff[0] = '[';
    out_buff[1] = c_hex[(x >> 4) & 0x0f];
    out_buff[2] = c_hex[x & 0x0f];
    out_buff[3] = ']';
    out_buff[4] = 0x00;

    //送信処理
    //send 8 byte
    pc_printf(out_buff);
    pc_printf("\r\n");



  int sensorValue; //センサーの読み取り値
  int Voltage;     //電圧
  int ir_length;   //長さ

  //アナログ値の読み込み
  analogReadResolution(12); //adc 12bit mode
  //sensorValue = analogRead(A9); // PB7  PIN1 031
  sensorValue = analogRead(A3); // PA11 PIN5 031


  //アナログ値を電圧に変換
  Voltage = (sensorValue * 3300) >> 12; //stm32　(s*3300)/4096
  if (Voltage > 5000) {
    Voltage = 5000; //アナログ変換エラー対策
  }//end if
  if (Voltage < 0   ) {
    Voltage = 0;
  }//end if
  //Voltage = 1300;//debug


  //赤外線距離センサー(GP2Y0A21YK)の電圧から距離を求める。
  ir_length = ir_len_i(Voltage);

  //ir_length = 210;


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

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

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

  b = ir_length - 60;

  } else {

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

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

    break;

  }//while

  //pc_printf("<ST>");

  //delay(1000);

} //loop






```