ESP32のULPでI2C通信(BMP180)mycropython版
ESP32のULPで実行する記事
https://miha.jugem.cc/?eid=409 で、
ESP32のULP紹介、GPIO入力、GPIO出力、ADC入力をやってみた。
これにI2Cが使えるようになると便利だなーと思い。挑戦し成功した記事です。
I2Cのセンサーとして選んだのが
BMP180という温度と気圧が取得できるセンサーだ。
https://amzn.to/4ljLPU1
3つ入ってて649yenって事は一つ220円ぐらいですね。
BME280より安いかなーと思いましたのでULPで温度と気圧を取得してみました。
今回もmycropythonでやります。
今回の元にしたプログラム
https://github.com/tomtor/ulp-i2c
ESP-IDEでコンパイルできます。
ULPでI2Cプログラムをしたいがために、
ESP-IDEも入れてしまった。
それで、ESP-IDEのクセを掴むのに結構かかってしまった。
こちら、ULPでセンサーの値を取得後、
前の値と比較してしきい値を超えた場合に本体復帰して表示するサンプルですが
mycropythonにするに当たり、ボタンで復帰する様に変更しております。
プログラムの仕様
mycropython上のULPプログラムをアセンブルして
メモリ上へロード、ULPプログラムをを起動する。
0.5秒単位でULPプログラムが起動して
センサーから値を持ってきてメモリ上に配置
ESP本体はdeepsleepする。ULPは動き続ける
ボタンが押されたら本体復帰しpython側で
メモリ上の値を取得して
温度と気圧を計算して出力する。(uart->comポート)
センサーからデータ取得する瞬間LEDを光らせる
表示例
ULP-BME180-R2
略
Temperature= 31.07753
Pressure= 1002.685
run
deepsleep(3600sec)
接続
ESP32 BME-180
GPIO32 scl (物理プルアップ)
GPIO33 sda (物理プルアップ)
3V VIN
GND GND
GPIO14 SW (物理プルアップ)
GPIO2 LED
プログラム
こちらからダウンロードできます。
https://drive.google.com/file/d/1UnT5i8G1GwxzGrEtb9N8IAs8-kNProBp/view?usp=sharing
#
# BME180のULP制御
#
# 0.5秒単位でセンサーから取得し
# GPIO14押下で本体復帰して最新の温度、気圧を表示する
#
# ULP I2C BME-180
# scl = GPIO32 物理プルアップ
# sda = GPIO33 物理プルアップ
# 復帰ボタン:GPIO14 プルアップ
# LED:GPIO2
#
#
VERSION_STR="ULP-BME180-R2"
import sys
import esp32
from esp32 import ULP
import time
import machine
from machine import Pin
from machine import mem32
import math
from esp32_ulp import src_to_binary
def end():
while True:
pass
time.sleep(1)
print(VERSION_STR)
def k(n) :
ret = ""
for i in range(n):
ret = ret + " "
return ret
#
#マクロ処理用
#
def src_to_preprocessor(input) :
output = ""
input_sp = input.split("¥n")
for line in input_sp:
#print("line=", line)
kuhaku=len(line)-len(line.lstrip())
#print("kuhaku=", kuhaku)
line = line.strip()
sp = line.split(" ")
#print("sp[0]=", sp[0])
if sp[0]=="psr" :
output = output + k(kuhaku)
output = output + "#psr "+sp[1]+"¥r¥n"+k(kuhaku)
output = output + "move r1, "+sp[1]+"¥r¥n"+k(kuhaku)
output = output + "st r1,r3,0"+"¥r¥n"+k(kuhaku)
output = output + "sub r3,r3,1"+"¥r¥n"
elif sp[0]=="ret" :
output = output + k(kuhaku)
output = output + "#ret¥r¥n"+k(kuhaku)
output = output + "add r3,r3,1¥r¥n"+k(kuhaku)
output = output + "ld r1,r3,0¥r¥n"+k(kuhaku)
output = output + "jump r1¥r¥n"
elif sp[0]=="push" :
output = output + k(kuhaku)
output = output + "#push "+sp[1]+"¥r¥n"+k(kuhaku)
output = output + "st "+sp[1]+",r3,0"+"¥r¥n"+k(kuhaku)
output = output + "sub r3,r3,1"+"¥r¥n"
elif sp[0]=="pop" :
output = output + k(kuhaku)
output = output + "#pop "+sp[1]+"¥r¥n"+k(kuhaku)
output = output + "add r3,r3,1"+"¥r¥n"+k(kuhaku)
output = output + "ld "+sp[1]+",r3,0"+"¥r¥n"
elif sp[0]=="I2C_delay" :
output = output + k(kuhaku)
output = output + "#I2C_delay"+"¥r¥n"+k(kuhaku)
output = output + "wait 10"+"¥r¥n"
elif sp[0]=="read_SCL" :
output = output + k(kuhaku)
output = output + "#read_SCL"+"¥r¥n"+k(kuhaku)
output = output + "READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 9, 1)"+"¥r¥n" #RTC_GPIO_9 == GPIO_32
elif sp[0]=="read_SDA" :
output = output + k(kuhaku)
output = output + "#read_SDA"+"¥r¥n"+k(kuhaku)
output = output + "READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 8, 1)"+"¥r¥n" #RTC_GPIO_8 == GPIO_33
elif sp[0]=="set_SCL" :
output = output + k(kuhaku)
output = output + "#set_SCL"+"¥r¥n"+k(kuhaku)
output = output + "WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC_S + 9, 1, 1)"+"¥r¥n"
elif sp[0]=="clear_SCL" :
output = output + k(kuhaku)
output = output + "#clear_SCL"+"¥r¥n"+k(kuhaku)
output = output + "WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS_S + 9, 1, 1)"+"¥r¥n"
elif sp[0]=="set_SDA" :
output = output + k(kuhaku)
output = output + "#set_SDA"+"¥r¥n"+k(kuhaku)
output = output + "WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC_S + 8, 1, 1)"+"¥r¥n"
elif sp[0]=="clear_SDA" :
output = output + k(kuhaku)
output = output + "#clear_SDA"+"¥r¥n"+k(kuhaku)
output = output + "WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS_S + 8, 1, 1)"+"¥r¥n"
else :
output = output + k(kuhaku)
output = output + line
output = output + "¥r¥n"
return output
#ULP実行ファイルのメモリ上にロードされるアドレスと実行開始アドレス
load_addr, entry_addr = 0, 40 * 4
ULP_MEM_BASE = 0x50000000
#16ビットデータマスク
ULP_DATA_MASK = 0xffff
#ULPプログラム
source = """¥
#define DR_REG_RTCIO_BASE 0x3ff48400
#define RTC_GPIO_ENABLE_W1TS_REG (DR_REG_RTCIO_BASE + 0x10)
#define RTC_GPIO_ENABLE_W1TS_S 14
#define RTC_GPIO_ENABLE_W1TC_REG (DR_REG_RTCIO_BASE + 0x14)
#define RTC_GPIO_ENABLE_W1TC_S 14
#define RTC_GPIO_IN_REG (DR_REG_RTCIO_BASE + 0x24)
#define RTC_GPIO_IN_NEXT_S 14
#define RTC_GPIO_OUT_REG (DR_REG_RTCIO_BASE + 0x0)
#define RTC_GPIO_OUT_DATA_S 14
#define RTC_GPIO_ENABLE_REG (DR_REG_RTCIO_BASE + 0xc)
#define RTC_GPIO_ENABLE_S 14
#define RTC_CNTL_STATE0_REG 0x3FF48018
#define RTC_CNTL_ULP_CP_SLP_TIMER_EN (BIT(24))
#define RTC_CNTL_LOW_POWER_ST_REG 0x3FF480C0
#define RTC_CNTL_RDY_FOR_WAKEUP (BIT(19))
#GPIO32------------------------------------------
#{RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, RTC_IO_X32P_FUN_SEL_S, RTC_IO_X32P_FUN_IE_M, RTC_IO_X32P_RUE_M, RTC_IO_X32P_RDE_M, RTC_IO_X32P_SLP_SEL_M, RTC_IO_X32P_SLP_IE_M, RTC_CNTL_X32P_HOLD_FORCE_M, 9}, //32
#define RTC_IO_XTAL_32K_PAD_REG (DR_REG_RTCIO_BASE + 0x8c)
#define RTC_IO_X32P_MUX_SEL_M (BIT(17))
#define RTC_IO_X32P_FUN_IE_M (BIT(5))
.set gpio32, 9
#GPIO33------------------------------------------
#{RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, RTC_IO_X32N_FUN_SEL_S, RTC_IO_X32N_FUN_IE_M, RTC_IO_X32N_RUE_M, RTC_IO_X32N_RDE_M, RTC_IO_X32N_SLP_SEL_M, RTC_IO_X32N_SLP_IE_M, RTC_CNTL_X32N_HOLD_FORCE_M, 8}, //33
#define RTC_IO_XTAL_32K_PAD_REG (DR_REG_RTCIO_BASE + 0x8c)
#define RTC_IO_X32N_MUX_SEL_M (BIT(18))
#define RTC_IO_X32N_FUN_IE_M (BIT(11))
.set gpio33, 8
#GPIO14------------------------------------------
#define RTC_IO_TOUCH_PAD6_REG (DR_REG_RTCIO_BASE + 0xac)
#define RTC_IO_TOUCH_PAD6_MUX_SEL_M (BIT(19))
#define RTC_IO_TOUCH_PAD6_FUN_IE_M (BIT(13))
.set gpio14, 16 # gpio14
#GPIO2------------------------------------------
#{RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, RTC_IO_TOUCH_PAD2_FUN_SEL_S, RTC_IO_TOUCH_PAD2_FUN_IE_M, RTC_IO_TOUCH_PAD2_RUE_M, RTC_IO_TOUCH_PAD2_RDE_M, RTC_IO_TOUCH_PAD2_SLP_SEL_M, RTC_IO_TOUCH_PAD2_SLP_IE_M, RTC_CNTL_TOUCH_PAD2_HOLD_FORCE_M, 12}, //2
#define RTC_IO_TOUCH_PAD2_REG (DR_REG_RTCIO_BASE + 0x9c)
#define RTC_IO_TOUCH_PAD2_MUX_SEL_M (BIT(19))
#define RTC_IO_TOUCH_PAD2_FUN_IE_M (BIT(13))
.set gpio2, 12
#16 * 4 = 64
status: .long 0
temp: .long 0
pressure: .long 0
pressure2: .long 0
ac1: .long 0
ac2: .long 0
ac3: .long 0
ac4: .long 0
ac5: .long 0
ac6: .long 0
b1: .long 0
b2: .long 0
mb: .long 0
mc: .long 0
md: .long 0
counter: .long 0
#20 * 4 = 80byte
stack:
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
stackEnd:
#1 * 4 = 4
.long 0
#3 * 4 = 12
prev_temp: .long 0
prev_pressure: .long 0
prev_pressure2: .long 0
entry:
move r3,stackEnd
# GPIO32 input mode
WRITE_RTC_REG(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, 1, 1)
WRITE_RTC_REG(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_FUN_IE_M, 1, 1)
# GPIO33 input mode
WRITE_RTC_REG(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, 1, 1)
WRITE_RTC_REG(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_FUN_IE_M, 1, 1)
# GPIO14 input mode
WRITE_RTC_REG(RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_MUX_SEL_M, 1, 1)
WRITE_RTC_REG(RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_FUN_IE_M, 1, 1)
#gpio2 output mode
WRITE_RTC_REG(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, 1, 1);
WRITE_RTC_REG(RTC_GPIO_ENABLE_REG, RTC_GPIO_ENABLE_S + gpio2, 1, 1)
//DEBUG
move r1, status
move r0, 100
st r0, r1, 0
wait 65535
//
// Read the BMP-180 every 4 timer cycles:
#move r1,counter
#ld r0,r1,0
#add r0,r0,1
#st r0,r1,0 // increment counter
#and r0,r0,0x3
#jumpr waitNext,1,ge
// GPIO2 LED ON
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + gpio2, 1, 1)
psr l00010
jump readBMP
l00010:
// GPIO2 LED OFF
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + gpio2, 1, 0)
/* wake up after significant change */
// move r1,pressure
// ld r0,r1,0
// move r1,prev_pressure
// ld r2,r1,0
// sub r0,r0,r2
// psr l00020
// jump abs
//l00020:
// jumpr testTemp,6,lt
// jump wakeUp
//
//testTemp:
// move r1,temp
// ld r0,r1,0
// move r1,prev_temp
// ld r2,r1,0
// sub r0,r0,r2
// psr l00030
// jump abs
//l00030:
// jumpr waitNext,10,lt
#GPIO14-----------------------------------------------
# GPIOからr0に読む
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + gpio14, 1)
#押されてたら0
jumpr wakeUp, 0, eq
jump waitNext
wakeUp:
//jump waitNext #DEBUG
/* save new pressure and temp */
move r1,pressure
ld r0,r1,0
move r1,prev_pressure
st r0,r1,0
move r1,temp
ld r0,r1,0
move r1,prev_temp
st r0,r1,0
#
#ここにwakeしても良いか?確認する処理が抜けている
#
/* Wake up the SoC, end program */
wake
/* Stop the wakeup timer so it does not restart ULP */
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
waitNext:
halt
// Compute abs value of R0
#abs:
# and r1,r0,0x8000
# jump noNegate,eq
# move r1,0
# sub r0,r1,r0
#noNegate:
# ret
////////////
//i2c-bme180.S
////////////
#define BMP180_ADDR 0x77
#define BMP180_REG_CONTROL 0xF4
#define BMP180_REG_RESULT 0xF6
#define BMP180_REG_RESULT2 0xF8
#define BMP180_COMMAND_TEMPERATURE 0x2E
#define BMP180_COMMAND_PRESSURE0 0x34
#define BMP180_COMMAND_PRESSURE1 0x74
#define BMP180_COMMAND_PRESSURE2 0xB4
#define BMP180_COMMAND_PRESSURE3 0xF4
readBMP:
move r1,ac1
ld r0,r1,0
jumpr initBMP,1,lt
didInit:
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_CONTROL
push r1
move r1,BMP180_COMMAND_TEMPERATURE
push r1
psr l0r010
jump write8
l0r010:
add r3,r3,3 // remove 3 arguments from stack
move r0,r2 // test for error in r2
jumpr fail,1,ge
// Wait 5ms for sensor computation
move r2,5
psr l0r020
jump waitMs
l0r020:
// Read 16 bit result
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_RESULT
push r1
psr l0r030
jump read16
l0r030:
add r3,r3,2 // remove call parameters from stack
move r1,r0 // save result
move r0,r2 // test for error
jumpr fail,1,ge
move r2,temp // store result
st r1,r2,0
// Read raw pressure
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_CONTROL
push r1
move r1,BMP180_COMMAND_PRESSURE1
push r1
psr l0r040
jump write8
l0r040:
add r3,r3,3 // remove 3 arguments from stack
move r0,r2 // test for error in r2
jumpr fail,1,ge
// Wait 8 ms for sensor computation
move r2,8
psr l0r050
jump waitMs
l0r050:
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_RESULT
push r1
psr l0r060
jump read16
l0r060:
add r3,r3,2 // remove call parameters from stack
move r1,r0 // save result
move r0,r2 // test for error
jumpr fail,1,ge
move r2,pressure // store result
st r1,r2,0
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_RESULT2
push r1
psr l0r070
jump read8
l0r070:
add r3,r3,2 // remove call parameters from stack
move r1,r0 // save result
move r0,r2 // test for error
jumpr fail,1,ge
move r2,pressure2 // store result
st r1,r2,0
ret
fail:
move r1,temp
move r0,0 // 0 signals error
st r0,r1,0
ret
#define BMP085_CAL_AC1 0xAA
#define BMP085_CAL_AC2 0xAC
#define BMP085_CAL_AC3 0xAE
#define BMP085_CAL_AC4 0xB0
#define BMP085_CAL_AC5 0xB2
#define BMP085_CAL_AC6 0xB4
#define BMP085_CAL_B1 0xB6
#define BMP085_CAL_B2 0xB8
#define BMP085_CAL_MB 0xBA
#define BMP085_CAL_MC 0xBC
#define BMP085_CAL_MD 0xBE
#define BMP085_END 0xC0
// Read calibration data
initBMP:
move r1,ac1
push r1
move r1,BMP180_ADDR
push r1
move r1,BMP085_CAL_AC1
push r1
read_cal:
psr l0i010
jump read16
l0i010:
or r2,r2,0 // test error
jump readok,eq
jump fail
readok:
ld r1,r3,12
st r0,r1,0
add r1,r1,1
st r1,r3,12 // next cal parameter address
ld r0,r3,4
add r0,r0,2 // next register
st r0,r3,4
jumpr read_cal,BMP085_END,lt
add r3,r3,3
jump didInit
// Wait for r2 milliseconds
waitMs:
wait 8000
sub r2,r2,1
jump doneWaitMs,eq
jump waitMs
doneWaitMs:
ret
////////////
//i2c-util.S
////////////
write_intro:
psr l00230
jump i2c_start_cond
l00230:
ld r2,r3,20 // Address
lsh r2,r2,1
psr l00240
jump i2c_write_byte
l00240:
jumpr popfail,1,ge
ld r2,r3,16 // Register
psr l00250
jump i2c_write_byte
l00250:
jumpr popfail,1,ge
ret
write8:
psr l00260
jump write_intro
l00260:
write_b:
ld r2,r3,8 // data byte
psr l00270
jump i2c_write_byte
l00270:
jumpr fail_util,1,ge
psr l00280
jump i2c_stop_cond
l00280:
move r2,0 // Ok
ret
write16:
psr l00290
jump write_intro
l00290:
ld r2,r3,8 // data byte 1
rsh r2,r2,8
psr l00300
jump i2c_write_byte
l00300:
jumpr fail_util,1,ge
jump write_b
read_intro:
psr l00310
jump i2c_start_cond
l00310:
ld r2,r3,16 // Address
lsh r2,r2,1
psr l00320
jump i2c_write_byte
l00320:
jumpr popfail,1,ge
ld r2,r3,12 // Register
psr l00330
jump i2c_write_byte
l00330:
jumpr popfail,1,ge
psr l00340
jump i2c_start_cond
l00340:
ld r2,r3,16
lsh r2,r2,1
or r2,r2,1 // Address Read
psr l00350
jump i2c_write_byte
l00350:
jumpr popfail,1,ge
ret
popfail:
pop r1 // pop caller return address
move r2,1
ret
read8:
psr l00360
jump read_intro
l00360:
move r2,1 // last byte
psr l00370
jump i2c_read_byte
l00370:
push r0
psr l00380
jump i2c_stop_cond
l00380:
pop r0
move r2,0 // OK
ret
fail_util:
move r2,1
ret
read16:
psr l00390
jump read_intro
l00390:
move r2,0
psr l00400
jump i2c_read_byte
l00400:
push r0
move r2,1 // last byte
psr l00410
jump i2c_read_byte
l00410:
push r0
psr l00420
jump i2c_stop_cond
l00420:
pop r0
pop r2 // first byte
lsh r2,r2,8
or r2,r2,r0
move r0,r2
move r2,0 // OK
ret
////////////
//i2c.S
////////////
i2c_started:
.long 0
i2c_didInit:
.long 0
i2c_start_cond:
move r1,i2c_didInit
ld r0,r1,0
jumpr i2cs_didInit,1,ge
move r0,1
st r0,r1,0
// set GPIO to pull low when activated
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + 9, 1, 0)
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + 8, 1, 0)
i2cs_didInit:
move r2,i2c_started
ld r0,r2,0
jumpr not_started,1,lt
// if started, do a restart condition
// set SDA to 1
set_SDA
I2C_delay
set_SCL
clock_stretch: // TODO: Add timeout?
read_SCL
jumpr clock_stretch,1,lt
// Repeated start setup time, minimum 4.7us
I2C_delay
not_started:
// if (read_SDA() == 0) {
// arbitration_lost();
// }
// SCL is high, set SDA from 1 to 0.
clear_SDA
I2C_delay
clear_SCL
move r0,1
st r0,r2,0
ret
i2c_stop_cond:
// set SDA to 0
clear_SDA
I2C_delay
set_SCL
clock_stretch_stop:
read_SCL
jumpr clock_stretch_stop,1,lt
// Stop bit setup time, minimum 4us
I2C_delay
// SCL is high, set SDA from 0 to 1
set_SDA
I2C_delay
// if (read_SDA() == 0) {
// arbitration_lost();
// }
move r2,i2c_started
move r0,0
st r0,r2,0
ret
// Write a bit to I2C bus
i2c_write_bit:
jumpr bit0,1,lt
set_SDA
jump bit1
bit0:
clear_SDA
bit1:
// SDA change propagation delay
I2C_delay
// Set SCL high to indicate a new valid SDA value is available
set_SCL
// Wait for SDA value to be read by slave, minimum of 4us for standard mode
I2C_delay
clock_stretch_write:
read_SCL
jumpr clock_stretch_write,1,lt
// SCL is high, now data is valid
// If SDA is high, check that nobody else is driving SDA
// if (bit && (read_SDA() == 0)) {
// arbitration_lost();
// }
// Clear the SCL to low in preparation for next change
clear_SCL
ret
// Read a bit from I2C bus
i2c_read_bit:
// Let the slave drive data
set_SDA
// Wait for SDA value to be written by slave, minimum of 4us for standard mode
I2C_delay
// Set SCL high to indicate a new valid SDA value is available
set_SCL
clock_stretch_read:
read_SCL
jumpr clock_stretch_read,1,lt
// Wait for SDA value to be written by slave, minimum of 4us for standard mode
I2C_delay
// SCL is high, read out bit
read_SDA
// Set SCL low in preparation for next operation
clear_SCL
ret // bit in r0
// Write a byte to I2C bus. Return 0 if ack by the slave.
i2c_write_byte:
stage_rst
next_bit:
and r0,r2,0x80
psr l00430
jump i2c_write_bit
l00430:
lsh r2,r2,1
stage_inc 1
jumps next_bit,8,lt
psr l00440
jump i2c_read_bit
l00440:
ret // nack
// Read a byte from I2C bus
i2c_read_byte:
push r2
move r2,0
stage_rst
next_bit_read:
psr l00450
jump i2c_read_bit
l00450:
lsh r2,r2,1
or r2,r2,r0
stage_inc 1
jumps next_bit_read,8,lt
pop r0
psr l00460
jump i2c_write_bit
l00460:
move r0,r2
ret
"""
#
#BME180から16bitで値を取得する時に負の数字の場合
#ちゃんと受け取れないので変換uint16→int16
#
def conv_int16(uint16) :
if uint16 > 32767 :
int16 = (-1)*(65536 - uint16)
else :
int16=uint16
return int16
#
#BME180からデータを取得必要な計算を実施し表示する
#
def display() :
#データ取得
status = mem32[ULP_MEM_BASE + load_addr + 0] & ULP_DATA_MASK
ulp_temp = mem32[ULP_MEM_BASE + load_addr + 4] & ULP_DATA_MASK
ulp_pressure = mem32[ULP_MEM_BASE + load_addr + 8] & ULP_DATA_MASK
ulp_pressure2 = mem32[ULP_MEM_BASE + load_addr + 12] & ULP_DATA_MASK
ac1 = mem32[ULP_MEM_BASE + load_addr + 16] & ULP_DATA_MASK
ac2 = mem32[ULP_MEM_BASE + load_addr + 20] & ULP_DATA_MASK
ac3 = mem32[ULP_MEM_BASE + load_addr + 24] & ULP_DATA_MASK
ac4 = mem32[ULP_MEM_BASE + load_addr + 28] & ULP_DATA_MASK
ac5 = mem32[ULP_MEM_BASE + load_addr + 32] & ULP_DATA_MASK
ac6 = mem32[ULP_MEM_BASE + load_addr + 36] & ULP_DATA_MASK
b1 = mem32[ULP_MEM_BASE + load_addr + 40] & ULP_DATA_MASK
b2 = mem32[ULP_MEM_BASE + load_addr + 44] & ULP_DATA_MASK
mb = mem32[ULP_MEM_BASE + load_addr + 48] & ULP_DATA_MASK
mc = mem32[ULP_MEM_BASE + load_addr + 52] & ULP_DATA_MASK
md = mem32[ULP_MEM_BASE + load_addr + 56] & ULP_DATA_MASK
counter = mem32[ULP_MEM_BASE + load_addr + 60] & ULP_DATA_MASK
ac1 = conv_int16(ac1)
ac2 = conv_int16(ac2)
ac3 = conv_int16(ac3)
b1 = conv_int16(b1)
b2 = conv_int16(b2)
mb = conv_int16(mb)
mc = conv_int16(mc)
md = conv_int16(md)
#print("status=", status)
#print("ulp_temp=", ulp_temp)
#print("ulp_pressure=", ulp_pressure)
#print("ulp_pressure2=", ulp_pressure2)
#print("ac1=", ac1)
#print("ac2=", ac2)
#print("ac3=", ac3)
#print("ac4=", ac4)
#print("ac5=", ac5)
#print("ac6=", ac6)
#print("b1=", b1)
#print("b2=", b2)
#print("mb=", mb)
#print("mc=", mc)
#print("md=", md)
#print("counter=", counter)
oversampling= 1
UP= ((((ulp_pressure) << 8) | (ulp_pressure2)) >> (8-oversampling))
#print("UP=", UP)
X1 = (ulp_temp - ac6) * (ac5) >> 15
#print("X1=", X1)
X2 = (mc << 11) / (X1+md)
#print("X2=", X2)
B5 = X1 + X2
#print("B5=", B5)
temp = (B5+8) / 16.0
#print("temp=", temp)
temp = temp / 10
print("Temperature=", temp)
B6 = B5 - 4000
#print("B6=", B6)
X1 = (b2 * ( int(B6 * B6)>>12 )) >> 11
#print("X1=", X1)
X2 = int(ac2 * B6) >> 11
#print("X2=", X2)
X3 = X1 + X2
#print("X3=", X3)
B3 = (((ac1*4 + X3) << oversampling) + 2) / 4
#print("B3=", B3)
X1 = int(ac3 * B6) >> 13
#print("X1=", X1)
X2 = int(b1 * (int(B6 * B6) >> 12)) >> 16
#print("X2=", X2)
X3 = int((X1 + X2) + 2) >> 2
#print("X3=", X3)
B4 = int(ac4 * (X3 + 32768)) >> 15
#print("B4=", B4)
B7 = (UP - B3) * ( 50000 >> oversampling )
#print("B7=", B7)
if (B7 < 0x80000000) :
p = (B7 * 2) / B4
#print("point 1")
else :
p = (B7 / B4) * 2
#print("point 2")
#print("p=", p)
X1 = (int(p) >> 8) * (int(p) >> 8)
#print("X1=", X1)
X1 = int(X1 * 3038) >> 16
#print("X1=", X1)
X2 = int(-7357 * p) >> 16
#print("X2=", X2)
p = p + (int(X1 + X2 + 3791)>>4)
#print("p=", p)
pressure = p
altitude_meters= 3
print("Pressure=", (pressure / math.pow(1.0-altitude_meters/44330, 5.255))/100.0);
###########
#MAIN
###########
#DEBUG
# print("ac1=", conv_int16(7493))
# print("ac2=", conv_int16(64488))
# print("ac3=", conv_int16(50901))
# print("ac4=", conv_int16(32931))
# print("ac5=", conv_int16(25567))
# print("ac6=", conv_int16(19438))
# end()
machine.Pin(2, machine.Pin.OUT) #LED
pin_scl = machine.Pin(32, machine.Pin.IN, machine.Pin.PULL_UP)
pin_sda = machine.Pin(33, machine.Pin.IN, machine.Pin.PULL_UP)
#ULP
ulp = ULP()
#ULP停止(前のdeepsleep中に動いていたプログラムを停止)
ulp.set_wakeup_period(0, -1)
print("machine.reset_cause() -->", machine.reset_cause())
print("machine.wake_reason() -->", machine.wake_reason())
if machine.wake_reason() != 6 :
print("prep start")
prep = src_to_preprocessor(source)
#print("prep=", prep)
print("src_to_binary start")
binary = src_to_binary(prep)
print("src_to_binary done")
ulp.load_binary(load_addr, binary)
else :
display()
#ULP
ulp.set_wakeup_period(0, 500000) # use timer0, wakeup after 500000usec (0.5s)
print("run")
ulp.run(entry_addr)
#ULP割り込みON
esp32.wake_on_ulp(True)
#
print("deepsleep(3600sec)")
machine.deepsleep(3600*1000)
#以下はDEBUG deepsleepを外すと走る
old = 0
while True:
#new = mem32[ULP_MEM_BASE + load_addr] & ULP_DATA_MASK # current state
#if old != new :
# print(new)
# old=new
#if new==888 :
# display()
# time.sleep(10)
# print()
time.sleep(3)
display()