LPC1114 製作
1 気圧計
2 データロガー
1 気圧計 2018.10.10( 2016.10.27 2016.04.17 2016.03.26)
これまでLPC1114について、キャラクタLCDによる表示、BMP180気圧・温度センサーとのI2C通信、同じくI2C通信によるeeprom(M24C64)の利用についてテストしてきました。これらを総合して一つのロガー付き気圧計としてまとめることを考えました。
スペックとしては、LCDに気圧(hPaで整数値)、温度(℃で小数1位まで)を10秒に1回表示して、記録のためにRTCを載せているので年月日と時分を同時に表示することにします。変更→月日と気圧・温度データを記録。1時間に1回のため時はなくても見当がつきます。
記録についてはeepromにM24C64を用いて、1時間に一度測定値を記録します。フォーマットは、第一バイトに気圧(hPa)-900、第二バイトに温度*10の上位8ビット、第三バイトには1ビット目に温度*10の最下位ビット、残りの7ビットに月を、第四ばいとには日を入れることにしました。気圧は900hPaシフトして使いますので900〜1125の範囲が記録できます。温度は測定値の10倍の整数値を記録しますので0.0℃〜51.2℃が記録されるはずです。室温専用のため零下の温度は考えていません。
eepromの容量は64kbit=8kBですから、4バイトデータが2048個記録できることになります。1時間に1データですから2048/24≒85日保存できます。サンプリングの間隔が1時間もありますから、resetごとに0番地から記録します。間違ってリセットしても次の00分まではデータが失われないので注意すれば喪失の心配はないと思います。TeraTeamにつながる環境であればデータを取り出すことができます。
(上記を変更しています。データ記録時に、次のアドレストップに 0 を書いています。リセットで再開するときは、このゼロの番地を探してそこから書き始めます。したがって、最も古いデータから上書きされます。読み出し時は 0 のすぐ手前が最新のデータとなります。)
リセット時の動作ですが、リセットスイッチだけを押した場合は、MCとeepromがリセットされて測定を始めます。TeraTermにつないでメニュースイッチを押した状態でリセットするとメニューが現れて、1測定 2時刻合わせ 3記録データの読み取り ができます。
ブレッドボード上で完成の域まで組み立てました。BPM180のシステムはArduinoもどきで動きましたので、Arduino型で万能基板に組み立てましたが、5Vでの実行は問題がないのですが、LCDに負電源を組み込んで3.3V動作にするとなぜかLCDが正常に動作しません。電圧を上げて4.3VにするとLCDの表示が正常になります。どこが悪いのか調べねばなりませんが、最終的にリチウムイオン電池で動作させたいので3.3V動作は必要になります。(あとで分かりました。BODを4.3Vに設定した古いAVRを使っていました。)
気圧計としてはmbed LPC1114で組み上げることにしました。
3.3VはTAR5SB33という超小型(実装に苦労しました)のLDOレギュレータを使いました。これは入力に3.3Vを加えても3.1Vの出力があり、3.3Vシステムが正常に動作します。
(2018.10.10追記)何故かEEPROMの記録がおかしいのでプログラムを見直しました。もとのソースをコンパイルして動作を確認しました。なお、容量の関係で月日はあるのですが時刻がありません。継続記録のときは1日24回で時刻がわかるのですが、リセットしたときに最初の書き込みルーチンが時刻に関係なく働いてしまいます。リセットごとに余分な記録がなされ、かつ、どれが余分なのかわかりません。そこで、saisho という変数を定め、最初は 0 で、時刻判定ルーチンが正常に働くときになれば 1 となるよう設定して、1 のときだけ記録するよう変更しました。これで、1日に24回を超える記録はされないことになります。
プログラムです。(2016.10.27 一部変更しました)→再度変更しました。2018.10.10
/* *************************************************************
barometer03
"barometer bmp180 ds3232 24LC64" 2016.04.08
LPC1114FN28 connection
1 LCD.RS(brown) 28 -sw-GND pullup 4k7 on = reset -> menu
2 LCD,E (yellow) 27 I2C.SCK I2C:pullup 10k
3 26 LCD.d7(white)
4 25 LCD.d6(gray)
5 I2C.SDA 24 mode sw ->GND on = program I2C:pullup 10k
6 23 reset
7 AVcc 22 GND
8 AGND 21 Vcc
9 20
10 19
11 18 LCD.d5(vioret)
12 17 LCD.d4(green)
13 16 serial.TX
14 15 serial.RX
I2C: DS3232(RTC) addr=0xd0(8bit)
BPM180(press sensore)
24LC64(eeprom) addr=0xa0(8bit)
include file: "BMP180.h" Copyright (c) 2014 Kenji Arai / JH1PJL
"TextLCD.h" Copyright (c) 2007-2010, sford, http://mbed.org Simon Ford
************************************************************* */
#include "mbed.h"
#include "BMP180.h" // Own lib. / Pressure sensor
#include "TextLCD.h"
TextLCD lcd(dp1, dp2, dp17, dp18, dp25, dp26); // rs e d4 d5 d6 d7
Serial pc(dp16,dp15); // UART (vertual COM)
I2C i2c(dp5,dp27); // SDA, SCL
BMP180 bmp180(dp5,dp27); // Bosch sensor
DigitalIn sw(dp28);
int main()
{
char menu,i;
char s[20],d[10],dd[10];
uint8_t day,hour,min,sec,year,month,u0,u1,v0,v1;
uint8_t saisho=0;
uint16_t pt,press,temper;
u0=1,v0=1;
// search eeprom data 0 for pt
pt=0;
/**/
for(int ii=0; ii<8100; ii++) {
s[0]=ii/256;
s[1]=ii%256;
i2c.write(0xa0,s,2,true);
i2c.read(0xa0|1,d,1);
if(d[0]==0) {
pt=ii;
break;
}
}// for ii
/**/
while(1) {
if(sw==0) { // display menu at dp28 is Low (0)
// ------- menu -----------------
pc.printf("--- MENU ---\n\r");
pc.printf(" 1 Clock on LCD\n\r");
pc.printf(" 2 Set Time\n\r");
pc.printf(" 3 Read Data (TeraTeam)\n\r");
pc.printf(" 1 -- 3 ? ");
menu=pc.getc();
pc.printf("\n\r");
} else {
menu='1';
}
while(1) { //--1
if(menu=='1') { // menu 1 desplay time 1111111
pc.printf(" Clock on LCD\n\r");
while(1) { //--2
s[0]=0;
s[1]=0;
i2c.write(0xd0,s,1,true);
i2c.read(0xd0|1,d,7);
year=(d[6]/16)*10+d[6]%16;
month=(d[5]/16)*10+d[5]%16;
day =(d[4]/16)*10+d[4]%16;
hour=(d[2]/16)*10+d[2]%16;
min =(d[1]/16)*10+d[1]%16;
sec =(d[0]/16)*10+d[0]%16;
lcd.writeCommand(12); //cursor off
wait(0.05); //cursor off
lcd.locate(0, 0);
lcd.printf("%d/%2d/%2d ",year,month,day);
lcd.locate(0, 1);
lcd.printf("%2d:%02d:%02d ",hour,min,sec);
u0=u1;
u1=sec/10; //
if(u1!=u0) { // per 10secs lcd display pressure
// ---------- Barometer Sensor / BMP180 ---------------
bmp180.normalize();
lcd.locate(10,0);
lcd.printf("%4.0f ",bmp180.read_pressure()+4.4);
lcd.locate(10,1);
lcd.printf(" %2.1f ",bmp180.read_temperature() );
}
#if 1 // rec EEPROM per 1 hour
//v0=v1; v1=min; //for test
v0=v1; v1=hour;
if((v0!=v1)&&(saisho!=0)) { // memory an hour or a min
//if(hour!=time) { // memory an hour
press=bmp180.read_pressure()+4.4;
temper=(bmp180.read_temperature()*10.0);
//pdata=(press-940)*512+temper;
dd[0]=press-900;
dd[1]=temper/2;
dd[2]=(temper%2)*128+month;
dd[3]=day;
if(pt>8100)pt=0;
for(char j=0; j<4; j++) {
s[0]=pt/256; // inner address H
s[1]=pt%256; // inner address L
s[2]=dd[j];
i2c.write(0xa0,s,3);
wait_ms(6);
pt++;
}
// write maker 0
dd[0]=0;
dd[1]=0;
dd[2]=0;
dd[3]=0;
for(char j=0; j<4; j++) {
s[0]=pt/256; // inner address H
s[1]=pt%256; // inner address L
s[2]=dd[j];
i2c.write(0xa0,s,3);
wait_ms(6);
pt++;
}
pt-=4;
// end write maker 0
}// if(d[1]==0)
saisho=1;
#endif
}// end of while 2
}//end of if--1
if(menu=='2') { // menu 2 time set 22222
pc.printf("Input yymmddwhhmmss on 24H\n\r");
wait(0.5);
for(i=0; i<13; i++) {
s[i]=pc.getc();
}
// inner address d[0]=0 then d[1]=ss . address +1 shift
d[7]=(s[0]-'0')*16+(s[1]-'0'); // yy
d[6]=(s[2]-'0')*16+(s[3]-'0'); // mm
d[5]=(s[4]-'0')*16+(s[5]-'0'); // dd
d[4]=(s[6]-'0'); // day of week
d[3]=(s[7]-'0')*16+(s[8]-'0'); // hh
d[2]=(s[9]-'0')*16+(s[10]-'0'); // mm
d[1]=(s[11]-'0')*16+(s[12]-'0'); //ss
d[3]=d[3]&0B10111111; // set 24h
d[0]=0;
//i2c.write(addr1);
i2c.write(0xd0,d,8);
menu='1';
}//end of if menu=2
if(menu=='3') { // read out EEPROM
pc.printf("read data...\n\r");
pt=0;
for(int i=0; i<2000; i++) {
s[0]=pt/256;
s[1]=pt%256;
i2c.write(0xa0,s,2,true);
i2c.read(0xa0|1,dd,4);
press=dd[0]+900;
temper=((dd[1]*2)+(dd[2]/128));
month=dd[2]%128;
day=dd[3];
pc.printf("%02d, %02d, %04d, %02.1f \n\r",month,day,press,temper/10.0);
pt+=4;
}
}// end of if(menu=='3')
menu='1';
}//end of while1
}
}
心配したプログラム量ですが 19kB に収まりました。
1 気圧計 終わり
2 データロガー 2016.9.05
データロガーというほどのものではありません。時刻と気圧・温度の記録をSDカードに書き込みたかったのですが、ライブラリが重くlpc1114には乗らないことがわかりました。SDカードだけで26kBほどのROMを消費します。簡単な記録だけですからもっと軽いライブラリがあればよいのですが探しだせませんでした。(mbedは本来大きなROMを持ったシステムですからしかたがないのかもしれません)
そこでシリアル通信回路を利用して、'q'という文字で始まり'\n'で終わる文字列をRXDに受けると'q'をブランクに変えて、その文字列の1行をテキストファイルに書き込む記録装置を作りました。
シリアル通信回路はすべてのマイコンが持ち、利用しやすいことから採用しました。文字qはとくに意味は無いのですが他へ送る通信内容と区別するために用いています。
稼動状態で書き込みが正常に行なわれたどうかを確認する方法がありませんが、多分大丈夫だろう、ということにしています。
プログラムはEEPROMに比べると簡単です。なお、mbedライブラリは 121:6c34061e7c34 でないとエラーとなり、up date の最新版ではダメなことがわかりました。SDFilesystemライブラリは、Micah B 作者のものを使用しました。同名のライブラリがいくつかありますが他のものではエラーになることがありました。まだ、センサーMCPと接続していませんが、PCからTeraterm経由のものは正しく記録しています。
// serial2sd\main.cpp (2018.10.11修正)
#include "mbed.h"
#include "SDFileSystem.h"
#include "Serial.h"
SDFileSystem sd(dp2,dp1,dp6,dp9, "sd"); // MOSI, MISO, SCLK, SSEL
Serial pc(USBTX, USBRX);
DigitalOut led(LED1);
int main()
{
char s[35];
uint8_t i=0;
led=0;
FILE *fp = fopen("/sd/mbed.txt", "a");
wait(0.1);
fclose(fp);
while(1) {
pc.printf(" put string\n\r");
i=0;
while(i<32){
if(pc.readable()){
s[i] = pc.getc();
if(s[i]==13)break;
i++;
}
}
s[i+1]=0x00;
i=0;
while(s[i] != 13) {
pc.putc(s[i]);
i++;
}
pc.printf("\n");
#if 1
led=1;
if(s[0]=='q') {
s[0]=' ';
FILE *fp = fopen("/sd/mbed.txt", "a");
fprintf(fp, "%s",s);
// fprintf(fp, "Hello World! %s ",s);
fclose(fp);
}
led=0;
#endif
wait(0.5);
}
}
2 データロガー 終わり
工事中
2 予 定 2016.00.00
2 予 定 終わり