// *** WiFi8266_OLED_2RC_2WD_with_Buzzer_V2.ino **** // ESP8266 WiFi と スマホを直結(AP不要) // WiFi 新キャタピラ駆動 ラジコン化 2022.1.15 // 効果音,LED, ヘッドライト,LED 追加 2022.3.3 // ⇒汎用 2WD とする.2022.2.24 // SDA⇒GPIO4 4 D2, SCL⇒GPIO5 6 D1 でI2C稼働. // // **** DRV8830 モータードライバ利用情報 **** // 2022.2.12(Sat.) 以上で WiFi R/C 完全動作. // DRV8830 で130Rが起動出来ないのが残念. // ⇒KKHMF 2組 DC 3-6Vギヤードモーター + // スマートカー ロボットタイヤ 65*28MM // DIY Arduinoと互換 電子工作用 ならば動作. // モータードライバにコマンド連続発行式として, // ⇒TAMIYA ダブルギアボックスも動作可となった. // 以上で,キャタピラ駆動制御プログラミングを作成 // // ************ OLED 情報 ************* // DiyStudio 0.91インチESP8266 OLED // ディスプレイ0.91インチOLED // ESP8266 WIFI開発ボードWIFIキット8 // CP2104 IOTサポート // Arduino IDE NodeMCU LUA // 白い底板+ブルースクリーンOLED // ¥1,199 アマゾン 2021/6/9 購入(2枚) // https://www.amazon.co.jp/gp/product/B07R33RSKN/ref=ppx_yo // _dt_b_asin_title_o01_s00?ie=UTF8&psc=1 // ********** コンパイル情報  ************ // CP210x USB to UART Bridge VCP Drivers // Board ==> Generic ESP8266 Module // Port ==> CP210x USB to UART Bridge (COM14, COM13 ...) // **** コンパイル 手順 **** // ファイル → 環境設定 // http://arduino.esp8266.com/stable/package_esp8266com_index.json // "esp8266 by ES8266 Community" → インストール // ボードマネージャー → "Generic ESP8266 Module" // ※以上で コンパイル&書き込みできる 但し,時間がかかる  // ************************************************ // ソースコード // https://www.elekit.co.jp/product/docs/PU-2709Wi-ficar.pdf // 日本語指定 // http://mukujii.sakura.ne.jp/esp1.html // OLED Display // https://qiita.com/jakalada/items/793a6cf5ff2796db4e86 #include #include #include #include #include #include #include #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 32 #define trig 12 // 効果音 #define Headlight 14 // ヘッドライト // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET 16 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); /* Set these to your desired credentials. */ const char *ssid = "WIFI-RC"; // AP モード時のSSID const char *password = "12345678"; // パスワード ESP8266WebServer server(80); #define form_chanum 500 String form = "\ \ \n\ \ \
   \
\

\
\
\  \
\  \
\

\
   \
\
\
\ スピード
\
\
\
\
\
\
\
\
\
\  \
\
\ "; /* プロトタイプ宣言*/ void handleRoot(); void handle_stop(); void handle_forward(); void handle_turn_left(); void handle_turn_right(); void handle_back(); void handle_speed1(); void handle_speed2(); void handle_speed3(); void handle_speed4(); void handle_LIGHT(); void handle_REV(); void ST_ACT(); void FD_ACT(); void TL_ACT(); void TR_ACT(); void BK_ACT(); void SP1(); void SP2(); void SP3(); void SP4(); void LIGHT(); void REV(); // DRV8830 Motor Driver I2Cアドレス //#define DRV_ADR_0 0x63 // DRV8830のI2Cアドレス #0 #define DRV_ADR_0 0x61 // DRV8830のI2Cアドレス #0 //#define DRV_ADR_2 0x63 // DRV8830のI2Cアドレス #2 #define DRV_ADR_2 0x64 // DRV8830のI2Cアドレス #2 #define CTR_ADR 0x00 // CONTROLレジスタのサブアドレス #define FLT_ADR 0x01 // FAULTレジスタのアドレス #define CLEAR 0x80 // ブリッジ制御 #define M_STANBY B00 // スタンバイ #define M_REVERSE B01 // 逆転 #define M_NORMAL B10 // 正転 #define M_BRAKE B11 // ブレーキ // 電圧定義 #define MAX_VSET 44 // 40,50,45,49,44* #define MIN_VSET 10 byte DRV_ADR; byte M1_DIREC, M2_DIREC ; // Motor DIRECTION byte vs_1, vs_2; // Motor PW float M_DIV ; // 減速変数 const float M_1 = 8.0, M_2 = 6.0; // Change Gear const float M_3 = 4.0, M_4 = 1.0; // boolean REV_SW = true; // 前後反転スイッチ boolean LIGHT_SW = false; // 制御コマンド送信 float mul_f_0 = 1.11 ; // モーターのバラつきを補正 int write_vset_s(byte vs, byte ctr, byte DRV_ADR) { clear_fault(DRV_ADR); Wire.beginTransmission(DRV_ADR); Wire.write(CTR_ADR); Wire.write( ctr + (vs << 2) ); return Wire.endTransmission(); } int write_vset(byte vs, byte ctr, byte DRV_ADR) { float vs_f; vs_f = vs; vs_f *= mul_f_0; if ( DRV_ADR == DRV_ADR_0 ) { vs = vs_f; // 2モーターのアンバランス調整 } write_vset_s(vs, ctr, DRV_ADR); return 1; } void clear_fault(byte ADR) { Wire.beginTransmission(ADR); Wire.write(FLT_ADR); Wire.write(CLEAR); // Clear FALUT flag Wire.endTransmission(); } void Pi() { digitalWrite(trig, HIGH); delay(50); digitalWrite(trig, LOW); delay(50); } void PiPi() { Pi(); Pi(); } void setup() { delay(300); Serial.begin(115200); while (!Serial); pinMode(trig, OUTPUT); pinMode(Headlight, OUTPUT); PiPi(); digitalWrite(Headlight, LOW); REV_SW = true; LIGHT_SW = false; Serial.println(); Serial.print("Configuring access point..."); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32 Serial.println(F("SSD1306 allocation failed")); for (;;); } display.display(); delay(1000); display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("WIFI-RC"); display.display(); delay(1000); byte error, address; int nDevices; Serial.println("Scanning..."); delay(500); nDevices = 0; display.clearDisplay(); display.display(); display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 5); for (address = 1; address < 127; address++ ) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C = 0x"); if (address < 16) Serial.print("0"); Serial.print(address, HEX); Serial.println(" !"); display.print("I2C = 0x"); display.println(address, HEX); display.display(); nDevices++; } else if (error == 4) { Serial.print("Unknown error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(1500); WiFi.softAP(ssid, password); IPAddress myIP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(myIP); server.on("/", handleRoot); /* 各アクション時のハンドル設定*/ server.on("/ST", handle_stop); server.on("/FD", handle_forward); server.on("/TL", handle_turn_left); server.on("/TR", handle_turn_right); server.on("/BK", handle_back); server.on("/SP1", handle_speed1); server.on("/SP2", handle_speed2); server.on("/SP3", handle_speed3); server.on("/SP4", handle_speed4); server.on("/LIGHT", handle_LIGHT); server.on("/REV", handle_REV); server.begin(); Serial.println("HTTP server started"); Serial.println("server STOP"); Serial.println("2WD R/C 2022.2.15"); display.clearDisplay(); display.display(); delay(100); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 5); display.println("server STOP"); display.println(); display.println("2WD R/C 2022.2.15"); display.display(); delay(1000); display.clearDisplay(); display.display(); delay(100); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(0, 2); display.println("Set IP add"); display.println("192168.4.1"); display.display(); Serial.println("End warm up"); Serial.println("Start WiFi R/C"); delay(300); vs_1 = vs_2 = 0; M_DIV = M_2; // 2速 digitalWrite(Headlight, HIGH); PiPi();delay(50); PiPi(); digitalWrite(Headlight, LOW); } // 連続vセット ⇒ 確実に回すための苦肉の策 // R/Cサーボモーターへの送信信号的制御 void loop() { float vsf; byte vs; server.handleClient(); vsf = vs_1; vsf = vsf / M_DIV; vs = vsf; write_vset(vs, M1_DIREC, DRV_ADR_0 ); vsf = vs_2; vsf = vsf / M_DIV; vs = vsf; write_vset(vs, M2_DIREC, DRV_ADR_2 ); } /* 各ハンドルの内容記述*/ void handleRoot() { server.send(form_chanum, "text/html", form); handle_stop(); } /* スピードハンドルの各記述*/ void handle_speed1() { Serial.println("①"); SP1(); PiPi(); server.send(form_chanum, "text/html", form); } void handle_speed2() { Serial.println("②"); SP2(); PiPi(); server.send(form_chanum, "text/html", form); } void handle_speed3() { Serial.println("③"); SP3(); PiPi(); server.send(form_chanum, "text/html", form); } void handle_speed4() { Serial.println("④"); SP4(); PiPi(); server.send(form_chanum, "text/html", form); } void handle_LIGHT() { Serial.println("LIGHT"); LIGHT(); PiPi(); delay(50); PiPi(); server.send(form_chanum, "text/html", form); } void handle_REV() { Serial.println("REV"); REV(); PiPi(); server.send(form_chanum, "text/html", form); } /*************************************/ /*---- 各ハンドル記述内の関数内容 --------*/ void SP1() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("SPEED 1"); display.display(); M_DIV = M_1; } void SP2() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("SPEED 2"); display.display(); M_DIV = M_2; } void SP3() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("SPEED 3"); display.display(); M_DIV = M_3; } void SP4() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("SPEED 4"); display.display(); M_DIV = M_4; } void LIGHT() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("LIGHT"); display.display(); if (LIGHT_SW == true) { digitalWrite(Headlight, HIGH); } else { digitalWrite(Headlight, LOW); } LIGHT_SW = !LIGHT_SW; } void REV() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("REV"); display.display(); REV_SW = !REV_SW ; } /* ストップハンドルの記述*/ void handle_stop() { Serial.println("□"); ST_ACT(); PiPi(); server.send(form_chanum, "text/html", form); } /* 前進ハンドルの記述*/ void handle_forward() { Serial.println("⇧"); FD_ACT(); PiPi(); server.send(form_chanum, "text/html", form); } /* 左折ハンドルの記述*/ void handle_turn_left() { Serial.println("<<==="); TL_ACT(); PiPi(); server.send(form_chanum, "text/html", form); } /* 右折ハンドルの記述*/ void handle_turn_right() { Serial.println("===>>"); TR_ACT(); PiPi(); server.send(form_chanum, "text/html", form); } /* バックハンドルの記述*/ void handle_back() { Serial.println("⇩"); BK_ACT(); PiPi(); server.send(form_chanum, "text/html", form); } /*---- 各ハンドル記述内の関数内容 --------*/ /* ストップの関数*/ void ST_ACT() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("STOP"); display.display(); M1_DIREC = M_BRAKE; M2_DIREC = M_BRAKE; vs_1 = 0; vs_2 = 0; digitalWrite(Headlight, LOW); } /* 前進の関数*/ void FD_ACT() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("FORWARD"); display.display(); if (REV_SW == false) { M1_DIREC = M_NORMAL; M2_DIREC = M_NORMAL; digitalWrite(Headlight, LOW); } else { M1_DIREC = M_REVERSE; M2_DIREC = M_REVERSE; digitalWrite(Headlight, HIGH); } vs_1 = MAX_VSET; vs_2 = MAX_VSET; } /* 左回転の関数*/ void TL_ACT() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("<<==="); display.display(); if (REV_SW == false) { M1_DIREC = M_BRAKE; M2_DIREC = M_NORMAL; vs_1 = 0; vs_2 = MAX_VSET; } else { M1_DIREC = M_REVERSE; M2_DIREC = M_BRAKE; vs_1 = MAX_VSET; vs_2 = 0; } digitalWrite(Headlight, HIGH); } /* 右回転の関数*/ void TR_ACT() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("===>>"); display.display(); if (REV_SW == false) { M1_DIREC = M_NORMAL; M2_DIREC = M_BRAKE; vs_1 = MAX_VSET; vs_2 = 0; } else { M1_DIREC = M_BRAKE; M2_DIREC = M_REVERSE; vs_1 = 0; vs_2 = MAX_VSET; } digitalWrite(Headlight, HIGH); } /* バックの関数*/ void BK_ACT() { display.clearDisplay(); display.setTextSize(3); display.setTextColor(WHITE); display.setCursor(0, 10); display.println("BACK"); display.display(); if (REV_SW == false) { M1_DIREC = M_REVERSE; M2_DIREC = M_REVERSE; vs_1 = MAX_VSET; vs_2 = MAX_VSET; digitalWrite(Headlight, HIGH); } else { M1_DIREC = M_NORMAL; M2_DIREC = M_NORMAL; vs_1 = MAX_VSET; vs_2 = MAX_VSET; digitalWrite(Headlight, LOW); } } // ***************************************