カテゴリー別アーカイブ: デバイス・モジュール

温度センサーIC LM19を使う

ここでは温度センサーIC LM19(National Semiconductor)を使ってRaspberry piで温度監視を行う事例を紹介します。

LM19仕様

  • パッケージ:TO-92
  • 動作電源電圧:2.4V~5.5V
  • 使用温度範囲:-30℃~+130℃
  • 精度:±2.5(@30℃)

接続例

スクリーンショット 2014-01-21 4.24.02
LM19からの出力はアナログ電圧のためRaspberry piでは直接扱うことができません。そこで一旦I2Cインターフェイス基盤でアナログ電圧を読み取り、その結果をI2Cをとおして取得することにします。
ICのデータシートを参考に出力には抵抗とコンデンサをつないでいます。

Python script


import i2cinterface99
ii = i2cinterface99.i2cinterface99()
state,value = ii.analogRead(0) #read A0 Pin 
if state == True:
 volt = value / 1023.0*3.3 #3.3V電圧でインターフェイス基盤を動作している場合のAD変換式
 temp = (1.8641 - volt)/0.0117 #ボルトから温度への変換の式
 print "%d deg/C" %(temp) #摂氏表示
else:
 print "I2C error"

温度への変換式はICのデータシートに記載されている−10℃〜65℃における推奨式を元にしています。
上記スクリプトをsudo python ファイル名.py で実行します。
温度センサーの値を読み取った結果がコンソールに表示されるはずです。
I2Cインターフェイス基盤にLCDを接続していれば、LCD上に温度の値が表示されるようにしてもよいでしょう。

今回行った実験では、LM19の測定値が温度湿度センサーDHT11による測定値とほぼ同じであることが確認できました。

CIMG2383

動体検出にPIRセンサーを

動体検出には幾つかの方法が有ります。まずカメラ画像の中から動いている物体を検出するものがあります。これは人でも車でもカメラが見ることのできる動いているものを検出します.カメラの性能にも依存しますので例えば暗い時のようにカメラの映像にノイズが入ってしまう場合にはご検出を頻繁に起こしてしまうでしょう。

赤外線の変化を検出して動体検出とするものが有り、これが焦電センサーまたはPIRセンサーで行うことができます。防犯ライトなどにも多く使われている一般的なセンサーです.人間や動物など熱を持つ物体は赤外線を放出しており、その赤外線をセンサーが検出します.赤外線の検出値に変化が有れば何らかの物体が動いたという事でセンサーからの出力を行います.カメラのように画像によることがありませんので暗闇でも検出することができます.一方風なども物体と捉える事が出来るため、風の強い日はその赤外線の変化さえも検出してしまいます.

ここでは安価に入手できるPIRセンサーを紹介します.
CIMG2383
PIR センサー A708-1H
AITENDOで購入
仕様概要:動作電圧0.8-8v、 出力電圧 h:3.3 l:0v、 検出距離5-7m
参考にRaspberry piで接続する場合の例を紹介します.
必要な回路部品はすべてセンサーモジュールに実装されています.接続はPIRの出力をRaspberry piのいずれかのGPIOにつなげるだけです.

スクリーンショット 2013-12-15 13.06.30
あえて書くまでもないかもしれませんが、一応サンプルコードを紹介します.
PythonのGPIOはインストールしている前提です.


#!/usr/bin/python3
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
io_pin=17
GPIO.setup(io_pin,GPIO.IN)
while True:
        gp17=GPIO.input(io_pin)
        if gp17 == 1:
                print ("Move!");
        else:
                print("No move");
        time.sleep(1)

電源電圧が3.3VであるRaspberry piはGPIOの入力電圧も電源電圧を超えないものとしなければなりません。このPIRセンサーの出力は3.3Vという事でそのまま接続できますので大変便利ですね。

シリアルインタフェイス I2CとSPIの選択

センサーや表示装置などのデバイスモジュールは多くの種類があり小型になり、また手頃な価格で入手できるようになりました。これらをマイコンまたはRaspberry piなどの小型Linux機で扱うのに容易なシリアルインターフェイスで制御できるものも多く有ります.

シリアルインターフェイスにはUART,I2C,SPI,Single wireなどがあります。UARTは主に一対一の通信に用いられます.Raspberry piでRaspbianをOSとして使っている場合はこのUARTはシリアルコンソール用と割り当てられています。
SPI通信ではマスターとスレーブを定義し、一つのマスターに対して複数のスレーブを持つことができます.スレーブの切り替えはSS(Slave select、CS:chip select, CE:Chip enableとも呼ばれる)信号で行います.Raspberry piには二つのCE信号線が有ります。
I2C通信では二つの信号線、データ線SDAとクロック線SCLによって通信します。(この他にモジュールはVccとGNDも接続します )SPIではMOSI,MISO,SCLK,SSの信号線が必要だったのと比較して信号線が少なくて済みますね。I2Cも複数のモジュールをスレーブとしてつなげることができます.同時に複数のデバイスをつなげた場合はそれそののデバイスが持つアドレスによってデータのやり取りの相手を指定します.同じバスで使うデバイスの持つアドレスが競合しないように気をつけなければなりませんが、標準の7ビットアドレスモードで使う場合は最大で112個のデバイスを扱うことができるのです.

センサーモジュールによっては同じ機能のものでもI2C用とSPI用と2種類有るものや、一つのモデルで設定でI2CとSPIを切り替えられるものも有ります.またI2CのみまたはSPIのみに対応しているデバイスもあります。

自分が実現したい仕様に対して、用いるデバイスがどちらのインターフェイスを持っているか、それと制御するマイコンまたはLinuxボードのインターフェイスの制約条件とを勘案してよりベターな組み合わせを模索する必要が有ります

IMG_1899

Raspberry piで大気圧センサーMPL115A1を使う

ここではRaspberry piで秋月電子で買える大気圧センサーモジュールを使ってみます.
I2Cインターフェイスに対応したMPL115A2もありますが今回はSPIインターフェイスに対応したMPL115A1を使います

IMG_1899

スクリーンショット 2013-12-14 6.13.23

事前にRaspberry piでSPI通信を行うための設定を済ませておきます.

今回はPythonでプログラムを組んでみました。
このデバイスではデバイスごとのばらつきを補正するための補正係数を内部に持っています。それら補正係数を読み出した上で大気圧を算出します。他のセンサーと比較して複雑な計算処理が必要になるという事で使いこなしは少々面倒です.Google検索で見つかる同様の使いこなしについての記事を見渡してもその計算はいろいろと工夫されているのがうかがえます.ここでは出来るだけデバイスのアプリケーションノートにそった形で作っています.


import spidev
import time
import math
#main
spi_ch = 0
spi = spidev.SpiDev()
spi.open(0,spi_ch)
spi.max_speed_hz=(100000)

msb = spi.xfer2([0x88,0x00])
lsb = spi.xfer2([0x8a,0x00])
a0=(msb[1]<<8)|lsb[1]
if a0 >> 15:
     a0 = ~a0
a0int= (a0>>3)& 0b111111111111
a0fract = (a0 & 0b111)/8.0
a0val = a0int + a0fract*(0.1** int(math.log10(a0fract)+1))
print a0val    
if a0>>15:
     a0=-a0val
else:
     a0 = a0val
print 'a0',a0

msb = spi.xfer2([0x8c,0x00])
lsb = spi.xfer2([0x8e,0x00])
b1 = (msb[1]<<8)|lsb[1]
if b1 >>15:
     b1 = ~b1
b1int= (b1>>13)& 0b11
b1fract = (b1 & 0b1111111111111)/8191.0
b1val = b1int + b1fract*(0.1** int(math.log10(b1fract)+1))
if b1 >> 15:
     b1=-b1val
else:
     b1=b1val
print 'b1',b1

msb = spi.xfer2([0x90,0x00])
lsb = spi.xfer2([0x92,0x00])
b2 = (msb[1]<<8)|lsb[1]
if b2 >>15:
     b2 = ~b2
b2int= (b2>>14)& 0b1
b2fract = (b2 & 0b11111111111111)/16383.0
b2val = b2int + b2fract*(0.1** int(math.log10(b2fract)+1))
if b2>>15:
     b2=-b2val
else:
     b2 =b2val
print 'b2',b2

msb = spi.xfer2([0x94,0x00])
lsb = spi.xfer2([0x96,0x00])
c12 = (msb[1]<<8)|lsb[1]
c12 >>= 2
c12value = c12 / 4194304.0
c12 = c12value
print 'c12',c12

print
values=[]
for i in range(10):
     spi.xfer2([0x24,0x00])
     time.sleep(0.003)
     padcm=spi.xfer2([0x80,0x00])
     padcl=spi.xfer2([0x82,0x00])
     padc = ((padcm[1]<<8) | padcl[1])
     tadcm=spi.xfer2([0x84,0x00])
     tadcl=spi.xfer2([0x86,0x00])
     tadc = ((tadcm[1]<<8)| tadcl[1])
     padc >>= 6
     tadc >>= 6
     c12x2 = c12*tadc
     a1 = b1 + c12x2
     a1x1 = a1*padc
     y1 = a0 +a1x1
     a2x2 = b2*tadc
     pcomp =y1+a2x2
     pressureValue = (pcomp *65.0/1023.0+50)*10 # hPa
     print "%d:pressure:%0.2f hPa"%(i,pressureValue)
     values.append(pressureValue)
sum = 0.0
for i in range(len(values)):
     sum += values[i]
ave = sum/len(values)
print"average pressure: %0.2f hPa"%ave

実行するとコンソールには補正係数の計算途中も表示されます。不要な場合はコメントアウトまたは削除して構いません。測定ばらつきを吸収するために10回測定値の平均を最後に表示するようにしています.単位は天気予報でもなじみのあるヘクトパスカル(hPa)です。

上手く動作すれば、天気予報でみる気圧と同じ様な値が出てくるはずです.気圧は標高にも左右されそしてセンサーの周りの気圧変化にも非常に敏感です.センサーの近くで息を吹きかければそれも気圧の変化を及ぼします.正確な測定値を期待する場合には設置場所にも配慮する必要が有ります.

定点観測する事で気圧の変化のトレンドを知ることができます.たとえば低気圧の通過に伴ってセンサーの出力結果も値が上下するのが分かるはずです.大気圧の測定は気圧の変化のあくまで結果(現在の事象)であり、そこから未来の天気を予報をするのは難しいと思います.測定結果と同時に天候の様子を記録し、それぞれの相関を観察するのも面白いでしょう。天気が急速に変化する時には大気圧も急激に変化していきます。台風の通過では気圧が普段よりも一層低い値を示します.

Raspberry piを使えば測定結果をその都度メールで発信したり、Twitterでtweetしたり、GoogleDocのスプレッドシートに記録したりと、応用範囲はずっと広がります。ぜひ挑戦してみてください.

IMG_1900

温度センサーADT7310をRaspberry piで使う

温度センサーADT7310をRaspberry piで使ってみます.
秋月電子で売られている同タイプの温度センサーにはI2Cインターフェイスに対応したADT7410もあります。
ここではSPIに対応したADT7310を使います。
IMG_1900

スクリーンショット 2013-12-14 5.55.12

事前にRaspberry piでSPIが使えるようシステムの設定を済ませておきます。
ここではPythonで制御します

import spidev
import time
spi_ch = 1
spi = spidev.SpiDev()
spi.open(0,spi_ch)
spi.max_speed_hz=(100000)   #クロック周波数を設定
spi.xfer2([0x08,0x80])  # センサーを16ビット精度に設定
time.sleep(0.5)
spi.xfer2([0x54]) #連続モードにセット
time.sleep(1) #ADT7410が測定データをAD変換するための時間を待つ
ret = spi.xfer2([0xff,0xff]) #ダミーの2バイトをセンサーに書き込んで2バイトの温度データを読み取る
temp = ret[0]<<8 | ret[1]
temp /= 128.0      #℃に変換
print "temparature:",temp
print "stop:",spi.xfer2([0x50]) #連続モードを停止
spi.close()

無事動作すればコンソールに現在温度を表示するはずです。定時観測に使う場合はこのプログラムに測定結果をメールなどで飛ばす処理を加えたスクリプトにしてcronで定期的に呼び出すようにすると良いでしょう。
ADT7310の制御コマンドは他にも有りますが、順番など含めて動作を確認できたのが上で紹介したコマンドの流れになります.使いこなしによっては他のコマンドも使えると思います。いろいろと試してみてください。

Raspberry piにはSPIで使えるCE信号がCE0とCE1の二つしか無いと言う事はSPIデバイスを二つ使えるという事ですね。液晶デバイスなどSPIシリアルを持ったモジュールなども有りますので使いこなしてみるのも面白いでしょうね。

今回はSPIシリアルを持った温度センサーを使いました。同タイプの温度センサーモジュールにはI2Cインターフェイスを持ったものが有ります.他にも気圧センサーなどもSPIとI2Cのどちらかを選択することができます.もっと多くのモジュールをつなげたい、ほかのセンサーも同時に使いたいと言った時にはI2C対応のモジュールを検討してみると良いでしょう。(それでもI2Cアドレスが競合してしまっては使えないので気をつけましょう)

CIMG2380

温度湿度センサーDHT11を使う

ここでは温度湿度センサーDHT11をRaspberry piで使う手順を説明します.

温度センサーは種類が多く安価なものも見つかるのですが、湿度センサーは手頃な価格のものがなかなか見つからないものです.
そこで今回見つけたのがDHT11 というセンサーです。Google検索で海外のブログで多く見つかるので、メジャーなのかもしれませんね。とりあえず日本で手に入るところとして見つけたのがaitendoでした。
aitendo のDHT11通販ページ
Single wire接続なのでとてもシンプルです。
センサーにはアプリケーションノートどおりにパスコンとプルアップ抵抗を接続します。
スクリーンショット 2013-12-13 18.09.46

CIMG2380
写真のセンサー左端が1ピンです。抵抗は2つ付いていますが、手持ちの10kを二つ使って5kにしてあります。パスコンのセラミックコンデンサーも忘れずに。
Raspberry piには7番ピンであるGPIO4(GPCLK0)とDHT11の信号線を接続します。

制御するプログラムはこちらを参考にしました。
Raspberry Pi Blog

ソースコードを引用します。

#include 
#include 
#include 
#include 
#define MAX_TIME 85
#define DHT11PIN 7
int dht11_val[5]={0,0,0,0,0};

void dht11_read_val()
{
  uint8_t lststate=HIGH;
  uint8_t counter=0;
  uint8_t j=0,i;
  float farenheit;
  for(i=0;i<5;i++)
     dht11_val[i]=0;
  pinMode(DHT11PIN,OUTPUT);
  digitalWrite(DHT11PIN,LOW);
  delay(18);
  digitalWrite(DHT11PIN,HIGH);
  delayMicroseconds(40);
  pinMode(DHT11PIN,INPUT);
  for(i=0;i=4)&&(i%2==0)){
      dht11_val[j/8]<<=1;
      if(counter>16)
        dht11_val[j/8]|=1;
      j++;
    }
  }
  // verify cheksum and print the verified data
  if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF)))
  {
    farenheit=dht11_val[2]*9./5.+32;
    printf("Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3],farenheit);
  }
  else
    printf("Invalid Data!!\n");
}

int main(void)
{
  printf("Interfacing Temperature and Humidity Sensor (DHT11) With Raspberry Pi\n");
  if(wiringPiSetup()==-1)
    exit(1);
  while(1)
  {
     dht11_read_val();
     delay(3000);
  }
  return 0;
}

dht11.cというファイル名で保存しておきましょう。つぎにgccでコンパイルします。

gcc -o dht11 -lwiringPi

wiringPiは事前にインストールしていますね。無事コンパイルが出来たら実行します
sudo ./dht11

測定結果がコンソールに出力されていきます.
湿度の測定はなかなか難しいものが有りますので、何かと比較といってもそれぞれの誤差を勘案してみる必要が有るでしょう。温度の測定精度ですが、手元の電子温度計と比較した限りではプラスマイナス1度の範囲に入っているようです.科学的な測定でなければ、ある程度の実用範囲の測定結果だと思います.

CIMG2378

I2C接続可能なLCD/ACM1602の使いこなし

Raspberry piにLCDモジュールを接続する場合にその選択肢は案外少ないものです.
まずは3.3Vで動作する事。Raspberry Pi の少ないDIOピンを節約したいのでバスインターフェイスではなくシリアルインターフェイスで接続できるのが望ましい。表示文字数も少ないよりも多い方が良いな。と言う事で選定したのがACM1602.

さっそく秋月電子で購入
CIMG2378

Raspberry piのI2Cを有効にするための諸設定は済んでいるものとして。
I2Cの2線SDAをSCLそしてVccとGNDを接続。

シェルから以下のコマンドを投げてみる。

pi@raspberrypi ~ $ sudo i2cdetect 1

しかし、呼べども答えず。返事を返してくれるデイバイスは誰もいません。

I will probe file /dev/i2c-1.
I will probe address range 0x03-0x77.
Continue? [Y/n]
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

接続を一通り確認したり、他のI2CデバイスとRaspberry Piとが通信できている事を確認し行き詰まった。
そこでGoogle検索の出番。ひたすら調べた結果次の事が判明。

  • デフォルトの通信速度では通信がつまずくことがある
  • Write専用で一度でもReadを掛けるとモジュールがフリーズする。製品に添付の資料にも明記しているが、Readを掛けた時の状態に付いては記載がない。

一つ目については通信スピードを落とせば同じバスに繋がるデバイスもそのスピードダウンの影響を受けるがまあよしと考えられる範囲ですが、二つ目については一度でもi2cdetectを掛けるとACM1601はフリーズ状態になりその都度モジュールの電源再投入して立ち上げ直す必要になるのです.Raspberry Pi本体のシステムをリスタートする必要はないのですが、やはり使いにくいことには変わりないですね。

一応I2Cの通信スピードを変更する手順について書き留めておきます。

sudo modprobe -r i2c-bcm2708
sudo modprobe i2c-bcm2708 baudrate=50000
sudo i2cdetect 1

この時点ではもちろんACM1602からの返答は有りません。ここでLCD電源を一度オフにしてオン ※1
これ以降はi2cdetectを掛けないでくださいね。するとまたACM1602がフリーズに落ちますので。
無事ACM1602が使えるようになっているはずなので、I2Cを通じて制御コマンドを渡して動作を確認してください。

通信速度をデフォルトのままだとI2Cでコマンドを渡した時にPythonなら「IOError: [Errno 5] Input/output error」が出ます。
上記コードをその都度シェルから入力するのが面倒だ、この設定をデフォルトにしたい場合は、/etc/modprobe.d/i2c.conf というファイル(ファイル名は .conf で終わっていれば何でもよい)を作って以下のように書いておけば良いようだ。

options i2c_bcm2708 baudrate=50000

でもi2cdetectを不用意に投げないようにご注意を

結論。秋月で買えるACM1602(I2Cインタフェイスキャラクターディスプレイ LCD 3.3V)はRaspberry pi との組み合わせでは使いにくい.

それからI2Cを使う場合sudo権限が必要なので、実行するPythonスクリプトなどはsudo権限を使って実行することを忘れずに。

LCDモジュールの取り扱いをもっと簡単に出来ないか、複数のI2Cデバイスをぶら下げた時に安心してi2cdetectを投げられるようにならないか。そういった悩みを解消するのに、i2cインターフェイス基板が便利かもしれませんね。
i2cインターフェイス基板
デジタルIOも拡張でき、アナログ入力にも対応。Raspberry piを使った電子工作を便利にする事だと思います.

IMG_3171

無線通信モジュール XBee

XBee シリーズ1とXBeeエクスプローラUSB

XBeeエクスプローラUSBを使うことでPCとXBeeをUSBケーブルで接続。他のXBee機器と無線通信(シリアル通信)を行うことが出来ます。

XBeeはArduino Fioと組み合わせて使うことができます。

XBeeのピンピッチは2mmであり、一般の2.54mmピッチとは異なります。上記製品は2mmピッチのコネクターを持つものです。汎用基板で用いる場合にはピッチ変換基板が必要になります。

ピッチ変換基板の製品例

XBeeで使用する周波数は2.4GHzであり、無線LANの他にもBluetoothやワイヤレス電話にも使われており、相互に干渉し通信の妨げになることも起こり得るので、設置場所等に注意が必要です。

加速度センサ


3軸加速度センサーモジュール MM-2860 (サンハヤト)

加速度を検出し、アナログ出力またはデジタル出力によってその値を得ることが出来る。デジタル出力はI2cまたはSPIによってセンサーモジュールと通信を行う。ArduinoではI2c、SPI通信のためのライブラリーが用意されているため、プログラム(スケッチ)の作成も簡単に行うことができる。

モジュールによって測定できる加速度の大きさが異なるので、測定する事象に合わせてモジュールを選定する必要がある。