いずれ消え行く無駄な情報を、密やかに発信する装置。つまり日記。
Raspberry Piと秋月電子で販売されている大気圧センサーのSCP1000を使用して大気圧計を作成しました。
使用したLinuxはdebianで、以下のバージョンです。
pi@raspberrypi ~/work/lcd $ uname -a Linux raspberrypi 3.12.22+ #691 PREEMPT Wed Jun 18 18:29:58 BST 2014 armv6l GNU/Linux
SPIを有効化するにはraspi-configコマンドを使用します。
pi@raspberrypi ~/work/lcd $ sudo raspi-config [8 Advanced Options -> A5 SPI -> Yes]
SCP1000はSPIインターフェースを備えています。以下の通り配線を行いました。どちらも物理ピン番号を記載しています。
[scp1000] - [RaspberryPi] 3pin(SCK) - 23pin(SCKL) 4pin(GND) - 25pin(GND) 5pin(MOSI) - 0.01uF - 19pin(MOSI) 6pin(MISO) - 21pin(MISO) 7pin(CSB) - 24pin(CE0) 8pin(VCC) - 17pin(3.3v)
本来、上記接続で問題なく接続できるはずですが、Raspberry Piからどんなコマンドを送っても、読み出すと0x00又は0xFFの値しか返ってこない状態となりました。そこで、SCP1000側のMOSIの近くに0.01uFを挟むと4回に1回程度ですが信号が届くようになりました。原因は不明ですが、ブレッドボードで接続しているため、ノイズ等の影響を受けて不安定になっている可能性があります。
表示デバイスは、秋月電子で販売されているSC2004CSWB-XA-LB-Gを使用しました。このデバイスは、4行x20桁が表示でき、バックライトに白色LEDを備えています。接続は以下の通り行っています。
[LCD] - [RaspberryPi] 1pin(VSS) - 3pin(GND) 2pin(VDD) - 1pin(3.3v) 3pin(Vo) - 2kΩ - 14pin(GND) 4pin(RS) - 16pin(GPIO23) 5pin(R/W) - 5pin(GND P5-Header) 6pin(E) - 18pin(GPIO24) 11pin(DB4) - 11pin(GPIO17) 12pin(DB5) - 12pin(GPIO18) 13pin(DB6) - 13pin(GPIO21) 14pin(DB7) - 15pin(GPIO22) [LCD LED] - [Raspberry Pi] A - 2pin(5v) K - 180Ω - 20pin(GND)
なお、コントラスト調整用のボリュームは測定すると1.98kΩでした。
また、LEDの駆動電源は5Vを用いています。Raspberry Piの3.3vピンは電流の制限値があることから、USBコネクタと直接つながっている5Vを使用し、制限抵抗は180Ωを用いました。
動作が安定しなかったため初期化に失敗した場合は、再試行を繰り返す動作にしています。一度でも正しく値を送信できると、極めて安定して気圧データを取得することができました。MOSIにコンデンサを挟むことで安定性が多少増しましたが、以下のコードの初期化の処理が誤っている可能性もあります。参考程度に留めておいて下さい。
#include<wiringPiSPI.h> #include<wiringPi.h> #include<stdio.h> #include<time.h> #include<lcd.h> #define SPI_CHANNEL 0 #define SPI_CLK 500000 int main(void){ double temp = 0; double pressure = 0; unsigned char buf[3]; char str[24]; time_t time_now; struct tm *local_time; int i,fd,flag1=0, flag2=0; //wiringPiライブラリの初期化 if (wiringPiSetup () == -1){ return (1) ; } /* LCDデバイスの初期化 */ if((fd = lcdInit(4,20,4, 4,5, 0,1,2,3,0,0,0,0)) < 0){ printf("[Error] open lcd device\n"); return(-1); } //SPIデバイスの初期化 if((wiringPiSPISetup(SPI_CHANNEL, SPI_CLK))<0){ printf("error SPI\n"); } //初期処理。失敗した場合は繰り返す。 while(1){ flag1 = 0; flag2 = 0; //時間の表示 time_now = time(NULL); local_time = localtime(&time_now); strftime(str, sizeof(str), "%Y/%m/%d %a %H:%M:%S", local_time); printf("%s\n", str); //ソフトリセットコード buf[0] = 0x1a; buf[1] = 0x01; wiringPiSPIDataRW(SPI_CHANNEL, buf, 2); printf("delay...\n"); delay(60); //STATUS確認 buf[0] = 0x1c; buf[1] = 0xff; wiringPiSPIDataRW(SPI_CHANNEL, buf, 2); printf("STATUS:%02x\n", buf[1]); i= buf[1]&0x01; if(i == 0){ flag1 = 1; printf("STATUS OK!\n"); } //DATARD8確認 buf[0] = 0x7c; buf[1] = 0xff; wiringPiSPIDataRW(SPI_CHANNEL, buf, 2); printf("DATARD8:%02x\n", buf[1]); i= buf[1]&0x01; if(i == 1){ flag2 = 1; printf("DATARD8 OK!\n"); } if(flag1==1 && flag2==1){ printf("START...\n"); break; } } //オペレーションレジスタに高精度測定モードを設定 buf[0] = 0x0e; buf[1] = 0x0a; wiringPiSPIDataRW(SPI_CHANNEL, buf, 2); //メインループ while(1){ //温度の測定 buf[0] = 0x84; buf[1] = 0x00; buf[2] = 0x00; wiringPiSPIDataRW(SPI_CHANNEL, buf, 3); temp = (double)((buf[1] << (8+2)) + (buf[2] << 2)) / 20 / 4; //気圧の測定 buf[0] = 0x7c; buf[1] = 0x00; wiringPiSPIDataRW(SPI_CHANNEL, buf, 2); pressure = buf[1] << 16; buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x01; wiringPiSPIDataRW(SPI_CHANNEL, buf, 3); pressure += (buf[1] << 8) + buf[2]; pressure = pressure / 4 / 100; //時間の取得 time_now = time(NULL); local_time = localtime(&time_now); //LCD表示 lcdClear(fd); lcdPosition(fd,0,0); strftime(str, sizeof(str), "%Y/%m/%d %a", local_time); lcdPrintf(fd, "DATE=%s", str); lcdPosition(fd,0,1); strftime(str, sizeof(str), "%H:%M:%S", local_time); lcdPrintf(fd, "TIME=%s", str); lcdPosition(fd,0,2); lcdPrintf(fd, "TEMP=%2.2f[C]", temp); lcdPosition(fd,0,3); lcdPrintf(fd, "PRESS=%4.4f[hPa]", pressure); delay(1000); } }
合同会社パレットソフト:気圧センサ SCP1000 (試食)