STM32L010と内部ADCと温度センサーMCP9701で液晶表示


x MCP9701-E/TO 販売コード 103199

温度を表示

目的 
STM32L010(STM32L010F4P6)には、内部温度センサーがついていないので
秋月で売っている安価なMCP9701(約25円)を使って温度を液晶に表示する。

構成
MCP9701-E/TO I-03199
STM32L010F4P6 I-15689 
AQM0802A-RN-GBW P-06669

説明
MCP9701は、
0℃の時、400mV
1℃あたり19.5mV
精度は、±4℃
電線が引き出しやすい位置のP_4をアナログ入力にする
計算には、容量削減の為に浮動小数点と割り算は、使わない
電圧表示との違いは、メインの式
MCP9700は、ファミリー、オフセット500mV、10mV/1℃ 今回は、使わない

メインの式 すべては、だいたい
496は、400mV(0℃)をADCの値に変更した値
ex 20℃の場合
(200*65536)/65536=200
(200*65536)=13,107,200
13,107,200/27081=483
483+496=979

adcの値が979の時
483=979-496
13,080,123=483*27081
13,080,123/65536=199

ADCの電圧が3.3Vで分解度4096の時

3,300,000uV/4096=811uV
400mVの時
400,000uV/811uV=493
20℃の時のADCの値
19,500uV*20=392,000
392,000/811=483
483+493=976

```c++

s=((s-496)*27081)>>16;


```


参考
STM32L010と内蔵ADCで電圧を測る

https://qiita.com/caa45040/items/bdcbf2197b03a9ddab49

忙しい人よう

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

いろいろ改良後

```c++

#include "mbed.h"

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

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

#define ADDR_LCD    (0x7C)   //  address

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

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

char INIT_com[]={0x0,0x38,
0x0,0x39,
0x0,0x4,
0x0,0x14,
0x0,0x70,
0x0,0x56,
0x0,0x6C,
0x0,0x38,
0x0,0xC,
0x0,0x1,
0x40,0x41};

char INIT_cls[]={0x0,0x1};

char ch_hex_a_b[5];
char *ch_hex_a(int l_num)
{
    int a,b,c;

    b=DVI10(l_num);
    c=l_num-(b*10);
    l_num=b;
    a=DVI10(l_num);
    b=l_num-(a*10);

    ch_hex_a_b[0] = '@';
    ch_hex_a_b[1] = '0' + a;
    ch_hex_a_b[2] = '0' + b;
    ch_hex_a_b[3] = '0' + c;
    ch_hex_a_b[4] = 0;

    return(ch_hex_a_b);
} //ch_hex_a

int ii;  //ループカウンタ
int s;   //アナログ読み取り値

int main()
{
    //printf("767\r\n"); //767
    //液晶の初期化
    for(ii=0;ii<11;ii++){
        i2c.write(ADDR_LCD, &INIT_com[ii*2], 2);wait_ms(2);
    } //for
    
    //無限ループ
    while (1) {
        //液晶のクリア
        i2c.write(ADDR_LCD,INIT_cls,2);wait_ms(2);

        //adcの読み込み 0から4096
        s = (adc_vbat.read_u16()>>4);
        
        //電圧を温度に変換 ex 20.0 -> 200 温度の十倍を出力
        s=((s-496)*27081)>>16;

        //小数点以上と小数点以下を分ける
        ii=DVI10(s);  // 10の桁
        s =(s-(ii*10))*10; //  1の桁
        
        //温度の小数点以上の表示
        i2c.write(ADDR_LCD, ch_hex_a( ii ) ,4);

       //温度の小数点以下の表示
        ch_hex_a( s );
        ch_hex_a_b[1] = '.';
      //ch_hex_a_b[2] = '0' + s;
        ch_hex_a_b[3] = 'C';
        i2c.write(ADDR_LCD, ch_hex_a_b ,4);

        //1秒待つ
        wait_ms(1000);

    }//while

}//main

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


```

改良前

```

#include "mbed.h"

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

//16ビットadcの4ビットの変換テーブル
#define ADC4BIT { 0   , 62 ,125 ,187 ,250 ,312 ,375 ,437 ,500 ,562 ,625 ,687 ,750 ,812 ,875 ,937 }

AnalogIn adc_vbat(A3); //PA_4
//AnalogIn adc_vbat(A0); //767

#define ADDR        (0xD0)   //  address
#define ADDR_LCD    (0x7C)   //  address

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

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

char INIT_com[]={0x0,0x38,
0x0,0x39,
0x0,0x4,
0x0,0x14,
0x0,0x70,
0x0,0x56,
0x0,0x6C,
0x0,0x38,
0x0,0xC,
0x0,0x1,
0x40,0x41};

char INIT_cls[]={0x0,0x1};

char ch_hex_a_b[5];
char *ch_hex_a(int l_num)
{
    int a,b,c;

    b=DVI10(l_num);
    c=l_num-(b*10);
    l_num=b;
    a=DVI10(l_num);
    b=l_num-(a*10);

    ch_hex_a_b[0] = '@';
    ch_hex_a_b[1] = '0' + a;
    ch_hex_a_b[2] = '0' + b;
    ch_hex_a_b[3] = '0' + c;
    ch_hex_a_b[4] = 0;

    return(ch_hex_a_b);
}

int ii;     //ループカウンタ

int main()
{
    //printf("767\r\n"); //767
    //液晶の初期化
    for(ii=0;ii<11;ii++){
        i2c.write(ADDR_LCD, &INIT_com[ii*2], 2);wait_ms(2);
    } //for

//16bit init
//e    i2c.write(ADDR, "\230", 1); //16bit 15sps PGA x1

//    int p,s; //767
    int s;   //101
    
//    float Volts;
//    float Vref = 2.048 ;
    
///e    short bit4[]=ADC4BIT;
    
    while (1) {
        //液晶のクリア
        i2c.write(ADDR_LCD,INIT_cls,2);wait_ms(2);

        //adcの読み込み
        s = (adc_vbat.read_u16()>>4);
        
//        printf("-\n\r"); //767
//        printf(" A=%d\r\n",s); //767
//        //s=s-496;
//        //printf(" a=%d\r\n",s); //767

        //電圧を温度に変換 ex 20.0 -> 200 温度の十倍を出力
        s=((s-496)*27081)>>16;

//        printf(" c=%d\r\n",s); //767

        ii=DVI10(s);  // 10の桁
        s =(s-(ii*10))*10; //  1の桁

//        printf(" t=%d %d\r\n",ii,s); //767
        
        //温度の小数点以上の表示
        i2c.write(ADDR_LCD, ch_hex_a( ii ) ,4);

////        ch_hex_a( s );
////
////    ch_hex_a_b[1] = '.';
//////  ch_hex_a_b[2] = '0' + b;
////    ch_hex_a_b[3] = 'C';

////        i2c.write(ADDR_LCD, ch_hex_a_b ,4);

    //  (4096*165)/2048=330 電圧の100倍に変換
//    //s = 13;
//    p = (s*165) >> 11; 

//e        //データの読み込み
//e        i2c.read(ADDR | 1, data_read, 2);
//e        
//e        s = (data_read[0] * 256 ) + data_read[1];
//e        //s = 32767;
//e        printf("-s=%d %d %d\r\n",s,s>>4,(((s>>4)-400)*10)/195); //767
//e        printf(" h=%d\r\n",data_read[0]); //767
//e        printf(" l=%d\r\n",data_read[1]); //767

//        Volts = s * Vref / 32767.0f ;
//        printf(" f=%f\r\n",Volts );

//e        ii = ( (s >> 4) * 1000 )  + (bit4[ s & 0xf ]) ; //767
//e        printf(" q= %d\r\n",ii); //767
//e
//e //s=(65536/2/2/2)+1;
//e
//e ii=(s >> 4);
//e if     ( ii >= 2000 ) { ii = ii - 2000; /*printf("2.\n\r");*/   i2c.write(ADDR_LCD,"@2.",3); }
//e else if( ii >= 1000 ) { ii = ii - 1000; /*printf("1.\n\r");*/   i2c.write(ADDR_LCD,"@1.",3); }
//e else                  {                 /*printf("0.\n\r");*/   i2c.write(ADDR_LCD,"@0.",3); }
//e
//e //printf(" o=%s\r\n",ch_hex_a( ii )                );
//e i2c.write(ADDR_LCD, ch_hex_a( ii ) ,4);
//e 
//e //printf(" o=%s\r\n",ch_hex_a( (bit4[ s & 0xf ]) ) );
//e i2c.write(ADDR_LCD,ch_hex_a( ( (int)bit4[ s & 0xf ]))  ,4);

//        // 32768/(163.84/2)=400 luxに変換
//        p=( ((s>>5)*6)  + (s>>7)  ) >> 4;
//        //printf(" p=%d\r\n",p); //767
//        
//        i2c.write(ADDR_LCD, ch_hex_a( p ) ,4);

        wait_ms(1000);
    }//while

}//main

void error(const char* format, ...){}


```