hiro yamamoto works

マイコンハード、ソフトを作ったりしています。
お家や現場のお困りごと解決に!
内容利用は自己責任でお願いします。

Wi-FiをスキャンしてSSID,ch,RSSIをLCDに表示する

2022-05-11 14:45:06 | マイコンソフトウェア

ESPr Developer(ESP-WROOM-02)を使って作り、ケースに収納しました。追記2022/06/23
プラスチックケース黒135x75x49秋月電子通販コードP-02774

余り物マイコンボードとLCDでWi-Fi測定器(?)作成しました。
ビーコンを受信して表示しますが、ぼかしてますが2つのSSID表示してます。
2つのSSIDに対応するRSSI(信号強度)とチャンネルを表示しています。
code中の記号<、>は半角に修正必要です。

/*WiFiScan.inoをLCD表示するように改変しました
1602,2004LCD用 I2C I/Fモジュールを使って8-BIT PARALLEL INTERFACEの2004LCDをI2C接続します 2004は20文字4行のLCDです ESP-WROOM-02 IO5-SCL,IO4-SDA ESP32 GPIO22-SCL,GPIO21-SDA*/
//#include "WiFi.h"//esp32のとき
#include "ESP8266WiFi.h"//esp8266(ESP-WROOM-02)のとき
#include <LiquidCrystal_PCF8574.h>//LCD表示用
#include <Wire.h>//LCD表示用
String ssid[32];
int8_t ch[32] , rssi[32];//配列
LiquidCrystal_PCF8574 lcd(0x27);
void setup() {
Serial.begin(115200);
Wire.begin();//LCD
// Set WiFi to station mode and disconnect from an AP if it was previously connected
// WiFiをステーションモードに設定し、以前接続していたAPを切断する。
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
//Serial.println("Setup done");//LCD出力へ変更します
lcd.begin(20, 4); // initialize the lcd
lcd.setBacklight(1);
lcd.home();
lcd.clear();
lcd.print("Setup done");
delay(5000);
}
void loop() {
//Serial.println("scan start");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Scanning now");
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
//Serial.println("scan done");
if (n == 0) {
//Serial.println("no networks found");
lcd.print("no networks found");
} else {
//Serial.print(n);
//Serial.println(" networks found");
for (int i = 0; i < n; ++i) {
// Print SSID and RSSI for each network found
//Serial.print(i + 1);
//Serial.print(": "); //Serial.print(WiFi.SSID(i));
//Serial.print(" ("); //Serial.print(WiFi.RSSI(i));
//Serial.print(")");
//Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");//esp8266のとき
//Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");//esp32のとき
ssid[i] = WiFi.SSID(i);//文字列です
rssi[i] = WiFi.RSSI(i);
ch[i] = WiFi.channel(i);
delay(20);
}
/*20文字x4行LCDに先ずSSID表示し対応するRSSIとchを同じ行に表示します。
表示を切り替えながらSSID,RSSI,chを8つまで表示します。
SSIDが無いときはNo Dataと表示し、RSSIとchは0を表示します。*/
lcd.clear();
lcd.setCursor(0, 0); lcd.print(ssid[0]); // コンパクトに記述する方法は無いか?
lcd.setCursor(0, 1); lcd.print(ssid[1]);
lcd.setCursor(0, 2); lcd.print(ssid[2]);
lcd.setCursor(0, 3); lcd.print(ssid[3]);
delay(3000);
lcd.clear();
lcd.setCursor(0, 0); lcd.print(rssi[0]);
lcd.setCursor(5, 0); lcd.print(ch[0]);
lcd.setCursor(8, 0); lcd.print("ch");
lcd.setCursor(0, 1); lcd.print(rssi[1]);
lcd.setCursor(5, 1); lcd.print(ch[1]);
lcd.setCursor(8, 1); lcd.print("ch");
lcd.setCursor(0, 2); lcd.print(rssi[2]);
lcd.setCursor(5, 2); lcd.print(ch[2]);
lcd.setCursor(8, 2); lcd.print("ch");
lcd.setCursor(0, 3); lcd.print(rssi[3]);
lcd.setCursor(5, 3); lcd.print(ch[3]);
lcd.setCursor(8, 3); lcd.print("ch");
delay(3000);
lcd.clear();
lcd.setCursor(0, 0); lcd.print(ssid[4]);
lcd.setCursor(0, 1); lcd.print(ssid[5]);
lcd.setCursor(0, 2); lcd.print(ssid[6]);
lcd.setCursor(0, 3); lcd.print(ssid[7]);
delay(3000);
lcd.clear();
lcd.setCursor(0, 0); lcd.print(rssi[4]);
lcd.setCursor(5, 0); lcd.print(ch[4]);
lcd.setCursor(8, 0); lcd.print("ch");
lcd.setCursor(0, 1); lcd.print(rssi[5]);
lcd.setCursor(5, 1); lcd.print(ch[5]);
lcd.setCursor(8, 1); lcd.print("ch");
lcd.setCursor(0, 2); lcd.print(rssi[6]);
lcd.setCursor(5, 2); lcd.print(ch[6]);
lcd.setCursor(8, 2); lcd.print("ch");
lcd.setCursor(0, 3); lcd.print(rssi[7]);
lcd.setCursor(5, 3); lcd.print(ch[7]);
lcd.setCursor(8, 3); lcd.print("ch");
}
for (int i = 0; i <= 32; ++i) {
ssid[i] = "No data";
ch[i] = 0;
rssi[i] = 0;
}
//Serial.println("");
// Wait a bit before scanning again
delay(3000);
}

サンプルスケッチや作例を公開されている方々に感謝します。


アクセスポイント経由のリモートI/O(受信)wireless IO

2022-04-02 18:06:33 | マイコンソフトウェア

仕様とスケッチの紹介です。仕様変更した箇所も追記しておきます。
仕様変更した理由
16bitのコードを送るような使い方をした場合に、各bitのONまたは
OFFのタイミングが揃わず違うコードが混じることがあったので<br />修正しました。
個別に接点伝送するような使い方なら問題なかったと思います。 2022.09.29

伝送接点数16 単方向(送信側→受信側への伝送のみ)
離れたところにある機器の信号を、電波が届く範囲で
配線無しで受け取ることができる。
アクセスポイント経由ESP32同士で通信します。
主な部品 ESP32開発ボード、I/OエキスパンダMCP23017
手動テストの様子
右側基板のスイッチを押すと接点信号が伝送され、左側基板の
LEDが点灯します。

 

 

右側が送信、左側が受信となっています。
スイッチ基板で信号を作ってMCP23017へ 入力しています。
MCP23017のデジタル入力を読み込み、16進数を文字配列
としてUDPで送信
受信した文字配列を16進数へ変換してMCP23017でデジタル
出力します。
Wi-Fi接続試行中GPIO2 LED250mS周期点滅 接続失敗でESP.restart()します。
通信中にアクセスポイントと通信できなくなった時もLED点滅700-300mS周期ESP.restart()します。
送信側の準備ができていない時に、出力が全ONしないように、出力ホトカプラアノードへの給電をGPIO12でコントロールしています。
受信が途中停止(パケット停止)した時に出力ONを1秒後に切るようにしました。
5秒ぐらいでも良いかもしれません。
準備
アクセスポイントとスケッチのIPアドレスを設定
アクセスポイントとSSIDとパスワードをあわせる
WiFiUDPClient.inoをベースにした受信側スケッチを紹介しておきます。
#include行の<>は半角に修正必要です

#include <WiFi.h>
#include <WiFiUdp.h>
#include <esp_wifi.h>
#include "Adafruit_MCP23017.h"//16bitIOExpander

// WiFi network name and password:
const char * ssid = "network name";
const char * password = "network password";

//IP address to send UDP data to:
// either use the ip address of the server or
// a network broadcast address
// UDPデータの送信先IPアドレス:
const int udpPort = 1234;
char incomingPacket[6];// buffer for incoming packets
unsigned int GPIO_BA;
unsigned int lastGPIO_BA;//追加

uint16_t ActiveCount = 0;//uint8_t→uint16_t変更
uint16_t prevActiveCount = 0;//uint8_t→uint16_t変更
unsigned int matchCount = 0;//追加
unsigned long previousMillis = 0;

//Are we currently connected?
boolean connected = false;

//The udp library class
WiFiUDP udp;
Adafruit_MCP23017 mcp;

void setup() {
// Initilize hardware serial:
Serial.begin(115200);

Wire.begin();//Wire.setClockのために必要と思う
Wire.setClock(400000);//fast modeにする必要はないと思う
//fast mode400000(400kHz) Standard mode100kHz (100000)はsetClock指定不要

pinMode(2, OUTPUT);//Wi-Fi接続試行中点滅し接続完了で消灯
pinMode(12, OUTPUT);
mcp.begin(); // use default address MCP23017をデフォルトアドレスで使う

IPAddress local_IP(192, 168, 1, 3);
IPAddress gateway(192, 168, 1, 1); 
IPAddress subnet(255, 255, 255, 0);
WiFi.mode(WIFI_STA);//Wi-Fi子機モート

WiFi.config(local_IP, gateway, subnet);//

Serial.println("Connecting to WiFi network: " + String(ssid));

// delete old config
WiFi.disconnect(true);
//register event handler イベントハンドラーの登録
WiFi.onEvent(WiFiEvent);

//Initiate connection
WiFi.begin(ssid, password);

Serial.println("Waiting for WIFI connection...");

uint8_t i = 0;
while (WiFi.status() != WL_CONNECTED && i++
digitalWrite(2, HIGH);
delay(250);
digitalWrite(2, LOW);
delay(250);
Serial.print(".");
}
// 10秒以上待ってもWi-Fi接続不能の時はESPをリスタートする。
if (i == 21) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
Serial.println(WiFi.status() == WL_CONNECTED ? "WiFi connected!" : "Failed!");

//Connect to the WiFi network
//connectToWiFi(networkName, networkPswd);
//udp.begin(udpPort); // UDP通信開始

for (uint8_t i = 0; i <= 15; i++) mcp.pinMode(i, OUTPUT); // Set pin to output mode for GPA
mcp.writeGPIOAB(0xFFFF);//出力を全OFFする
digitalWrite(12, HIGH);//TLP592をONして、出力ホトカプラのアノードへ5V供給
}
void loop() {
//only receive data when connected 接続時にのみデータを受信する

if (connected) {

while (udp.parsePacket()) {//UDPパケットのサイズを取得 戻り値:受信UDPパケットのサイズ
udp.read(incomingPacket, 6);//incomingPacketは文字配列です。
//バッファにUDPデータを読み込む 戻り値 読み取り文字数(読み取り文字は指定バッファに入る)文字配列
//1回に1byte読む サイズ分だけ読み込み位置が進む
//Serial.println(ReadDataByte); //パケット到着中のみ表示される
//}

//起動時と送信が途切れた時出力全OFFしたい パケット到着中のみ whileの{}中を回る
long Data = strtol(incomingPacket, NULL, 16);
//16進数表示で送られてきた文字配列を16進数数値に変換する
GPIO_BA = Data;
mcp.writeGPIOAB(GPIO_BA);
//Serial.println(GPIO_BA, DEC);
ActiveCount++;//パケット到着中はwhileの{}中を回りカウントアップする
//uint8_t ActiveCount 0〜255までカウント
} // while
//****ここから変更箇所 ねらい データ変化時に過渡状態(類似)になるので、
    //一致回数を数えて複数回一致したらGPIO出力 プランB
          if (GPIO_BA == lastGPIO_BA) {// 前回値と一致
        matchCount++;
        if(matchCount >= 7){ // 一致した回数が7以上の時を安定値とする
          mcp.writeGPIOAB(GPIO_BA);
          //Serial.println(GPIO_BA);
        }
        //Serial.println(" match!!");
      } else {//前回値と不一致(前回値と一致以外)
        matchCount = 0;//カウントクリア
          //Serial.println(" no match!!");
        }
      lastGPIO_BA = GPIO_BA;
     //***ここまで変更箇所 
    } // if(connected)

//定期的に1回前と現在のActiveCountを比較して、同じ時はUDPパケットが未到着
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 1000) { // パケット停止をチェックする時間間隔
previousMillis = currentMillis;
if (ActiveCount == prevActiveCount) {
Serial.println("udp packet is stopped");//Active Count停止はパケット停止による
mcp.writeGPIOAB(0xFFFF);//出力を全OFFする
}
prevActiveCount = ActiveCount;
}

delay(1); //Wait for 1 millisecond
}//loop

/*void connectToWiFi(const char * ssid, const char * pwd) {
Serial.println("Connecting to WiFi network: " + String(ssid));

// delete old config
WiFi.disconnect(true);
//register event handler
WiFi.onEvent(WiFiEvent);

//Initiate connection
WiFi.begin(ssid, pwd);

Serial.println("Waiting for WIFI connection...");
}*/

//wifi event handler
void WiFiEvent(WiFiEvent_t event) {
switch (event) {
case SYSTEM_EVENT_STA_GOT_IP:
//When connected set
Serial.print("WiFi connected! IP address: ");
Serial.println(WiFi.localIP());
Serial.print("ESP Mac Address: "); Serial.println(WiFi.macAddress());
//initializes the UDP state
//This initializes the transfer buffer
udp.begin(WiFi.localIP(), udpPort);
connected = true;
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("WiFi lost connection");
connected = false;
//connected がfalseになった時はdelay(5000)後ESP.restart()している
for (int i = 0; i <= 5; i++) {
digitalWrite(2, HIGH);
delay(700);
digitalWrite(2, LOW);
delay(300);
}
ESP.restart();
default: break;
}
}

 

スケッチ作例を公開している方々へ感謝します。


アクセスポイント経由のリモートI/O(送信)wireless IO

2022-04-02 18:05:41 | マイコンソフトウェア

注意

delay(1)でloopしていますが、用途によってはdelayを大きくしたり、<br />入力変化時に送信する方式ても良いかもしれません。<br />専用アクセスポイントと送受信機1台づつという想定ですが、<br />アクセスポイントを複数の送受信機で共有したりすると<br />パケットロスによる問題が発生するかもしれません。

伝送接点数16 単方向(送信側→受信側への伝送のみ)
離れたところにある機器の信号を、電波が届く範囲で
配線無しで受け取ることができる。
アクセスポイント経由ESP32同士で通信します。
主な部品 ESP32開発ボード、I/OエキスパンダMCP23017
手動テストの様子
右側基板のスイッチを押すと接点信号が伝送され、左側基板の
LEDが点灯します。

右側が送信、左側が受信となっています。
スイッチ基板で信号を作ってMCP23017へ 入力しています。
MCP23017のデジタル入力を読み込み、16進数を文字配列
としてUDPで送信
受信した文字配列を16進数へ変換してMCP23017でデジタル
出力します。
Wi-Fi接続試行中GPIO2 LED250mS周期点滅 接続失敗でESP.restart()します。
通信中にアクセスポイントと通信できなくなった時もLED点滅700-300mS周期
ESP.restart()します。
準備
アクセスポイントとスケッチのIPアドレスを設定
アクセスポイントとSSIDとパスワードをあわせる
WiFiUDPClient.inoをベースにした送信側スケッチを紹介しておきます。
#include行の<>は半角に修正必要です

#include <WiFi.h>
#include <WiFiUdp.h>
#include <esp_wifi.h>
#include "Adafruit_MCP23017.h"//16bitIOExpander
// WiFi network name and password:
const char * ssid = "network name";
const char * password = "network password";
//IP address to send UDP data to:
// either use the ip address of the server or
// a network broadcast address
// UDPデータの送信先IPアドレス:
const char * udpAddress = "192.168.1.3";//受信側のIPアドレス
const int udpPort = 1234;//受信側と合わせる
//Are we currently connected?
boolean connected = false;
//The udp library class
WiFiUDP udp;
Adafruit_MCP23017 mcp;
void setup() {
  // Initilize hardware serial:
  Serial.begin(115200);
  Wire.begin();//Wire.setClockのために必要と思う
  Wire.setClock(400000);//Fast-mode400kHzにする時(デフォルトは100kHz記述不要)
  pinMode(2, OUTPUT);//Wi-Fi接続試行中点滅し接続完了で消灯
  mcp.begin(); // use default address 0 MCP23017をデフォルトアドレスで使う
  IPAddress local_IP(192, 168, 1, 4);//送信側(自機)IPアドレス
  IPAddress gateway(192, 168, 1, 1); //
  IPAddress subnet(255, 255, 255, 0);
  WiFi.mode(WIFI_STA);//Wi-Fi子機モート
  WiFi.config(local_IP, gateway, subnet);
  Serial.println("Connecting to WiFi network: " + String(ssid));
  // delete old config
  WiFi.disconnect(true);
  //register event handler イベントハンドラーの登録
  WiFi.onEvent(WiFiEvent);
  //Initiate connection
  WiFi.begin(ssid, password);
  Serial.println("Waiting for WIFI connection...");
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++
    digitalWrite(2, HIGH);
    delay(250);
    digitalWrite(2, LOW);
    delay(250);
    Serial.print(".");
  }
  if (i == 21) { // Wi-Fi接続不能を回避 10秒待ってESPをリスタートする。
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }
  Serial.println(WiFi.status() == WL_CONNECTED ? "WiFi connected!" : "Failed!");

  //Connect to the WiFi network
  //connectToWiFi(networkName, networkPswd);
  //udp.begin(udpPort);           // UDP通信開始
  for (int i = 0; i
    mcp.pinMode(i, INPUT);    // mcp23017の全ピンをPULLUPを有効
    mcp.pullUp(i, HIGH);  // turn on a 100K pullup internally
  }
}
void loop() {
  //only send data when connected接続時にのみデータを送信する
  //if (WiFi.status() == WL_CONNECTED) {
  if (connected) {
    //connected がfalseになった時はdelay(5000)後ESP.restart()している
    //Send a packet
    udp.beginPacket(udpAddress, udpPort);
    /*Serial.printf("%05x", mcp.readGPIOAB()); Serial.println();*/
    udp.printf("%05x", mcp.readGPIOAB());//桁を揃えて送るため0埋め
    //udp.printf(" Seconds since boot: %lu", millis() / 1000);//使い方の例
    udp.endPacket();
  }
  //Wait for
  delay(1);
}
/*void connectToWiFi(const char * ssid, const char * pwd) {
  Serial.println("Connecting to WiFi network: " + String(ssid));
  // delete old config
  WiFi.disconnect(true);
  //register event handler
  WiFi.onEvent(WiFiEvent);
  //Initiate connection
  WiFi.begin(ssid, pwd);
  Serial.println("Waiting for WIFI connection...");
  }*/
//wifi event handler
void WiFiEvent(WiFiEvent_t event) {
  switch (event) {
    case SYSTEM_EVENT_STA_GOT_IP:
      //When connected set
      Serial.print("WiFi connected! IP address: ");
      Serial.println(WiFi.localIP());
      Serial.print("ESP Mac Address: "); Serial.println(WiFi.macAddress());
      //initializes the UDP state
      //This initializes the transfer buffer
      udp.begin(WiFi.localIP(), udpPort);
      connected = true;
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      Serial.println("WiFi lost connection");
      connected = false;
      //connected がfalseになった時はdelay(5000)後ESP.restart()している
      for(int i = 0; i <= 5; i++){
      digitalWrite(2, HIGH);
      delay(700);
      digitalWrite(2, LOW);
      delay(300);
      }
      ESP.restart();
    default: break;
  }
}

スケッチ作例を公開している方々へ感謝します。


ESP32pcntカウンタをテストしてみた

2021-12-09 17:25:00 | マイコンソフトウェア

ESP32でpcntカウンタでパルスをただ数えるだけ。
16bitの符号付きの高速なパルスカウンタです。
もっと詳しい事を知りたい方は
esp32 pcntで検索するとなにか見つかると思います。

桁数が足らないので工夫しています。
素人の書いたコードなので間違いがあるかも知れません。

#include "driver/pcnt.h"

#define PULSE_INPUT_PIN 32 //パルスの入力ピン
#define PULSE_CTRL_PIN 33 //制御ピン
#define PCNT_H_LIM_VAL 32768 //カウンタの上限32768 16bit Counter 65536
#define PCNT_L_LIM_VAL -32768 //カウンタの下限-32768

int16_t count = 0; //カウント数
unsigned long currentCount = 0;
unsigned long previousCount = 0;
unsigned long addCount = 0;

unsigned long previousMillis = 0;
const long interval = 1000;

void setup() {
pcnt_config_t pcnt_config;//設定用の構造体の宣言
pcnt_config.pulse_gpio_num = PULSE_INPUT_PIN;
//pcnt_config.ctrl_gpio_num = PULSE_CTRL_PIN;//制御信号入力GPIO番号
pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED;
pcnt_config.lctrl_mode = PCNT_MODE_REVERSE;//_REVERSE:invert counter mode(increase -> decrease, decrease -> increase)
pcnt_config.hctrl_mode = PCNT_MODE_KEEP;//_KEEP:won’t change counter mode
// PCNT_MODE_DISABLE:Inhibit counter(counter value will not change in this condition)
pcnt_config.channel = PCNT_CHANNEL_0;
pcnt_config.unit = PCNT_UNIT_0;
//pcnt_config.pos_mode = PCNT_COUNT_INC;//positive edge count mode _INC:Increase counter value
pcnt_config.pos_mode = PCNT_COUNT_DEC;//positive edge count mode _INC:Increase counter value
//pcnt_config.neg_mode = PCNT_COUNT_DEC;//negative edge count mode _DEC:Decrease counter value
pcnt_config.neg_mode = PCNT_COUNT_DIS;//negative edge count mode _DEC:Decrease counter value
pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;
pcnt_config.counter_l_lim = PCNT_L_LIM_VAL;

pcnt_unit_config(&pcnt_config); //ユニット初期化
pcnt_counter_pause(PCNT_UNIT_0); //カウンタ一時停止
pcnt_counter_clear(PCNT_UNIT_0); //カウンタ初期化
Serial.begin(115200);
pcnt_counter_resume(PCNT_UNIT_0); //カウント再開
}

void loop() {
pcnt_get_counter_value(PCNT_UNIT_0, &count);

unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;

currentCount = count;
if ( currentCount > previousCount) { //以前値より現在値が大きい時
//16bitカウンタ(-32,768〜+32,768)では1日の生産数の途中でオーバーフローするので、
//一定時間毎にカウント値の差を算出して変数へ加算する
//addCount:カウント値を加算するための変数
addCount += currentCount - previousCount; //現在値-以前値をaddCountへ加算
} else if (currentCount < previousCount) { //カウンタオーバーフローで以前値より現在値が小さい
addCount += currentCount - previousCount - 4294934529; //カウンタオーバーフロー時の
}
Serial.println(addCount); //カウント値加算する変数を表示
//if(count > 100) pcnt_counter_clear(PCNT_UNIT_0);
//if(count < -100) pcnt_counter_clear(PCNT_UNIT_0);
Serial.print("Counter value: ");

Serial.println(count); //
previousCount = currentCount;
//delay(50);
}
}


ESP32 HTTPサーバからのダウンロード速度UP(調査中)

2021-10-22 11:15:00 | マイコンソフトウェア

調査継続中ですが

わかったことを載せておきます。

SD.begin(5, SPI, 24000000, "/sd");//24000000=24Mhz デフォルト 4Mhz

SPI.begin(); // start up the SPI bus
SPI.setFrequency(6000000);//6000000=6Mhz デフォルト 1Mhz

デフォルト設定でのテスト結果
平均 230 KB/s
ESP-WROOM-02では
平均 150 KB/s(120〜180 KB/s)

設定変更後
平均 366 KB/s(416〜330 KB/s)
SPIの変更効果は?再検証予定

条件
約8MBファイルをRasPi4(4GB)のLXTerminalでwgetで
ダウンロード