imm が 2021年02月27日01時03分55秒 に編集
初版
タイトルの変更
【ESP32】Webからの入力でモールス信号をLチカ
タグの変更
ESP32
秋葉原2021
メイン画像の変更
本文の変更
概要 ==== ESP32でWi-Fi通信を行い、webブラウザで入力した文字列をモールス信号に変換し、2色のLEDの点滅として出力します。 モールス信号を光の明滅で表現するのは最近見た某映画から発想しました。 主要な部品 ======== - ESP32開発ボード - LED×2(赤/青) - 抵抗(100Ω)×2 その他導線、電池、外装(3Dプリンターで制作)など 回路 ==== 2番ピンと19番ピンにそれぞれLEDと抵抗を接続しています。 ![キャプションを入力できます](https://camo.elchika.com/3d7313cbb6418f3de653c711508d64eea9337f49/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f37326439326639632d666432622d343764632d396530622d3163366561613563343435392f31323932306166332d343632652d343162612d393365652d653530633533323739626530/) プログラム ==== ``` #include <WiFi.h> //ここに自分の環境のWiFi情報を入れる const char* ssid = "hogehoge"; const char* password = "hogehogepaswd"; WiFiServer server(80); int pin1 = 2; int pin2 = 19; int timeUnit = 100; char inputChar; void setup() { Serial.begin(115200); pinMode(pin1, OUTPUT); // set the LED pin mode pinMode(pin2,OUTPUT); delay(10); // We start by connecting to a WiFi network ----------------------------- Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected."); Serial.print("IP address: "); Serial.println(WiFi.localIP()); //ここで取得したIPアドレスをブラウザで入力 server.begin(); } void loop(){ WiFiClient client = server.available(); // listen for incoming clients int pos ; String cmd = "" ; if (client) { // if you get a client, Serial.println("***** Client access start *****"); // print a message out the serial port while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, String line = client.readStringUntil('\n'); // Get Line data until '\n'1行ずつ読んでいく Serial.print("client:"); Serial.println(line); if ((pos= line.indexOf("GET /?led_v")) != -1) {//指定の文字列がある Serial.print("client:") ; Serial.println(line); Serial.println("volume"); pos += 12 ; Serial.println(pos); while(line.charAt(pos) !='&') {//文字列からpos番目の文字列を抜き出す(〜&が出てくるまで) inputChar = line.charAt(pos++) ; morse(inputChar);//対応する文字のモールス信号を出力 cmd += inputChar;//1文字ずつ右に足していく } Serial.print("cmd : "); Serial.println(cmd) ;//入力した文字列(シリアルモニタで確認する用) } if (line.length() == 1 && line[0] == '\r'){ // end of HTTP request send_response(client) ; // send response to client break; // break while loop } } } delay(1); // give the web browser time to receive the data // close the connection: client.stop(); Serial.println("Client Disconnected."); Serial.println("--------------------------------------------------"); } } // ------------------------------------------------------------------ //ブラウザ表示用のHTML void send_response(WiFiClient client) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println(); // the content of the HTTP response follows the header: client.println("<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>" ) ; client.println("<style>" ) ; //client.println(" input.button {margin-left:8px; width:80px; height:30px;background-color:#4682b4; color:#fff;}" ) ; client.println(" inlut.button{width:80px; height:30px;margin-left:8px;text-decoration: none;color:#fff;border: solid 2px #4682b4;border-radius: 3px;transition: .4s;}"); client.println(" input.button:hover{background-color:#4682b4; color:#fff;border-radius: 3px;}" ) ; client.println(" input.text {border-radius: 3px;}" ) ; client.println(" div {font-size:20pt;text-align:center;margin:5%;padding:10%;border:solid 10px #4682b4;} " ) ; client.println(" </style>" ) ; client.println("<title>LED Morse Signal</title></head>" ) ; client.println() ; client.println("<body><div><p>LED Morse Signal</p>" ) ; client.println(" <form method='get'style='text-align:center'> " ) ; client.println(" <span style=' font-size:12pt ;text-align:center'> <p>input text(a-z only)</p></span> " ) ; client.print(" <input class='text' type='text' name='led_v'>" ) ; client.println("<input class='button' type='submit' name='convert' value='CONVERT'></form> " ) ; client.println(" </div></body>" ) ; client.println("</html>" ) ; client.println(); Serial.println( " --- send responce --- "); } //以下はモールス信号用のプログラム void dot(){//トン digitalWrite(pin1,HIGH); delay(timeUnit); digitalWrite(pin1,LOW); delay(timeUnit); } void dash(){//ツー digitalWrite(pin2,HIGH); delay(timeUnit * 3); digitalWrite(pin2,LOW); delay(timeUnit); } void letterPause(){//2符号の間隔 delay(timeUnit *3); } void wordPause(){//2語の間隔 delay(timeUnit *7); } void lA () {dot();dash();letterPause();}//letter A in morse code! void lB () {dash();dot();dot();dot();letterPause();}//same for B void lC () {dash();dot();dash();dot();letterPause();} void lD () {dash();dot();dot();letterPause();} void lE () {dot();letterPause();} void lF () {dot();dot();dash();dot();letterPause();} void lG () {dash();dash();dot();letterPause();} void lH () {dot();dot();dot();dot();letterPause();} void lI () {dot();dot();letterPause();} void lJ () {dot();dash();dash();dash();letterPause();} void lK () {dash();dot();dash();letterPause();} void lL () {dot();dash();dot();dot();letterPause();} void lM () {dash();dash();letterPause();} void lN () {dash();dot();letterPause();} void lO () {dash();dash();dash();letterPause();} void lP () {dot();dash();dash();dot();letterPause();} void lQ () {dash();dash();dot();dash();letterPause();} void lR () {dot();dash();dot();letterPause();} void lS () {dot();dot();dot();letterPause();} void lT () {dash();letterPause();} void lU () {dot();dot();dash();letterPause();} void lV () {dot();dot();dot();dash();letterPause();} void lW () {dot();dash();dash();letterPause();} void lX () {dash();dot();dot();dash();letterPause();} void lY () {dash();dot();dash();dash();letterPause();} void lZ () {dash();dash();dot();dot();letterPause();} void morse(char input){ if (input == 'a' || input == 'A') {lA();}//if the input is a or A go to function lA if (input == 'b' || input == 'B') {lB();}//same but with b letter if (input == 'c' || input == 'C') {lC();} if (input == 'd' || input == 'D') {lD();} if (input == 'e' || input == 'E') {lE();} if (input == 'f' || input == 'F') {lF();} if (input == 'g' || input == 'G') {lG();} if (input == 'h' || input == 'H') {lH();} if (input == 'i' || input == 'I') {lI();} if (input == 'j' || input == 'J') {lJ();} if (input == 'k' || input == 'K') {lK();} if (input == 'l' || input == 'L') {lL();} if (input == 'm' || input == 'M') {lM();} if (input == 'n' || input == 'N') {lN();} if (input == 'o' || input == 'O') {lO();} if (input == 'p' || input == 'P') {lP();} if (input == 'q' || input == 'Q') {lQ();} if (input == 'r' || input == 'R') {lR();} if (input == 's' || input == 'S') {lS();} if (input == 't' || input == 'T') {lT();} if (input == 'u' || input == 'U') {lU();} if (input == 'v' || input == 'V') {lV();} if (input == 'w' || input == 'W') {lW();} if (input == 'x' || input == 'X') {lX();} if (input == 'y' || input == 'Y') {lY();} if (input == 'z' || input == 'Z') {lZ();} if (input == ' ') {wordPause();} } ``` Webからの入力に関してはこちらを、 https://qazsedcftf.blogspot.com/2018/07/arduinoled.html モールス信号に関してはこちらを https://deviceplus.jp/hobby/how-to-create-morse-code-generator/ 参考にさせていただいています。 外装設計 ==== 3DCADで設計しました。 電池ケースと、マイコンを搭載するスペース、LEDを設置する場所を内部に用意して、対応する蓋の部分にトン・ツーを表象する穴を開けています。 正面の蓋は上下にスライドして開きます。3Dプリンタで造形する都合を考え、蓋部・箱部・電池ボックス・電子部品用ユニットの4つに分けてあります。 ![外装蓋付](https://camo.elchika.com/93c12e190e64178ead6319d32aa35803c4a76ca1/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f37326439326639632d666432622d343764632d396530622d3163366561613563343435392f37313262356564352d356632392d343336392d383331312d666361616234323537623034/) ![外装内部](https://camo.elchika.com/e620255f1b189df4ff8a126006ca26c74c14f06c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f37326439326639632d666432622d343764632d396530622d3163366561613563343435392f32383132306639332d386563332d343638322d613535332d623865376663353537373466/) 完成 ==== はんだ付けを行い、3Dプリンタで造形した外装の中に電子部品類を収めて完成。 ![完成](https://camo.elchika.com/1917d6d3ec6be32df408c69271f098ba7b55e662/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f37326439326639632d666432622d343764632d396530622d3163366561613563343435392f34636462623037322d633266382d346561632d393336362d366636383033653562663064/) ![蓋を外した状態](https://camo.elchika.com/46616fde227982901998ffd944d9653210c641f1/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f37326439326639632d666432622d343764632d396530622d3163366561613563343435392f38336565353763612d393662642d346532322d623232332d346435376337633335666161/) 電源を入れ、事前にシリアルモニタを見て取得していたIPアドレスをブラウザに入力すると、入力画面が表示されます。モールス信号に変換したい文字列を入力窓に記入して、[CONVERT]ボタンを押すと、対応するLEDが点滅します。 ブラウザからの入力によって光らせた様子がこちら。 @[twitter](https://twitter.com/imm_eaten/status/1365318938746232834) うまくいきました! おわりに ==== 電子工作初心者なものでプログラムはほとんど先人の方がwebで公開されていたものを組み合わせただけですが、自分で作りたいと思ったものが実際に完成すると感動しますね。 キャンペーンが良いきっかけになったのでこれからも色々作ってみたいと思います。