【9月15日】mbed OMRONアプリNOTE丁寧です。_I2C Class Library 勉強

●OMRON D6F-PH アプリケーションNOTEがなくなってます。

=>2018年1月記
2016年には公開されていたのですが、公開がなくなってました。顧客へのサービスが低下してます。

=>2020年6月記
最近、PITO管風速センサの閲覧客が急増しているので、しばらくぶりにOMRON D6FPHのサイトへいくと
アプリケーションNOTEはなくなっているのですが、ユーザーマニュアルにプログラムの作り方が丁寧に記載されていることを発見しました。これを見ながらなら、自作できると思います。
OMRONの会員(無料)にならないとダウンロードできません。
https://www.fa.omron.co.jp/products/family/3213/download/manual.html

信州MAKERSでは、パワーメーター2020テーマの開発中ですが、人間の発生する全パワーを測定するシステム
ですが、次のテーマとして、ロードバイクにかかる走行抵抗いますをすべて測定するシステムを考えております。
風速センサ以外に走行抵抗を精度よく測定するセンサ技術を調査している段階ですが、走行抵抗が実走行時に
わかるとサイクリングがより楽しめるとおもいます。

————————————————————————————————————-
そこで、私のD6FPHサンプルプログラムを公開いたします。(mbedを使える方)
D6FPHをライブラリーなしで動作させてます。
SD書き込みと液晶表示のライブラリーをつかってますが読み飛ばしていただけば大丈夫です。
D6f-ph_make_armc5_lpc1768.zipをインポートしてください。

D6f-ph_make_armc5_lpc1768.zip

//実装接続プログラム2016/10/16 rev.1.0
//単一プログラムでライブラリー化せず
// ********************Wind meter*****************************
// Target LPC1768
// 1)ACM1602NI (I2C text LCD library)
// Takuo WATANABE (wtakuo)
// http://mbed.org/users/takuo/code/ACM1602NI/
// 2)SD FIle read/write
// Junichi Katsu “超お手軽マイコンmbed入門”P60~
//example writing to SD card, sford
// 3)Frequency Counter x2ch
// Neel Shah
//https://developer.mbed.org/users/Neel/code/Frequency_counter/
// 4)OMRON D6F-PH5050 I2C diff pressure meter
// Kunihiko Matsuhashi
//*************************************************************
//————————————Header ———————————–#include “mbed.h”
#include “ACM1602NI.h”
#include “SDFileSystem.h”
#define D6F_ADDR 0xD8 //I2Cアドレス定義
I2C i2c1(p28,p27);
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut pinout(p19);
ACM1602NI lcd(p28, p27);//I2C LCD
SDFileSystem sd(p5, p6, p7, p8, “sd”); // the pinout on the mbed Cool Components workshop board
Serial pc(USBTX, USBRX);//USB serial
InterruptIn in1(p16); //Wind sensor
InterruptIn in2(p15);//Wheel encoder
Timer t1;//for Wind sensor
Timer t2;//for Wheel encoder
//————————-const 定義————————————//
float t1_period = 0; // This is the period between interrupts in microseconds
float t1_freq = 0;
float t2_period = 0; // This is the period between interrupts in microseconds
float t2_freq = 0;
float Wind_speed=0;
float Wheel_speed=0;
float pitos=0;
float mitudo=0;
float tmpr=20;
float Cof=0.9;
int wtime=500;
static const char d6f_config[5]={0x00,0xD0,0x40,0x18,0x06};
static const char d6f_comp_read[4]={0x00,0xD0,0x51,0x2c};//差圧データx51hを指定
static const char d6f_temp_read[4]={0x00,0xD0,0x61,0x2c};//温度テータx61hを指定
static const char d6f_mem_read[1]={0x07};//リードレジスタx07hから読む
static const char d6f_init[2]={0x0B,0x00};//初期化レジスタx0Bhをx00でリセット
//—————————————————————————–
//初期化関数//uint8_t d6fph_strt(void) {
uint8_t error;//D6F-PHのレジスタ通信データを宣言・初期化する

error=i2c1.write(D6F_ADDR,d6f_init,2);
return(error);
}

//差圧読み込み関数//
float read_pressure(void) {
char error;
char rdata[2];
uint16_t raw_diff_pa;
float diff_pa;
error=i2c1.write(D6F_ADDR,d6f_config,5);
wait_us(33000);
error=i2c1.write(D6F_ADDR,d6f_comp_read,4);
error=i2c1.write(D6F_ADDR,d6f_mem_read,1,true);
error=i2c1.read(0xD9,rdata,2);
if (error){
return(error);
}
raw_diff_pa=(rdata[0]<<8)+rdata[1];
diff_pa=((float)raw_diff_pa-1024)/60-500;
return(diff_pa);
}
//温度読み取り関数//
float read_d6f_temp(void) {
char error;
char rdata[2];
uint16_t raw_ref_temp;
float ref_temp;

i2c1.write(D6F_ADDR,d6f_config,5);
wait_us(33000);
error=i2c1.write(D6F_ADDR,d6f_temp_read,4);
error=i2c1.write(D6F_ADDR,d6f_mem_read,1,true);
error=i2c1.read(0xD9,rdata,2);
if(error){
return(error);
}
raw_ref_temp=(rdata[0]<<8)+rdata[1];
ref_temp=((float)raw_ref_temp-10214)/37.39;
return(ref_temp);
}

//cout関数
void flip1(void)//TIMER WIND
{
led1=!led1;
pinout=!pinout;
t1_period = t1.read_us(); // Get time since last interrupt
//pc.printf(“t1_read_us=%5.1f\n”,t1_period);
t1_freq = (1/t1_period)*1000000; // Convert period (in us) to frequency (Hz)
t1.reset(); // Reset timer and wait for next interrupt
}
//——————————-
void flip2(void)//TIMER WHEEL
{
led2=!led2;
t2_period = t2.read_us(); // Get time since last interrupt
t2_freq = (1/t2_period)*1000000; // Convert period (in us) to frequency (Hz)
t2.reset(); // Reset timer and wait for next interrupt
}
//関数定義終わり—————————//

//————————-main—————————
// データ読みこみ毎にLEDが点滅する

int main() {
float prs;
int i=0;
prs=0;

mkdir(“/sd/mydir”, 0777);
in1.mode(PullDown); // Set the pin to Pull Down mode.
in1.rise(&flip1); // Set up the interrupt for rising edge
in2.mode(PullDown); // Set the pin to Pull Down mode.
in2.rise(&flip2); // Set up the interrupt for rising edge
t1.start(); // start the timer1
t2.start(); //start the timer 2
FILE *fp = fopen(“/sd/mydir/sdtest.csv”, “w”);
fprintf(fp,”Wind speed ,Pressure,temp,Wheelspeed,wtime%d\n”,wtime);
fclose(fp);

while(1){
wait_ms(wtime);

//Wind_speed=t1_freq*0.0577;
//if(t2_freq<0.31 or t2_freq>20) t2_freq=0;
//

Wheel_speed=t2_freq*0.11644;//2.096/18;

d6fph_strt();
prs=read_pressure();//差圧データ読んで代入////
tmpr=read_d6f_temp();//温度データ読んで代入//
mitudo=353/(273+tmpr);
pitos=Cof*sqrt(2*prs/mitudo);
lcd.locate(0,0);
lcd.printf(“Pito:Bike:<%2.1f>\r\n”,Wheel_speed-pitos);
lcd.locate(0,1);
lcd.printf(“%2.1f,%2.1f\r\n”,pitos,Wheel_speed);
//lcd.printf(“\r\n”);
pc.printf(“Pitos=%3.1f,tmp=%2.1f,pa=%2.1f\r\n”,pitos,tmpr,prs);

fp=fopen(“/sd/mydir/sdtest.csv”, “a”);
fprintf(fp,”%2.1f,%2.1f,%2.1f\n”,pitos,tmpr,Wheel_speed);
fclose(fp);
i++;
}
}

 

 

D6F-PHのアプリケーションNOTEを見てると、レジスタとプロトコルの説明図と更に見本プログラムが載ってました。これで、D6F-PHへのアクセス方法が分りました。mbed LibraryのBMP085のプログラムも、コメントが少ないD6F-PHのライブラリーを参考にしなくても大丈夫そうです。
①OMRON D6F-PH アプリケーションNOTE

=>2016年には公開されていたのですが、公開がなくなってました。顧客へのサービスが低下してます。

この図を見れば、データの流れとレジスタへのWRITEとREADをどうすればいいかがわかります。

サンプルプログラムがついてますが、いかんせんマイコンSTM32というマイコン用で組んであるのでmbedでは全く使えません。
しかし、アルゴリズムと関数の種類と構造はそのまま移植できますのでこれでプログラミングができそうです。

②mbed C++を作り始める
今までは、mbed ライブラリをコピーして、計算式を追記するだけでプログラムできていたのですが、今回は、初めてゼロから作成することになります。そこで、C++の初歩から勉強しながら1歩1歩進めてます。
#include “mbed.h”
からスタートです。今までmbedライブラリを空気の存在のように使ってましたが、いざ、ゼロからプログラムを書くとなるとC++の教科書とmbedのI2Cライブラリを比較しながら、1行1行コメントをいれながら進めてます。

i2c_classreference
ここからI2C.hへ飛んで、

i2c_h_top
一番最初に
namespace mbed{
が書いてありますので、これからはmbed内の名前を使っているということになります。

Class定義からConstructorの記述を見ると

    I2C(PinName sda, PinName scl);

となってました。CLASS名 I2CのConstructorに()引数がついてますので、クラス インスタンス作成時に引数をつけることでオブジェクトができます。
i2c_h_constructor

#include “mbed.h”

I2C  i2c(p5,p27);

/*クラスI2Cからインスタンス i2cを定義して、かつ引数ピンアサインを初期値として与え られます*/

たった2行ですが、これの意味を理解するのに、

①C++の教科書 「猫でもわかるC++プログラミング」
クラスとコンストラクタ 9章
②クラスとオブジェクトの解説記事 函館高専様の資料
http://www.hakodate-ct.ac.jp/~tokai/tokai/doc2009/proen/cpp-2.html
③MBED I2C LIBRARY REFERENCE
https://developer.mbed.org/users/mbed_official/code/mbed/docs/2e9cc70d1897/classmbed_1_1I2C.html
④mbed I2C.h
https://developer.mbed.org/users/mbed_official/code/mbed/docs/2e9cc70d1897/I2C_8h_source.html

を眺めながら、漸く納得できた次第ですので、これからも相当時間がかかると思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です