├── .gitignore ├── README.md ├── 参考代码 ├── BLE_client │ └── BLE_client.ino └── ESP32_car_test │ └── ESP32_car_test.ino ├── 实际运行效果 └── readme.txt ├── 小车源码 └── smart_car │ └── smart_car.ino └── 测试代码 ├── FNG └── FNG.ino ├── Serve └── Serve.ino ├── XJ └── XJ │ └── XJ.ino └── 按键 ├── 下降沿按键检测 └── buttonactttch │ └── buttonactttch.ino └── 消抖式按键检测 └── BUTTON └── BUTTON.ino /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arduino-ESP32-F 2 | Arduino+ESP32-F实现蓝牙控制、光电寻迹、超声波避障功能的智能小车 3 | -------------------------------------------------------------------------------- /参考代码/BLE_client/BLE_client.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * A BLE client example that is rich in capabilities. 3 | * There is a lot new capabilities implemented. 4 | * author unknown 5 | * updated by chegewara 6 | */ 7 | 8 | #include "BLEDevice.h" 9 | //#include "BLEScan.h" 10 | 11 | // The remote service we wish to connect to. 12 | static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b"); 13 | // The characteristic of the remote service we are interested in. 14 | static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8"); 15 | 16 | static boolean doConnect = false; 17 | static boolean connected = false; 18 | static boolean doScan = false; 19 | static BLERemoteCharacteristic* pRemoteCharacteristic; 20 | static BLEAdvertisedDevice* myDevice; 21 | 22 | static void notifyCallback( 23 | BLERemoteCharacteristic* pBLERemoteCharacteristic, 24 | uint8_t* pData, 25 | size_t length, 26 | bool isNotify) { 27 | Serial.print("Notify callback for characteristic "); 28 | Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); 29 | Serial.print(" of data length "); 30 | Serial.println(length); 31 | Serial.print("data: "); 32 | Serial.println((char*)pData); 33 | } 34 | 35 | class MyClientCallback : public BLEClientCallbacks { 36 | void onConnect(BLEClient* pclient) { 37 | } 38 | 39 | void onDisconnect(BLEClient* pclient) { 40 | connected = false; 41 | Serial.println("onDisconnect"); 42 | } 43 | }; 44 | 45 | bool connectToServer() { 46 | Serial.print("Forming a connection to "); 47 | Serial.println(myDevice->getAddress().toString().c_str()); 48 | 49 | BLEClient* pClient = BLEDevice::createClient(); 50 | Serial.println(" - Created client"); 51 | 52 | pClient->setClientCallbacks(new MyClientCallback()); 53 | 54 | // Connect to the remove BLE Server. 55 | pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private) 56 | Serial.println(" - Connected to server"); 57 | 58 | // Obtain a reference to the service we are after in the remote BLE server. 59 | BLERemoteService* pRemoteService = pClient->getService(serviceUUID); 60 | if (pRemoteService == nullptr) { 61 | Serial.print("Failed to find our service UUID: "); 62 | Serial.println(serviceUUID.toString().c_str()); 63 | pClient->disconnect(); 64 | return false; 65 | } 66 | Serial.println(" - Found our service"); 67 | 68 | 69 | // Obtain a reference to the characteristic in the service of the remote BLE server. 70 | pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); 71 | if (pRemoteCharacteristic == nullptr) { 72 | Serial.print("Failed to find our characteristic UUID: "); 73 | Serial.println(charUUID.toString().c_str()); 74 | pClient->disconnect(); 75 | return false; 76 | } 77 | Serial.println(" - Found our characteristic"); 78 | 79 | // Read the value of the characteristic. 80 | if(pRemoteCharacteristic->canRead()) { 81 | std::string value = pRemoteCharacteristic->readValue(); 82 | Serial.print("The characteristic value was: "); 83 | Serial.println(value.c_str()); 84 | } 85 | 86 | if(pRemoteCharacteristic->canNotify()) 87 | pRemoteCharacteristic->registerForNotify(notifyCallback); 88 | 89 | connected = true; 90 | return true; 91 | } 92 | /** 93 | * Scan for BLE servers and find the first one that advertises the service we are looking for. 94 | */ 95 | class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { 96 | /** 97 | * Called for each advertising BLE server. 98 | */ 99 | void onResult(BLEAdvertisedDevice advertisedDevice) { 100 | Serial.print("BLE Advertised Device found: "); 101 | Serial.println(advertisedDevice.toString().c_str()); 102 | 103 | // We have found a device, let us now see if it contains the service we are looking for. 104 | if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) { 105 | 106 | BLEDevice::getScan()->stop(); 107 | myDevice = new BLEAdvertisedDevice(advertisedDevice); 108 | doConnect = true; 109 | doScan = true; 110 | 111 | } // Found our server 112 | } // onResult 113 | }; // MyAdvertisedDeviceCallbacks 114 | 115 | 116 | void setup() { 117 | Serial.begin(115200); 118 | Serial.println("Starting Arduino BLE Client application..."); 119 | BLEDevice::init(""); 120 | 121 | // Retrieve a Scanner and set the callback we want to use to be informed when we 122 | // have detected a new device. Specify that we want active scanning and start the 123 | // scan to run for 5 seconds. 124 | BLEScan* pBLEScan = BLEDevice::getScan(); 125 | pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); 126 | pBLEScan->setInterval(1349); 127 | pBLEScan->setWindow(449); 128 | pBLEScan->setActiveScan(true); 129 | pBLEScan->start(5, false); 130 | } // End of setup. 131 | 132 | 133 | // This is the Arduino main loop function. 134 | void loop() { 135 | 136 | // If the flag "doConnect" is true then we have scanned for and found the desired 137 | // BLE Server with which we wish to connect. Now we connect to it. Once we are 138 | // connected we set the connected flag to be true. 139 | if (doConnect == true) { 140 | if (connectToServer()) { 141 | Serial.println("We are now connected to the BLE Server."); 142 | } else { 143 | Serial.println("We have failed to connect to the server; there is nothin more we will do."); 144 | } 145 | doConnect = false; 146 | } 147 | 148 | // If we are connected to a peer BLE Server, update the characteristic each time we are reached 149 | // with the current time since boot. 150 | if (connected) { 151 | String newValue = "Time since boot: " + String(millis()/1000); 152 | Serial.println("Setting new characteristic value to \"" + newValue + "\""); 153 | 154 | // Set the characteristic's value to be the array of bytes that is actually a string. 155 | pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length()); 156 | }else if(doScan){ 157 | BLEDevice::getScan()->start(0); // this is just example to start scan after disconnect, most likely there is better way to do it in arduino 158 | } 159 | 160 | delay(1000); // Delay a second between loops. 161 | } // End of loop 162 | -------------------------------------------------------------------------------- /参考代码/ESP32_car_test/ESP32_car_test.ino: -------------------------------------------------------------------------------- 1 | //**************LED相关********************** 2 | 3 | // NeoPixelFunLoop 4 | // This example will move a trail of light around a series of pixels. 5 | // A ring formation of pixels looks best. 6 | // The trail will have a slowly fading tail. 7 | // 8 | // This will demonstrate the use of the NeoPixelAnimator. 9 | // It shows the advanced use an animation to control the modification and 10 | // starting of other animations. 11 | // It also shows the normal use of animating colors. 12 | // It also demonstrates the ability to share an animation channel rather than 13 | // hard code them to pixels. 14 | // 15 | 16 | #include 17 | #include 18 | 19 | 20 | const uint16_t PixelCount = 8; // make sure to set this to the number of pixels in your strip 21 | const uint16_t PixelPin = 32; // make sure to set this to the correct pin, ignored for Esp8266 22 | const uint16_t AnimCount = PixelCount / 5 * 2 + 1; // we only need enough animations for the tail and one extra 23 | 24 | const uint16_t PixelFadeDuration = 300; // third of a second 25 | // one second divide by the number of pixels = loop once a second 26 | const uint16_t NextPixelMoveDuration = 1000 / PixelCount; // how fast we move through the pixels 27 | 28 | NeoGamma colorGamma; // for any fade animations, best to correct gamma 29 | 30 | NeoPixelBus strip(PixelCount, PixelPin); 31 | // For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. 32 | // There are other Esp8266 alternative methods that provide more pin options, but also have 33 | // other side effects. 34 | // for details see wiki linked here https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods 35 | 36 | // what is stored for state is specific to the need, in this case, the colors and 37 | // the pixel to animate; 38 | // basically what ever you need inside the animation update function 39 | struct MyAnimationState 40 | { 41 | RgbColor StartingColor; 42 | RgbColor EndingColor; 43 | uint16_t IndexPixel; // which pixel this animation is effecting 44 | }; 45 | 46 | NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object 47 | MyAnimationState animationState[AnimCount]; 48 | uint16_t frontPixel = 0; // the front of the loop 49 | RgbColor frontColor; // the color at the front of the loop 50 | 51 | void SetRandomSeed() 52 | { 53 | uint32_t seed; 54 | 55 | // random works best with a seed that can use 31 bits 56 | // analogRead on a unconnected pin tends toward less than four bits 57 | seed = analogRead(0); 58 | delay(1); 59 | 60 | for (int shifts = 3; shifts < 31; shifts += 3) 61 | { 62 | seed ^= analogRead(0) << shifts; 63 | delay(1); 64 | } 65 | 66 | // Serial.println(seed); 67 | randomSeed(seed); 68 | } 69 | 70 | void FadeOutAnimUpdate(const AnimationParam& param) 71 | { 72 | // this gets called for each animation on every time step 73 | // progress will start at 0.0 and end at 1.0 74 | // we use the blend function on the RgbColor to mix 75 | // color based on the progress given to us in the animation 76 | RgbColor updatedColor = RgbColor::LinearBlend( 77 | animationState[param.index].StartingColor, 78 | animationState[param.index].EndingColor, 79 | param.progress); 80 | // apply the color to the strip 81 | strip.SetPixelColor(animationState[param.index].IndexPixel, 82 | colorGamma.Correct(updatedColor)); 83 | } 84 | 85 | void LoopAnimUpdate(const AnimationParam& param) 86 | { 87 | // wait for this animation to complete, 88 | // we are using it as a timer of sorts 89 | if (param.state == AnimationState_Completed) 90 | { 91 | // done, time to restart this position tracking animation/timer 92 | animations.RestartAnimation(param.index); 93 | 94 | // pick the next pixel inline to start animating 95 | // 96 | frontPixel = (frontPixel + 1) % PixelCount; // increment and wrap 97 | if (frontPixel == 0) 98 | { 99 | // we looped, lets pick a new front color 100 | frontColor = HslColor(random(360) / 360.0f, 1.0f, 0.25f); 101 | } 102 | 103 | uint16_t indexAnim; 104 | // do we have an animation available to use to animate the next front pixel? 105 | // if you see skipping, then either you are going to fast or need to increase 106 | // the number of animation channels 107 | if (animations.NextAvailableAnimation(&indexAnim, 1)) 108 | { 109 | animationState[indexAnim].StartingColor = frontColor; 110 | animationState[indexAnim].EndingColor = RgbColor(0, 0, 0); 111 | animationState[indexAnim].IndexPixel = frontPixel; 112 | 113 | animations.StartAnimation(indexAnim, PixelFadeDuration, FadeOutAnimUpdate); 114 | } 115 | } 116 | } 117 | 118 | //**************以上为LED相关********************** 119 | 120 | #include 121 | #include 122 | #include 123 | 124 | #define ServoPin1 18 125 | #define ServoPin2 19 126 | 127 | #define PWMA 33 //TB6612的相关引脚 128 | #define AIN2 25 129 | #define AIN1 26 130 | #define STBY 27 //使能引脚,没特殊需求时可以直接接高电平(3.3V) 131 | #define BIN1 14 132 | #define BIN2 12 133 | #define PWMB 13 134 | 135 | // use first channel of 16 channels (started from zero) 136 | #define LEDC_CHANNEL_0 0 //PWMA的PWM 137 | #define LEDC_CHANNEL_1 1 //PWMB的PWM 138 | #define LEDC_CHANNEL_2 2 //板载LED的PWM 139 | 140 | // use 13 bit precission for LEDC timer 141 | #define LEDC_TIMER_13_BIT 13 142 | 143 | // use 5000 Hz as a LEDC base frequency 144 | #define LEDC_BASE_FREQ 5000 145 | 146 | // fade LED PIN (replace with LED_BUILTIN constant for built-in LED) 147 | #define LED_PIN 2 148 | 149 | int brightness = 0; // how bright the LED is 150 | int fadeAmount = 5; // how many points to fade the LED by 151 | 152 | // Arduino like analogWrite 153 | // value has to be between 0 and valueMax 154 | void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) { 155 | // calculate duty, 8191 from 2 ^ 13 - 1 156 | uint32_t duty = (8191 / valueMax) * min(value, valueMax); 157 | 158 | // write duty to LEDC 159 | ledcWrite(channel, duty); 160 | } 161 | void runLED1(){ //板载LED 162 | ledcAnalogWrite(LEDC_CHANNEL_2, brightness); 163 | 164 | // change the brightness for next time through the loop: 165 | brightness = brightness + fadeAmount; 166 | 167 | // reverse the direction of the fading at the ends of the fade: 168 | if (brightness <= 0 || brightness >= 255) { 169 | fadeAmount = -fadeAmount; 170 | } 171 | } 172 | void runLED2(){ //板载LED 173 | ledcAnalogWrite(LEDC_CHANNEL_2, brightness); 174 | 175 | // change the brightness for next time through the loop: 176 | brightness = brightness + fadeAmount*8; 177 | 178 | // reverse the direction of the fading at the ends of the fade: 179 | if (brightness <= 0 || brightness >= 255) { 180 | fadeAmount = -fadeAmount; 181 | } 182 | } 183 | 184 | unsigned long previousMillis1 = 0; 185 | unsigned long previousMillis2 = 0; 186 | const long LEDdelay=10; //(milliseconds)板载LED变化时间间隔 187 | 188 | #define MAX_SPEED 200 //0-255 189 | 190 | char BluetoothData; //蓝牙数据 191 | boolean d1,d2; 192 | int spdBR, spdBL; 193 | int lpad_x=127,lpad_y=127,rpad_x=127,rpad_y=127; // 摇杆初始值 194 | 195 | 196 | Servo servo1,servo2; //将要加上的两个舵机 197 | BluetoothSerial ESP32_BT; 198 | 199 | void tb6612_init(){ 200 | pinMode(AIN2,OUTPUT); 201 | pinMode(AIN1,OUTPUT); 202 | pinMode(BIN2,OUTPUT); 203 | pinMode(BIN1,OUTPUT); 204 | pinMode(STBY,OUTPUT); 205 | 206 | ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT); 207 | ledcAttachPin(PWMA, LEDC_CHANNEL_0); 208 | ledcSetup(LEDC_CHANNEL_1, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT); 209 | ledcAttachPin(PWMB, LEDC_CHANNEL_1); 210 | 211 | digitalWrite(STBY,LOW); 212 | } 213 | 214 | 215 | void setup(){ 216 | //将要加上的舵机 217 | // Allow allocation of all timers 218 | ESP32PWM::allocateTimer(0); 219 | ESP32PWM::allocateTimer(1); 220 | ESP32PWM::allocateTimer(2); 221 | ESP32PWM::allocateTimer(3); 222 | servo1.setPeriodHertz(50); // standard 50 hz servo 223 | servo1.attach(ServoPin1, 1000, 2000); // attaches the servo on pin 18 to the servo object 224 | servo2.setPeriodHertz(50); // standard 50 hz servo 225 | servo2.attach(ServoPin2, 1000, 2000); // attaches the servo on pin 18 to the servo object 226 | // using default min/max of 1000us and 2000us 227 | // different servos may require different min/max settings 228 | // for an accurate 0 to 180 sweep 229 | 230 | ledcSetup(LEDC_CHANNEL_2, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT); //板载LED 231 | ledcAttachPin(LED_PIN, LEDC_CHANNEL_2); 232 | 233 | tb6612_init(); 234 | ESP32_BT.begin("BTcar"); 235 | 236 | dcMotorIni(1,1); 237 | 238 | // Serial.begin(115200); // 启动硬件串口(用于输出调试信息和接收控制指令) 239 | delay(100); 240 | 241 | strip.Begin(); 242 | strip.Show(); 243 | 244 | SetRandomSeed(); 245 | 246 | // we use the index 0 animation to time how often we move to the next 247 | // pixel in the strip 248 | animations.StartAnimation(0, NextPixelMoveDuration, LoopAnimUpdate); 249 | } 250 | 251 | void loop(){ 252 | unsigned long currentMillis = millis(); 253 | 254 | if(ESP32_BT.connected()){ 255 | digitalWrite(STBY,HIGH); 256 | if (currentMillis - previousMillis1 >= LEDdelay) { 257 | previousMillis1 = currentMillis; 258 | runLED1(); //RGB环形LED灯的变化 259 | } 260 | }else { 261 | digitalWrite(STBY,LOW); 262 | if (currentMillis - previousMillis1 >= LEDdelay) { 263 | previousMillis1 = currentMillis; 264 | runLED2(); //RGB环形LED灯的变化 265 | } 266 | } 267 | 268 | 269 | if(ESP32_BT.available()){ 270 | BluetoothData=ESP32_BT.read(); 271 | 272 | switch(BluetoothData){ 273 | 274 | //***Control Pad on Left - Sends 'X__,Y__*' every 100ms 275 | case'X': //左摇杆 276 | lpad_x=ESP32_BT.parseInt(); 277 | while (BluetoothData!='*'){ 278 | if(ESP32_BT.available()){ 279 | BluetoothData=ESP32_BT.read(); //Get next character from bluetooth 280 | if(BluetoothData=='Y')lpad_y=ESP32_BT.parseInt(); 281 | } 282 | } 283 | break; 284 | //***Control Pad on Right - Sends 'RX__,Y__*' every 100ms 285 | case'R': //右摇杆 286 | while (BluetoothData!='*'){ 287 | if(ESP32_BT.available()){ 288 | BluetoothData=ESP32_BT.read(); //Get next character from bluetooth 289 | if(BluetoothData=='X')rpad_x=ESP32_BT.parseInt(); 290 | if(BluetoothData=='Y')rpad_y=ESP32_BT.parseInt(); 291 | } 292 | } 293 | break; 294 | } 295 | } 296 | 297 | Mapdata(); //将遥杆数据转换成电机运行的数据 298 | 299 | manualMode(); 300 | 301 | // this is all that is needed to keep it running 302 | // and avoiding using delay() is always a good thing for 303 | // any timing related routines 304 | animations.UpdateAnimations(); 305 | strip.Show(); 306 | } 307 | 308 | 309 | //将遥杆数据转换成电机运行的数据 310 | void Mapdata(){ 311 | int valLX = map(lpad_x, 0, 255, -MAX_SPEED, MAX_SPEED); 312 | int valLY = map(lpad_y, 255, 0, -MAX_SPEED, MAX_SPEED); 313 | int valRX = map(rpad_x, 0, 255, -MAX_SPEED, MAX_SPEED); 314 | int valRY = map(rpad_y, 255, 0, -MAX_SPEED, MAX_SPEED); 315 | 316 | spdBL = valLY + valLX; 317 | spdBR = valLY - valLX; 318 | 319 | spdBR += valRY - valRX; 320 | spdBL += valRY + valRX; 321 | 322 | if (abs(spdBL)<20) spdBL=0; 323 | if (abs(spdBR)<20) spdBR=0; 324 | 325 | spdBL = constrain(spdBL,-255,255); 326 | spdBR = constrain(spdBR,-255,255); 327 | 328 | } 329 | 330 | void manualMode(){ 331 | ledcAnalogWrite(LEDC_CHANNEL_0, abs(spdBL)); 332 | ledcAnalogWrite(LEDC_CHANNEL_1, abs(spdBR)); 333 | 334 | if (spdBL > 30) { 335 | M1Forward(); 336 | } else if (spdBL < -30) { 337 | M1Backward(); 338 | } else M1Release(); 339 | if (spdBR > 30) { 340 | M2Forward(); 341 | } else if (spdBR < -30) { 342 | M2Backward(); 343 | } else M2Release(); 344 | } 345 | 346 | void M1Forward(){ 347 | digitalWrite (AIN2,d1); 348 | digitalWrite (AIN1,!d1); 349 | } 350 | void M1Backward(){ 351 | digitalWrite (AIN2,!d1); 352 | digitalWrite (AIN1,d1); 353 | } 354 | void M1Release(){ 355 | digitalWrite (AIN1,0); 356 | digitalWrite (AIN2,0); 357 | } 358 | void M2Forward(){ 359 | digitalWrite (BIN1,d2); 360 | digitalWrite (BIN2,!d2); 361 | } 362 | void M2Backward(){ 363 | digitalWrite (BIN1,!d2); 364 | digitalWrite (BIN2,d2); 365 | } 366 | void M2Release(){ 367 | digitalWrite (BIN1,0); 368 | digitalWrite (BIN2,0); 369 | } 370 | 371 | void dcMotorIni(bool dir1, bool dir2){ 372 | d1=dir1; 373 | d2=dir2; 374 | } 375 | -------------------------------------------------------------------------------- /实际运行效果/readme.txt: -------------------------------------------------------------------------------- 1 | 因为买板子没考虑到口子不够的问题,所以买了一个oled显示屏也没用上,因此先把模式调好了的进行演示,还请大家多多包涵。 2 | 演示视频链接:https://www.aliyundrive.com/s/JjZxuFVnEHX 3 | -------------------------------------------------------------------------------- /小车源码/smart_car/smart_car.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | //CarMottoDefine 6 | #define RBIN2 12 7 | #define RPWMB 13 8 | #define RBIN1 14 9 | #define RAIN2 25 10 | #define RAIN1 26 11 | #define RSTBY 27 12 | #define RPWMA 33 13 | 14 | #define LPWMA 22 15 | #define LAIN2 23 16 | #define LAIN1 18 17 | #define LSTBY 5 18 | #define LBIN1 4 19 | #define LBIN2 19 20 | #define LPWMB 21 21 | 22 | #define servo 5 23 | #define Trig 15 24 | #define Echo 4 25 | 26 | int LED = 2; 27 | int btn1=18; 28 | //int BEEP=19; 29 | int btn2=22; 30 | int LXJ=32; 31 | int RXJ=23; 32 | int num=0,a=0; 33 | int flag=0; 34 | int distance=0; 35 | int left_distance=0; 36 | int right_distance=0; 37 | hw_timer_t *timer=NULL;//创建一个定时器结构体 38 | void pinModeinit() 39 | { 40 | //RightMottoPinInit 41 | pinMode(RSTBY,OUTPUT); 42 | pinMode(RPWMA,OUTPUT); 43 | pinMode(RPWMB,OUTPUT); 44 | pinMode(RAIN1,OUTPUT); 45 | pinMode(RAIN2,OUTPUT); 46 | pinMode(RBIN1,OUTPUT); 47 | pinMode(RBIN2,OUTPUT); 48 | pinMode(LXJ,INPUT); 49 | pinMode(RXJ,INPUT); 50 | pinMode(btn1,INPUT_PULLUP); 51 | pinMode(btn2,INPUT_PULLUP); 52 | // pinMode(BEEP,OUTPUT); 53 | pinMode(LED,OUTPUT); 54 | } 55 | //car_dir_contorl 56 | void Before() 57 | { 58 | digitalWrite(RSTBY,HIGH); 59 | digitalWrite(RPWMA,HIGH); 60 | digitalWrite(RPWMB,HIGH); 61 | digitalWrite(RAIN1,LOW); 62 | digitalWrite(RAIN2,HIGH); 63 | digitalWrite(RBIN1,HIGH); 64 | digitalWrite(RBIN2,LOW); 65 | } 66 | void Left()//01 67 | { 68 | digitalWrite(RSTBY,HIGH); 69 | digitalWrite(RPWMA,HIGH); 70 | digitalWrite(RPWMB,HIGH); 71 | digitalWrite(RAIN1,LOW); 72 | digitalWrite(RAIN2,HIGH); 73 | digitalWrite(RBIN1,LOW); 74 | digitalWrite(RBIN2,HIGH); 75 | } 76 | void Right()//10 77 | { 78 | digitalWrite(RSTBY,HIGH); 79 | digitalWrite(RPWMA,HIGH); 80 | digitalWrite(RPWMB,HIGH); 81 | digitalWrite(RAIN1,HIGH); 82 | digitalWrite(RAIN2,LOW); 83 | digitalWrite(RBIN1,HIGH); 84 | digitalWrite(RBIN2,LOW); 85 | } 86 | 87 | void Back() 88 | { 89 | digitalWrite(RSTBY,HIGH); 90 | digitalWrite(RPWMA,HIGH); 91 | digitalWrite(RPWMB,HIGH); 92 | digitalWrite(RAIN1,HIGH); 93 | digitalWrite(RAIN2,LOW); 94 | digitalWrite(RBIN1,LOW); 95 | digitalWrite(RBIN2,HIGH); 96 | } 97 | void Stop() 98 | { 99 | digitalWrite(RSTBY,HIGH); 100 | digitalWrite(RPWMA,HIGH); 101 | digitalWrite(RPWMB,HIGH); 102 | digitalWrite(RAIN1,LOW); 103 | digitalWrite(RAIN2,LOW); 104 | digitalWrite(RBIN1,LOW); 105 | digitalWrite(RBIN2,LOW); 106 | } 107 | //BLEInit 108 | BLEServer *pServer = NULL; 109 | BLECharacteristic * pTxCharacteristic; 110 | bool deviceConnected = false; 111 | bool oldDeviceConnected = false; 112 | uint8_t txValue = 0; 113 | 114 | // See the following for generating UUIDs: 115 | // https://www.uuidgenerator.net/ 116 | 117 | #define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID 118 | #define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" 119 | #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" 120 | 121 | 122 | class MyServerCallbacks: public BLEServerCallbacks { 123 | void onConnect(BLEServer* pServer) { 124 | deviceConnected = true; 125 | }; 126 | 127 | void onDisconnect(BLEServer* pServer) { 128 | deviceConnected = false; 129 | } 130 | }; 131 | 132 | class MyCallbacks: public BLECharacteristicCallbacks { 133 | void onWrite(BLECharacteristic *pCharacteristic) { 134 | std::string rxValue = pCharacteristic->getValue(); 135 | if (rxValue.length() > 0) { 136 | Serial.println("*********"); 137 | Serial.print("Received Value: "); 138 | 139 | for (int i = 0; i < rxValue.length(); i++) { 140 | Serial.print(rxValue[i]); 141 | } 142 | // Do stuff based on the command received from the app 143 | if (rxValue.find("Q") != -1) { 144 | Serial.print("behind!"); 145 | Before(); 146 | } 147 | else if (rxValue.find("H") != -1) { 148 | Serial.print("Turning Back!"); 149 | Back(); 150 | } 151 | else if (rxValue.find("Z") != -1) { 152 | Serial.print("Turning Left!"); 153 | Left(); 154 | } 155 | else if (rxValue.find("Y") != -1) { 156 | Serial.print("Turning Right!"); 157 | Right(); 158 | } 159 | else if (rxValue.find("S") != -1) { 160 | Serial.print("Turning Stop!"); 161 | Stop(); 162 | } 163 | 164 | // Serial.println(); 165 | // Serial.println("*********"); 166 | // while(rxValue.find("EXIT") != -1) 167 | // { 168 | // delay(1000); 169 | // Serial.println("NOW BLE() EXIT!"); 170 | // break; 171 | // } 172 | // Serial.println(); 173 | Serial.println("*********"); 174 | } 175 | } 176 | }; 177 | void BLEInit() 178 | { 179 | // Create the BLE Device 180 | 181 | BLEDevice::init("ESP32 UART Test"); // Give it a name 182 | // Create the BLE Server 183 | pServer = BLEDevice::createServer(); 184 | pServer->setCallbacks(new MyServerCallbacks()); 185 | 186 | // Create the BLE Service 187 | BLEService *pService = pServer->createService(SERVICE_UUID); 188 | 189 | // Create a BLE Characteristic 190 | pTxCharacteristic = pService->createCharacteristic( 191 | CHARACTERISTIC_UUID_TX, 192 | BLECharacteristic::PROPERTY_NOTIFY 193 | ); 194 | 195 | pTxCharacteristic->addDescriptor(new BLE2902()); 196 | 197 | BLECharacteristic * pRxCharacteristic = pService->createCharacteristic( 198 | CHARACTERISTIC_UUID_RX, 199 | BLECharacteristic::PROPERTY_WRITE 200 | ); 201 | 202 | pRxCharacteristic->setCallbacks(new MyCallbacks()); 203 | 204 | // Start the service 205 | pService->start(); 206 | 207 | // Start advertising 208 | pServer->getAdvertising()->start(); 209 | Serial.println("Waiting a client connection to notify..."); 210 | } 211 | //function_control 212 | void BLE() 213 | { 214 | if (deviceConnected) { 215 | digitalWrite(LED,HIGH); 216 | pTxCharacteristic->setValue(&txValue, 1); 217 | pTxCharacteristic->notify(); 218 | txValue++; 219 | delay(10); // bluetooth stack will go into congestion, if too many packets are sent 220 | } 221 | 222 | // disconnecting 223 | if (!deviceConnected && oldDeviceConnected) { 224 | delay(500); // give the bluetooth stack the chance to get things ready 225 | pServer->startAdvertising(); // restart advertising 226 | Serial.println("start advertising"); 227 | oldDeviceConnected = deviceConnected; 228 | delay(1000); 229 | digitalWrite(LED,LOW); 230 | } 231 | // connecting 232 | if (deviceConnected && !oldDeviceConnected) { 233 | // do stuff here on connecting 234 | oldDeviceConnected = deviceConnected; 235 | } 236 | // Serial.print("BLE():"); 237 | // Serial.println(num); 238 | } 239 | void XJ() 240 | { 241 | Serial.println("XJ()"); 242 | if(digitalRead(LXJ)==1&&digitalRead(RXJ)==0) 243 | { 244 | Serial.println("Right()"); 245 | Right(); 246 | delay(50); 247 | } 248 | if(digitalRead(RXJ)==1&&digitalRead(LXJ)==0) 249 | { 250 | Serial.println("Left()"); 251 | Left(); 252 | delay(50); 253 | } 254 | if(digitalRead(LXJ)==0 && digitalRead(RXJ)==0) 255 | { 256 | Serial.println("Before()"); 257 | Before(); 258 | } 259 | if(digitalRead(LXJ)==1 && digitalRead(RXJ)==1) 260 | { 261 | Serial.println("Stop()"); 262 | Stop(); 263 | delay(1000); 264 | } 265 | Serial.print("XJ():"); 266 | Serial.println(num); 267 | } 268 | 269 | int measure() 270 | { 271 | digitalWrite(Trig,HIGH); 272 | delayMicroseconds(20); 273 | digitalWrite(Trig,LOW); 274 | while(digitalRead(Echo)==0);//一旦收到D7信号 275 | int s=micros(); 276 | while(digitalRead(Echo)==1); 277 | int e=micros(); 278 | return e-s; 279 | } 280 | void check_behind() 281 | { 282 | digitalWrite(servo,HIGH); 283 | delayMicroseconds(1500); 284 | digitalWrite(servo,LOW); 285 | delay(18); 286 | delayMicroseconds(500);//前 287 | } 288 | void check_right() 289 | { 290 | digitalWrite(servo,HIGH); 291 | delayMicroseconds(1000); 292 | digitalWrite(servo,LOW); 293 | delay(19);//右 294 | } 295 | void check_left() 296 | { 297 | digitalWrite(servo,HIGH); 298 | delayMicroseconds(2000); 299 | digitalWrite(servo,LOW); 300 | delay(18);//左 301 | } 302 | 303 | void IRAM_ATTR timer_event()//中断处理函数,每秒执行一次 304 | { 305 | check_left(); 306 | measure(); 307 | left_distance=measure()/58; 308 | delay(250); 309 | check_right(); 310 | measure(); 311 | right_distance=measure()/58; 312 | delay(250); 313 | } 314 | 315 | void timerInit() 316 | { 317 | timer = timerBegin(0,80,true); 318 | // 配置定时器 这里使用的是定时器0(一共四个0123) 319 | // 80是这个定时器的分频系数 由于定时器基频是80Mhz 320 | // 这里设置80 就是1Mhz 就能保证定时器1us记录一次 321 | // true表面该定时器向上计数 322 | timerAttachInterrupt(timer,&timer_event,true); 323 | // 配置定时器的中断函数 true表示边沿触发 324 | timerAlarmWrite(timer,1000000000,true); 325 | // 设置定时器的报警值 当计时器计数值达到1000000时触发中断 326 | // true表示重加载 327 | timerAlarmEnable(timer); 328 | // 使能定时器报警 329 | } 330 | 331 | void BZ() 332 | { 333 | Serial.println("BZ()"); 334 | check_behind(); 335 | delay(50); 336 | measure(); 337 | distance=measure()/58; 338 | // Serial.print("distance:"); 339 | // Serial.print(distance); 340 | // Serial.println("cm"); 341 | // delay(500); 342 | if(distance<=25) 343 | { 344 | Stop(); 345 | delay(300); 346 | timer_event(); 347 | if(left_distance>right_distance) 348 | { 349 | Left(); 350 | delay(600); 351 | } 352 | else if(left_distanceright_distance) 181 | { 182 | Left(); 183 | delay(600); 184 | } 185 | else if(left_distance