■動作テスト:mqttあり
・コードはベタで載せます。
・参照URLの改行異常有無にご留意のうえ適宜調整ください。
・今回は取り急ぎmqttありのテストです。
・受信(subscribe)は以前の記事ご参照
(修正前の問題点)
・受信と送信の時刻がずれる→NTPで時刻合わせをしたい。
・月日時分秒は一桁だと文字数が減る→0埋めしたい。
(修正方法)
↓コレだけで一気に片付きました。
出典1
https://interface.cqpub.co.jp/wp-content/uploads/if2207_144.pdf
【フォルダ構成】
【動作テストコード:mqttあり】
###### server room monitor ######
# version 0.2
# required W5100-EVB-PICO
# required UF2 for W5100-EVB-PICO
# https://micropython.org/download/W5100S_EVB_PICO/
# required rtc DS3231
# required labrary for mqtt
# get simple.py from as bellows;
# https://github.com/micropython/micropython-lib/blob/master/micropython/umqtt.simple/umqtt/simple.py
# set simple.py in umqtt folder
# get robust.py from as bellows;
# https://github.com/micropython/micropython-lib/tree/master/micropython/umqtt.robust
# set robust.py in umqtt folder
# robust.py adds auto-reconnect facilities for some of networking errors.
from umqtt.simple import MQTTClient
#typical UF2 for PICO has no network-library
#so,required UF2 for W5100-EVB-PICO
import network
#libraries for connecting to NTP
import ntptime
import utime
#library for AHT20 as Humidity and Temperature Sensor
from ahtx0 import AHT20
#ds3231 require special library
# arranged by kabayon 241111
from ds3231 import DS3231
#ssd1306 oled-dsiplay require special library
#import ssd1306
from machine import Pin,SPI
from machine import SoftI2C
from time import sleep_ms
import time
# スイッチ(入力)オブジェクト設定
as01 = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)
as02 = machine.Pin(3, machine.Pin.IN, machine.Pin.PULL_UP)
as03 = machine.Pin(4, machine.Pin.IN, machine.Pin.PULL_UP)
as04 = machine.Pin(5, machine.Pin.IN, machine.Pin.PULL_UP)
ms01 = machine.Pin(7, machine.Pin.IN, machine.Pin.PULL_UP)
ms02 = machine.Pin(8, machine.Pin.IN, machine.Pin.PULL_UP)
ms03 = machine.Pin(9, machine.Pin.IN, machine.Pin.PULL_UP)
sts_as01 = as01.value()
sts_as02 = as02.value()
sts_as03 = as03.value()
sts_as04 = as04.value()
dec_address = 8*sts_as01 + 4*sts_as02 + 2*sts_as03 + sts_as04
bit_address = str(sts_as01) + str(sts_as02) + str(sts_as03) + str(sts_as04)
sts_ms01 = ms01.value()
sts_ms02 = ms02.value()
sts_ms03 = ms03.value()
dec_mode = 4*sts_ms01 + 2*sts_ms01 + sts_ms03
bit_mode = str(sts_ms01) + str(sts_ms02) + str(sts_ms03)
#print("address - ",bit_address,dec_address," mode - ",bit_mode,dec_mode)
set_on =1
set_off=0
if sts_ms03==1:
mode_ntp_get=set_on
else:
mode_ntp_get=set_off
if sts_ms02==1:
mode_continuous=set_on
else:
mode_continuous=set_off
#set i2c0
sda_i2c0 = 0
scl_i2c0 = 1
freq_i2c0= 400000
i2c0 = SoftI2C(scl=Pin(scl_i2c0), sda=Pin(sda_i2c0), freq=freq_i2c0)
#set AHT20-object
aht21 = AHT20(i2c0)
#set RTC-object
rtc_ds3231 = DS3231(i2c0)
sleep_ms(2000)
#def MQTT connect
def mqtt_connect():
client = MQTTClient(client_id, address_mqtt_broker, keepalive=60)
client.connect()
print('Connected to %s MQTT Broker'%(address_mqtt_broker))
return client
#def reconnect & reset
def reconnect():
print('Failed to connected to MQTT Broker. Reconnecting...')
time.sleep(5)
machine.reset()
#connect to w5100
#initialize W5100
#set valiables for SPI
spi_chn = 0
baud_rate = 400000
pin_mosi = 19
pin_miso = 16
pin_sck = 18
pin_cs = 17
pin_reset= 20
#set spi-object with spi-channel,bauerate,mosi,miso,sck
spi=SPI(spi_chn,baud_rate, mosi=Pin(pin_mosi),miso=Pin(pin_miso),sck=Pin(pin_sck))
#set WIZNET5100 with spi-object,pin-CS,pin-reset
nic = network.WIZNET5K(spi,Pin(pin_cs),Pin(pin_reset))
#activate nic, after that RJ45-lamp is on and blinking
nic.active(True)
#setting ip-parameter
address_me = '192.168.10.88'
net_mask = '255.255.255.0'
address_rooter = '192.168.10.1'
address_dns = '192.168.10.1'
nic.ifconfig((address_me,net_mask,address_rooter,address_dns))
#check nic-connection
while not nic.isconnected():
time.sleep(1)
print('--- waiting connection to nic')
print('nic connect to network')
# get UTC from NTP and convert JST
import ntptime
import utime
ntptime.settime()
JST_OFFSET = 9*60*60
# 時刻を取得、JST で表示する
(year_ntp, month_ntp, day_ntp, hour_ntp, minute_ntp, second_ntp, weekday_ntp, year_day_ntp) = utime.localtime(utime.time() + JST_OFFSET)
#set time_ntp to rtc
if mode_ntp_get==set_on:
rtc_ds3231.set_time(year_ntp, month_ntp, day_ntp, hour_ntp, minute_ntp, second_ntp, weekday_ntp, 00)
#set configuration for mqtt-broker and topic
address_mqtt_broker = '192.168.10.24'
client_id = 'kabaw5101'
topic_pub = b'test_mqtt/kabaw5101'
try:
client = mqtt_connect()
except OSError as e:
reconnect()
if mode_continuous==set_on:
i_max=300000
else:
i_max=1 #one-shot
#interval 600000msec=10minutes
time_interval=600000
for i in range(0,i_max):
time_rtc = rtc_ds3231.get_time()
year_rtc = f"{time_rtc[0]:4d}"
month_rtc = f"{time_rtc[1]:02d}"
day_rtc = f"{time_rtc[2]:02d}"
hour_rtc = f"{time_rtc[3]:02d}"
minute_rtc = f"{time_rtc[4]:02d}"
second_rtc= f"{time_rtc[5]:02d}"
time_record = year_rtc+month_rtc+day_rtc+hour_rtc+minute_rtc+second_rtc
#print("temp:",aht21.temperature," humd:",aht21.relative_humidity)
temperature_record = str
temp_now = aht21.temperature
humd_now = aht21.relative_humidity
aht20_record ="T" + str(round(temp_now,1)) + "H" + str(round(humd_now,1))
data_record = "A"+bit_address+"M"+bit_mode+"D"+time_record+aht20_record
print(data_record)
topic_msg = data_record
client.publish(topic_pub, topic_msg)
if i_max==1:
sleep_ms(100)
print ("one-shot end")
else:
sleep_ms(time_interval)
print ("program end at i_max:",i_max)
■動作結果
【Publish側】PICO接続Thonnyのコンソール表示
MPY: soft reboot
--- waiting connection to nic
--- waiting connection to nic
nic connect to network
Connected to 192.168.10.24 MQTT Broker
A0101M111D20241112134401T25.6H50.7
A0101M111D20241112134406T25.7H50.8
A0101M111D20241112134411T25.6H50.7
A0101M111D20241112134416T25.6H50.5
A0101M111D20241112134421T25.6H50.6
A0101M111D20241112134426T25.6H50.7
A0101M111D20241112134431T25.6H50.6
A0101M111D20241112134436T25.6H50.6
A0101M111D20241112134441T25.7H50.7
A0101M111D20241112134447T25.7H50.6
【Subscribe側】VSCODE上のJupyterコンソール表示
Connected with result code 0
2024/11/12 13:44:00,b'A0101M111D20241112134401T25.6H50.7',test_mqtt/kabaw5101,0
2024/11/12 13:44:05,b'A0101M111D20241112134406T25.7H50.8',test_mqtt/kabaw5101,0
2024/11/12 13:44:10,b'A0101M111D20241112134411T25.6H50.7',test_mqtt/kabaw5101,0
2024/11/12 13:44:15,b'A0101M111D20241112134416T25.6H50.5',test_mqtt/kabaw5101,0
2024/11/12 13:44:20,b'A0101M111D20241112134421T25.6H50.6',test_mqtt/kabaw5101,0
2024/11/12 13:44:25,b'A0101M111D20241112134426T25.6H50.7',test_mqtt/kabaw5101,0
2024/11/12 13:44:31,b'A0101M111D20241112134431T25.6H50.6',test_mqtt/kabaw5101,0
2024/11/12 13:44:36,b'A0101M111D20241112134436T25.6H50.6',test_mqtt/kabaw5101,0
2024/11/12 13:44:41,b'A0101M111D20241112134441T25.7H50.7',test_mqtt/kabaw5101,0
2024/11/12 13:44:46,b'A0101M111D20241112134447T25.7H50.6',test_mqtt/kabaw5101,0
Pub側のDデータ(時刻)はRTC(DS3231)の時刻です。
Sub側にはNTCで時刻合わせされた受信時刻が記載されています。
短時間のテストでは送信時刻とSub受信時刻のズレは概ね1秒以内です。
今回使用のDS3231はMEMS方式ですが、結構ずれやすいとの話があるようですので、1週間ほど連続稼働してズレを確認したいと思います。(後日報告予定)
【241112当日追記】
・2時間連続稼働して、ズレはほぼなしでした。
2024/11/12 14:29:30,b'A0101M111D20241112142930T26.2H51.6',test_mqtt/kabaw5101,0
・・・
2024/11/12 16:38:42,b'A0101M111D20241112163842T25.6H54.0',test_mqtt/kabaw5101,0
5秒毎のmqttだとデータが無駄に多くなりますので、
sleepの値を1時間にしてデータ取り再開しました。
【241118追記】
Connected with result code 0
2024/11/18 11:15:36,b'A0101M100D20241118111535T25.4H56.0',test_mqtt/kabaw5101,0
一旦停止して電源ケーブルを外し、RTCは電池だけで維持して一週間ほど立ちましたが、時刻のズレは1秒以内に収まっていました。
ディップスイッチでモードをセットするようにして、NTP時刻取得&RTC修正モード
、ワンショットモードを設け、より実用的にしました。
【追記241124】
コードを貼り替えました。
また、久々にNTPと同期させずに起動、接続してみました。
Connected with result code 0
2024/11/24 14:10:56,b'A0101M100D20241124141052T20.9H43.5',test_mqtt/kabaw5101,0
2024/11/24 14:11:55,b'A0101M100D20241124141151T20.7H43.8',test_mqtt/kabaw5101,0
おおお、4秒ズレました。
ここ1週間で急に気温が低下してきましたし、暑い寒いを鑑みて、
定期的に、例えば毎日1回、NTPと同期したほうがよいようです。
多少のコード追記は後日トライします。
以上、本件終了。