コントロールソフトをすこし解説。
以前にも書いたように、外にあるスイッチャー本体と室内のコントローラは ESP-NOW という仕組みで通信を行う。この方式は、一度に伝送できるデータ数が 260Byte に限定されるが、SSIDなどの設定が不要で使いやすい。
画像のように MACアドレスで識別してやり取りをするものなので、お互いの MAC アドレスを知る必要がある。
ESP32のMACアドレスを表示するスケッチは以下の通りで、リセットするとMACアドレスがシリアルモニタに出力される。
#include "WiFi.h"
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println();
Serial.print("ESP8266 Board MAC Address: ");
Serial.println(WiFi.macAddress());
}
void loop() {
}
室内側のコントローラメインプログラムは以下のとおり。
イニシャライズ後、切替スイッチの情報を取得して、その番号を外側のスイッチャー本体(Sub)に送信する。Sub側から応答がないときには、スイッチ番号の前に「*」を表示して通信が確立していないことを表示する。今回は、128x64 OLED を使ったがシンプルにLEDを点灯させるのも良いと思う。
// Antenna Coaxial SW'er Main Program
// Pins Definition For ESP32
#define SwitchPIN11 19 //Switch 1
#define SwitchPIN12 18 //Switch 2
#define SwitchPIN13 5 //Switch 3
#define SwitchPIN14 17 //Switch 4
#define NoSelect 9 // Switch is Not selected
#include "U8x8lib.h"
#include "WiFi.h"
#include "esp_now.h"
// PUBlic variables
int SetSwitchNo1 ; // Set Switch Number Main to Switcher
int SetSwitchNo2 ; // Set Switch Number Main to Switcher
int GetSwitchNo ; // Get Switch Number Switcher to Main
String AntName; // Antenna Name
//For ESP-NOW Communication setting
boolean RxStatus; // Receiver Status form Send TASK
// MAC Address of ESP32 Switcher Receiver
uint8_t broadcastAddress1[] = {0x30, 0xAE, 0xA4, 0x96, 0x5A, 0xD0};
// Structure to Send/Receive Data Must match the receiver structure
typedef struct struct_message {
int SwitchNo ; // 1-4 Antenna Switch No.
} struct_message;
// Create a struct_message to Send & ReceiveData
struct_message MtoS;
struct_message StoM;
// Definition For OLED Display
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE);
void setup() {
pinMode(SwitchPIN11, INPUT_PULLUP);
pinMode(SwitchPIN12, INPUT_PULLUP);
pinMode(SwitchPIN13, INPUT_PULLUP);
pinMode(SwitchPIN14, INPUT_PULLUP);
// OLED Library Starts
u8x8.begin();
// WiFi Parameters Setting Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Initialize ESP-NOW
if (esp_now_init() != ESP_OK) {
u8x8.setFont(u8x8_font_8x13_1x2_f);
u8x8.setCursor(0,6);
u8x8.print("ESP-NOW: NG");
return;}
else{u8x8.setCursor(0,6);
u8x8.print("ESP-NOW: OK"); }
delay(2000);
// Once ESPNow is successfully Init, we will register for
// Send CB toget the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_peer_info_t peerInfo;
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add 1st peer
memcpy(peerInfo.peer_addr, broadcastAddress1, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK){
u8x8.setFont(u8x8_font_8x13_1x2_f);
u8x8.setCursor(0,6);
u8x8.print(" ");
u8x8.print("Peer 1: NG");
delay(2000);
return; }
// Register for a callback function that will be called
// when data is received
esp_now_register_recv_cb(OnDataRecv);
// Set up Form Display
u8x8.setFont(u8x8_font_8x13B_1x2_f);
u8x8.clear();
u8x8.setCursor(0,0);
u8x8.print(" -Ant Switcher-");
u8x8.setCursor(0,3);
u8x8.print(" SW1:");
} // END Setup()
void loop() {
// Read Switch1 Status and Set Switch Number
if ( digitalRead(SwitchPIN11) == LOW ) SetSwitchNo1 = 1 ;
else if ( digitalRead(SwitchPIN12) == LOW ) SetSwitchNo1 = 2 ;
else if ( digitalRead(SwitchPIN13) == LOW ) SetSwitchNo1 = 3 ;
else if ( digitalRead(SwitchPIN14) == LOW ) SetSwitchNo1 = 4 ;
else SetSwitchNo1 = NoSelect ;
// Send Switch Data message to Switcher Receiver via ESP-NOW
MtoS.SwitchNo = SetSwitchNo1 ; // Update SW Status
esp_now_send(broadcastAddress1, (uint8_t *) &MtoS, sizeof(MtoS));
delay(100); // 100msec Block
// Display Switcher1 Status
u8x8.setFont(u8x8_font_8x13B_1x2_f);
u8x8.setCursor(10,3);
if ( RxStatus ) u8x8.print(" ");
else u8x8.print("*");
u8x8.print(SetSwitchNo1);
} //End Loop()
// Communication TASK via ESP NOW
// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
{ if (status ==0) RxStatus = true;
else RxStatus = false; }
// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
{ memcpy(&StoM, incomingData, sizeof(StoM));
GetSwitchNo = StoM.SwitchNo ; // Data Update
}
室外のスイッチャー(Sub)のスケッチは以下のとおり。
イニシャライズ後、単純にメインから受信したデータに従って出力ポートに出力するだけのものである。
// 1:4 Switcher Sub Program
// Pins Definition for ESP32 Devkit Switcher Controler
#define SwitchPIN11 15 // Switch 1
#define SwitchPIN12 12 // Switch 2
#define SwitchPIN13 14 // Switch 3
#define SwitchPIN14 27 // Switch 4
#define NoSelect 9 // Switch is Not selected
#include "WiFi.h"
#include "esp_now.h"
// PUBlic variables
int SetSwitchNo ; // Set Switch Number Main to Switcher
int GetSwitchNo ; // Get Switch Number Switcher to Main
//For ESP-NOW Communication setting
boolean RxStatus; // Receiver Status form Send TASK
// MAC Address of ESP32 Main Transmitter
uint8_t broadcastAddress[] = {0xA4, 0xCF, 0x12, 0x96, 0x8E, 0xE8};
// Variable to store if sending data was successful
String success;
// Structure to Send/Receive Data Must match the receiver structure
typedef struct struct_message {
int SwitchNo ; // 1-4 Antenna Switch No.
} struct_message;
// Create a struct_message to Send & ReceiveData
struct_message MtoS;
void setup() {
pinMode(SwitchPIN11, OUTPUT);
pinMode(SwitchPIN12, OUTPUT);
pinMode(SwitchPIN13, OUTPUT);
pinMode(SwitchPIN14, OUTPUT);
// All Switch are OFF
digitalWrite(SwitchPIN11,LOW);
digitalWrite(SwitchPIN12,LOW);
digitalWrite(SwitchPIN13,LOW);
digitalWrite(SwitchPIN14,LOW);
// WiFi Parameters Setting Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Initialize ESP-NOW
esp_now_init();
delay(500);
// Once ESPNow is successfully Init, we will register for
// Send CB to get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
esp_now_add_peer(&peerInfo) ;
delay(500);
// Register for a callback function that will be called when data is received
esp_now_register_recv_cb(OnDataRecv);
} // END Setup()
void loop() {
// Set Switch Status and Set Switch Number
switch(SetSwitchNo){
case 1 : // Switch 1 ON
digitalWrite(SwitchPIN11,HIGH);
digitalWrite(SwitchPIN12,LOW);
digitalWrite(SwitchPIN13,LOW);
digitalWrite(SwitchPIN14,LOW);
break;
case 2 : // Switch 2 ON
digitalWrite(SwitchPIN12,HIGH);
digitalWrite(SwitchPIN11,LOW);
digitalWrite(SwitchPIN13,LOW);
digitalWrite(SwitchPIN14,LOW);
break;
case 3 : // Switch 3 ON
digitalWrite(SwitchPIN13,HIGH);
digitalWrite(SwitchPIN11,LOW);
digitalWrite(SwitchPIN12,LOW);
digitalWrite(SwitchPIN14,LOW);
break;
case 4 : // Switch 4 ON
digitalWrite(SwitchPIN14,HIGH);
digitalWrite(SwitchPIN11,LOW);
digitalWrite(SwitchPIN12,LOW);
digitalWrite(SwitchPIN13,LOW);
break;
default: // All Switch OFF
{ digitalWrite(SwitchPIN11,LOW);
digitalWrite(SwitchPIN12,LOW);
digitalWrite(SwitchPIN13,LOW);
digitalWrite(SwitchPIN14,LOW);
}
}
delay(200); // 200msec Block
} //End Loop()
// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
{
if (status ==0) RxStatus = true;
else RxStatus = false;
}
// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
{
memcpy(&MtoS, incomingData, sizeof(MtoS));
SetSwitchNo = MtoS.SwitchNo ; // Switch Data Update
}