11-22-2022 11:57 PM
ラインセンサーTCD1304を使った分光器の3694個のデータをシリアル通信で送るとかなり時間がかかって苦労しました。ESP32を使っているのだから、WiFi使えばイイジャンと思われていた方は多いと思います。
やってみました。
ところで中部地方の方、12月3日、4日の大垣ミニメイカーフェアにはラインセンサを利用した簡易分光器 を出展しています。入場料無料(要予約)なのでぜひのぞいてみてください。
12月18日のいわてメイカー展にも出展しますので盛岡に近い方はいらしてください。
ESP32でWiFiアクセスポイントをつくり、そこにTCPサーバーを作ります。PCのWiFiをESP32のアクセスポイントに接続させて、LabVIEWからクライアントとしてTCPサーバーにアクセスしてデータを受け取ります。ESP32側の送信時間を測定すると4096個の2バイトデータを8msecぐらいで送っていました。
1kByte/1msecとすると8Mbpsなので、ふつうのWiFi通信速度の1/10以下ですが、シリアル通信よりははるかに速いことが実感できました。
受信側のLabVIEWプログラムはほぼサンプルVI(Simple TCP - Client.vi)のままです。
サーバーにコマンドらしきものを送ると、サーバーからデータが送られて来るので受け取る、というプログラムです。
送られてくるデータは0から4097までの数値です。
ESP32のWiFi設定方法を調べてみると、SSIDとパスワードはESP32のフラッシュ領域に自動的に保存されてしまうこと、文字列の長さが8文字未満のパスワードは使用できないことがわかりました。
TCPサーバーのプログラムを書き込む前に次のプログラム(ESP32_Set_AP_nvsPref.ino)を書き込んでアクセスポイントモードのSSIDとパスワードを記録します。
//Write SSID and Password of AP-mode to NVS Preference
//Upload and run this program and the SSID and password will be recorded in NVS.
//After that, when you use AP mode, you don't need to write SSID and password in the program.
//for example: WiFi.softAP("","");
//Special thanks to
//https://lang-ship.com/blog/work/esp32-wi-fi-setting/
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#include <Preferences.h>
const char ssid[] = "TCP_server";
const char pass[] = "ap1234567";// should be password length > 8
const IPAddress ip(192,168,10,30);
const IPAddress subnet(255,255,255,0);
WiFiServer server(80);
Preferences preferences;
void setup()
{
Serial.begin(115200);
WiFi.softAP(ssid,pass);
delay(100);
WiFi.softAPConfig(ip,ip,subnet);
IPAddress myIP = WiFi.softAPIP();
server.begin();
delay(200);
Serial.print("SSID: ");
Serial.println(ssid);
Serial.print("Password: ");
Serial.println(pass);
Serial.println("Done");
delay(2000);
Serial.println("Check Preference Data");
char ap_wifi_ssid[37] = {};
char ap_wifi_key[66] = {};
preferences.begin("nvs.net80211", true);
preferences.getBytes("ap.ssid", ap_wifi_ssid, sizeof(ap_wifi_ssid));
preferences.getBytes("ap.passwd", ap_wifi_key, sizeof(ap_wifi_key));
Serial.printf("ap.ssid : %s\n", &ap_wifi_ssid[4]);
Serial.printf("ap.pswd : %s\n", ap_wifi_key);
}
void loop(){
}
ESP32にアップロードすると以下のようにシリアルモニターに表示されます。
その後、SSIDとパスワードをブランクにしたプログラムを書き込むと、実行時にフラッシュ領域に記録されたSSIDとパスワードでアクセスポイントが動作します。
//Special thanks to
//TCP data server
//https://tsunelab-programming.com/esp32-socket
//https://lang-ship.com/blog/work/esp32-tcp-ip-socket/
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#include <ESPmDNS.h>
const IPAddress ip(192,168,10,30);
const IPAddress subnet(255,255,255,0);
WiFiServer server(5000);
#define CMND_SIZE 256
byte myCmnd[CMND_SIZE];
#define DATA_SIZE 4096
int dataArray[DATA_SIZE];
byte dataArrayByte[DATA_SIZE*2];
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_AP);
WiFi.softAP("", "");
delay(100);
WiFi.softAPConfig(ip,ip,subnet);
IPAddress myIP = WiFi.softAPIP();
server.begin();
MDNS.begin("MaDALab");
Serial.println("MaDALab.local Server started");
setDataArray();
}
void loop() {
int time0,time1;
WiFiClient client = server.available();
if (client) {
Serial.println("New Client.");
String currentLine = "";
while (client.connected()) {
int available_count = client.available();
if (available_count) {
client.read(myCmnd,available_count);
Serial.write(myCmnd,available_count);
Serial.println("");
time0=millis();
client.write(dataArrayByte,DATA_SIZE*2);
time1=millis();
Serial.print(time1-time0);
Serial.println(" msec taken to send all data.");
}
}
client.stop();
Serial.println("Client Disconnected.");
}
}
void setDataArray(){
for(int i=0; i<DATA_SIZE; i++){
int myData=i;
dataArray[i]=i;
dataArrayByte[i*2]= myData >> 8;
dataArrayByte[i*2+1]= myData & 0x00ff;
}
}
mDNSライブラリを使ったのでLabVIEWから「MaDALab.local」でアクセスできます。現状はクライアントからのコマンドを受け取ってプリントするだけですが、文字列に応じて処理を分岐することができます。
実行後クライアントからアクセスされた時のシリアルモニターの表示です。
分光器のESP32をTCPサーバーにすればモバイルバッテリーで動作できて設置場所の自由度の高い分光器になるのではないでしょうか。
ラインセンサーのコントローラーとしても50Hzぐらいで動作できそうな気がします。
ESP32のプログラムで修正すべき点や改良点がありましたら返信等でお知らせいただければありがたいと思います。
VIs.zipに以下のファイルを圧縮保存しました。
Simple TCP Client01.vi
ESP32_Set_AP_nvsPref.ino
ESP32_TCP_Server.ino
12-27-2022 03:23 AM
割り込みを使ったアナログ入力でサンプリングしたデータをTCPサーバー経由でLabVIEWに渡すサンプルを作りました。
ESP32 Arduino固有の事情ですが、WiFi機能を使うときに使用できるアナログ入力が限定されます。ADC1とADC2の2系統のうちADC2が使えなくなります。
ADC1系統はGPIO32, 33, 34, 35, 36, 37, 38, 39です。
今回のプログラムではGPIO32を使いました。
もう一つESP32ボードマネージャーのバージョンによってADCの動作時間が異なります。
何気なく1.0.4を使い続けていたのですが、最新の2.0.6にバージョンを上げたら20kHzの割り込み信号の場合に追従できずに1個飛ばしのサンプリングになってしまいました。結局2.0.6では10kHzの割り込み信号に変更する必要がありました。
Arduino IDEは1.8.16を使いました。
前回のArduinoプログラムを改造してダミーデータの部分をアナログ入力に変更しました。
信号には100Hzのノコギリ波を使いました。
ESP32用プログラムとLabVIEWプログラムを添付します。
ESP32_TCP_Server_AI04.ino
Simple TCP Client02.vi
01-09-2023 01:55 AM
ノコギリ波のスロープが直線でないのはADCのリニアリティの問題でしょうか?
元の信号がそのような形なのかもしれませんが・・・
01-09-2023 05:05 AM
信号発生器も怪しいものですが、大部分はESP32のADCのリニアリティが悪いためだと思います。
SPI接続のAD変換ボード(ADS8688 8ch 500kSPS)を見つけたのでチャレンジしています。