とある目的で、プログラムから複数の100VのON/OFFを制御したかったので、以下のSolid State Relayを購入しました。
4 Channels Solid State Relay Module(Low Trigger)

100Vを4チャンネル制御でき、信号も3.3V~5Vで送れるので、ArduinoやRaspberry Piで使えそうです。
ラッキーなことに、このリレーをArduinoから制御する動画がありましたので、これを参考に実装を進めていきます。
ただ、Webブラウザから制御したかったので、ArduinoではなくESP32で実装します。
材料
- ESP32-DevKitC
- 4 Channels Solid State Relay Module
- ブレッドボード
- ケーブル(オス-メス)
このほかに、100VでON/OFFしたい機器も用意します。
(今は内緒なので、今回は公開しません)
また、開発はArduino IDEで行います。
注意事項
100Vの交流を扱うので、触るときには気をつけるとともに、電気を通さない板の上などで作業を行うようにしてください。
接続
ESP32とリレーは以下のように接続します。
| ESP32 | リレー |
|---|---|
| 5V | DC+ |
| GND | DC- |
| IO4 | CH1 |
| IO5 | CH2 |
| IO16 | CH3 |
| IO17 | CH4 |
今回はとりあえず2チャンネルだけ使用します。

※ケーブルが全部黒で、わかりづらく、申し訳ないです...
プログラム
ベースはこちらと同じになります。
違う部分だけ書いていきます。
4チャンネル対応
4チャンネル分のポート番号を設定しておきます。
int ssr[] = [4, 5, 16, 17];
int triggerType = LOW;
int ssrON, ssrOFF;
モジュールにより、リレーのON/OFFが逆になっていることがあり、Arduino UNOの場合はON/OFFがHIGH/LOWでいいのですが、ESP32の場合は逆にする必要があります。
そして初期化時等では、4チャンネルに対して処理を行っていきます。
for (i=0; i < 4; i++)
{
pinMode(ssr[i], OUTPUT);
digitalWrite(ssr[i], ssrOFF);
}
初期状態として、すべてのリレーをOFFにしておきます。
URLのパラメータとして、どのチャンネルをON/OFFするかを指定させます。
server.on("/", handleRoot);
server.on("/relay", handleRelay);
server.onNotFound(handleNotFound);
最初に表示するHTMLも4チャンネル対応にします。
html += "<li>リレー1を<a href=\"/relay?c=0&s=on\">ON</a>/<a href=\"/relay?c=0&s=off\">OFF</a>にする</li>";
html += "<li>リレー2を<a href=\"/relay?c=1&s=on\">ON</a>/<a href=\"/relay?c=1&s=off\">OFF</a>にする</li>";
html += "<li>リレー3を<a href=\"/relay?c=2&s=on\">ON</a>/<a href=\"/relay?c=2&s=off\">OFF</a>にする</li>";
html += "<li>リレー4を<a href=\"/relay?c=3&s=on\">ON</a>/<a href=\"/relay?c=3&s=off\">OFF</a>にする</li>";
制御処理も、リンクのパラメータの指定に従って設定するように修正します。
void handleRelay(void)
{
String msg;
int c = -1;
int s = -1;
// 「/relay?c=○&s=□」のパラメータが指定されているかどうかを確認
if (server.hasArg("c") && server.hasArg("s"))
{
// 「○」の値に応じて、リレーのチャンネルを設定する
msg = "リレー";
if (server.arg("c").equals("0"))
{
c = 0;
msg += "1";
}
else if (server.arg("c").equals("1"))
{
c = 1;
msg += "2";
}
else if (server.arg("c").equals("2"))
{
c = 2;
msg += "3";
}
else if (server.arg("c").equals("3"))
{
c = 3;
msg += "4";
}
msg += "を";
// 「□」の値に応じて、リレーのON/OFFを設定する
if (server.arg("s").equals("on"))
{
s = ssrON;
msg += "ON";
}
else if (server.arg("s").equals("off"))
{
s = ssrOFF;
msg += "OFF";
}
msg += "にしました";
// 設定
if ((c >= 0) && (s >= 0))
{
digitalWrite(ssr[c], s);
}
else
{
msg = "パラメータが正しく指定されていません";
}
}
// 変数msgの文字列を送信する
server.send(200, "text/plain; charset=utf-8", msg);
}
実行
制御されている100Vの機器のほうは、今はまだ見せられないのですが、一応ちゃんと動いています。
起動時のシリアル出力です。
このIPアドレスにWebブラウザからアクセスします。

Webブラウザに表示された画面です。
リレーのそれぞれのチャンネルにON/OFFを指定します。

ソースコード
# include <WiFi.h>
# include <WebServer.h>
WebServer server(80);
// WiFi情報
const char* ssid = "wifi_ssid";
const char* pass = "wifi_pass";
// 使用ピン
int ssr[] = {4, 5, 16, 17};
int triggerType = LOW;
int ssrON, ssrOFF;
// 初期画面
void handleRoot(void)
{
String html;
// HTMLを組み立てる
html = "<!DOCTYPE html>";
html += "<html>";
html += "<head>";
html += "<meta charset=\"utf-8\">";
html += "<title>リレーをON/OFFする</title>";
html += "</head>";
html += "<body>";
html += "<p>リンクをクリックするとリレーがON/OFFします</p>";
html += "<ul>";
html += "<li>リレー1を<a href=\"/relay?c=0&s=on\">ON</a>/<a href=\"/relay?c=0&s=off\">OFF</a>にする</li>";
html += "<li>リレー2を<a href=\"/relay?c=1&s=on\">ON</a>/<a href=\"/relay?c=1&s=off\">OFF</a>にする</li>";
html += "<li>リレー3を<a href=\"/relay?c=2&s=on\">ON</a>/<a href=\"/relay?c=2&s=off\">OFF</a>にする</li>";
html += "<li>リレー4を<a href=\"/relay?c=3&s=on\">ON</a>/<a href=\"/relay?c=3&s=off\">OFF</a>にする</li>";
html += "</ul>";
html += "</body>";
html += "</html>";
// HTMLを出力する
server.send(200, "text/html", html);
}
// リレーのON/OFF
void handleRelay(void)
{
String msg;
int c = -1;
int s = -1;
// 「/relay?c=○&s=□」のパラメータが指定されているかどうかを確認
if (server.hasArg("c") && server.hasArg("s"))
{
// 「○」の値に応じて、リレーのチャンネルを設定する
msg = "リレー";
if (server.arg("c").equals("0"))
{
c = 0;
msg += "1";
}
else if (server.arg("c").equals("1"))
{
c = 1;
msg += "2";
}
else if (server.arg("c").equals("2"))
{
c = 2;
msg += "3";
}
else if (server.arg("c").equals("3"))
{
c = 3;
msg += "4";
}
msg += "を";
// 「□」の値に応じて、リレーのON/OFFを設定する
if (server.arg("s").equals("on"))
{
s = ssrON;
msg += "ON";
}
else if (server.arg("s").equals("off"))
{
s = ssrOFF;
msg += "OFF";
}
msg += "にしました";
// 設定
if ((c >= 0) && (s >= 0))
{
digitalWrite(ssr[c], s);
}
else
{
msg = "パラメータが正しく指定されていません";
}
}
// 変数msgの文字列を送信する
server.send(200, "text/plain; charset=utf-8", msg);
}
// 存在しないアドレスが指定された時の処理
void handleNotFound(void)
{
server.send(404, "text/plain", "Not Found.");
}
// 初期化
void setup()
{
int i;
// シリアルポートの初期化
Serial.begin(115200);
// WiFiのアクセスポイントに接続
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
// ESP32のIPアドレスを出力
Serial.println("WiFi Connected.");
Serial.print("IP = ");
Serial.println(WiFi.localIP());
// Groveセンサーの初期化
if (triggerType)
{
ssrON = HIGH;
ssrOFF = LOW;
}
else
{
ssrON = LOW;
ssrOFF = HIGH;
}
for (i=0; i < 4; i++)
{
pinMode(ssr[i], OUTPUT);
digitalWrite(ssr[i], ssrOFF);
}
// 処理するアドレスを定義
server.on("/", handleRoot);
server.on("/relay", handleRelay);
server.onNotFound(handleNotFound);
// Webサーバーを起動
server.begin();
}
// 処理ループ
void loop()
{
server.handleClient();
}
最後に
このリレーで何を制御しようとしているのかは、そのうちどこかで発表した後に記事にします。

