気温センサーBMP180のI2C読み取り
Rasberry Pi Picoを用いたI2Cの読み取りについての備忘録です。
プログラミング初心者なので、センサーのデータを読むことが出来ただけで
大分進歩した感じで、非常に嬉しいものです。
気温/気圧/高度センサーのBMP180を用いました。
今回は、気温のみの読み取りになりますが、気圧/高度にも挑戦したいと思っています。
ちなみに、I2C読み取りの学習のために、BMP180用にクラスを作成していない
初心者が書きそうなプログラムコードになっているので、ご注意ください。
接続
Picoの3.3V --- センサーのVCC
PicoのGND --- センサーのGND
PicoのGPIO0 --- SDA
PicoのGPIO1 --- SCL
コード
from machine import Pin, I2C
import time
import ustruct
# I2Cに使うピンの設定
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
# デバイスのアドレススキャン
address = i2c.scan()[0]
print("address is:" + hex(address))
#I2Cアドレス119のデバイスのレジスタ0xAA~0xBFまで2Byteごと読み取り
#BMP180のセンサー補正値読み取り
AC1 = i2c.readfrom_mem(address,0xAA,2)
AC2 = i2c.readfrom_mem(address,0xAC,2)
AC3 = i2c.readfrom_mem(address,0xAE,2)
AC4 = i2c.readfrom_mem(address,0xB0,2)
AC5 = i2c.readfrom_mem(address,0xB2,2)
AC6 = i2c.readfrom_mem(address,0xB4,2)
B1 = i2c.readfrom_mem(address,0xB6,2)
B2 = i2c.readfrom_mem(address,0xB8,2)
MB = i2c.readfrom_mem(address,0xBA,2)
MC = i2c.readfrom_mem(address,0xBC,2)
MD = i2c.readfrom_mem(address,0xBE,2)
#補正値ビット列を10進数へ変換
#unpackするとタプルで返すため、[0]で先頭データを読み取る
fmt = '>h' #short big-endian
fmt2 = '>H' #unsigned short big-endian
AC1_x = ustruct.unpack(fmt, AC1)[0]
AC2_x = ustruct.unpack(fmt, AC2)[0]
AC3_x = ustruct.unpack(fmt, AC3)[0]
AC4_x = ustruct.unpack(fmt2, AC4)[0]
AC5_x = ustruct.unpack(fmt2, AC5)[0]
AC6_x = ustruct.unpack(fmt2, AC6)[0]
B1_x = ustruct.unpack(fmt, B1)[0]
B2_x = ustruct.unpack(fmt, B2)[0]
MB_x = ustruct.unpack(fmt, MB)[0]
MC_x = ustruct.unpack(fmt, MC)[0]
MD_x = ustruct.unpack(fmt, MD)[0]
#0xF4に0x2Eを書くと気温測定を開始
i2c.writeto_mem(address,0xF4, bytearray([0x2E]))
time.sleep(0.005)
#補正前の気温データの読み取り
UT = i2c.readfrom_mem(address,0xF6,2)
UT_raw = ustruct.unpack(fmt2, UT)[0]
#気温の計算
X1 = (UT_raw - AC6_x)*AC5_x/2**15
X2 = MC_x*2**11/(X1 + MD_x)
B5 = X1 + X2
Temp = (B5 + 8)/2**4/10
するとこんな感じで出力されます。
address is:0x77
AC1: 8233
AC2: -1091
AC3: -14152
AC4: 33442
AC5: 25693
AC6: 16550
B1: 6515
B2: 39
MB: -32768
MC: -11786
MD: 2398
Temperature: 24.36 C
つまづきやすいのは、タプルの扱いでしょうか。
address = i2c.scan() でもアドレスは取得できるのですが、複数データの入ったタプルというものになっており、
address = i2c.scan()[0] という風に最初のデータを参照しないとエラーになってしまいました。
ustruct.unpack の部分も同じく、アンパックするとタプルになるようで、タプルの最初のデータをセンサーの補正値として取り出しています。
ここでのアンパックはレジスタの0,1のデータを10進数に戻す作業です。
fmt = '>h' #short big-endian
に関しては、センサーのメモリから取り出したビットデータをどの順に並べて、
どの型(short、int、longなど)に変換しますかという部分です。
上のコードは基本的には以下を参考にしています。
micropython-bmp180/bmp180.py at master · micropython-IMU/micropython-bmp180 · GitHub
こちらでは、読み取りからunpackを1行で書いています。手慣れたものですね(^^ ;
structに関しては以下も参考になります
なかなか経験がないと、I2Cの読み取りも大変ですね。
少しづつ経験値を増やしていきたいです。
Micro Python の書き方(I2Cスキャン)
Raspberry Pi Pico用です。
接続したセンサーやLCDディスプレイのI2Cアドレスのスキャン方法になります。
GPIO0とGPIO1にI2Cを接続して、以下のコードを走らせます。
from machine import Pin, I2C
# I2Cに使うピンの設定
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
# デバイスのアドレススキャン
address = i2c.scan()[0]
print("address is :" + hex(address))
すると、接続したデバイスのI2Cアドレスが16進数で返ってきます。
address is :0x77
追加で以下を書くと、接続したデバイスのメモリのレジスタ0xAA番地から始まる
2バイト分のデータを読みます。
AA1 = i2c.readfrom_mem(address,0xAA,2)
まだ、Micro Python初心者なので間違え等ありましたら、ご指摘ください。
Micro Python の書き方(ADC アナログ/デジタル変換)
忘れてしまうのでメモ。Rasberry Pi Pico用。
from machine import ADC, Pin
# ADC0を使う設定
PIN_ADC = 0
# ADC0~ADC2のあるGPIO26~28を使う記述でもOK
PIN_ADC = 26
# ADCの電圧は3.3V
VREF =3.3
# ADC オブジェクトを作成
adc = machine.ADC( PIN_ADC )
# ADCの値を読み取り
value = adc.read_u16()
# デジタル値を電圧に変換
volt = value /65535 * VREF
# 電圧を表示する
print("電圧は:",volt ,"V" )
Micro Python の書き方(PWM)
忘れてしまうのでメモ。Rasberry Pi Pico用。
from machine import PWM
# LEDを接続したGPIOの番号
LED_PIN = 18
# PWMの周波数
FREQ = 100
# duty比を0~100で設定
DUTY = 25
# 指定したピンをPWM出力するようにする
led = PWM( PIN (LED_PIN) )
# PWMの周波数を設定する
led.freq( FREQ )
# デューティー比を0~65535の範囲で設定する
pwm_out = int( DUTY / 100 * 65535 )
# PWM出力する
led.duty_u16( pwm_out )
Micro Python の書き方 (PIN)
忘れてしまうのでメモ。Rasberry Pi Pico用。
from machine import Pin
# GPIO23番を出力モードにして、出力High(3.3V)にする
LED_PIN = 23
led = Pin(LED_PIN, Pin.OUT)
led.value(1)
# GPIO18番を入力モードにする
LED_PIN = 18
led = Pin(LED_PIN, Pin.IN)
# プルアップ抵抗を有効にする
LED_PIN = 18
led = Pin(LED_PIN, Pin.IN, Pin.PULL_DOWN)
# Pin.PULL_DOWN:プルダウンを有効
# Pin.PULL_UP:プルアップを有効
# Pin.NONE :無効化
# ピンの値を読み込んで表示
print(led.value())
Raspberry Pi Pico でCircuit Pythonを使う準備
Raspberry Pi Pico でCircuit Pythonを使ってみたので、準備方法を備忘録として残しています。
Picoのプログラミング言語はC/C++、MicroPythonですが
Adafruit Industriesが開発を支援するCircuitPythonによる記述も可能です。
PicoがUSBメモリとして認識され、パソコンのエディッタでPico内のコードを
編集することができるので、特別な開発環境が要らないメリットがあるようです。
1. 以下のサイトからPico用のCircuitPythonのUF2ファイルをダウンロードします。
2021/9/11現在は、CircuitPython 6.3.0が安定している最新版のようです。
Pico Download (circuitpython.org)
2. Pico本体のBOOTSELボタンを押しながら、PCに接続します。
3. RPI-RP2ドライブが見えるので、先ほどダウンロードしたUF2ファイルを
ドラッグ&ドロップして、RPI-RP2ドライブへコピーします。
すると、Picoが自動で再起動されます。
4. 自動起動したあと、Pico内にCIRCUITPYドライブが見えるので、
その直下にある code.pyにプログラムを記述します。
またはcode.pyを消してmain.pyでも動作しました。
追加でimportするLibraryなどは、CIRCUITPYドライブ直下にあるlibフォルダ内
に置きます。