MicroPythonのマイクロファン専用ファームウェア

ドライバとライブラリ

MicroPythonで入出力装置やセンサーを使用したプログラミングを行う際には、一般的に、あらかじめそれらを制御するドライバーやライブラリを開発ボードに組み込んでおく必要があります。このため、使用する入出力装置やセンサーに対応した適切なドライバーやライブラリを探して取得し、さらに開発ボードのファイルシステムに登録しておくことは、特に初心者にとっては面倒な作業になります。

マイクロファンは、このような面倒な準備作業を軽減できるように、マイクロファンの開発ボード専用のMicroPythonファームウェアを配布しています。このファームウェアには、マイクロファンの開発ボードで標準的に使用する入出力装置やセンサーなどのドライバーやライブラリがあらかじめ組み込まれており、開発ボードに専用ファームウェアを書き込めば、その開発ボードで使用する様々な入出力装置やセンサーを使用したプログラムをすぐに開発することができるようになります。

専用ファームウェア

マイクロファンの専用ファームウェアは以下のページから取得できるので、ESP32-C3M-TRYに書き込んでご利用ください。下記のページには、ドライバーやライブラリの組込み以外のマイクロファンの専用ファームウェアの追加機能なども記載されているのでご確認ください。


MicroPythonプログラミング

以下に、専用ファームウェアを書き込んだ開発ボードの使用法を説明します。専用ファームウェアの固有機能を使っている部分があるので、MicroPythonのオリジナルのファームウェアを書き込んだ開発ボードではここで示す方法では利用できないことがあります。

以下にMicroPythonのプログラム例を示しますが、合わせてMicroPythonのサイトのESP32用クイックリファレンスのページもご参照ください。


ESP32-C3M-TRYでのプログラム例

この章では、ESP32-C3M-TRYのプログラム例を示しています。

端子の割り当て

シンボル信号線備考
SW1
SW2
SW3
SW4
SW5
D2
D3
D6
D9/SCL
RST
負倫理
負論理
負論理
BOOTローダーモード移行用
リセット
LED1
LED10-LED12
D0
D10
正論理
WS2812B(NeoPixel), CN4
SCL0
SDA0
D9
D10
OLEDディスプレイ、温度・湿度センサー、加速度センサー
X1D21圧電スピーカー
Q2D1(ADC)明るさセンサー(フォトトランジスタ)、アナログ値
CN2D20人感センサー
CN3D7RCサーボ
CN5 TRIG
CN5 ECHO
D4
D5
超音波距離センサー

SW4 は、リセット時のブートモード(MicroPythonのファームウェアの書き込み)の切り替え
用ですが、信号線が I2C の SCL 信号と共用のため、プログラムが走り始めたあとは、一般的な入
力用のスイッチとして利用するこはできません。

CN2-CN5 のコネクタは、標準的な使用法は決まっていますが、電源や信号線を適切に使用する
ならば、標準的な使用法以外の拡張用端子として使用することができます。


LED

LEDの点灯

マイクロファンのESP32開発ボードには、マイクロコントローラから点滅を指示できるLEDが搭載されています。そのLEDをMicroPythonで操作する方法を示します。

ESP32のMicroPythonでは、一般的にはLEDが接続されている端子番号を使用して、制御用端子の指定や制御を行います。マイクロファンのファームウェアでは、LED制御用の端子に、’LED’および’LED1’という機能名が付けられており、端子番号ではなく機能名で指定することができます。(もちろん、従来通り、端子番号で指定することもできます。)

from machine import Pin
import time

led1 = Pin('LED1', Pin.OUT) # 'D13'でも10でもよい
led1.on()
time.sleep_ms(1000) # 1000ms, 1秒待つ
led1.off()

このプログラムは、単純に1秒だけLEDを点灯させています。

マイクロファンはいくつかのESP32開発ボードを提供しており、開発ボードによってLEDが接続されている端子番号が異なります。このため、LEDの操作をしようとすると、LEDの端子番号を確認したり、プログラムを他の開発ボードに移植しようとすると、端子番号を変更する必要があります。

しかしながら、マイクロファンのMicroPythonファームウェアでは、このように機能名でLEDを指定できるので、端子番号を調べたり、移植の際に端子番号を変更したりする必要がありません。

LEDの点滅

LEDを一定間隔で点滅するプログラムを示します。

from machine import Pin
import time

led1 = Pin('LED1', Pin.OUT)
while True:
    led1.on()
    time.sleep_ms(1000) # 1000ms, 1秒待つ
    led1.off()
    time.sleep_ms(1000)

# CTRL-Cで中断

LEDの明暗制御

LEDはPWMを使用して、単純に点灯、消灯だけでなく、明暗の度合いを制御できます。

PWMを使用してLEDの明暗を制御するプログラムを示します。

from machine import Pin, PWM
import time

led1 = PWM(Pin('LED1'), freq=1000)

delta = 1
duty = 0
while True:
    duty += delta
    if duty == 1023:
        delta = -1
    elif duty == 0:
        delta = 1
    led1.duty(duty) # 0-1023
    time.sleep_ms(1)

# CTRL-Cで中断

LEDをPWMで制御するように初期化し、Whileループの中で、PWMのデューティー比を増減させて、LEDの明暗を変化させています。


スイッチ

ESP32-C3M-TRYにはSW1-SW3の3個のスイッチが搭載されています。

スイッチによるLEDの点灯

このスイッチを使用して、スイッチを押したときにLEDが点灯し、スイッチを離したときにLEDが消灯するプログラムを以下に示します。

from machine import Pin

led1 = Pin('LED1', Pin.OUT)
sw1 = Pin('SW1', Pin.IN)
while True:
    led1.value(not sw1.value())

# CTRL-Cで中断

スイッチもLEDと同様に、端子番号で指定・制御することができますが、マイクロファンのファームウェアでは、例えばSW1に’SW1’という機能名が割り当てられているため、その機能名で端子を指定することができます。

ESP32-C3M-TRYのスイッチは負論理となっており、スイッチが押されたときにoffもしくは0、離されている時にonもしくは1となります。このプログラムでは、正論理のLEDを接続している場合のもので、負論理のスイッチの読み取り結果を ‘not’ を付けて正論理に変換してLEDの引数としています。


圧電スピーカー

明るく光るLEDは出力装置として魅力的ですが、音を出す圧電スピーカーも電子工作では外せませんね。圧電スピーカーは圧電素子を使ったスピーカーで、ESP32-C3M-TRYに搭載されているものは直径が1センチ程度の小さなものです。

圧電スピーカーを操作するTONEドライバーは、マイクロファンのファームウェアにあらかじめ組み込まれているため、改めて導入する必要などはありません。

異なる周波数の音の出力

周波数が100Hzから1000Hzまで、100Hzごとに周波数を上げて音を出力するプログラム例を示します。(実際に出力される音(の高さ)は、圧電スピーカーの特性によるのか、ちょっと違和感があります。)

from tone import TONE
import time

snd = TONE('SND')

for hz in range(100,1001,100): # 100Hz -1000Hz
    snd.on(hz)
    time.sleep_ms(500)
    
snd.off()

ESP32-C3M-TRY用のファームウェアを使用している場合、圧電スピーカーが接続されている端子には’SND’という機能名が割り当てられているので、端子番号の代わりに、’SND’を指定できます。

スイッチによる音の出力

スイッチを押すと音が鳴るプログラム例を示します。

from machine import Pin
from tone import TONE
import time

snd=TONE('SND')
sw1=Pin('SW1', Pin.IN)

while True:
    if (sw1.value() == 0): # スイッチが押されたとき
        snd.on(400)
    else:
        snd.off()
    time.sleep_ms(100)

# CTRL-Cで中断

カエルの歌

TONEでは、音の周波数だけでなく音名を指定することができます。

皆様ご存じカエルの歌です。お楽しみください。

以下のサイトの音符を利用させていただきました。

from tone import TONE
import time

snd=TONE('SND',50)

kaeru = [ 'ド4', 'レ4', 'ミ4', 'ファ4', 'ミ4', 'レ4', 'ド4', 'ド4',
'ミ4', 'ファ4', 'ソ4', 'ラ4', 'ソ4', 'ファ4', 'ミ4', 'ミ4',
'ド4', '休符', 'ド4', '休符', 'ド4', '休符', 'ド4', '休符', 
'ド4', 'レ4', 'ミ4', 'ファ4', 'ミ4', 'レ4', 'ド4', 'ド4']

for s in kaeru:
    snd.on(s)
    time.sleep_ms(400)

snd.off()

圧電スピーカーの周波数特性なのか、方形波の高調波成分のせいなのか、そもそも、周波数リストの数値誤りなのか、ちょっと違う感じもありますが、楽しめましたか?

それから、音符の長さを一定にしている都合で、あからさまに表現が異なるところがありますがご容赦ください。:-P


OLEDディスプレイ

OLEDディスプレイを使用するためには、そのドライバーが必要ですが、マイクロファンのMicroPythonファームウェアには、あらかじめOLEDディスプレイ用のドライバーが内蔵されているので、そのインストール作業などを行うことなく利用することができます。

ここで使用例を示すssd1306の説明書を以下に示すので、参考にしてください。

OLEDディスプレイ表示用のドライバは、FrameBufferというクラスをベースに作成されています。したがって、OLEDディスプレイ表示用のドライバで使用できるメソッド(文字の表示やグラフィックス)の多くは、FrameBufferの説明書で確認することができます。以下にFrameBufferの説明書を示すので、参考にしてください。

OLEDディスプレイへの文字表示

コントローラにSSD1306を使用した0.96インチのOLEDディスプレイに文字列を表示するプログラム例を示します。

I2Cクラスの引数は、複数あるI2Cチャネルの番号を指定するだけで、具体的な端子などを指定する必要はありません。ESP32-C3M-TRYのOLEDディスプレイを使用する場合には、0番を指定します。

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C

i2c = I2C(0) #
# i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=400000)
oled = SSD1306_I2C(128, 64, i2c)

oled.text('-ESP32-C3M-TRY-', 8, 0) # 第二引数は文字を出力する横のピクセル座標、第三引数は縦のピクセル座標
oled.text('MicroFan', 32, 8)
oled.text('OLED Display', 0, 16)
oled.text('Piezo Speaker', 0, 24)
oled.text('Brightness SNSR', 0, 32)
oled.text('Temp. Hum. SNSR ', 0, 40)
oled.text('Accelerometer', 0, 48)
oled.text('WS2812 RGB LED', 0, 5)
oled.show()

ssd1306での文字出力は、文字を出力する座標を毎回指定する必要があります。グラフィックス表示と合わせて文字表示をする場合には役立ちますが、文字だけを出力する場合には、少々面倒です。

また、文字もグラフィックスも、表示の指示をしただけではOLEDディスプレイの画面に表示されず、show()メソッドを呼び出した時点で初めてすべての表示指示が画面に反映されます。

OLEDディスプレイへのコンソール的文字表示

何を言っているかわかりにくいのですが、OLEDディスプレイに文字を表示する際に、文字を表示する座標を明示せずに出力できる機能を備えたドライバを作成しました。oledcsもマイクロファンのMicroPythonファームウェアに組み込まれているので、導入作業などをせずに利用できます。

利用法は簡単で、単に出力したい文字列をprintln()あるいはprint()メソッドで出力するだけです。文字の出力位置は、ドライバが自動的に管理してくれますし、いちいちshow()メソッドを利用する必要もありません。

メッセージやデータをOLEDディスプレイに表示する場合には、ssd1306を使用するよりも、oledcsを使用したほうが手軽で便利でしょう。なお、oledcsはssd1306を継承して作成されているため、ssd1306の機能もそのまま利用できます。

from machine import I2C
from oledcs import OLEDCS_I2C
import time

i2c = I2C(0)
oled = OLEDCS_I2C(128, 64, i2c)

oled.println('123456789012345678901234567890')
time.sleep(3)

for i in range(1,20):
    oled.print('OLED-')
    oled.println('{:.3f}'.format(1/i))
time.sleep(3)

oled.println('OLEDCS Driver for MicroPython')

oledcsの詳細は、以下のページをご参照ください。

OLEDディスプレイへの日本語表示

OLEDディスプレイに日本語列を表示するプログラム例です。

日本語表示機能を持ったOLEDドライバoledjpや日本語フォントは、MicroPythonのファームウェアにあらかじめ組み込まれていますので、それらの導入作業をしなくても、プログラムを動かすことができます。

oledjpは、ssd1306の上位互換ドライバとなっていますので、ssd1306ドライバを使っているプログラムでは、日本語を使っていなくてもssd1306をoledjpに置き換えてもかまいません。

from machine import I2C
from oledjp import OLEDJP_I2C

i2c = I2C(0)
oled = OLEDJP_I2C(128, 64, i2c) # 日本語表示機能付きOLEDドライバ
oled.setFont(OLEDJP_I2C.MISAKI) # 日本語フォントの利用設定

str = "OLEDディスプレイやカラーLED、気温、しつ度、明るさ、加速度などの多種のセンサ、圧電スピーカーやスイッチなどが組こまれており、単体でMicroPythonやArduinoのプログラミングを楽しむことができます。超音波センサや人感センサなども接続できます"
oled.print(str)

OLEDドライバoledjpに関しては以下のページをご参照ください。

OLEDディスプレイへのグラフィックス表示

OLEDディスプレイにグラフィックス表示するプログラム例です。

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import time

i2c = I2C(0)
# i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=400000)
oled = SSD1306_I2C(128, 64, i2c)

oled.fill(0) # 画面のクリア
for y in range(0,64,8):
    oled.line(0,0,127,y,1) # 斜線
    oled.show()

for x in range(127,0,-8):
    oled.line(0,0,x,63,1) # 斜線
    oled.show()

time.sleep_ms(500)

oled.fill(0) # 画面のクリア
for n in range(0,32,4):
    oled.rect(64-n*2,32-n,n*4,n*2,1) # 方形
    oled.show()

time.sleep_ms(500)

oled.fill(0) # 画面のクリア
for n in range(0,32,2):
    oled.fill_rect(64-n*2,32-n,n*4,n*2,1) # 塗潰し方形
    oled.show()

time.sleep_ms(500)

oled.fill(0) # 画面のクリア
for n in range(2,32,2):
    oled.ellipse(64,32,n*4,n*2,1) # 楕円
    oled.show()

time.sleep_ms(500)

oled.fill(0) # 画面のクリア
for n in range(2,18,2):
    oled.ellipse(64,32,n*4,n*2,1,True) # 塗潰し楕円
    oled.show()

気温・湿度センサー

気温・湿度センサーAHT21のドライバーに関しては以下のページをご参照ください。

気温・湿度・明るさ表示

OLEDディスプレイに気温・湿度センサーAHT21で得られた気温と湿度、明るさセンサー(フォトトランジスタ)で得られた明るさを表示するプログラム例です。

AHT21はI2Cで接続されており、OLEDディスプレイと同じ0番チャネルに接続されています。

明るさは、フォトトランジスタの出力電圧をAD変換で読み取って表示しています。明るさの範囲は0-1で、1に近い方が明るい状態を表します。

from machine import Pin, I2C, ADC
import time
from ssd1306 import SSD1306_I2C
from aht21 import AHT21

i2c = I2C(0)
oled = SSD1306_I2C(128, 64, i2c)
aht21 = AHT21(i2c)
brt = ADC(Pin('BRT')) # 明るさセンサーに割り当てられている端子には'BRT'という名前が割り当てられています。
# brt = ADC(Pin(1))

while True:
    oled.fill(0)
    oled.text('TEMP: {:.1f}\''.format(aht21.temperature),0,0,1)
    oled.text('HUM: {:.1f}%'.format(aht21.relative_humidity),0,16,1)
    oled.text('BRT: {:.3f}'.format(brt.read()/4095),0,32,1)
    oled.show()
    time.sleep_ms(1000)

# CTRL-Cで終了

加速度センサー

加速度センサーKXTJ3は、RP2040-SLIMには装備されていません。

加速度センサーKXTJ3のドライバーに関しては以下のページをご参照ください。

3軸の傾きを3個のカラーLEDで表示

加速度センサーのKXTJ3ドライバーは、3軸の加速度の計測値をそれぞれ-32768-32767の範囲で返します。また、計測加速度の設定値は2-16Gで設定できますが、初期状態では2Gの設定になっています。加速度の方向は、X軸が基板の縦方向、Y軸が横方向、Z軸が上下方向になっています。

以下のプログラムでは、各軸に対応するカラーLEDが、各軸の加速度がほぼ0の場合に青、正の値だと大きいほど明るい赤、負の値だと絶対値が大きいほど明るい緑に光ります。

水平の机の上などに基板を置くと、X,Y軸に対応する1番目と2番目のカラーLEDが青色に光ります。

from machine import Pin, I2C
from kxtj3 import KXTJ3
from neopixel import NeoPixel
import time

i2c = I2C(0)
acc = KXTJ3(i2c)

rgb = NeoPixel(Pin('RGB', Pin.OUT), 3) # 3ピクセル用の NeoPixel ドライバーをRGB端子に設定

while True:
    vacc = acc.getXYZ()
    x = int(vacc[0] / 32768 * 255) # 最大変位量を255に
    y = int(vacc[1] / 32768 * 255)
    z = int(vacc[2] / 32768 * 255)
    if abs(x) < 10: # ほぼ水平
        rgb[0] = (0,0,100) # 青で表示
    elif x > 0:
        rgb[0] = (x,0,0) # 傾きに応じて赤で表示
    else:
        rgb[0] = (0,-x,0) # 傾きに応じて緑で表示
    if abs(y) < 10:
        rgb[1] = (0,0,100)
    elif y > 0:
        rgb[1] = (y,0,0)
    else:
        rgb[1] = (0,-y,0)
    if abs(z) < 10:
        rgb[2] = (0,0,100)
    elif z > 0:
        rgb[2] = (z,0,0)
    else:
        rgb[2] = (0,-z,0)
    rgb.write() # 全ピクセルにデータ書込み
    time.sleep_ms(100)

傾き表示

OLEDディスプレイに3軸の加速度と、基板の傾きを表示するプログラム例です。

加速度センサーKXTJ3はI2Cで接続されており、OLEDディスプレイと同じ0番チャネルに接続されています。

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
from kxtj3 import KXTJ3
import time
import math

i2c = I2C(0)
oled = SSD1306_I2C(128, 64, i2c)
acc = KXTJ3(i2c)

while True:
    oled.fill(0)
    vacc = acc.getXYZ()
    oled.text('X: {:.2f}'.format(vacc[0] / 16384), 0, 0)
    oled.text('Y: {:.2f}'.format(vacc[1] / 16384), 0, 16)
    oled.text('Z: {:.2f}'.format(vacc[2] / 16384), 0, 32)
    t = math.degrees(math.atan2(-vacc[1], vacc[0]))
    oled.text('DEG: {:.1f}'.format(t), 0, 48)
    oled.show()
    time.sleep_ms(100)

水平儀

OLEDディスプレイに水平線を表示する(いわゆる水平儀)プログラム例です。

from machine import Pin, I2C
import time
from ssd1306 import SSD1306_I2C
from kxtj3 import KXTJ3
import math

i2c = I2C(0)
oled = SSD1306_I2C(128, 64, i2c)
acc = KXTJ3(i2c)

while True:
    oled.fill(0)
    vacc = acc.getXYZ()
    x = int(vacc[0] / 16384 * 40)
    y = int(vacc[1] / 16384 * 40)
    oled.line(64-x,32-y,64+x,32+y,1)
    oled.ellipse(64,32,40,40,1)
    t = math.degrees(math.atan2(-vacc[1], vacc[0]))
    oled.text('{:4.1f}'.format(t), 45, 36)
    oled.show()
    time.sleep_ms(100)

WS2812カラーLED

RGB表示

3個のWS2812タイプのカラーLEDに赤、緑、青色を出力するプログラム例です。

各LEDの明るさは、0-255の範囲で指定できますが、LEDの点灯確認目的であれば、10程度の明るさ指定でも十分な明るさで発光します。

# Ws2812 カラーLEDの点灯
from neopixel import NeoPixel
from machine import Pin

rgb = NeoPixel(Pin('RGB', Pin.OUT), 3)
rgb[0] = (10,0,0) # 赤
rgb[1] = (0,10,0) # 緑
rgb[2] = (0,0,10) # 青
rgb.write() # 全ピクセルにデータ書込み

neopixelライブラリの利用法は、以下のページをご参照ください。

1/fゆらぎを利用したLEDキャンドル

1/fゆらぎを利用して、1個のカラーLEDをキャンドルの様に光らせるプログラム例です。

下記ページのプログラムでNeoPixelコンストラクタの引数として指定するLEDの端子機能名は、’LED10’に変更してください。

カラーLEDマトリックス表示

CN4にカラーLEDマトリックスを接続して使用することができます。カラーLEDマトリックスを利用すると、カラーLEDで文字やグラフィックス表示ができるようになります。

カラーLEDマトリックスはLEDMATRIXライブラリで操作することができ、LEDMATRIXライブラリは専用ファームウェアにあらかじめ組み込まれているので、事前の準備などなく使用することができます。

カラーLEDマトリックスへの日本語表示

カラーLEDマトリックスで日本語表示することもできます。

カラーLEDマトリックスでの日本語表示はLEDMATRIXJPライブラリで行うことでき、LEDMATRIXJPライブラリは専用ファームウェアにあらかじめ組み込まれているので、事前の準備などなく使用することができます。


WiFi

WiFi機能の利用は、ESP32の本領発揮ですね。

アクセスポイントの確認

ESP32のWiFi機能を有効化して、周辺のアクセスポイントをリスト表示するプログラム例です。

import network

wifi = network.WLAN(network.STA_IF) # クライアントとして設定
wifi.active(True) # WiFiを有効化

sta = wifi.scan() # アクセスポイントをスキャン
# print(sta)

authmodes = ['Open', 'WEP', 'WPA-PSK' 'WPA2-PSK', 'WPA/WPA2-PSK', '?5', '?6', '?7', '?8', '?9', ]
for (ssid, mac, channel, rssi, auth, hidden) in sta:
    name = ssid.decode()
    print("*", name if name != "" else "???")
    print("  - Auth:", authmodes[auth])
    print("  - Channel:", channel)
    print("  - RSSI:", rssi)
    print("  - MAC: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(*mac))
    print()

このプログラムは、アクセスポイントをスキャンするだけなのでSSIDやパスワードは不要です。

NTPを使用した時刻同期

NTPプロトコルを使用して、RTCを設定するプログラムです。

ESP32は目が覚めた時は今何時なのかわかってないのですが、バッテリーバックアップされたRTCがなくてもいつでも正確な時間を利用できるので、ネットワークが使えると便利ですね。

import network
import ntptime
import utime
import time
from machine import RTC

ssid = 'YOUR_SSID'
passwd = 'YOUR_PASSWD'

def wifi_connect(ssid, passwd): # アクセスポイントへの接続
    wifi = network.WLAN(network.STA_IF)
    wifi.active(True)
    if not wifi.isconnected():
        print('connecting to network...')
        wifi.connect(ssid, passwd)
        while not wifi.isconnected():
            print('.',end='')
            time.sleep_ms(500)
        print()
    return wifi

wifi = wifi_connect(ssid, passwd)
print('network config:', wifi.ifconfig()) # 接続時のIP情報表示

rtc = RTC() # リアルタイムクロックを取得
print("RTC初期値:", rtc.datetime()) # 2000/1/1になっていなければ、Thonnyの設定オプションが有効

print('--- NTP同期')
ntptime.settime() # RTCをNTPと同期
print("utime:", utime.localtime()) # 設定された時刻はグリニッジ標準時相当:任本の時間JSTじゃない
print("RTC設定値:", rtc.datetime()) # 同上:データの順序と内容が微妙に違う。。。

print('--- RTCをJSTに')
JST_OFFSET = 9 * 60 * 60 # 9時間(32400秒)
ut = utime.localtime(utime.time() + JST_OFFSET)
rtc.datetime((ut[0], ut[1], ut[2], ut[6]+1, ut[3], ut[4], ut[5], 0))
print("RTC(JST):", rtc.datetime())

天気予報

気象庁が提供する天気予報データを利用するプログラム例です。

import network
import urequests
import ujson
import time

ssid = 'YOUR_SSID'
passwd = 'YOUR_PASSWD'

def wifi_connect(ssid, passwd): # アクセスポイントへの接続
    wifi = network.WLAN(network.STA_IF)
    wifi.active(True)
    if not wifi.isconnected():
        print('connecting to network...')
        wifi.connect(ssid, passwd)
        while not wifi.isconnected():
            print('.',end='')
            time.sleep_ms(500)
        print()
    return wifi

wifi = wifi_connect(ssid, passwd)
# print('network config:', wifi.ifconfig())

# 気象庁予報データの取得:福岡県
jma_url = "https://www.jma.go.jp/bosai/forecast/data/forecast/400000.json"
forecast_json = urequests.get(jma_url).json()

forecast_major = forecast_json[0]["timeSeries"][0] # 参照データセットの選択
forecast_date = forecast_major["timeDefines"][0] # 0:福岡県の最初の地域:福岡地方
forecast_weather = forecast_major["areas"][0]["weathers"][0]
forecast_wind = forecast_major["areas"][0]["winds"][0]

print(forecast_date)
print(forecast_weather.replace(' ', '')) # 全角スペースを削除して表示
print(forecast_wind.replace(' ', '')) # 全角スペースを削除して表示