
特価品(見切り品?)のGR-CITRUSボード(ルネサスRX631搭載)で組み込みRuby(mruby)してます。今回はMicroPython上で動いている「フルソフトウエア」のDHT11センサ読み取りプログラムのRubyへの移植にトライ。しかし湿度の読み取りだけ成功?したところで止めました。タイミング違い過ぎ。
※Rubyと一緒 投稿順indexはこちら
今回は、以下の別シリーズ記事にて動作確認済のMicroPythonスクリプトのRuby(mruby)への移植トライアルです。元になったMicroPythonソースは以下の記事の後ろの方に貼り付けてあります。
MicroPython的午睡(27) ラズパイPico、DHT11接続、ソフト現物合わせ
DHT11は、Arduinoなどへの接続で定番の温湿度センサです。インタフェースはDHT11規格とでもいうべき「1-wire風」の双方向通信です。1本の線でマイコン側からのトリガを受信すると今度はDHT11が自分のタイミングで、湿度、温度、CRCを送信してくるもの。
通信スピードは結構遅いので、MicroPython上では遅延関数以外のタイミングを用いず、ソフトウエアで「タイミング」をとって通信してました。特段ハードウエアを使っていないので、「タイミング」さえMicroPythonと合わせられればRubyちゃんでも通信可能な筈。ただ、ラズパイPico上のMicroPythonで元のプログラムを作成したときはオシロで波形を見ながら「現物あわせでタイミングを調整」してます。成り行きまかせ。ただ、Pico上のMicroPythonはそこそこ速かったので「なんとかできた」感じ。Rubyちゃんではどうか?
Rubyちゃん上での実装、湿度だけ
最初、湿度、温度、CRC全てを受信すべくMicroPythonコードをほぼほぼ1対1な形でRubyに移植しました。Ruby素人は沢山コーディングミスをして結構手間取りました。なにせ使用している、Rubic処理系のエラー表示が素っ気なさすぎます。![]()
前にも書きましたが、どこにエラーがあるのかサッパリです。まあ、Runtimeエラーの方が多少筋がいいですが、「多少」です。こんな感じ。
苦難の道のりを乗り越え、ようやく移植完了。当然ながら動きはしません、はい。
そこからはオシロでタイミング調整です。成り行きまかせの現物あわせ。なおDHT11との通信タイミングを外部から観察するのに
-
- DHT11はピン4で双方向通信(以下のオシロ画面で黄色C1)
- 通信タイミングを知るためにピン6にパルス出力(青色C2)
DHT11は生きてなにやらデータを送ってきている感じですが、受け取る側のスクリプト、青色パルスの方はほとんどデータ終わってから動き始めてないかい?
MicroPythonのコードはデータシートの波形に従って「マイコンとDHT11間の頭出しプロトコル」的なところを実装していたのですが、そんなものを受け入れる余裕はRubyちゃんには無さそうでした。仕方ないのでバッサリやって頭を合わせました。こんな感じ。
青色パルスの最初の一発は頭出しのところですが、引き続く4発は4ビットを「捕獲」するためのタイミングです。全然ダメじゃん。捕獲側が4回回っている間にDHT11の方は5ビット以上送ってきてるじゃん。ぜんぜん間に合ってねずら。
タイミング表示の青パルスの生成だけでも負荷重そうだったのでさらに軽減。最初の8ビットの頭とお尻だけに青パルスを入れ、ビットを拾うことに。最初の太いハイは無視して次の細いパルスが0、太いパルスが1ということであります。
ソフトでやることはこのパルス幅を測って0/1決定すれば良いのですが、MicroPythonで余裕をもってできていた観察ができません。forループでビット処理を回転させることすら負荷重いみたい。それでもかなり無理やりだけれども最初の8ビットは受信できる感じになってきました(でも8ビット以上長くするとどこかでSYNCハズレそうな感じがヒシヒシと。)
最初の8ビットに%表示の湿度が載っているので、そこだけ取り出してみることにいたしました。
実験に使用したRubyスクリプト
現物あわせのやっつけが以下に。結構あちこちにコメントアウトしてあるのは、当初組み込んであった、温度やCRC計算やらの残骸デス。「ハードウエア」でのデバッグ用のコードもありで、かなり汚い。
#!mruby
class Dht11
def initialize(pinname)
@pin = pinname
@buf = []
@crcR = 0
@crcC = 0
@crc = true
@temperature = 0
@humidity = 0
@error = 0
pinMode(@pin, 3) # output, opendrain
pinMode(6, 1) # Hardware debug only
end
def readCRC
return @crc
end
def readERROR
return @error
end
def readTemperature
return @temperature
end
def readHumidity
return @humidity
end
def readERROR
return @error
end
def readBUF
return @buf.join
end
def clearBUF
@buf = []
end
def markSignal
digitalWrite(6, 0)
digitalWrite(6, 1)
digitalWrite(6, 0)
end
def startSignal
digitalWrite(@pin, 0)
delay(19) #min low pulse > 18msec
digitalWrite(@pin, 1)
end
def waitSIG(sig, timeOut)
count = 0
while digitalRead(@pin) == sig do
count +=1
if count > timeOut then
return false
end
end
return true
end
def bitRead
while digitalRead(@pin) == 0 do
end
return 0 if digitalRead(@pin) == 0
return 1 if digitalRead(@pin) == 0
return 1
end
def b2B(lis)
work = 0
for i in lis do
work <<=1
work += i
end
return work
end
def convertData
rhI = b2B(@buf[0..7])
# rhD = b2B(@buf[8..15])
# tmI = b2B(@buf[16..23])
# tmD = b2B(@buf[24..31])
# @crcR = b2B(@buf[32..39])
# @crcC = (rhI + rhD + tmI + tmD) & 0xFF
# if @crcR == @crcC then
# @crc = true
# else
# @crc = false
# end
# @temperature = (tmI & 0x7F) + (tmD / 10)
# if (tmI & 0x80) != 0 then
# @temperature *= -1
# end
@humidity = rhI
# @humidity = rhI + (rhD / 10)
# @buf = []
end
def read
@error = 0
startSignal
markSignal
if !waitSIG(0, 100) then
@error = 1
return false
end
markSignal
b1 = bitRead #bit 0
@buf.push(b1)
b1 = bitRead #bit 1
@buf.push(b1)
b1 = bitRead #bit 2
@buf.push(b1)
b1 = bitRead #bit 3
@buf.push(b1)
b1 = bitRead #bit 4
@buf.push(b1)
b1 = bitRead #bit 5
@buf.push(b1)
b1 = bitRead #bit 6
@buf.push(b1)
b1 = bitRead #bit 7
@buf.push(b1)
markSignal
convertData
return true
end
end
usb = Serial.new(0, 9600)
usb.println("DHT11 Read, Pin.4")
dht11pin=4
dht11 = Dht11.new(dht11pin)
loop_interval = 2000
while true do
usb.println("DHT11 temperature & humidity")
if dht11.read then
usb.println("BUF:" + dht11.readBUF)
dht11.clearBUF
usb.println("HUMIDITY: " + dht11.readHumidity.to_s)
usb.println("ERROR:" + dht11.readERROR.to_s)
end
delay(loop_interval)
end
実験に使用した回路
息をDHT11に吹きかけたら値が大きくなったので、湿度センサのデータを拾っているみたいっす。しまらんなあ。



