プログラム集

4輪駆動車のプログラム集

便宜上、2022年にAD1で作成した基板を「2022バージョン」、 2023年にAD1で作成した基板を「2023バージョン」と呼ぶことにします。
両者は基板(ピンアサインなど)が少し異なるのでコメントを参考にして適宜変更ください。


1.前後に往復し続けるプログラム

#include <Arduino.h>
const int in1 = 25;
const int in2 = 26;
const int in3 = 32;    // 2023バージョンでは32だが、2022バージョンでは5
const int in4 = 33;    // 2023バージョンでは33だが、2022バージョンでは15

void setup() {
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  digitalWrite(in1, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in2, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in3, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in4, HIGH);    // 2023バージョンではこの行はなくてもよい
}

void loop() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  delay(600);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  delay(600);
}


2.その場で左右に旋回を繰り返すプログラム

#include <Arduino.h>
const int in1 = 25;
const int in2 = 26;
const int in3 = 32;
const int in4 = 33;

void setup() {
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  digitalWrite(in1, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in2, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in3, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in4, HIGH);    // 2023バージョンではこの行はなくてもよい
}

void loop() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  delay(300);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  delay(300);
}


3.発進・停止を繰り返す

#include <Arduino.h>
const int in1 = 25;
const int in2 = 26;
const int in3 = 32;
const int in4 = 33;

void setup() {
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  digitalWrite(in1, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in2, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in3, HIGH);    // 2023バージョンではこの行はなくてもよい
  digitalWrite(in4, HIGH);    // 2023バージョンではこの行はなくてもよい
}

void loop() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  delay(300);
  digitalWrite(in1, HIGH);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, HIGH);
delay(300);
}


4.超音波センサーの試運転

岡田先生がAD2の競技会の事前学習として用意したもの。2022、2023共通。

#include <Arduino.h>
#define Trig 14
#define Echo 12
float Distance = 0.00;

int Search () {
  float Duration = 0.0;
  float CM = 0.0;
  digitalWrite (Trig, LOW);
  delayMicroseconds (2);
  digitalWrite (Trig, HIGH);
  delayMicroseconds (10);
  digitalWrite (Trig, LOW);
  Duration = pulseIn (Echo, HIGH);
  CM = (Duration / 58.8);
  return CM;
}

void setup () {
  Serial.begin(115200);
  pinMode (Trig, OUTPUT);
  pinMode (Echo, INPUT);
}
void loop () {
  delay (1000);
  Distance = Search ();
  Serial.print(F("\r\nDistance Cm: "));
  Serial.println(Distance);
}


5.マイクロサーボ動作確認

ESP32入門の9と同じです。

#include <Arduino.h> #include <ESP32Servo.h> #define SERVO_PIN 13 Servo myServo; void setup() { myServo.attach(SERVO_PIN); } void loop() { myServo.write(0); delay(1000); myServo.write(90); delay(1000); myServo.write(180); delay(1000); myServo.write(90); delay(1000); }

6.壁の前で止まるロボット

永田先生提供作品をESP用に改変。ピンアサインは2022バージョン。

#include <Arduino.h> #define Trig 14 #define Echo 12 #define LF 25 #define LB 26 #define RF 5 #define RB 15 #define ledR 27 int Search () { float Duration = 0.0; float CM = 0.0; digitalWrite (Trig, LOW); delayMicroseconds (2); digitalWrite (Trig, HIGH); delayMicroseconds (10); digitalWrite (Trig, LOW); Duration = pulseIn (Echo, HIGH); CM = (Duration / 58.8); return CM; } void setup() { Serial.begin(115200); pinMode (Trig, OUTPUT); pinMode (Echo, INPUT); pinMode (RF, OUTPUT); pinMode (LF, OUTPUT); pinMode (RB, OUTPUT); pinMode (LB, OUTPUT); pinMode (ledR, OUTPUT); } void loop() { int Distance = Search (); if (Distance > 20){ digitalWrite (LF, LOW); digitalWrite (LB, HIGH); digitalWrite (RF, LOW); digitalWrite (RB, HIGH); delay (100); digitalWrite (ledR, LOW); } else{ digitalWrite (LF, HIGH); digitalWrite (LB, HIGH); digitalWrite (RF, HIGH); digitalWrite (RB, HIGH); digitalWrite (ledR, HIGH); delay (100); } }

7.机から落ちないロボット

永田先生提供作品をESP用に改変。ピンアサインは2022バージョン。

#include <Arduino.h> #define Trig 14 #define Echo 12 #define LF 25 #define LB 26 #define RF 5 #define RB 15 #define ledR 27 int Search () { float Duration = 0.0; float CM = 0.0; digitalWrite (Trig, LOW); delayMicroseconds (2); digitalWrite (Trig, HIGH); delayMicroseconds (10); digitalWrite (Trig, LOW); Duration = pulseIn (Echo, HIGH); CM = (Duration / 58.8); return CM; } void setup() { Serial.begin(115200); pinMode (Trig, OUTPUT); pinMode (Echo, INPUT); pinMode (RF, OUTPUT); pinMode (LF, OUTPUT); pinMode (RB, OUTPUT); pinMode (LB, OUTPUT); pinMode (ledR, OUTPUT); } void loop() { int Distance = Search (); if (Distance < 10){ digitalWrite (ledR, LOW); digitalWrite (LF, LOW); digitalWrite (LB, HIGH); digitalWrite (RF, LOW); digitalWrite (RB, HIGH); } else{ digitalWrite (ledR, HIGH); digitalWrite (LF, HIGH); digitalWrite (LB, LOW); digitalWrite (RF, HIGH); digitalWrite (RB, LOW); delay (100); digitalWrite (LF, HIGH); digitalWrite (LB, LOW); digitalWrite (RF, LOW); digitalWrite (RB, HIGH); delay (100); } }

8.デフォルトの自動運転プログラム

左右に超音波センサーを振りながら走行。障害物を発見したら一旦バックし、左右を広角で確認し、空間距離が大きい方向に舵を切る。
目的値は与えないので どこに行くかはわからない。

#include <Arduino.h> #include <ESP32Servo.h> #define Trig 14 #define Echo 12 #define LEDB 16 #define LEDG 17 #define LEDR 27 #define in1 25 #define in2 26 #define in3 32 // 2022バージョンでは5 #define in4 33 // 2022バージョンでは15 Servo servo1; int Search () { float Duration = 0.0; float CM = 0.0; digitalWrite (Trig, LOW); delayMicroseconds (2); digitalWrite (Trig, HIGH); delayMicroseconds (10); digitalWrite (Trig, LOW); Duration = pulseIn (Echo, HIGH); CM = (Duration / 58.8); return CM; } int LeftDistance, RightDistance; float Distance = 0.00; int servoR = 30; int servoL = 150; int servoN = 90; int servoscanpos[4]={50,90,130,90}; int i = 0; void setup () { Serial.begin(9600); pinMode (Trig, OUTPUT); pinMode (Echo, INPUT); pinMode (LEDB, OUTPUT); pinMode (LEDG, OUTPUT); pinMode (LEDR, OUTPUT); pinMode (in1, OUTPUT); pinMode (in2, OUTPUT); pinMode (in3, OUTPUT); pinMode (in4, OUTPUT); servo1.attach (13); digitalWrite (in1, HIGH); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, HIGH); servo1.write (90); delay (2000); } void loop () { if(i > 3){ i=0 ; } servo1.write (servoscanpos[i]); delay (200); Distance = Search (); if (Distance < 30) { //Stop digitalWrite (LEDB, LOW); digitalWrite (LEDG, LOW); digitalWrite (LEDR, HIGH); digitalWrite (in1, HIGH); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, HIGH); delay (500); //Backward digitalWrite (in1, HIGH); digitalWrite (in2, LOW); digitalWrite (in3, HIGH); digitalWrite (in4, LOW); delay (500); //Stop digitalWrite (in1, HIGH); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, HIGH); delay (500); //Move Servo Right Turn servo1.write (servoR); delay (300); RightDistance = Search (); delay (500); //Move Servo Left Turn servo1.write (servoL); delay (500); LeftDistance = Search (); delay (500); //Move Servo Neutral servo1.write (servoN); delay (300); //Compare Distance if (RightDistance > LeftDistance) { //Turn Right 緑点灯し旋回 digitalWrite (LEDB, LOW); digitalWrite (LEDG, HIGH); digitalWrite (LEDR, LOW); digitalWrite (in1, LOW); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, LOW); delay (700); digitalWrite (LEDG, LOW); } else if (LeftDistance > RightDistance) { //Turn Left 青点灯し旋回 digitalWrite (LEDB, HIGH); digitalWrite (LEDG, LOW); digitalWrite (LEDR, LOW); digitalWrite (in1, HIGH); digitalWrite (in2, LOW); digitalWrite (in3, LOW); digitalWrite (in4, HIGH); delay (700); digitalWrite (LEDB, LOW); } else { //Turn Around digitalWrite (in1, LOW); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, LOW); delay (1400); } } else if (Distance >= 30) { //Forward 青点灯し走行 digitalWrite (LEDB, HIGH); digitalWrite (LEDG, LOW); digitalWrite (LEDR, LOW); digitalWrite (in1, LOW); digitalWrite (in2, HIGH); digitalWrite (in3, LOW); digitalWrite (in4, HIGH); } i++ ; // serial monitor // Serial.print(F("\r\nDistance Cm: ")); // Serial.print(Distance); // Serial.print(F("\tRightDistance Cm: ")); // Serial.print(RightDistance); // Serial.print(F("\tLeftDistance Cm: ")); // Serial.print(LeftDistance); }

9.リチウムイオン電池電圧監視

前後に行ったり来たり永遠に繰り返す。 一方で、電池電圧を常時監視し、2本のうち1本でも電池電圧が3V以下なら赤LEDを点灯し車両を止める。

#include <Arduino.h> #define ATT1 34 #define ATT2 35 #define LEDB 16 #define LEDR 27 const int in1 = 25; const int in2 = 26; const int in3 = 32; const int in4 = 33; float volt1,volt2; void setup() { pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); digitalWrite(in1, HIGH); digitalWrite(in2, HIGH); digitalWrite(in3, HIGH); digitalWrite(in4, HIGH); pinMode(LEDB, OUTPUT); pinMode(LEDR, OUTPUT); pinMode(ATT1, ANALOG); pinMode(ATT2, ANALOG); analogSetAttenuation(ADC_11db); } void loop() { volt1= analogRead(ATT1) *3500/4095*4; volt2= analogRead(ATT2) *3500/4095*4; if(volt1>6000 && volt2>3000){ digitalWrite(LEDB,HIGH); digitalWrite(LEDR,LOW); } else { digitalWrite(LEDB,LOW); digitalWrite(LEDR,HIGH); while(1) { digitalWrite(in1, HIGH); digitalWrite(in2, HIGH); digitalWrite(in3, HIGH); digitalWrite(in4, HIGH); digitalWrite(LEDR,LOW); delay (300); digitalWrite(LEDR,HIGH); delay (300); } } digitalWrite(in1, LOW); digitalWrite(in2, HIGH); digitalWrite(in3, LOW); digitalWrite(in4, HIGH); delay(600); digitalWrite(in1, HIGH); digitalWrite(in2, LOW); digitalWrite(in3, HIGH); digitalWrite(in4, LOW); delay(600); }

10.LEDC関数を使って速度調整をする

ESP32用の標準ライブラリにあるLEDC関数は本来LEDの調光を目的とするのもだが、機能自体はanalogWriteと同じもの。
モーター制御ピンに使用すればモーターの速度調整に使える。
ここでのサンプルは

#include <Arduino.h> #define Trig 14 // ESP32の標準ライブラリに含まれるのでinclude命令は不要 #define Echo 12 #define LEDB 16 #define LEDG 17 #define LEDR 27 #define in1 25 #define in2 26 #define in3 32 #define in4 33 #define LEDC_CHANNEL_1 3 // サーボと干渉するチャネルがありそうなので避ける 3~5chではとりあえずOKだった。 #define LEDC_CHANNEL_2 4 #define LEDC_CHANNEL_3 5 #define LEDC_CHANNEL_4 6 #define LEDC_BASE_FREQ 1200.0 // キャリア周波数設定 1200Hz #define LEDC_TIMER_BIT 8 // 分解能8bit(0-255) int duty1 = 0; // デューティ比1 ここでは0% に設定 int setBit1 = 255*duty1/100; int duty2 = 50; // デューティ比2 ここでは50% に設定 int setBit2 = 255*duty2/100; void setup () { ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_BIT); ledcSetup(LEDC_CHANNEL_2, LEDC_BASE_FREQ, LEDC_TIMER_BIT); ledcSetup(LEDC_CHANNEL_3, LEDC_BASE_FREQ, LEDC_TIMER_BIT); ledcSetup(LEDC_CHANNEL_4, LEDC_BASE_FREQ, LEDC_TIMER_BIT); ledcAttachPin(in1, LEDC_CHANNEL_1); ledcAttachPin(in2, LEDC_CHANNEL_2); ledcAttachPin(in3, LEDC_CHANNEL_3); ledcAttachPin(in4, LEDC_CHANNEL_4); ledcWrite(LEDC_CHANNEL_1, setBit1); ledcWrite(LEDC_CHANNEL_2, setBit2); ledcWrite(LEDC_CHANNEL_3, setBit1); ledcWrite(LEDC_CHANNEL_4, setBit2); delay (2000); } void loop () { }


11.自動運転スラローム走行

#include <Arduino.h> #include <ESP32Servo.h> #define Trig 14 #define Echo 12 #define LEDB 16 #define LEDG 17 #define LEDR 27 #define in1 25 #define in2 26 #define in3 32 #define in4 33 #define SERVO_PIN 13 Servo servo1; int Search () { float Duration = 0.0; float CM = 0.0; digitalWrite (Trig, LOW); delayMicroseconds (2); digitalWrite (Trig, HIGH); delayMicroseconds (10); digitalWrite (Trig, LOW); Duration = pulseIn (Echo, HIGH); CM = (Duration / 58.8); return CM; } int leftDistance, rightDistance; float Distance = 0.00; int servoR = 30; int servoL = 150; int servoN = 90; int servoscanpos[4]={50,90,130,90}; int i = 0; void setup () { Serial.begin(9600); pinMode (Trig, OUTPUT); pinMode (Echo, INPUT); pinMode (LEDB, OUTPUT); pinMode (LEDG, OUTPUT); pinMode (LEDR, OUTPUT); pinMode (in1, OUTPUT); pinMode (in2, OUTPUT); pinMode (in3, OUTPUT); pinMode (in4, OUTPUT); digitalWrite (in1, HIGH); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, HIGH); servo1.attach(SERVO_PIN); delay (2000); } void loop () { if(i > 3){ i=0 ; } servo1.write (servoscanpos[i]); delay (200); Distance = Search (); if(i==0){ rightDistance = Distance; } if(i==2){ leftDistance = Distance; } if (Distance < 30) { if (i==0) { // move left digitalWrite (LEDB, LOW); digitalWrite (LEDG, LOW); digitalWrite (LEDR, HIGH); digitalWrite (in1, HIGH); digitalWrite (in2, LOW); digitalWrite (in3, LOW); digitalWrite (in4, HIGH); } if (i==2) { // move right digitalWrite (LEDB, LOW); digitalWrite (LEDG, HIGH); digitalWrite (LEDR, LOW); digitalWrite (in1, LOW); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, LOW); } if (i==3 || i==1) { if(rightDistance > leftDistance) { // move right digitalWrite (LEDB, LOW); digitalWrite (LEDG, HIGH); digitalWrite (LEDR, LOW); digitalWrite (in1, LOW); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, LOW); } if(rightDistance <= leftDistance) { // move left digitalWrite (LEDB, LOW); digitalWrite (LEDG, LOW); digitalWrite (LEDR, HIGH); digitalWrite (in1, HIGH); digitalWrite (in2, LOW); digitalWrite (in3, LOW); digitalWrite (in4, HIGH); } } } else{ digitalWrite (LEDB, HIGH); digitalWrite (LEDG, LOW); digitalWrite (LEDR, LOW); digitalWrite (in1, LOW); digitalWrite (in2, HIGH); digitalWrite (in3, LOW); digitalWrite (in4, HIGH); } i++; }

12.Bluetoothリモコン

スマホアプリ Bluefruit Connect を使ってリモコン化

/*This sketch was applied to my TJ5-ROBOT with the sketch for ESP32_BLE_server_UART_Robot posted on pcbreflux's GitHub as a hint.*/ #include <Arduino.h> #include <ESP32Servo.h> #include "BLEDevice.h" #include "BLEServer.h" #include "BLEUtils.h" #include "BLE2902.h" Servo servo1; int UA1 = 25; // ↑ button int LA1 = 26; // ↑ button int UA2 = 15; // ↓ button int LA2 = 5; // ↓ button int SV1 = 13; // Servo int LED_1 = 27; // 1 button to LED int LED_2 = 17; // 2 button to LED int LED_3 = 16; // 3 button to LED int servoR = 20; int servoL = 140; int servoN = 80; BLECharacteristic *pCharacteristic; BLEDescriptor *pDescriptor; bool deviceConnected = false; bool deviceNotifying = false; uint8_t txValue = 0; #define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" #define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; } }; class MyCallbacks: public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); if (rxValue.length() > 0) { Serial.print("Received Value: "); for (int i = 0; i < rxValue.length(); i++) Serial.print(rxValue[i]); if (rxValue == "!B516") { // ↑ button push digitalWrite(UA1, LOW); digitalWrite(LA1, HIGH); digitalWrite(UA2, LOW); digitalWrite(LA2, HIGH); } else if (rxValue == "!B507") { // ↑ button Release digitalWrite(UA1, HIGH); digitalWrite(LA1, HIGH); digitalWrite(UA2, HIGH); digitalWrite(LA2, HIGH); } else if (rxValue == "!B615") { // ↓ button push digitalWrite(UA1, HIGH); digitalWrite(LA1, LOW); digitalWrite(UA2, HIGH); digitalWrite(LA2, LOW); } else if (rxValue == "!B606") { // ↓ button Release digitalWrite(UA1, HIGH); digitalWrite(LA1, HIGH); digitalWrite(UA2, HIGH); digitalWrite(LA2, HIGH); } else if (rxValue == "!B714") { // ← button push digitalWrite(UA1, HIGH); digitalWrite(LA1, HIGH); digitalWrite(UA2, LOW); digitalWrite(LA2, HIGH); } else if (rxValue == "!B705") { // ← button Release digitalWrite(UA1, HIGH); digitalWrite(LA1, HIGH); digitalWrite(UA2, HIGH); digitalWrite(LA2, HIGH); } else if (rxValue == "!B813") { // → button push digitalWrite(UA1, LOW); digitalWrite(LA1, HIGH); digitalWrite(UA2, HIGH); digitalWrite(LA2, HIGH); } else if (rxValue == "!B804") { // → button Release digitalWrite(UA1, HIGH); digitalWrite(LA1, HIGH); digitalWrite(UA2, HIGH); digitalWrite(LA2, HIGH); } if (rxValue == "!B11:") { // 1 button push digitalWrite(LED_1, HIGH); // LED ON digitalWrite(LED_2, LOW); // LED OFF digitalWrite(LED_3, LOW); // LED OFF } else if (rxValue == "!B10;") { // 1 button Release digitalWrite(LED_1, LOW); // LED OFF } if (rxValue == "!B219") { // 2 button push digitalWrite(LED_2, HIGH); // LED ON digitalWrite(LED_1, LOW); // LED OFF digitalWrite(LED_3, LOW); // LED OFF } else if (rxValue == "!B20:") { // 2 button Release digitalWrite(LED_2, LOW); // LED OFF } if (rxValue == "!B318") { // 3 button push } else if (rxValue == "!B309") { // 3 button Release } if (rxValue == "!B417") { // 4 button push } else if (rxValue == "!B408") { // 4 button Release } Serial.println(); } } }; class MyDisCallbacks: public BLEDescriptorCallbacks { void onWrite(BLEDescriptor *pDescriptor) { uint8_t* rxValue = pDescriptor->getValue(); if (pDescriptor->getLength() > 0) { if (rxValue[0] == 1) { //deviceNotifying=true; } else { deviceNotifying = false; } Serial.print("Received Descriptor Value: "); for (int i = 0; i < pDescriptor->getLength(); i++) Serial.print(rxValue[i]); Serial.println(); } } }; void setup() { Serial.begin(115200); pinMode(UA1, OUTPUT); pinMode(LA1, OUTPUT); pinMode(UA2, OUTPUT); pinMode(LA2, OUTPUT); pinMode(LED_1, OUTPUT); pinMode(LED_2, OUTPUT); pinMode(LED_3, OUTPUT); digitalWrite(LED_1, LOW); //Motor POWER OFF digitalWrite(LED_2, LOW); //Motor POWER OFF digitalWrite(LED_3, LOW); //Motor POWER OFF digitalWrite(UA1, HIGH); //Motor POWER OFF digitalWrite(UA2, HIGH); //Motor POWER OFF digitalWrite(LA1, HIGH); //Motor POWER OFF digitalWrite(LA2, HIGH); //Motor POWER OFF pinMode(SV1, OUTPUT); servo1.attach(SV1); // Create the BLE Device BLEDevice::init("UART Service"); // Device Name // Create the BLE Server BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); // Create the BLE Service BLEService *pService = pServer->createService(SERVICE_UUID); // Create a BLE Characteristic pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY ); pDescriptor = new BLE2902(); pCharacteristic->addDescriptor(pDescriptor); BLECharacteristic *pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE ); pCharacteristic->setCallbacks(new MyCallbacks()); pDescriptor->setCallbacks(new MyDisCallbacks()); // Start the service pService->start(); // Start advertising pServer->getAdvertising()->start(); Serial.println("Waiting a client connection to notify..."); servo1.write (servoN); } void loop() { if (deviceConnected && deviceNotifying) { Serial.printf("*** Sent Value: %d ***\n", txValue); pCharacteristic->setValue(&txValue, 1); pCharacteristic->notify(); txValue++; } }

13.APmodeによるwifiリモコン

ESP32をwifiアクセスポイント化し、スマホからこれにアクセスする。
4輪車の電源を入れ、スマホのwifi設定画面でESPを選ぶ。ブラウザで192.168.30.5に接続する。

/* WiFi-Control-Car(softAP) */ // 2022ピンアサイン、額縁なし、左右逆は直した #include <Arduino.h> #include <WiFi.h> const int in1 = 25; const int in2 = 26; const int in3 = 32; const int in4 = 33; const char ssid[] = "SkynsESP32-2"; const char pass[] = "hatumei"; const IPAddress ip(192,168,30,5); const IPAddress subnet(255,255,255,0); const char html[] = "<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>\ <style>body {zoom: 2.0;-moz-transform: scale(1.0);}\ input {margin:8px;width:80px;}\ div {font-size:16pt;color:red;text-align:center;}</style>\ <title>WiFi_Car Controller</title></head>\ <body><div>RC Car Controller<br>\ <form method='get'>\ <input type='submit' name='le' value='左' />\ <input type='submit' name='fo' value='前' />\ <input type='submit' name='ri' value='右' /><br>\ <input type='submit' name='st' value='停止' /><br>\ <input type='submit' name='ba' value='後ろ' />\ </form></div></body></html>"; void stop(){ digitalWrite(in1, HIGH); digitalWrite(in2, HIGH); digitalWrite(in3, HIGH); digitalWrite(in4, HIGH); //digitalWrite(0, LOW); //digitalWrite(2, LOW); //digitalWrite(4, LOW); //digitalWrite(5, LOW); } WiFiServer server(80); void setup() { Serial.begin(115200); WiFi.softAP(ssid,pass); delay(100); WiFi.softAPConfig(ip,ip,subnet); IPAddress myIP = WiFi.softAPIP(); pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); delay(10); server.begin(); Serial.print("SSID: "); Serial.println(ssid); Serial.print("AP IP address: "); Serial.println(myIP); Serial.println("Server start!"); } void loop(){ WiFiClient client = server.available(); if (client) { String currentLine = ""; Serial.println("New Client."); while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); if (c == '\n') { if (currentLine.length() == 0) { client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println(); client.print(html); client.println(); break; } else { currentLine = ""; } } else if (c != '\r') { currentLine += c; } if (currentLine.endsWith("GET /?fo")) { stop(); digitalWrite(in1, LOW); digitalWrite(in3, LOW); } if (currentLine.endsWith("GET /?le")) { stop(); digitalWrite(in3, LOW); } if (currentLine.endsWith("GET /?ri")) { stop(); digitalWrite(in1, LOW); } if (currentLine.endsWith("GET /?ba")) { stop(); digitalWrite(in2, LOW); digitalWrite(in4, LOW); } if (currentLine.endsWith("GET /?bl")) { stop(); digitalWrite(in2, LOW); } if (currentLine.endsWith("GET /?br")) { stop(); digitalWrite(in4, LOW); } if (currentLine.endsWith("GET /?st")) { stop(); } } } client.stop(); Serial.println("Client Disconnected."); } }

14.Bluetoothserial (マスター用:リモコン側 廃止)

赤字部分は各自のESP32のMACアドレスを調べて書き換える必要がある

// ==== ESP32 Bluetooth Serial Master Sample Sketch ==== #include <Arduino.h> #include <BluetoothSerial.h> #include <Ticker.h> BluetoothSerial SerialBT; Ticker blinker; String MACadd = "70:B8:F6:70:76:2E"; // リモコン側ESP32のMACアドレスを書き込む uint8_t address[6] = { 0xD0,0xEF,0x76,0x09,0xF9,0x72 }; // 4輪車側ESP32のMACアドレスを書き込む(書式に注意) bool connected; #define builtinLED 2 void ledBlink() { digitalWrite(builtinLED, !digitalRead(builtinLED)); } void setup() { pinMode(builtinLED, OUTPUT); // pinMode(LED17, OUTPUT); pinMode(26, OUTPUT); pinMode(27, OUTPUT); pinMode(12,ANALOG); pinMode(14,ANALOG); pinMode(13, INPUT_PULLUP); digitalWrite(27, HIGH); digitalWrite(26, LOW); analogSetAttenuation(ADC_11db); Serial.begin(115200); SerialBT.begin("ESP32test", true); Serial.println("device start"); connected = SerialBT.connect(address); if (connected) { Serial.println("Connect OK"); } else { while (!SerialBT.connected(10000)) { Serial.println("No connect"); } } if (SerialBT.disconnect()) { Serial.println("Disconnected Succesfully!"); } SerialBT.connect(); // blinker.attach(0.1, ledBlink); } void loop() { // send data Package uint8_t send_data[4]; send_data[0] = !digitalRead(13); send_data[1] = analogRead(14)/16; // joystick X position send_data[2] = analogRead(12)/16; // joystick Y position send_data[3] = 0; SerialBT.write(send_data, 4); delay(5); // receive data Package if (SerialBT.available()) { digitalWrite(builtinLED, HIGH); Serial.print(F("\r\njoystickX: ")); Serial.print(send_data[1]); Serial.print(F("\tjoystickY: ")); Serial.print(send_data[2]); Serial.print(F("\tbutton: ")); Serial.print(send_data[0]); } delay(5); } // A-1 Mac Address [Master] = D0:EF:76:48:BC:1E Mac Address [Slave] = 0xD0,0xEF,0x76,0x48,0xBC,0x1E // A-2 Mac Address [Master] = D0:EF:76:08:16:BE Mac Address [Slave] = 0xD0,0xEF,0x76,0x08,0x16,0xBE // A-3 Mac Address [Master] = CC:7B:5C:27:9C:9E Mac Address [Slave] = 0xCC,0x7B,0x5C,0x27,0x9C,0x9E // A-4 Mac Address [Master] = 70:B8:F6:70:72:4A Mac Address [Slave] = 0x70,0xB8,0xF6,0x70,0x72,0x4A // A-5 Mac Address [Master] = 70:B8:F6:71:44:9E Mac Address [Slave] = 0x70,0xB8,0xF6,0x71,0x44,0x9E // A-6 Mac Address [Master] = D0:EF:76:0A:13:8E Mac Address [Slave] = 0xD0,0xEF,0x76,0x0A,0x13,0x8E // A-7 Mac Address [Master] = 70:B8:F6:71:DB:52 Mac Address [Slave] = 0x70,0xB8,0xF6,0x71,0xDB,0x52 // A-8 Mac Address [Master] = 70:B8:F6:70:66:C2 Mac Address [Slave] = 0x70,0xB8,0xF6,0x70,0x66,0xC2 // A-9 Mac Address [Master] = 70:B8:F6:70:76:2E Mac Address [Slave] = 0x70,0xB8,0xF6,0x70,0x76,0x2E // A-10 Mac Address [Master] = D0:EF:76:09:F9:72 Mac Address [Slave] = 0xD0,0xEF,0x76,0x09,0xF9,0x72 // A-11 Mac Address [Master] = 70:B8:F6:72:0D:EE Mac Address [Slave] = 0x70,0xB8,0xF6,0x72,0x0D,0xEE // A-12 Mac Address [Master] = 70:B8:F6:70:67:4E Mac Address [Slave] = 0x70,0xB8,0xF6,0x70,0x67,0x4E // A-13 Mac Address [Master] = D0:EF:76:48:47:02 Mac Address [Slave] = 0xD0,0xEF,0x76,0x48,0x47,0x02 // A-14 Mac Address [Master] = 70:B8:F6:70:B9:F6 Mac Address [Slave] = 0x70,0xB8,0xF6,0x70,0xB9,0xF6 // A-15 Mac Address [Master] = D0:EF:76:48:11:BA Mac Address [Slave] = 0xD0,0xEF,0x76,0x48,0x11,0xBA // A-16 Mac Address [Master] = 70:B8:F6:70:6E:5E Mac Address [Slave] = 0x70,0xB8,0xF6,0x70,0x6E,0x5E // B-1 Mac Address [Master] = C8:F0:9E:F2:9A:82 Mac Address [Slave] = 0xC8,0xF0,0x9E,0xF2,0x9A,0x82 // B-2 Mac Address [Master] = C8:F0:9E:F2:8F:62 Mac Address [Slave] = 0xC8,0xF0,0x9E,0xF2,0x8F,0x62 // B-3 Mac Address [Master] = E0:5A:1B:A1:E3:DE Mac Address [Slave] = 0xE0,0x5A,0x1B,0xA1,0xE3,0xDE // B-4 書き込めず // B-5 Mac Address [Master] = C8:F0:9E:F2:89:62 Mac Address [Slave] = 0xC8,0xF0,0x9E,0xF2,0x89,0x62

15.Bluetoothserial (スレーブ用くわがた対応:4輪車側 廃止)

// ==== ESP32 Bluetooth Serial Slave Sample Sketch ==== #include <Arduino.h> #include <BluetoothSerial.h> #include <Ticker.h> #include <ESP32Servo.h> #if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED) #error Bluetooth is not enabled! Please run `make menuconfig` to and enable it #endif BluetoothSerial SerialBT; Ticker blinker; #define builtinLED 2 #define LEDR 27 #define LEDG 17 #define LEDB 16 #define in1 25 #define in2 26 #define in3 32 #define in4 33 #define LEDC_CHANNEL_1 3 // サーボと干渉するチャネルがありそうなので避ける 3~5chではとりあえずOKだった。 #define LEDC_CHANNEL_2 4 #define LEDC_CHANNEL_3 5 #define LEDC_CHANNEL_4 6 #define LEDC_BASE_FREQ 1000.0 // キャリア周波数設定 8kHz #define LEDC_TIMER_BIT 8 // 分解能8bit(0-255) int xAxis = 510; int yAxis = 510; int button5; int speedLeft = 100; // 反転回路があるので100が最弱、0が最強である int speedRight = 100; int data0,data1,data2,data3; void ledBlink() { digitalWrite(builtinLED, !digitalRead(builtinLED)); } #define SERVO_PIN 13 Servo myServo; void setup() { myServo.attach(SERVO_PIN); Serial.begin(115200); pinMode(5,INPUT); pinMode(in1,OUTPUT); pinMode(in2,OUTPUT); pinMode(in3,OUTPUT); pinMode(in4,OUTPUT); digitalWrite(in1,HIGH); digitalWrite(in2,HIGH); digitalWrite(in3,HIGH); digitalWrite(in4,HIGH); SerialBT.begin("ESP32test"); Serial.println("device start"); pinMode(builtinLED, OUTPUT); pinMode(LEDR, OUTPUT); pinMode(LEDG, OUTPUT); pinMode(LEDB, OUTPUT); blinker.attach(0.1, ledBlink); myServo.write(90); delay(1000); } void loop() { // send data Package // uint8_t send_data[4]; // send_data[0] = !digitalRead(Button5); // send_data[1] = !digitalRead(Button5); // send_data[2] = !digitalRead(Button5); // send_data[3] = !digitalRead(Button5); // SerialBT.write(send_data, 1); // delay(5); // receive data Package while (!SerialBT.available()) { } digitalWrite(builtinLED, HIGH); uint8_t recv_data[4]; SerialBT.readBytes(recv_data, 4); data0 = recv_data[0]; data1 = recv_data[1]; data2 = recv_data[2]; data3 = recv_data[3]; delay(5); xAxis = map (data2, 0, 230, 0, 1023); // data2はジョイスティックのVRYの読み ジョイスティックが90度回っているのでのxyを逆にする yAxis = map (data1, 0, 230, 0, 1023); button5 = data0; // Forward if (yAxis > 550) { speedLeft = map(yAxis, 510, 1160, 100, 0); // speedRight = map(yAxis, 510, 1160, 100, 0); pinMode(in2,OUTPUT); pinMode(in4,OUTPUT); ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in2,HIGH); ledcSetup(LEDC_CHANNEL_3, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in4,HIGH); ledcAttachPin(in1, LEDC_CHANNEL_1); ledcAttachPin(in3, LEDC_CHANNEL_3); ledcWrite(LEDC_CHANNEL_1, speedLeft); ledcWrite(LEDC_CHANNEL_3, speedRight); } // Backward if (yAxis < 470) { speedLeft = map(yAxis, 510, 0, 100, 0); speedRight = map(yAxis, 510, 0, 100, 0); pinMode(in1,OUTPUT); pinMode(in3,OUTPUT); ledcSetup(LEDC_CHANNEL_2, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in1,HIGH); ledcSetup(LEDC_CHANNEL_4, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in3,HIGH); ledcAttachPin(in2, LEDC_CHANNEL_2); ledcAttachPin(in4, LEDC_CHANNEL_4); ledcWrite(LEDC_CHANNEL_2, speedLeft); ledcWrite(LEDC_CHANNEL_4, speedRight); } // Pivot Left turn if (yAxis > 470 && yAxis < 550 && xAxis < 470) { speedLeft = map(xAxis, 510, 0, 100, 0); speedRight = map(xAxis, 510, 0, 100, 0); pinMode(in1,OUTPUT); pinMode(in4,OUTPUT); ledcSetup(LEDC_CHANNEL_2, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in1,HIGH); ledcSetup(LEDC_CHANNEL_3, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in4,HIGH); ledcAttachPin(in2, LEDC_CHANNEL_2); ledcAttachPin(in3, LEDC_CHANNEL_3); ledcWrite(LEDC_CHANNEL_2, speedLeft); ledcWrite(LEDC_CHANNEL_3, speedRight); } // Left turn else if (xAxis < 470) { int xMapped = map(xAxis, 510, 0, 100, 0); speedLeft = speedLeft - xMapped; speedRight = speedRight + xMapped; if (speedLeft < 0) {speedLeft = 0;} if (speedRight > 100) {speedRight = 100;} pinMode(in2,OUTPUT); pinMode(in4,OUTPUT); ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in2,HIGH); ledcSetup(LEDC_CHANNEL_3, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in4,HIGH); ledcAttachPin(in1, LEDC_CHANNEL_1); ledcAttachPin(in3, LEDC_CHANNEL_3); ledcWrite(LEDC_CHANNEL_1, speedLeft); ledcWrite(LEDC_CHANNEL_3, speedRight); } // Pivot Right turn if (yAxis > 470 && yAxis < 550 && xAxis > 550) { speedLeft = map(xAxis, 510, 1160, 100, 0); speedRight = map(xAxis, 510, 1160, 100, 0); pinMode(in2,OUTPUT); pinMode(in3,OUTPUT); ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in1,HIGH); ledcSetup(LEDC_CHANNEL_4, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in4,HIGH); ledcAttachPin(in1, LEDC_CHANNEL_1); ledcAttachPin(in4, LEDC_CHANNEL_4); ledcWrite(LEDC_CHANNEL_1, speedLeft); ledcWrite(LEDC_CHANNEL_4, speedRight); } // Right turn else if (xAxis > 550) { int xMapped = map(xAxis, 510, 1160, 100, 0); speedLeft = speedLeft + xMapped; speedRight = speedRight - xMapped; if (speedLeft > 100) {speedLeft = 100;} if (speedRight < 0) {speedRight = 0;} pinMode(in2,OUTPUT); pinMode(in4,OUTPUT); ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in2,HIGH); ledcSetup(LEDC_CHANNEL_3, LEDC_BASE_FREQ, LEDC_TIMER_BIT); digitalWrite(in4,HIGH); ledcAttachPin(in1, LEDC_CHANNEL_1); ledcAttachPin(in3, LEDC_CHANNEL_3); ledcWrite(LEDC_CHANNEL_1, speedLeft); ledcWrite(LEDC_CHANNEL_3, speedRight); } // Joystick neutral if ((yAxis > 470 && yAxis < 550) && (xAxis > 470 && xAxis < 550)) { speedLeft = 100; speedRight = 100; pinMode(in1,OUTPUT); pinMode(in2,OUTPUT); pinMode(in3,OUTPUT); pinMode(in4,OUTPUT); digitalWrite(in1,HIGH); digitalWrite(in2,HIGH); digitalWrite(in3,HIGH); digitalWrite(in4,HIGH); } // joystick button LED if (button5 == 1) { digitalWrite(LEDB, HIGH); myServo.write(130); } else { digitalWrite(LEDB, LOW); myServo.write(90); } // Motor Drive LED if (speedLeft < 95 || speedRight < 95) { digitalWrite(LEDG, HIGH); } else { digitalWrite(LEDG, LOW); } // serial monitor Serial.print(F("\r\nxAxis: ")); Serial.print(xAxis); Serial.print(F("\tyAxis: ")); Serial.print(yAxis); Serial.print(F("\tspeedLeft: ")); Serial.print(speedLeft); Serial.print(F("\tspeedRight: ")); Serial.print(speedRight); Serial.print(F("\tbutton5: ")); Serial.print(button5); }

16.ESP32が自分のMACアドレスを表示するプログラム(廃止)

書き込み後、Arduino IDE画面右上の虫眼鏡アイコンをクリックしてシリアルモニタを表示(通信速度は115200)させ、ESP32のリセットボタン(USB端子の隣のEN)を押す。
MACアドレスはシリアルモニタの一番最後に "E0:5A:1B:A1:D2:76" のように表示されるので。これをメモしておく。

/* === ESP32 Get MAC Address === */ #include <Arduino.h> #include "esp_mac.h" // required - exposes esp_mac_type_t values String getDefaultMacAddress() { String mac = ""; unsigned char mac_base[6] = {0}; if (esp_efuse_mac_get_default(mac_base) == ESP_OK) { char buffer[18]; // 6*2 characters for hex + 5 characters for colons + 1 character for null terminator sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X", mac_base[0], mac_base[1], mac_base[2], mac_base[3], mac_base[4], mac_base[5]); mac = buffer; } return mac; } String getInterfaceMacAddress(esp_mac_type_t interface) { String mac = ""; unsigned char mac_base[6] = {0}; if (esp_read_mac(mac_base, interface) == ESP_OK) { char buffer[18]; // 6*2 characters for hex + 5 characters for colons + 1 character for null terminator sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X", mac_base[0], mac_base[1], mac_base[2], mac_base[3], mac_base[4], mac_base[5]); mac = buffer; } return mac; } void setup() { Serial.begin(115200); while (!Serial) { delay(100); } Serial.println("Interface\t\t\t\t\t\tMAC address (6 bytes, 4 universally administered, default)"); Serial.print("Wi-Fi Station (using 'esp_efuse_mac_get_default')\t"); Serial.println(getDefaultMacAddress()); Serial.print("WiFi Station (using 'esp_read_mac')\t\t\t"); Serial.println(getInterfaceMacAddress(ESP_MAC_WIFI_STA)); Serial.print("WiFi Soft-AP (using 'esp_read_mac')\t\t\t"); Serial.println(getInterfaceMacAddress(ESP_MAC_WIFI_SOFTAP)); Serial.print("Bluetooth (using 'esp_read_mac')\t\t\t"); Serial.println(getInterfaceMacAddress(ESP_MAC_BT)); Serial.print("Ethernet (using 'esp_read_mac')\t\t\t\t"); Serial.println(getInterfaceMacAddress(ESP_MAC_ETH)); } void loop() { /* Nothing in loop */ }

17.ライントレース

2022バージョン用

#include <Arduino.h> #define in1 25 #define in2 26 #define in3 5 #define in4 15 #define piL 36 #define piR 39 int thlev=200; int ir1 = 0.00; int ir2 = 0.00; void setup () { Serial.begin(115200); pinMode (in1, OUTPUT); pinMode (in2, OUTPUT); pinMode (in3, OUTPUT); pinMode (in4, OUTPUT); pinMode (piL, ANALOG); pinMode (piR, ANALOG); analogSetAttenuation(ADC_11db); } void loop () { ir1 = analogRead(piL); ir2 = analogRead(piR); if (ir1 > thlev && ir2 <= thlev) { //Turn Right digitalWrite (in1, LOW); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, LOW); } else if (ir1 < thlev && ir2 >= thlev) { //Turn Left digitalWrite (in1, HIGH); digitalWrite (in2, LOW); digitalWrite (in3, LOW); digitalWrite (in4, HIGH); } else if (ir1 < thlev && ir2 < thlev ) { digitalWrite (in1, LOW); digitalWrite (in2, HIGH); digitalWrite (in3, LOW); digitalWrite (in4, HIGH); } else if (ir1 >= thlev && ir2 >= thlev ) { digitalWrite (in1, HIGH); digitalWrite (in2, HIGH); digitalWrite (in3, HIGH); digitalWrite (in4, HIGH); } //serial monitor Serial.print(F("\r\nDistance IR1: ")); Serial.print(ir1); Serial.print(F(" \tRightDistance IR2: ")); Serial.print(ir2); delay(10); }

18.BLEリモコン(リモコン側)

3つのUUIDの頭8桁を本体側と共通の自分固有のコードにしておきましょう。
1つめはSERVICE_UUID、2つめは受信用(RX)、3つめは送信用(TX)のUUID。 これを3つともプログラムに書き込んでおく。
本体側にも同じUUIDを書き込んでおいて相互に相手を認識する。 リモコンと本体(No.19)とはRXとTXが逆なので注意。

// === ESP32 BLE Server sample skech === #include <Arduino.h> #include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #include <Ticker.h> Ticker ticker; BLEServer *pServer = NULL; BLECharacteristic *pTxCharacteristic; bool deviceConnected = false; bool oldDeviceConnected = false; // 3つのUUIDを下に書き込む。hatumei1を自分の好きな(本体と同じ)8文字に変えてください。 #define SERVICE_UUID "hatumei1-23f3-4fd7-9271-96aee32da1a3" #define CHARACTERISTIC_UUID_RX "hatumei1-ce72-452f-af50-67cb23484128" #define CHARACTERISTIC_UUID_TX "hatumei1-7116-4d54-b676-b81a86e3f407" #define SERVER_NAME "esp32ble" // I/O configuration #define potGND 26 #define potVCC 27 #define potX 12 #define potY 14 #define joyK 13 #define BuiltinLED 2 uint16_t neutral_potX; uint16_t neutral_potY; uint16_t potX_val; uint16_t potY_val; uint16_t potX_data; uint16_t potY_data; uint16_t Txflag_F; uint16_t button_K; uint16_t data0 = 0; std::string rx_Data; class MyServerCallbacks : public BLEServerCallbacks { void onConnect(BLEServer *pServer) { deviceConnected = true; }; void onDisconnect(BLEServer *pServer) { deviceConnected = false; } }; class MyCallbacks : public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); if (rxValue.length() > 0) { for (int i = 0; i < rxValue.length(); i++) rx_Data = rx_Data + rxValue[i]; } } }; // LED Blink void ledBlink() { volatile static int led = HIGH; digitalWrite(BuiltinLED, led); led = !led; } void setup() { Serial.begin(115200); pinMode(potX, INPUT); pinMode(potY, INPUT); pinMode(joyK, INPUT_PULLUP); pinMode(potVCC, OUTPUT); pinMode(potGND, OUTPUT); pinMode(BuiltinLED, OUTPUT); digitalWrite(potVCC, HIGH); digitalWrite(potGND, LOW); analogReadResolution(12); neutral_potX = map(analogRead(potX), 0, 4095, 0, 255); neutral_potY = map(analogRead(potY), 0, 4095, 0, 255); ticker.attach(0.1, ledBlink); Serial.println("BLE_Server_start"); delay(1000); // Create the BLE Device BLEDevice::init(SERVER_NAME); // Create the BLE Server BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); // Create the BLE Service BLEService *pService = pServer->createService(SERVICE_UUID); // Create a BLE Characteristic pTxCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY); pTxCharacteristic->addDescriptor(new BLE2902()); BLECharacteristic *pRxCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE); pRxCharacteristic->setCallbacks(new MyCallbacks()); // Start the service pService->start(); // Start advertising pServer->getAdvertising()->start(); Serial.println("Waiting a client connection to notify..."); } void loop() { digitalWrite(potVCC, HIGH); digitalWrite(potGND, LOW); analogReadResolution(12); Txflag_F = 1; // Flag data potX_val = map(analogRead(potX), 0, 4095, 0, 255); // Pot_x data potY_val = map(analogRead(potY), 0, 4095, 0, 255); // Pot_y data button_K = !digitalRead(joyK); // Joystick Button data // convert potX neutral value if (neutral_potX >= potX_val) { potX_data = map(potX_val, neutral_potX, 0, 128, 0); } else if (neutral_potX < potX_val) { potX_data = map(potX_val, neutral_potX, 255, 128, 255); } // convert potY neutral value if (neutral_potY >= potY_val) { potY_data = map(potY_val, neutral_potY, 0, 128, 0); } else if (neutral_potY < potY_val) { potY_data = map(potY_val, neutral_potY, 255, 128, 255); } if (deviceConnected) { //char buffer[10]; char buffer[20]; // Send data write sprintf(buffer, "F:%d,X:%03d,Y:%03d,K:%d", Txflag_F, potX_data, potY_data, button_K); pTxCharacteristic->setValue(buffer); pTxCharacteristic->notify(); Serial.printf("*** NOTIFY: F:%d,X:%03d,Y:%03d,K:%d ***\n", Txflag_F, potX_data, potY_data, button_K); // Receive data read String Rxdata = rx_Data.c_str(); String str(Rxdata); String subf = str.substring(0, 1); data0 = subf.toInt(); // receive flag //Serial.printf("%s", rx_Data.c_str()); //delay(1000); } else { data0 = 0; } // Connected LED if (data0 == 1) { digitalWrite(BuiltinLED, HIGH); } // disconnecting if (!deviceConnected && oldDeviceConnected) { delay(500); // give the bluetooth stack the chance to get things ready pServer->startAdvertising(); // restart advertising Serial.println("start advertising"); oldDeviceConnected = deviceConnected; } // connecting if (deviceConnected && !oldDeviceConnected) { // do stuff here on connecting oldDeviceConnected = deviceConnected; } //Serial monitor // Serial.print(F("\n\rTxflag: ")); // Serial.print(Txflag_F); // Serial.print(F("\tpotX_data: ")); // Serial.print(potX_val); // Serial.print(F("\tpotY_data: ")); // Serial.print(potY_val); // Serial.print(F("\tbutton_K: ")); // Serial.print(button_K); }

19.BLEリモコン(本体側)

3つのUUIDの頭8桁をリモコン側と共通の自分固有のコードにしておきましょう。
1つめはSERVICE_UUID、2つめは送信用(TX)、3つめは受信用(RX)のUUID。リモコン(No.18)とはRXとTXが逆なので注意。

// === ESP32 BLE Client sample skech === #include <Arduino.h> #include <BLEDevice.h> #include <ESP32Servo.h> #include <Ticker.h> Ticker ticker; Servo myServo; // See the following for generating UUIDs: // https://www.uuidgenerator.net/ // 3つのUUIDを下に書き込む。hatumei1を自分の好きな(リモコンと同じ)8文字に変えてください。 #define SERVICE_UUID "hatumei1-23f3-4fd7-9271-96aee32da1a3" #define CHARACTERISTIC_UUID_TX "hatumei1-ce72-452f-af50-67cb23484128" #define CHARACTERISTIC_UUID_RX "hatumei1-7116-4d54-b676-b81a86e3f407" #define SERVER_NAME "esp32ble" #define Tx_value '1' // send to Server "1" // Board Using pin #define builtinLED 2 // Onboard Blue LED LEDC_BASE_FREQ, LEDC_TIMER_BIT #define SERVO_PIN 13 // Servo Orange Wire #define LEDR 27 // Red LED #define LEDG 17 // Green LED #define LEDB 16 // Blue LED #define in1 25 // PWM pin #define in2 26 // PWM pin #define in3 32 // PWM pin #define in4 33 // PWM pin #define LEDC_CHANNEL_1 3 // Channel 3 #define LEDC_CHANNEL_2 4 // Channel 4 #define LEDC_CHANNEL_3 5 // Channel 5 #define LEDC_CHANNEL_4 6 // Channel 6 #define LEDC_BASE_FREQ 100.0 // キャリア周波数設定 100Hz #define LEDC_TIMER_BIT 8 // 分解能8bit(0-255) int Rx_flag = 0; // received flag int xAxis = 512; // Joystick X-Nutral Value int yAxis = 512; // Joystick Y-Nutral Value int speedLeft = 255; // 反転回路があるので255が最弱、0が最強である int speedRight = 255; int stop_speed = 255; // DC Motor Stop Value int lowest_speed_bitL = 140; // DC Motor lowest rotation Value int lowest_speed_bitR = 160; // DC Motor lowest rotation Value int data0, data1, data2, data3; // Recieve data 0-3 unsigned long previoustime0 = 0; unsigned long previoustime1 = 0; unsigned long previoustime2 = 0; static BLEUUID serviceUUID(SERVICE_UUID); static BLEUUID charUUID_RX(CHARACTERISTIC_UUID_RX); static BLEUUID charUUID_TX(CHARACTERISTIC_UUID_TX); static BLEAddress *pServerAddress; static boolean doConnect = false; static boolean connected = false; static BLERemoteCharacteristic *pRemoteCharacteristicRX; static BLERemoteCharacteristic *pRemoteCharacteristicTX; static void notifyCallback( BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify) { Serial.print("Notify callback for characteristic "); Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); Serial.print(" of data length "); Serial.println(length); Serial.print("data: "); Serial.println((char *)pData); } class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient *pclient) { } void onDisconnect(BLEClient *pclient) { connected = false; Serial.println("onDisconnect"); } }; bool connectToServer(BLEAddress pAddress) { Serial.print("Forming a connection to "); Serial.println(pAddress.toString().c_str()); BLEClient *pClient = BLEDevice::createClient(); Serial.println(" - Created client"); pClient->setClientCallbacks(new MyClientCallback()); // Connect to the remove BLE Server pClient->connect(pAddress); Serial.println(" - Connected to server"); pClient->setMTU(517); // set client to request maximum MTU from server BLERemoteService *pRemoteService = pClient->getService(serviceUUID); Serial.print(" - Connected to server :"); Serial.println(serviceUUID.toString().c_str()); if (pRemoteService == nullptr) { Serial.print("Failed to find our service UUID: "); Serial.println(serviceUUID.toString().c_str()); pClient->disconnect(); return false; } // Get the reference of the characteristic for Receive pRemoteCharacteristicRX = pRemoteService->getCharacteristic(charUUID_RX); if (pRemoteCharacteristicRX == nullptr) { Serial.print("Failed to find characteristic RX ID: "); Serial.println(charUUID_RX.toString().c_str()); pClient->disconnect(); return false; } Serial.print(" - Found characteristic RX ID: "); Serial.println(charUUID_RX.toString().c_str()); // Get the reference of the characteristic for Send pRemoteCharacteristicTX = pRemoteService->getCharacteristic(charUUID_TX); if (pRemoteCharacteristicTX == nullptr) { Serial.print("Failed to find characteristic TX ID "); Serial.println(charUUID_TX.toString().c_str()); pClient->disconnect(); return false; } Serial.print(" - Found characteristic TX ID: "); Serial.println(charUUID_TX.toString().c_str()); // Read the value of the characteristic if (pRemoteCharacteristicRX->canRead()) { std::string value = pRemoteCharacteristicRX->readValue(); Serial.print("The characteristic value was: "); Serial.println(value.c_str()); } if (pRemoteCharacteristicRX->canNotify()) // pRemoteCharacteristicRX->registerForNotify(notifyCallback); // Serial.println("End of notify"); return true; } class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.print("BLE Advertised Device found: "); Serial.println(advertisedDevice.toString().c_str()); Serial.println(advertisedDevice.getName().c_str()); if (advertisedDevice.getName() == SERVER_NAME) { Serial.println(advertisedDevice.getAddress().toString().c_str()); advertisedDevice.getScan()->stop(); pServerAddress = new BLEAddress(advertisedDevice.getAddress()); doConnect = true; } } }; void get_scan() { BLEScan *pBLEScan = BLEDevice::getScan(); Serial.println("getScan"); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); Serial.println("setAdvertisedDeviceCallbacks"); pBLEScan->setActiveScan(true); pBLEScan->start(5); Serial.println(""); Serial.println("End of scan"); } // LEDC Setup Attach Channel void ledc_attach_channel() { ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_BIT); ledcSetup(LEDC_CHANNEL_2, LEDC_BASE_FREQ, LEDC_TIMER_BIT); ledcSetup(LEDC_CHANNEL_3, LEDC_BASE_FREQ, LEDC_TIMER_BIT); ledcSetup(LEDC_CHANNEL_4, LEDC_BASE_FREQ, LEDC_TIMER_BIT); ledcAttachPin(in1, LEDC_CHANNEL_1); ledcAttachPin(in2, LEDC_CHANNEL_2); ledcAttachPin(in3, LEDC_CHANNEL_3); ledcAttachPin(in4, LEDC_CHANNEL_4); } void ledBlink() { volatile static int led = HIGH; digitalWrite(builtinLED, led); led = !led; } void setup() { Serial.begin(115200); pinMode(LEDR, OUTPUT); pinMode(LEDG, OUTPUT); pinMode(LEDB, OUTPUT); pinMode(builtinLED, OUTPUT); Serial.println("BLE_Cliant_start"); BLEDevice::init(""); get_scan(); Serial.println("BLE End of setup"); ticker.attach(0.1, ledBlink); myServo.attach(SERVO_PIN); ledc_attach_channel(); delay(500); } void loop() { unsigned long currenttime = millis(); if (doConnect == true) { if (connectToServer(*pServerAddress)) { Serial.println("We are now connected to the BLE Server."); connected = true; } else { Serial.println("We have failed to connect to the server; there is nothin more we will do."); connected = false; } doConnect = false; } if (connected) { // Connection Handling ticker.detach(); digitalWrite(builtinLED, HIGH); // Receive data read std::string Rxvalue = pRemoteCharacteristicRX->readValue(); String Rxdata = Rxvalue.c_str(); // copy str(value) String str(Rxdata); String subf = str.substring(2, 3); // Flag String subx = str.substring(6, 9); // potX data String suby = str.substring(12, 15); // potY data String subk = str.substring(18, 19); // buttonK data // Convert int flag xyAxis and buttonK data0 = subf.toInt(); // receive flag data1 = subx.toInt(); // joystick X value data2 = suby.toInt(); // joystick Y value data3 = subk.toInt(); // joystick button // Serial Monitor Received Data char buffer[20]; // sprintf(buffer, "F:%d X:%03d Y:%03d K:%d", data0, data1, data2, data3); // Serial.println(buffer); // to Server Send data pRemoteCharacteristicTX->writeValue(Tx_value); // Serial.println(Tx_value); // delay(1000); } else { digitalWrite(builtinLED, LOW); ticker.attach(0.1, ledBlink); // reconnecting Serial.println("Not connected"); doConnect = false; get_scan(); } // Connected Receive Flag if (data0 == 1) { // Pot data Numeric Replace xAxis = map(data1, 0, 255, 0, 1023); yAxis = map(data2, 0, 255, 0, 1023); // Forward if (yAxis > 660) { speedLeft = map(yAxis, 510, 1023, lowest_speed_bitL, 0); speedRight = map(yAxis, 510, 1023, lowest_speed_bitR, 0); // Left turn if (xAxis < 360) { // int xMapped = map(xAxis, 0, 510, 255, 0); speedLeft = lowest_speed_bitL; if (speedRight < 0) { speedRight = 0; } if (speedLeft > 100) { speedLeft = 100; } } // Right turn else if (xAxis > 660) { // int xMapped = map(xAxis, 510, 1023, 0, 255); speedRight = lowest_speed_bitR; } ledcWrite(LEDC_CHANNEL_1, speedLeft); ledcWrite(LEDC_CHANNEL_2, stop_speed); ledcWrite(LEDC_CHANNEL_3, speedRight); ledcWrite(LEDC_CHANNEL_4, stop_speed); } // Backward if (yAxis < 360) { speedLeft = map(yAxis, 510, 0, lowest_speed_bitL, 0); speedRight = map(yAxis, 510, 0, lowest_speed_bitR, 0); // Left turn (back) if (xAxis < 360) { // int xMapped = map(xAxis, 0, 510, 255, 0); speedLeft = lowest_speed_bitL; } // Right turn (back) else if (xAxis > 660) { // int xMapped = map(xAxis, 510, 1023, 0, 255); speedRight = lowest_speed_bitR; } ledcWrite(LEDC_CHANNEL_1, stop_speed); ledcWrite(LEDC_CHANNEL_2, speedLeft); ledcWrite(LEDC_CHANNEL_3, stop_speed); ledcWrite(LEDC_CHANNEL_4, speedRight); } // Pivot Left turn if (yAxis >= 360 && yAxis <= 660 && xAxis < 360) { speedLeft = map(xAxis, 510, 0, lowest_speed_bitL, 0); speedRight = map(xAxis, 510, 0, lowest_speed_bitR, 0); ledcWrite(LEDC_CHANNEL_1, stop_speed); ledcWrite(LEDC_CHANNEL_2, speedLeft); ledcWrite(LEDC_CHANNEL_3, speedRight); ledcWrite(LEDC_CHANNEL_4, stop_speed); } // Pivot Right turn if (yAxis >= 360 && yAxis <= 660 && xAxis > 660) { speedLeft = map(xAxis, 510, 1023, lowest_speed_bitL, 0); speedRight = map(xAxis, 510, 1023, lowest_speed_bitR, 0); ledcWrite(LEDC_CHANNEL_1, speedLeft); ledcWrite(LEDC_CHANNEL_2, stop_speed); ledcWrite(LEDC_CHANNEL_3, stop_speed); ledcWrite(LEDC_CHANNEL_4, speedRight); } // Joystick neutral if ((yAxis >= 360 && yAxis <= 660) && (xAxis >= 360 && xAxis <= 660)) { ledcWrite(LEDC_CHANNEL_1, stop_speed); ledcWrite(LEDC_CHANNEL_2, stop_speed); ledcWrite(LEDC_CHANNEL_3, stop_speed); ledcWrite(LEDC_CHANNEL_4, stop_speed); } // joystick button LED if (data3 == 1) { digitalWrite(LEDB, HIGH); myServo.write(150); } else { digitalWrite(LEDB, LOW); myServo.write(90); } // Motor Drive LED if (speedLeft < 95 || speedRight < 95) { digitalWrite(LEDG, HIGH); } else { digitalWrite(LEDG, LOW); } // serial monitor // Serial.print(F("\r\nxAxis: ")); // Serial.print(xAxis); // Serial.print(F("\tyAxis: ")); // Serial.print(yAxis); // Serial.print(F("\tspeedLeft: ")); // Serial.print(speedLeft); // Serial.print(F("\tspeedRight: ")); // Serial.print(speedRight); // Serial.print(F("\tbutton5: ")); // Serial.print(data3); } }