WiFiとNTP
WiFiとNTPから時間を取得するプログラムは、インターネットから容易に取得できるので、取得して、実行します(この時WiFiのSSIDとPasswordは環境に合わせます)。
WiFiに接続後に、NTPサーバより時間を取得して、1秒ごとに時間を表示しています。
WiFi設定の課題と解決策
WiFiは便利に使え、FreeWiFiも増えてきています。タブレットやノートPCでは、簡単にWiFiへの接続設定ができますが、マイコンではプログラム中にSSIDとPASSを書き込んでいます。WiFi環境が変わると接続できなくなり、プログラムを書き換えるしかありません。
この課題は先駆者たちが、WiFiに接続できないときにタブレットと連携して設定する仕組み(WiFi Manager)などを開発しています。
今回はUSBメモリが利用できるため、以前に紹介した「esp32s3_USB_Drive-main.zip」を使います。USBメモリにWiFi設定ファイルを作成しておき、このファイルを読み込んでWiFi設定をします。
WiFi設定ファイルの構造
WiFi設定ファイルはメモ帳などで作成できます。
ただし、文字コードに注意が必要です。近年は、UTFコードが標準になりつつあります。
ここでBOM(Byte Order Mark)は、ファイル形式がUTF-8コードであることを示すため、3バイト「EF BB BF」(16進数)が先頭に付加されるものです。
これをUSBメモリに保存して、ESP32マイコンから読み込むと、本来「mySSID」の文字列が「???mySSID」のようになってしまいます。このSSIDとPasswordを使ってWiFiに接続しても接続できません。
WiFi設定ファイルを読み込む方法
SSIDに設定する文字は「ASCIIコード(7ビット)」です。このことから制御コード(00H~1FH、7FH)を除いたコード 20H~7EHの文字を有効な文字として処理します。これによりUTF-8のBOMは除外(削除処理)されることになります。
この処理はプログラムで処理します。
esp32s3_USB_Driveの改造
USBメモリを読み込む「esp32s3_USB_Drive」にWiFiに接続する機能を追加します。
プログラムの先頭で、WiFiに関する定義を追加
#include <WiFi.h> char ssid[30], pass[30];
file_operations関数を変更
読み込むファイルは「/usb/wifi.txt」
不要なコードを取り除く処理。
static void file_operations(void)
{
const char *file_path = "/usb/wifi.txt";
FILE *f;
ESP_LOGI(TAG, "Reading file");
f = fopen(file_path, "r");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
char line[64];
int ptr;
// 読み込んだデータをSSIDに格納
char *pos;
fgets( line, sizeof(line), f);
//文字列のクリア
for ( int i = 0; i < 30; i++) ssid[i] = 0;
ptr = 0;
for ( int i = 0; i < strlen(line); i++) {
if ( 0x20 <= line[i] && line[i] < 0x7f ) {
ssid[ptr] = line[i];
ptr++;
}
}
// 読み込んだデータをPASSに格納
fgets(line, sizeof(line), f);
//文字列のクリア
for ( int i = 0; i < 30; i++) pass[i] = 0;
ptr = 0;
for ( int i = 0; i < strlen(line); i++) {
if ( 0x20 <= line[i] && line[i] < 0x7f ) {
pass[ptr] = line[i];
ptr++;
}
}
fclose(f);
}
setup関数の終わりでWiFiに接続する処理
このサンプルは、外部入力スイッチを押すと、USBメモリを取り外す処理をしています。今回スイッチ処理は使わないため、不要な部分をコメントアウトしました。
// do {
uint8_t device_address = wait_for_msc_device();
ESP_ERROR_CHECK( msc_host_install_device(device_address, &msc_device) );
msc_host_print_descriptors(msc_device);
ESP_ERROR_CHECK( msc_host_get_device_info(msc_device, &info) );
print_device_info(&info);
ESP_ERROR_CHECK( msc_host_vfs_register(msc_device, "/usb", &mount_config, &vfs_handle) );
//while (!wait_for_event(DEVICE_DISCONNECTED, 200)) {
file_operations();
//}
// xEventGroupClearBits(usb_flags, READY_TO_UNINSTALL);
// ESP_ERROR_CHECK( msc_host_vfs_unregister(vfs_handle) );
// ESP_ERROR_CHECK( msc_host_uninstall_device(msc_device) );
// } while (gpio_get_level(USB_DISCONNECT_PIN) != 0);
// ESP_LOGI(TAG, "Uninitializing USB ...");
// ESP_ERROR_CHECK( msc_host_uninstall() );
// wait_for_event(READY_TO_UNINSTALL, portMAX_DELAY);
// ESP_ERROR_CHECK( usb_host_uninstall() );
// ESP_LOGI(TAG, "Done");
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi OK.");
esp32s3_USB_Driveを改良して分かったこと
USB Driveのサンプルプログラムは、ソースコードを見てわかるように、FreeRTOSを利用し、割り込みにより処理をしています。
このサンプルでは、USBメモリを認識するまで、処理が進まず待ち続けます。しかし、常にUSBメモリが接続されているわけでなく、処理によってはUSBメモリがない時には、次の処理に移りたい時があります。
解析の結果、この場合には次の場所を変えることで、一定時間、USBを認識しないと次の処理に移行するように変更できます。
wait_for_msc_device関数内を変更
プログラムの行末のパラメータ「portMAX_DELAY」のままであると、無制限に待ちます。これを「3000」に変更すると、3秒(3000mS)待ち、ループを抜けるようになります。
event = xEventGroupWaitBits(usb_flags, DEVICE_CONNECTED | DEVICE_ADDRESS_MASK, pdTRUE, pdFALSE, portMAX_DELAY);




0 件のコメント:
コメントを投稿