STM32L010のI2CスレーブモードでGP2Y0A21YK(赤外線距離センサー)の値をマスターで受信する。



目的
I2Cのテスト
距離センサーのI2C化
I2C間通信の応用
赤外線距離センターを使い距離を測る。


![o_con349.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c242f1d2-8b52-9d52-972b-f36f2dbd76c2.jpeg)



忙しい人よう


https://os.mbed.com/users/caa45040/code/i2c_slave_ir_length_010_1/


バイナリー


https://os.mbed.com/users/caa45040/code/f303_h_p1//file/886e1432b0a3/i2c_slave_ir_length_010_BIN/



スレーブのプログラム

mbed2リビジョン130


```c++



//i2c_slave_ir_length_010_1


#include "mbed.h"


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

/*
DigitalOut TX(PB_1);

//仮想シリアルへの一文字出力 1200bps
int pc_putc(char ch)
{
    TX=1;
    TX=0;//Start
    wait_us(832);

    for(int ii=0; ii<8; ii++) { //Data x 8
        TX=(ch>>ii)&1;
        wait_us(832);
    }; //for

    TX=1;//Stop
    wait_us(832);

    return(0);
} //pc_putc
*/

//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


//アナログ入力の設定
AnalogIn adc_vbat(A3); //PA_4

unsigned char b=200; //マスターに返す値

//I2Cの初期化
I2CSlave slave(PA_10, PA_9); //010

//メインルーチン
int main()
{

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


    //TX=1; //ポートの初期化

    char buf[10];//I2Cバッファー

    //I2Cスレーブのアドレスの設定
    slave.address(0x10);

    //無限ループ
    while(1) {

        //I2Cの状態の読み出し(ポーリング)
        while(  slave.receive()  == I2CSlave::ReadAddressed   ) {};


        buf[0] = b;

        //I2Cマスターに送信する
        slave.write(buf,1);

/*

        //I2Cスレーブの送信データの表示 num debug
        int d = b; //buf[0];
        char data_read[3]; //バッファーの定義
        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');
*/

        //アナログ値の読み込み  0から4096
        sensorValue = (adc_vbat.read_u16()>>4);
        //sensorValue = 1024;

        //アナログ値を電圧に変換
        Voltage = (sensorValue * 3300) >> 12; //stm32　(s*3300)/4096
        //Voltage = 2300; //debug

        ir_length = ir_len_i(Voltage);


        if ( ir_length <= 199 ) {

            b = ir_length - 60;

        } else {

            b = (unsigned char)(   DIV10(ir_length)-20+140 );

        }


        //0.5秒の待ち
        //wait_ms(500);

    }//while

}//main


//容量削減
void error(const char* format, ...) {}






```



マスターのプログラム

mbed2リビジョン125


```c++


//i2c_master_ir_length_031_1

#include "mbed.h"

//I2C i2c(I2C_SDA, I2C_SCL); //767
//I2C i2c(dp5, dp27); //1114
I2C i2c(PA_10, PA_9); //010


//Serial pc(USBTX, USBRX); // tx, rx
//Serial pc(SERIAL_TX, SERIAL_RX); //767
RawSerial pc(PA_2, PA_3); //010

//#define S5851A 0x48
#define ADDR        (0x10)   //  address

int main() {

    char data_read[8]; //バッファー

    //無限ループ
    while(1){

        //dataの読み込み
        i2c.read(ADDR, data_read,1,false);

        //データの保存
        int b =  data_read[0]; //dataの転記
        if(b >= 200) {b = 200;}
        if(b <= 0)   {b = 0;  }
        
        
        //レンジ圧縮で140でレンジ切り替え
        int l;
        if( b <= 139 ) {
            l = b + 60;
        } else {
            l = ((int)(b - 140 + 20)) * 10;
        }  
        

        //画面に表示
        //pc.printf("Read : %x\r\n",l);
        //pc.printf("Read : %d\r\n",l);
        pc.printf("%d\r\n",l);

        //1/100秒待つ
        wait_ms(10);

    }//while

}//main

//容量削減
void error(const char* format, ...){}




```





関連 Arduinoのマスタープログラム



```c++



//i2c_master_HC_SR04_UNO_1

//インクルド
#include <Arduino.h>
#include <Wire.h>

//初期化
void setup()
{

  //シリアルポートの初期化(9600bps)
  Serial.begin(9600);

  //I2Cの初期化
  Wire.begin(); //UNO

} //setup


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

  int  l;                //距離
  unsigned char b = 200; //レンジ圧縮の値

  //I2C読み込み
  Wire.requestFrom(8, 1);
  while(Wire.available())  { // 要求より短いデータが来る可能性あり
    b = Wire.read();         // 1バイトを受信
  }//while

  //レンジ圧縮をして8ビット(256)に収める
  //60mm から　200mmまでは、1mm単位
  //60mm = 0 , 200mm = 140
  //200mm から　800mmまでは、1cm単位
  //200mm =140 ,  800mm = 200
  if( b <= 139 ) {
    l = b + 60;
  } else {
    l = ((int)(b - 140 + 20)) * 10;
  }//endif

  //距離の表示
  Serial.print("800,");
  Serial.print( l ); //UNO
  Serial.print(",0");
  Serial.println(" ");
  delay(500); // 0.5秒の待ち

} //loop




```