おもちゃ、家電、もろもろの修理の足跡と備忘録

色々と忘れるので、趣味のメモ

LUAを使ってAmbientでグラフ化

2020-03-08 14:50:01 | ESP8266DEVkitで遊ぶ
ESP8266 LUA/NodeMCUでAmbientでグラフ化しました。

Facebookのとあるグループで、LUAを使ってAmbient(https://ambidata.io/ )に書き込む方法があったら教えて、と以前投稿したのですが、Cのコードがあるから移植すればできるよね、とか情報を頂きました。投稿する前に調べたのですが、探し方が悪くでてきませんでした。いくつか教えて頂いた中に、shellでの例題を教えてくれた方がいらっしゃったので、それを例題にLUAで動かしてみました。
教えて頂いたshellは、githubのこちら。

httpでPOSTすれば良さげなので、LUAのCustomBuildの中にHTTPモジュールが入っていることを確認してやってみました。shellでの例題をみて、JSONって何さ、とかcurlってなんだろう、とかちょっと調べましたが、まぁ、そういうのがあるんだ、とかと納得しながら、Try and Errorで、mqtt向けに作ったLUA scriptを修正して、動くようにしました。

肝の部分は、こんな感じです。ご参考まで。
サーバでうまく取り込めると、responce_code: 200が返ってきます。
---------------
--[[
ESP8266 NodeMCU LUA言語でambient.ioへデータを送信する
事前にNodeMCUのCustome Buildされたものに、http moduleが
入っていることを確認
ambientの、d1-channelで気温、d2-channelで気圧。
Ambient関連の変数、JSON設定の前にtemp,baroに値を設定
--]]
-- for ambient
AmbientChannelId=xxxxx
AmbientWriteKey='xxxxxxxxxxxxxxxx'
AmbientHeader='Content-Type: application/json\r\n'
AmbientUrl='http://ambidata.io/api/v2/channels/'..AmbientChannelId..'/data'

-- IP関連の設定/NetworkのUpを確認した後
JSON='{"writeKey":"' .. AmbientWriteKey .. '","d1":"'.. temp ..'","d2":"'.. baro ..'"}'

http.post(AmbientUrl, AmbientHeader, JSON,
function(code, data)
if (code < 0) then
print("HTTP request failed")
else
print(code, data)
end
end)


ESP8266DEVkit, nodeMCU, LUAで温度と気圧をInternetで送る(software編5-souce)

2020-02-09 12:05:51 | ESP8266DEVkitで遊ぶ
Luaで書いた、NodeMCU用のsource codeです。
 あちこちの先人達の知恵を頂いて作りました。とりあえず動いておりますがソフトは素人なので、try and errorの結果のcodeです。deep sleepは使っていません。実際のpasswordやtest用のcodeを消して、commentを入れました。
 これを動かすハードウェアについては、前の記載の通りです。
プログラムをコピペするとindentなどが飛んでしまうので、見ずらいですが、ご参考までに。
2020/2/9

-----------------------------------------------------------
-- Send Baro and Temp with NodeMCU over wifi connection using mqtt
-- writen in lua language.
-- tomoharika 2020/2/9 last update..
-----------------------------------------------------------
-- Connection:
-- [mqtt_server]--(wifi)--[NodeMCU]--(i2c)--[bmp280]
--
-- It will send status and messages on your serial line.
-- If it meets some errors, NodeMCU will restart from
-- begining of the source again.
-- So you can find the status by checking the access LED
-- on your NodeMCU, many flushes will be occured error
-- somewhere. Check the serial messages.
-- It goes no error, the access LED flushes every
-- main_loop_interval.
-----------------------------------------------------------

-- initial setting..
alt=50

--for i2c
sda=2 ---D2, GPIO04
scl=1 ---D1, GPIO05
--for main measurement loop timer
main_loop_interval = 300 --[sec]

--set your mqtt server address
mqtt_server_address = "aa.bb.cc.dd"

--for access LED indicator
ledpin = 0 --for D4

--for wifi retry counter
error_count = 0
error_max = 4

--set wifi environment
station_cfg.ssid="set_your_wifi_ssid"
station_cfg.pwd="set_your_wifi_password"

-----------------------------------------------------------------------------
m = mqtt.Client(node.chipid(), 120) -- clientID, keepalive, username, password, cleansession, max_message_length)

m:lwt("/lwt", "offline", 0, 0)
m:on("connect", function(client) print ("connected") end)
m:on("offline", function(client) print ("offline")
print("Restart..")
node.restart()
end)
m:on("message", function(client, topic, data)
print(topic .. ":" )
if data ~= nil then
print(data)
end
end)

-- on publish overflow receive event
m:on("overflow", function(client, topic, data)
print(topic .. " partial overflowed message: " .. data )
end)

function mqtt_loop()
gpio.write(ledpin, gpio.LOW)
P = bme280.baro()
T = bme280.temp()
print(string.format("QFE=%d.%03d Temp=%d.%02d", P/1000, P%1000, T/100, T%100))
m:publish("room1/temp", T/100, 0, 0, function(client) print("sent") end)
m:publish("room1/baro", P/1000, 0, 0, function(client) print("sent") end)
gpio.write(ledpin, gpio.HIGH)
mqtt_timer:start()

end
-----------------------------------------------------------------------------
--when wifi connected..
wifi.eventmon.register(wifi.eventmon.STA_CONNECTED, function(T)
print("\n\tSTA - CONNECTED".."\n\tSSID: "..T.SSID.."\n\tBSSID: "..
T.BSSID.."\n\tChannel: "..T.channel.."\n")
wifi_Up = 1
wifi_timer:start()
end)

--when wifi disconnected..
wifi.eventmon.register(wifi.eventmon.STA_DISCONNECTED, function(T)
print("\n\tSTA - DISCONNECTED".."\n\tSSID: "..T.SSID.."\n\tBSSID: "..
T.BSSID.."\n\tReasone: "..T.reason.."\n")
wifi_Up = 0
wifi_wait_ip()
end)

--when get ip address over the wifi
function wifi_wait_ip()
if wifi.sta.getip()== nil then
print("IP unavailable, Waiting.", error_count)
if error_count > error_max then
print("Error_max exceeded. Wifi reconnecting.")
error_count = 0
wifi.sta.connect()
else
error_count = error_count + 1
end
wifi_timer:start()
else
wifi_timer:stop()
print("\n====================================")
print("ESP8266 mode is: " .. wifi.getmode())
print("MAC address is: " .. wifi.ap.getmac())
print("IP is "..wifi.sta.getip())
print("====================================")
error_count = 0

--after getting ip address over the wifi, then connecting to mqtt server
print("Connecting to Mqtt server with ".. mqtt_server_address )
m:connect( mqtt_server_address, 1883, 0, function(client)
print("Connected to Mqtt server @"..mqtt_server_address)
mqtt_loop()
end,
function(client, reason)
print("Mqtt failed. reason: " .. reason)
print("Restart..")
node.restart()
end)
end
end
--------------------------------------------------------------------------------
-- Start main routine here...
--------------------------------------------------------------------------------
print("### Start Measurement at every "..main_loop_interval.."[sec] ###")

-- for access indicater
gpio.mode(ledpin, gpio.OUTPUT)
gpio.write(ledpin, gpio.HIGH)

-- i2c initializing
print("i2c initializing.")
if i2c.setup(0,sda,scl,i2c.SLOW) == 0 then
print("i2c initializing error. Check i2c connection. Restart.")
node.restart()
end

-- bmp280 initializing
print("bme280 initializing.")
if bme280.setup() == nil then
print("BME/P280 initializing error. Restart.")
node.restart()
end

-- wifi initializing
print("Wifi initializing.")
wifi.setmode(wifi.STATION)
station_cfg={}
-- station_cfg.ssid="xxxxxx" -> set at top of this source program..
-- station_cfg.pwd="xxxxxx" -> set at top of this source program..
station_cfg.auto=false -- true for wifi auto connect mode
station_cfg.save=false
wifi.sta.config(station_cfg)
wifi.sta.connect()
print("Connecting to wifi.")

-- ip connection timer set
wifi_timer = tmr.create()
wifi_timer:register( 3*1000, tmr.ALARM_SEMI, wifi_wait_ip)

-- mqtt connection timer set
mqtt_timer = tmr.create()
mqtt_timer:register( main_loop_interval * 1000, tmr.ALARM_SEMI, mqtt_loop )

wifi_timer:start()
-- end of program lua..


ESP8266DEVkit, nodeMCU, LUAで温度と気圧をInternetで送る(software編4-通信系の設定)

2020-01-04 19:26:44 | ESP8266DEVkitで遊ぶ

i2cで気圧/気温センサBMP280の接続ができたら、いよいよ通信系の設定です。結構手こずったので、作った順にメモと一緒に記憶を整理します。


■通信系の設定


  • 必要なnodeMCUモジュール:wifi

i2c経由でBMP280気圧/温度センサの情報を取得できるようになったら、次は通信系。通信系の設定は色々と手こずりました。複数のタイマーで接続完了を監視をしました。

  • wifi接続をタイマーで監視、
  • DHCPでIPをもらうのをタイマー監視、
  • 後述するMQTTサーバへの接続をタイマー監視、 でようやく、温度と気圧をMQTTサーバへ送ることができます。

以下、参考にした情報を記載します。


■wifi.sta.status()


wifiの接続時にwifi.sta.status()の戻り値によって動作を確認しますが、戻り値(数値)が何を表しているのかが不明で、色々と探した情報です。戻り値”5”が"wifi.STA_GOTIP"のようですので、IPで通信するためには、DHCPでIPアドレスがもらえるまで待つ必要があります。

Return value

https://nodemcu.readthedocs.io/en/master/modules/wifi/#wifistastatus

The current state which can be one of the following:

  • wifi.STA_IDLE
  • wifi.STA_CONNECTING
  • wifi.STA_WRONGPWD
  • wifi.STA_APNOTFOUND
  • wifi.STA_FAIL
  • wifi.STA_GOTIP

hint:

node.restartをかけると、しばらく(5秒くらい)は"1"を返すが、その後"5"に変わる。ping も、restart後は返らないが、同様に5秒ほどすると返るようになる。ESP8266Devkit上のSWでのrestartでも同様。

2019/7/21

→5: wifi.STA_GOTIP

  • wifiがつながっても、DHCPによるIP_addressの取得には時間がかかる → wifiの接続確認と、IPアドレス獲得の2つの監視が必要。

■MQTT


  • 必要なnodeMCUモジュール:MQTT

MQTTとは、”MQTT:Message Queuing Telemetry Transport”。詳細は他のWEBを参照していただくとして、概要は以下の通り。

  • データ発信端末(Publisher)、中継ノード(Broker)、データ受信端末(Subscriber)、の3つの要素からなる、軽量なデータ転送プロトコル
  • Queuingそのものはしてくれない

当初、ESP8266DevkitにmqttのPubulisherを載せて、以下の参考に書いてある、Openなmqttサーバへの接続を試みたがうまく接続できず。結局、同じsubnet内のPCにBrokerを作って、同じsubnet内で閉じる系とすることとした。

→結局、加入しているプロバイダ側でhighport(port>1024?:詳細は不明、聞いても教えてくれない、、)をBlockするサービスを入れていて、それを解除しないと通信ができないことが後でわかった。Debugするためには、まずは全て手元でやるのが良いかもしれません。

下の方でMQTTサーバ(broker)の立て方に触れていますので、参考に。

参考:

nodeMCU/Luaを使って、BME280をMQTTで動かす例が載っている。 https://blog.alexellis.io/iot-nodemcu-sensor-bme280/

初めてのmqtt @GitHub https://gist.github.com/voluntas/89000a06a7b79f1230ab


■mqtt.client callback


  • 必要なnodeMCUモジュール:mqtt

mqttの戻り値です。接続できなければResetして再度接続をするようにしました。

結局、同じsubnet内にbrokerを立ててやりましたが、実際には以下のreturn codeでerror code"-5"が戻って来て動かず、、。

Connection failure callback reason codes:

<figure>
ConstantValueDescription
mqtt.CONN_FAIL_SERVER_NOT_FOUND-5There is no broker listening at the specified IP Address and Port
mqtt.CONN_FAIL_NOT_A_CONNACK_MSG-4The response from the broker was not a CONNACK as required by the protocol
mqtt.CONN_FAIL_DNS-3DNS Lookup failed
mqtt.CONN_FAIL_TIMEOUT_RECEIVING-2Timeout waiting for a CONNACK from the broker
mqtt.CONN_FAIL_TIMEOUT_SENDING-1Timeout trying to send the Connect message
mqtt.CONNACK_ACCEPTED0No errors. Note: This will not trigger a failure callback.
mqtt.CONNACK_REFUSED_PROTOCOL_VER1The broker is not a 3.1.1 MQTT broker.
mqtt.CONNACK_REFUSED_ID_REJECTED2The specified ClientID was rejected by the broker. (See mqtt.Client())
mqtt.CONNACK_REFUSED_SERVER_UNAVAILABLE3The server is unavailable.
mqtt.CONNACK_REFUSED_BAD_USER_OR_PASS4The broker refused the specified username or password.
mqtt.CONNACK_REFUSED_NOT_AUTHORIZED5The username is not authorized.
</figure>

■MQTTのDebug環境整備


  • PCでmosquittoサーバ(broker)を立ち上げる

    この辺りなどを参照

    https://www.1ft-seabass.jp/memo/2015/07/13/windows-7-64bit-install-mosquitto/

    windows10/64bitのCMD.exeを起動して、"mosquiito.exe -v" でbrokerを起動する

    option ”-v” でbroker/subscriberからの情報がコンソールに出力される。(default port=1883)

    この状態で、wifi-up して IP獲得が確認できたら mosquitto-serverに向かって接続をする。

  • AndroidでMQTT Dashboardを立ち上げてサーバにサブスクライバで覗きに行くとデータが見える

    subscriberは、Androidの”MQTT Dashboard"とかなんでも良いですが、接続します。

    mosquito.exe の入ったフォルダに、mosquitto_subというsubscribeのソフトも入っています。

    立ち上げ方は、"mosquitto_sub.exe -v -h localhost -t "#"。

brokerを立ち上げた状態で、subscriberを立ち上げるとbroker側に接続された旨のメッセージがでるので、あとは自分の作ったアプリをDebugします。

  • ESPlorer.exeで wifi_up.lua と wifi-status.lua でwifiに接続する

  • wifiを起ち上げるスクリプト、wifiのstatusを確認するスクリプトをESP8266Devkitに入れておいて、dofileで叩くと、コマンドのように都度確認できます。

  • send-baro-temp.luaを立ち上げて走らせると、サーバに向かってデータを投げる

    • wifiが立ち上がって、IPが取得できたあと、mqtt brokerにデータを投げる

memo:

★wifiのUpを確認するスクリプトをTryしたがうまくゆかず。 wifi.sta.status()が変わらない。

以下のスクリプトで、イベント待ちはできることは確認した。

wifi.eventmon.STA_CONNECTED 状態になったら function(T)をする、というもの。

wifi.eventmon.register(wifi.eventmon.STA_CONNECTED, function(T)  print("\n\tSTA - CONNECTED".."\n\tSSID: "..T.SSID.."\n\tBSSID: "..  T.BSSID.."\n\tChannel: "..T.channel)  end)

https://nodemcu.readthedocs.io/en/master/modules/wifi/#wifieventmon-module のあたりを参考に。

2019/7/28


■通信系の状態管理


通信はプロトコルの積み重ねで成立するので、上位は下部のプロトコルが接続されているかどうかを知る必要があります。wifi/IP/mqttの順で確立してゆくので、その状態を引き渡してゆきます。今回は、下部でエラーなり接続が切れた場合は、Full-resetするようにしました。

この状態遷移をEventDrivenでうまく書けなかったので、statusを持ちまわることで具現化。

 status: 0初期化後の状態

status: 1wifiがUpした状態

status: 2mqttが接続完了した状態

2019/8/1

 


mqtt関連参考


https://iotbytes.wordpress.com/mqtt-with-nodemcu/

https://github.com/hobbyquaker/nodemcu-gpiomqtt/blob/master/gpiomqtt.lua

https://learn.adafruit.com/diy-esp8266-home-security-with-lua-and-mqtt/programming-the-esp8266-with-lua

https://www.foobarflies.io/a-simple-connected-object-with-nodemcu-and-mqtt/

2019/8/6

 


色々と悩みつつLUAスクリプトの開発


そもそもLUA言語の考え方がよくわかっていなかったのですが、TRY&ERRORでやっちゃいました。先人のWEBを参考似、使い方については、https://nodemcu.readthedocs.io/en/master/ の中で検索しつつ作り上げました。上記URLには、それぞれの使い方も記載されているので、非常に参考になりました。スクリプトの名前があちこちにありますが、途中のスクリプトは掲載しませんが、最後に出来上がったスクリプトをご参考までに載せます。

■ wifi-reconnect-ok1.lua

  • wifi.sta.getip()を待つ

wifi.eventmon.register(wifi.eventmon.STA_CONNECTED/DISCONNECTED)で表示されて、IPが払い出されるまでに6秒ほどかかる模様。なので、wifi.sta.getip()でIPをチェックしてから次に進まないとどこかでerrorになる。

error_max でIPがもらえない回数が超えると、reconnectする。

tmrは、MODEでtmr.ALARM_SEMIを設定すると、一度設定した割込みが入ると停止する、再度起動するためには、wifi.timer:start()が必要。

  • wifi.sta.config(cfg)

cfg={}

 cfg.auto=false でAutoConnectがFalseになる、=true でAutoConnect。Config RegisterにModeが記憶されるので、AutoConnectにすると、次にRebootから自動的に接続される。


wifi-reconnect-mqtt-ok2.lua

ok1のUpdate版。mqttでpublishしている時に表示のためにnodeMCU基板上のLEDを点灯させる。

以下は、モバイルバッテリーにつないだESP8266Devkitをwifi経由でPCのMQTTBroker経由してAndroidのアプリでMQTT subcribeしたもの。有効数字?は少数以下2桁くらいありそう。止めてからキャプチャしたのでStatusは”Disconnected"となっています。つながっているときには、”Connected to 192.168.0.30"とかサーバ(MQTTBroker)のアドレスが表示されます。


Androidでbroker(参考)


MQTT Brokerをスマホにインストールして、スマホだけで覗けるようにもしてみました。

Androidに以下の手順でmosquittoをインストール

  • APP storeで‘termux`をインストール(termuxはLinuxのターミナルソフト)
  • apt update
  • apt upgrade
  • pkg install mosquitto
  • mosquitto -v でbrokerを立ち上げる

192.168.0.3x(SmartPhoneを固定IP化して)で検証、動作確認しました。

これに加えて、同じSmartPhoneで同時にsubscribeするために、2画面にしてsubscriberを起動して動作を確認しました。OK!

2019/8/17


wifi-reconnect-ok3.lua

PCのMQTT Brokerで、clean session=false とすることでMQTT Brokerでのclean sessionをfalse, つまりsubscriber側が切れたら、brokerでpublishされたデータを保持してくれる。mqtt.Clientのパラメータで設定する。

(Brokerが落ちているとerror=-5で落ちて動かなくなるのが判明、、。要修正)→とりあえず、mqtt関連でofflineとか Mqtt failed. reason: -5、とかerrorが出たら、node.restart()するようにコード修正。

2019/8/18


なんだかわからないが、起動しても動かない、、。→i2cのケーブルが一本抜けていた。コードで以下の対処をした。

  • BME280.setup()でinitializingの成功を確認、不成功の場合はnode.restartするようにした。i2cでも同様の仕組みを組み込んだ。→この場合、1秒間隔くらいでLEDが点滅する。(node.restartすると、D1pinのあたりの大きなLEDが点灯したのち、RST端子近くの小さなLEDが連続して点滅する。
  • brokerが落ちた場合も、mqtt がofflineになるので、その時にもnode.restart。→この場合、15秒間隔くらいでLEDが点滅する。
これらの対処により、シリアルを接続しなくても、ESP8266Devkitの上のLEDの状態を見るとどの辺りが不良なのかがわかるようにしました。

2019/8/19

 


ESP8266DEVkit, nodeMCU, LUAで温度と気圧をInternetで送る(software編3-i2cの設定)

2020-01-04 18:20:41 | ESP8266DEVkitで遊ぶ
<title>3-i2c-BMP280設定a</title>

LUA開発環境が整ったところで、今度はLUAから見た時のinterfaceや使用したモジュールの使い方のポイントについて記載します。


nodeMCU v1.0 Pins


EPS8266Devkitの基板上に書かれたPinの名称(GPIO番号<以下の表では"ESP8266 Pin"の項目>)は、nodeMCUのポート(I/O index)番号とは異なります。以下がそのMapになります。i2cで使ったSCLとSDAのPinを表の右に示します。(i2cでは、この信号Pinと、電源:3V3、GNDの合計4本が必要です)

NodeMCU provides access to the GPIO (General Purpose Input/Output) and a pin mapping table is part of the API documentation.[17]

<figure>
I/O indexESP8266 pin備考
0 [*]D0:GPIO16 
1D1:GPIO5SCL
2D2:GPIO4SDA
3D3:GPIO0 
4D4:GPIO2 
5D5:GPIO14 
6D6:GPIO12 
7D7:GPIO13 
8D8:GPIO15 
9RX:GPIO3 
10TX:GPIO1 
11SD2:GPIO9 
12SD:3GPIO10 
</figure>

[*] D0 (GPIO16) can only be used for GPIO read/write. It does not support open-drain/interrupt/PWM/I²C or 1-Wire.

上記はhttps://en.wikipedia.org/wiki/NodeMCUから持ってきたものに、I/O indexに9-12と備考を追加したもの。2019/7/21


■ESP8266Devkitにi2cをつなげる


温度、気圧センサBMP280をi2cでESP8266Devkitに接続します。i2cはSCL(clock)、SDA(data)とGNDの3本(電源の供給も必要であれば4本)の信号線でデバイスを接続します。hardware編で記載したように接続します。まずはちゃんとnodeMCUからBMP280が見えるかどうか確認します。もちろん、nodeMCU上にi2cのソフトウェアモジュールが必要です。なければnodeMCUの再構築が必要となります。


■i2cの接続確認 "i2c_scanner.lua"


  • 必要なnodeMCUモジュール:i2c

LUAで自動的にi2cの接続されているpin番号と、i2cのアドレスをチェックしてくれるプログラム。i2cの接続確認に非常に役に立ったので載せておきます。

https://www.esp8266.com/viewtopic.php?f=19&t=1049#p6198 です。

-- i2c_scanner.lua
-- Based on work by sancho and zeroday among many other open source authors
-- This code is public domain, attribution to gareth@l0l.org.uk appreciated.
id=0  -- need this to identify (software) IC2 bus?
gpio_pin= {5,4,0,2,14,12,13} -- this array maps internal IO references to GPIO numbers
-- user defined function: see if device responds with ACK to i2c start
function find_dev(i2c_id, dev_addr)
i2c.start(i2c_id)
c=i2c.address(i2c_id, dev_addr ,i2c.TRANSMITTER)
i2c.stop(i2c_id)
return c
end
print("Scanning all pins for I2C Bus device")
for scl=1,7 do
for sda=1,7 do
  tmr.wdclr() -- call this to pat the (watch)dog!
  if sda~=scl then -- if the pins are the same then skip this round
       i2c.setup(id,sda,scl,i2c.SLOW) -- initialize i2c with our id and current pins in slow mode :-)
       for i=0,127 do -- TODO - skip invalid addresses 
            if find_dev(id, i)==true then
            print("Device found at address 0x"..string.format("%02X",i))
            print("Device is wired: SDA to GPIO"..gpio_pin[sda].." - IO index "..sda)
            print("Device is wired: SCL to GPIO"..gpio_pin[scl].." - IO index "..scl)
            end
       end
  end
end
end

以下は、実際にESP8266Devkitに接続したBMP280の接続確認結果。 上記プログラムを、file名'i2c_scan.lua'でnodeMCUに登録(Save to ESPで書き込む)して、ESPloereの右ペインの最下段から”dofile('i2c_scan.lua')”で起動した結果です。I/O index 1,2 (GPIO4,5)につながった0x76番デバイスを見つけたことになります。私が使ったBMP280モジュールはdefaultでアドレスが0x76でした。BMP280を複数つなげるときには、アドレスを変更するため(同一i2cBUS上に同じアドレスは許容されない)にBMP280モジュール側でジャンパ等の対応をする必要があります。これにより0x77に設定できるようです。

dofile("i2c_scan.lua")
--
Scanning all pins for I2C Bus device
Device found at address 0x76
Device is wired: SDA to GPIO4 - IO index 2
Device is wired: SCL to GPIO5 - IO index 1

■i2cで接続されたBMP280から気温と気圧を得る


  • 必要なnodeMCUモジュール:i2c、BME280

timer割り込みを使って、設定された時間(ここでは60sec)ごとに計測した温度と気圧を表示します。

★hints:

tmrモジュールはhttps://nodemcu.readthedocs.io/en/master/modules/tmr/ の記載(以下の注意書き)にあるように、2019年Q1(第一四半期)にI/Fが変更されていて、internet上に転がっている古いLUAプログラムを持ってきて動かすとエラーになることがあります。→私ははじめこれがわからず、随分苦労しました。nodeMCUのバージョンとLUAの組み合わせには注意が必要です。以下は、新しいnodeMCUで動作しますが、古いnodeMCUではエラーになります。

これをやっていた頃は2019の夏、丁度切り替わりの時期だったんですね。混乱しました。

■Attention

NodeMCU formerly provided 7 static timers, numbered 0-6, which could be used instead of OO API timers initiated with tmr.create(). After a long period of deprecation, these were removed in 2019 Q1.

https://nodemcu.readthedocs.io/en/master/modules/tmr/ に記載があります。

tmr moduleは、static と dynamicがあって、staticは将来なくなる、と記載あり。で、例えば

--

NodeMCU custom build by frightanic.com branch: master commit: c16adb5dfb8c02b692034bbd553502765b9733cc SSL: false modules: adc,bme280,file,gpio,http,i2c,mqtt,net,node,pwm,rtctime,tmr,uart,wifi build created on 2019-07-20 23:15 powered by Lua 5.1.4 on SDK 2.2.1(6ab97e9) lua: cannot open init.lua

--

では、staticではエラーとなる。なので”dynamic”で動かす必要ある。

tmr.alarm([id/obj],interval,,,,,, と書いてあるので、[id/obj]を抜けばよいような気もする。→未確認。

2019/8/7

--- read-baro-temp-by-timer.lua
--- alarmを使って定期的に気圧と気温を得る
--- 2019/7/20

alt=50
scl=1   ---D1, GPIO05
sda=2   ---D2, GPIO04
interval = 60000
i2c.setup(0,sda,scl,i2c.SLOW)
bme280.setup()
print("## Start sensing with interval ", interval ,"msec ##")
tmr.create():alarm(interval, tmr.ALARM_AUTO, function()
P = bme280.baro()
T = bme280.temp()
print(string.format("QFE=%d.%03d Temp=%d.%02d", P/1000, P%1000, T/100, T%100))
end)

以下は、上記のプログラムの出力、60秒ごとに気圧と気温情報を取得して値を印字する。上記は、nodeMCUで、BME280モジュールが必要です。今回接続しているモジュールはBMP280ですが、nodeMCUのモジュール名はBME280です。nodeMCUがrestartされた時の搭載モジュール名にBME280がなければ、nodeMCUの再構築が必要です。

## Start sensing with interval 	60000	msec ##
QFE=1769.129 Temp=26.88
QFE=1769.143 Temp=26.89
QFE=1769.178 Temp=26.90
QFE=1769.205 Temp=26.91
QFE=1769.247 Temp=26.92
QFE=1769.288 Temp=26.94
QFE=1769.329 Temp=26.95

気圧が1769ヘクトパスカル、このBMP280の気圧の数値は明らかにおかしい。二個買ったのでもう一つで確認したところ、1000位の数値を出したので、そちらが正しい模様。この個体は不良品でした。



ESP8266DEVkit, nodeMCU, LUAで温度と気圧をInternetで送る(software編2-アプリ作成環境)

2019-12-23 22:00:15 | ESP8266DEVkitで遊ぶ
<title>Lua開発環境の設定</title>

nodeMCU(Firmware)がESP8266Devkitに載せられたら、次はLUAの開発環境を用意します。


■PCとESP8266Devkitとの接続


ESP8266Devkitとの接続は前述のnodeMCUをインストールした時の構成、PCのUSBでESP8266Devkitと接続します。


■パソコンとESP8266Devkitのモニタプログラムとをつなぐ


私は、ESPlorerというIDEを使ってlua言語で開発を行いました。ESPlorerはJavaで作ってあって、Windows、Linux、MacなどのJavaVMの上で動くようです。それぞれの環境用のJavaVMのインストールが必要です。PCとはシリアル(USBでPCとESP8266Devkitとを接続して使用)で接続して、PC上で開発、ESP8266Devkit側にダウンロードして動作を確認する、所望の動作が確認できたらESP8266Devkitに転送して書き込む、という開発スタイルとなります。

このあたりを参考にしてください。

https://github.com/NightRobot/nodemcu/blob/master/Getting%20Started%20with%20the%20ESPlorer%20IDE%20-%20Rui%20Santos.pdf

https://www.esp8266.com/viewtopic.php?f=22&t=882

 

大まかに言うと、ESPlorerの画面右半分がPCとESP8266Devkitとのシリアル通信、nodeMCUのモニタプログラムとの通信のモニタができます。左半分がLUAのプログラムを作成する部分です。まずは、PCとESP8266Devkitとのシリアル通信開始。

  1. 右上のPCの[Serial Port]を設定して、

  2. [Open]を押下するとPCとESP8266DevkitがSerialで通信を始めます。通信が疎通するとDTR/RTS、Openが緑に変わります。(上記の図ではSerial通信が確立した状態です)

  3. 通信速度は、多分[115200bps]で通信ができると思いますが、だめなら9600bpsなどに変えてみてください。通信が確立すると、右中央の大きなコンソールに、通信ログが表示され、nodeMCUの情報が表示されます。

  4. 同時にESP8266Devkitのボードの上のLEDが点滅します。

  5. うまくつながると以下のようなメッセージが右ペインの中央のウィンドウに表示されます。

    <調歩同期の速度が変わるので、文字化けが数行続きます>
    
    NodeMCU custom build by frightanic.com
    	branch: master
    	commit: c16adb5dfb8c02b692034bbd553502765b9733cc
    	SSL: false
    	modules: adc,bme280,file,gpio,http,i2c,mqtt,net,node,pwm,rtctime,tmr,uart,wifi
     build created on 2019-07-20 23:15
     powered by Lua 5.1.4 on SDK 2.2.1(6ab97e9)
    lua: cannot open init.lua
    

    "NodeMCU custom build...."の以下は、前の項目でcloudで作成したnodeMCU Firmwareの情報が表示されます。

    また、nodeMCUが正常に起動すると、"init.lua"という名前のlua fileに実行が移ります。上記の場合は、"init.lua"がまだないので、”lua: cannot open init.lua"とエラーが出ています。電源On、software-resetなどで自分が作ったソフトを起動したい場合は、"init.lua"とファイルをESP8266Devkitに登録しておけば良いことになります。


■nodeMCU monitorのrestart


右最下段の、右側に「←Send」があるところに"node.restart()"と記入してまたは「←Send」を押すとソフトウェアでESP8266Devkitをsoftware-resetすることができます。ここではその他、nodeMCUとの通信によってnodeMCUの上での操作(例えばESP8266Devkit上のプログラムファイルの読み書き、File Format、プログラムファイルの実行など)が可能です。

例:
node.restart()				←reset
=file.rename('xxx','yyy')	 ←fileのrename
=file.remove('xxx')			←fileの削除
dofile('xxx')				←fileの実行

■Luaで上位アプリを作成する。


手始めに、ESP8266Devkitの基板の上についているLEDをブリンク(いわゆるLチカ)させてみます。以下のLuaプログラムを左ペイン中央のwindowで[Script]タブになっていることを確認して、Copy&Pasteします。

pin = 4
status = gpio.LOW
gpio.mode(pin, gpio.OUTPUT)

tmr.create():alarm(1000, tmr.ALARM_AUTO, function()
if status==gpio.LOW then
    status=gpio.HIGH
else
    status = gpio.LOW
end
gpio.write(pin, status)
end)

左ペインの最下段、左から2番目の「Send to ESP」ボタンを押下します。これにより、ESP8266Devkitに転送され自動的に実行されます。基板上の青いLEDが一秒間隔で点滅していると思います。

その上でもう一度「Send to ESP」ボタンを押下してみてください。点滅間隔が変わりませんか。押下するタイミングで色々と変化すると思いますが、上記のプログラムは、「今のStatusを見てそれをひっくり返す」動作をします。二回ボタンを押下したことで、2つのプログラムが同時に走行している状態となり、それぞれが今の状態をひっくり返しているのです。「同時に複数のプログラムを走らせられる」のですね。面白い。

先程の"node.restart()"で上記は止められます。


■ESP8266Devkitにプログラムを書き込む


ESP8266Devkitにプログラムを書き込むのは簡単、一旦PCにプログラムをファイル名をつけて書き込んだ後に、左側ペインの最下段の左端「Save to ESP」を押下することで、書き込まれます。


■書き込まれたかを確認する(snippetに登録する)


ESP8266Devkitにファイルとして書き込まれたかを確認するには、以下を使うと簡単にできます。上記と同様に一旦PCに"list-file"とかの名前をつけて保存して、都度右下で"dofile('list-file')"で使うことができますが、よく使う機能を登録する方法があります。snippetと呼ばれる機能です。右側ペインの通信ログのすぐ下に"snippet0.....snipet1"というボタンがあります。そこに登録するのですが、登録するには、左側ペインのプログラムを記入するエリアの上に、先程の[script]の並びに[snippets]というタブがあり、それを選択して、[Edit SnippetX]に登録したい機能を記載することで、いつでも使えるようになります。

l = file.list();
for k,v in pairs(l) do
  print("name:"..k..", size:"..v)
end

以上で、ESPlorer IDEの使い方を大まかに説明しました。これであとは自分で作りたいアプリを作成して、ESP8266Devkitに"init.lua"名前で登録すれば、電源Onまたはrestart等で自動起動できるようになります。

次は、私が作ったESP8266Devkitで動くソフトについて記載します。


ESPloereインストールの参考WEB page:


https://www.electronicwings.com/nodemcu/getting-started-with-nodemcu-using-esplorer

https://www.esp8266.com/viewtopic.php?f=22&t=882