5ebb30abdac05aa2abf10dc076178bede929bb58
Chip-cn-dat/Espressif-dat/ESP32-C3-dat/ESP32-C3-DAT.md
| ... | ... | @@ -11,13 +11,15 @@ |
| 11 | 11 | |
| 12 | 12 | - [[ESP32-C3-wroom-02-dat]] - [[ESP32-C3-USB-dat]] - [[ESP32-SDK-dat]] - [[ESP32-C3-mini-1-dat]] |
| 13 | 13 | |
| 14 | + |
|
| 15 | + |
|
| 14 | 16 | ## tech |
| 15 | 17 | |
| 16 | 18 | - [[RISC-V-dat]] - [[zigbee-dat]] - [[wifi-dat]] |
| 17 | 19 | |
| 18 | 20 | - [[conn-USB-dat]] - [[ESP32-USB-dat]] - [[USB-CDC-dat]] - [[jtag-dat]] - [[USB-SDK-dat]] |
| 19 | 21 | |
| 20 | - |
|
| 22 | +- [[ESP-SDK-dat]] - [[rc-code-dat]] |
|
| 21 | 23 | |
| 22 | 24 | |
| 23 | 25 | |
| ... | ... | @@ -167,6 +169,13 @@ If you have a serial USB-TTL bridge board or cable, you can read following debug |
| 167 | 169 | - [[CONN-USB-micro-vertical-dat]] |
| 168 | 170 | |
| 169 | 171 | |
| 172 | + |
|
| 173 | + |
|
| 174 | + |
|
| 175 | +进入下载模式:按住ESP32C3的BOOT按键,然后按下RESET按键,松开RESET按键,再松开B00T按键,此时ESP32C3会进入下载模式。(每次连接都需要重新进入下载模式,有时按一遍,端口不稳定会断开,可以通过端□识别声音来判断) |
|
| 176 | + |
|
| 177 | + |
|
| 178 | + |
|
| 170 | 179 | ## ref |
| 171 | 180 | |
| 172 | 181 | - [[USB-OTG-dat]] |
Chip-cn-dat/Espressif-dat/ESP32-C3-dat/ESP32-C3-supermini-dat/2026-06-09-19-29-45.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Espressif-dat/ESP32-C3-dat/ESP32-C3-supermini-dat/2026-06-09-19-29-45.png differ |
Chip-cn-dat/Espressif-dat/ESP32-C3-dat/ESP32-C3-supermini-dat/2026-06-09-19-32-37.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Espressif-dat/ESP32-C3-dat/ESP32-C3-supermini-dat/2026-06-09-19-32-37.png differ |
Chip-cn-dat/Espressif-dat/ESP32-C3-dat/ESP32-C3-supermini-dat/2026-06-09-19-32-50.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Espressif-dat/ESP32-C3-dat/ESP32-C3-supermini-dat/2026-06-09-19-32-50.png differ |
Chip-cn-dat/Espressif-dat/ESP32-C3-dat/ESP32-C3-supermini-dat/ESP32-C3-supermini-dat.md
| ... | ... | @@ -0,0 +1,39 @@ |
| 1 | + |
|
| 2 | +# ESP32-C3-supermini-dat |
|
| 3 | + |
|
| 4 | +- [[ESP32-C3-dat]] |
|
| 5 | + |
|
| 6 | +## pin definitions |
|
| 7 | + |
|
| 8 | + |
|
| 9 | + |
|
| 10 | + |
|
| 11 | + |
|
| 12 | +H2 |
|
| 13 | + |
|
| 14 | +- VBUS |
|
| 15 | +- 3V3 |
|
| 16 | +- GPIO4/ADC1/SD |
|
| 17 | +- GPI03 |
|
| 18 | +- GPIO2 |
|
| 19 | +- GPIO1 / U1RXD |
|
| 20 | +- GPIOO / U1TXD |
|
| 21 | + |
|
| 22 | +H1 |
|
| 23 | + |
|
| 24 | +- GPIO5/ADC2/SCL |
|
| 25 | +- GPI06 |
|
| 26 | +- GPI07 |
|
| 27 | +- GPIO8/PWM |
|
| 28 | +- GPIO9/BOOt |
|
| 29 | +- GPI010 |
|
| 30 | +- GPIO20 |
|
| 31 | +- GPIO21 |
|
| 32 | + |
|
| 33 | +## SCH |
|
| 34 | + |
|
| 35 | + |
|
| 36 | + |
|
| 37 | + |
|
| 38 | +## ref |
|
| 39 | + |
SDK-dat/ESP-SDK-dat/ESP-NOW-dat/ESP-NOW-dat.md
| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +# ESP-NOW-dat |
|
| 4 | + |
|
| 5 | +- [[ESP32-S3-dat]] |
|
| 6 | + |
|
| 7 | +- [[ESP32-C3-supermini-dat]] - [[ESP32-C3-NOW-code-1]] - [[ESP-NOW-dat]] |
|
| 8 | + |
|
| 9 | + |
|
| 10 | +### 1. Enable ESP-NOW "Long Range" Mode (LR Mode) |
|
| 11 | +By default, ESP-NOW runs on standard Wi-Fi physical rates. However, Espressif built a hidden protocol layer called **LR Mode** specifically for long-distance communication. It reduces the data rate down to 256 Kbps or 512 Kbps (which is still a massive amount of speed for tiny RC joystick coordinates) but heavily boosts the receiver's sensitivity. |
|
| 12 | + |
|
| 13 | +In your initialization code (after `esp_wifi_start()`), use this to force the radio into Long Range mode: |
|
| 14 | + |
|
| 15 | +```cpp |
|
| 16 | +// Set the Wi-Fi protocol to Long Range mode on the station interface |
|
| 17 | +esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); |
|
| 18 | +``` |
|
| 19 | + |
|
| 20 | +**The Impact:** This simple software toggle can easily double or triple your line-of-sight range in open fields. |
|
| 21 | + |
|
| 22 | +### 2. Max Out the Transmission Power |
|
| 23 | +Dev boards sometimes ship with conservative radio transmission settings to save power. For an RC vehicle where reliability is everything, you want to force the S3’s internal power amplifier to its absolute hardware limit (21 dBm). |
|
| 24 | + |
|
| 25 | +Add this right after initializing your Wi-Fi settings: |
|
| 26 | + |
|
| 27 | +```cpp |
|
| 28 | +// Set maximum TX power (84 represents 21dBm, where 1 unit = 0.25dBm) |
|
| 29 | +esp_wifi_set_max_tx_power(84); |
|
| 30 | +``` |
|
| 31 | + |
|
| 32 | +### 3. Lock Down a Clean Wi-Fi Channel |
|
| 33 | +Standard home Wi-Fi routers hop around channels 1 through 11, causing massive interference if your RC toy crosses paths with a residential area. |
|
| 34 | + |
|
| 35 | +In your code, explicitly bind both your transmitter and receiver to Channel 1, 6, or 11 (the non-overlapping channels). |
|
| 36 | + |
|
| 37 | +Make sure both chips are hard-coded to the exact same channel so they don't waste precious time searching for each other if a packet drops. |
|
| 38 | + |
|
| 39 | +### A Critical Note on Your Specific S3 Hardware |
|
| 40 | +Since you are avoiding extra hardware add-ons, look closely at your ESP32-S3 boards right now: |
|
| 41 | + |
|
| 42 | +If they have a built-in PCB Trace Antenna (the onboard wavy copper line): You will get a reliable 80 to 150 meters outdoors with the software optimizations above. |
|
| 43 | + |
|
| 44 | +If they have an IPEX/U.FL connector (the tiny gold metal circle): Make sure you plug a standard 2.4GHz rubber ducky antenna into it. With a proper antenna attached directly to that port, ESP-NOW in LR mode can routinely push 400 to 700+ meters line-of-sight. |
|
| 45 | + |
|
| 46 | +If you are using the tiny "Super Mini" style S3 boards, be extra careful to keep the built-in antenna clear of power wires or metal structural components on your toy, as their small antennas are highly sensitive to nearby electronic noise. |
|
| ... | ... | \ No newline at end of file |
SDK-dat/ESP-SDK-dat/ESP-NOW-dat/ESP32-C3-NOW-code-1/ESP32-C3-NOW-RX-1.ino
| ... | ... | @@ -0,0 +1,103 @@ |
| 1 | +#include <esp_now.h> |
|
| 2 | +#include <WiFi.h> |
|
| 3 | +#include <esp_wifi.h> |
|
| 4 | + |
|
| 5 | +// --- Pin Allocations --- |
|
| 6 | +// Motor A (Left) |
|
| 7 | +const int M1_PWM = 6; |
|
| 8 | +const int M1_DIR = 7; |
|
| 9 | + |
|
| 10 | +// Motor B (Right) |
|
| 11 | +const int M2_PWM = 9; |
|
| 12 | +const int M2_DIR = 10; |
|
| 13 | + |
|
| 14 | +// --- PWM Properties --- |
|
| 15 | +const int PWM_FREQ = 5000; // 5kHz keeps the motor humming quiet |
|
| 16 | +const int PWM_RES = 8; // 8-bit resolution (0-255) |
|
| 17 | + |
|
| 18 | +// --- ESP-NOW Payload Structure --- |
|
| 19 | +// Must match the transmitter's struct exactly |
|
| 20 | +typedef struct struct_message { |
|
| 21 | + int16_t throttle; // -255 to 255 (Forward / Reverse) |
|
| 22 | + int16_t steering; // -255 to 255 (Left / Right) |
|
| 23 | +} struct_message; |
|
| 24 | + |
|
| 25 | +struct_message incomingData; |
|
| 26 | + |
|
| 27 | +// --- Motor Control Helper Function --- |
|
| 28 | +void driveMotors(int16_t throttle, int16_t steering) { |
|
| 29 | + // Simple differential drive mixing |
|
| 30 | + int16_t leftSpeed = throttle + steering; |
|
| 31 | + int16_t rightSpeed = throttle - steering; |
|
| 32 | + |
|
| 33 | + // Constrain to valid 8-bit PWM bounds |
|
| 34 | + leftSpeed = constrain(leftSpeed, -255, 255); |
|
| 35 | + rightSpeed = constrain(rightSpeed, -255, 255); |
|
| 36 | + |
|
| 37 | + // Control Motor A (Left) |
|
| 38 | + if (leftSpeed >= 0) { |
|
| 39 | + digitalWrite(M1_DIR, LOW); |
|
| 40 | + analogWrite(M1_PWM, leftSpeed); |
|
| 41 | + } else { |
|
| 42 | + digitalWrite(M1_DIR, HIGH); |
|
| 43 | + analogWrite(M1_PWM, 255 + leftSpeed); // Invert PWM for inverted logic direction pins |
|
| 44 | + } |
|
| 45 | + |
|
| 46 | + // Control Motor B (Right) |
|
| 47 | + if (rightSpeed >= 0) { |
|
| 48 | + digitalWrite(M2_DIR, LOW); |
|
| 49 | + analogWrite(M2_PWM, rightSpeed); |
|
| 50 | + } else { |
|
| 51 | + digitalWrite(M2_DIR, HIGH); |
|
| 52 | + analogWrite(M2_PWM, 255 + rightSpeed); |
|
| 53 | + } |
|
| 54 | +} |
|
| 55 | + |
|
| 56 | +// --- ESP-NOW Callback Execution --- |
|
| 57 | +void OnDataRecv(const uint8_t * mac, const uint8_t *incomingDataRaw, int len) { |
|
| 58 | + memcpy(&incomingData, incomingDataRaw, sizeof(incomingData)); |
|
| 59 | + |
|
| 60 | + // Pass the received control parameters straight to the motor driver |
|
| 61 | + driveMotors(incomingData.throttle, incomingData.steering); |
|
| 62 | +} |
|
| 63 | + |
|
| 64 | +void setup() { |
|
| 65 | + Serial.begin(115200); |
|
| 66 | + |
|
| 67 | + // Initialize Motor Pins |
|
| 68 | + pinMode(M1_PWM, OUTPUT); |
|
| 69 | + pinMode(M1_DIR, OUTPUT); |
|
| 70 | + pinMode(M2_PWM, OUTPUT); |
|
| 71 | + pinMode(M2_DIR, OUTPUT); |
|
| 72 | + |
|
| 73 | + // Set up PWM properties for analogWrite |
|
| 74 | + analogWriteFrequency(M1_PWM, PWM_FREQ); |
|
| 75 | + analogWriteResolution(M1_RES); |
|
| 76 | + analogWriteFrequency(M2_PWM, PWM_FREQ); |
|
| 77 | + analogWriteResolution(PWM_RES); |
|
| 78 | + |
|
| 79 | + // Initialize Wi-Fi in Station Mode |
|
| 80 | + WiFi.mode(WIFI_STA); |
|
| 81 | + WiFi.disconnect(); |
|
| 82 | + |
|
| 83 | + // 1. Force Long Range (LR) Mode Protocol for hardware-level reliability |
|
| 84 | + esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); |
|
| 85 | + |
|
| 86 | + // 2. Maximize internal TX Power to 21dBm |
|
| 87 | + esp_wifi_set_max_tx_power(84); |
|
| 88 | + |
|
| 89 | + // Initialize ESP-NOW Protocol |
|
| 90 | + if (esp_now_init() != ESP_OK) { |
|
| 91 | + Serial.println("Error initializing ESP-NOW"); |
|
| 92 | + return; |
|
| 93 | + } |
|
| 94 | + |
|
| 95 | + // Register the Receive Callback |
|
| 96 | + esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv)); |
|
| 97 | + |
|
| 98 | + Serial.println("Receiver Ready. Waiting for packet data..."); |
|
| 99 | +} |
|
| 100 | + |
|
| 101 | +void loop() { |
|
| 102 | + // Keep loop non-blocking. ESP-NOW relies entirely on hardware interrupts. |
|
| 103 | +} |
|
| ... | ... | \ No newline at end of file |
SDK-dat/ESP-SDK-dat/ESP-NOW-dat/ESP32-C3-NOW-code-1/ESP32-C3-NOW-TX-1.ino
| ... | ... | @@ -0,0 +1,68 @@ |
| 1 | +#include <esp_now.h> |
|
| 2 | +#include <WiFi.h> |
|
| 3 | +#include <esp_wifi.h> |
|
| 4 | + |
|
| 5 | +// REPLACE WITH YOUR ESP32-C3 MAC ADDRESS |
|
| 6 | +uint8_t broadcastAddress[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; |
|
| 7 | + |
|
| 8 | +// Joystick Analog Input Pins |
|
| 9 | +const int PIN_THROTTLE = 1; |
|
| 10 | +const int PIN_STEERING = 2; |
|
| 11 | + |
|
| 12 | +typedef struct struct_message { |
|
| 13 | + int16_t throttle; |
|
| 14 | + int16_t steering; |
|
| 15 | +} struct_message; |
|
| 16 | + |
|
| 17 | +struct_message outgoingData; |
|
| 18 | +esp_now_peer_info_t peerInfo; |
|
| 19 | + |
|
| 20 | +void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { |
|
| 21 | + // Optional transmission debugging over serial |
|
| 22 | +} |
|
| 23 | + |
|
| 24 | +void setup() { |
|
| 25 | + Serial.begin(115200); |
|
| 26 | + |
|
| 27 | + WiFi.mode(WIFI_STA); |
|
| 28 | + WiFi.disconnect(); |
|
| 29 | + |
|
| 30 | + // Force matching Long Range Mode and Max Power on the S3 side |
|
| 31 | + esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); |
|
| 32 | + esp_wifi_set_max_tx_power(84); |
|
| 33 | + |
|
| 34 | + if (esp_now_init() != ESP_OK) { |
|
| 35 | + Serial.println("Error initializing ESP-NOW"); |
|
| 36 | + return; |
|
| 37 | + } |
|
| 38 | + |
|
| 39 | + esp_now_register_send_cb(OnDataSent); |
|
| 40 | + |
|
| 41 | + // Register Peer Car |
|
| 42 | + memcpy(peerInfo.peer_addr, broadcastAddress, 6); |
|
| 43 | + peerInfo.channel = 1; // Bound cleanly to fixed Channel 1 |
|
| 44 | + peerInfo.encrypt = false; |
|
| 45 | + |
|
| 46 | + if (esp_now_add_peer(&peerInfo) != ESP_OK){ |
|
| 47 | + Serial.println("Failed to add peer"); |
|
| 48 | + return; |
|
| 49 | + } |
|
| 50 | +} |
|
| 51 | + |
|
| 52 | +void loop() { |
|
| 53 | + // Read your remote joysticks (Maps standard 12-bit ADC 0-4095 down to signed -255 to 255) |
|
| 54 | + int16_t rawThrottle = analogRead(PIN_THROTTLE); |
|
| 55 | + int16_t rawSteering = analogRead(PIN_STEERING); |
|
| 56 | + |
|
| 57 | + outgoingData.throttle = map(rawThrottle, 0, 4095, -255, 255); |
|
| 58 | + outgoingData.steering = map(rawSteering, 0, 4095, -255, 255); |
|
| 59 | + |
|
| 60 | + // Tiny deadzone filter to prevent motor creep at center stick |
|
| 61 | + if(abs(outgoingData.throttle) < 15) outgoingData.throttle = 0; |
|
| 62 | + if(abs(outgoingData.steering) < 15) outgoingData.steering = 0; |
|
| 63 | + |
|
| 64 | + // Transmit control packet over the LR link layer |
|
| 65 | + esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &outgoingData, sizeof(outgoingData)); |
|
| 66 | + |
|
| 67 | + delay(20); // 50Hz refresh rate is standard for smooth responsive driving |
|
| 68 | +} |
|
| ... | ... | \ No newline at end of file |
SDK-dat/ESP-SDK-dat/ESP-NOW-dat/ESP32-C3-NOW-code-1/ESP32-C3-NOW-code-1.md
| ... | ... | @@ -0,0 +1,5 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +# ESP32-C3-code-1 |
|
| 4 | + |
|
| 5 | +use GPIO2 and GPIO3 to |
|
| ... | ... | \ No newline at end of file |
SDK-dat/ESP-SDK-dat/ESP-SDK-dat.md
| ... | ... | @@ -8,6 +8,10 @@ |
| 8 | 8 | |
| 9 | 9 | - [[ESP-dat]] |
| 10 | 10 | |
| 11 | +- [[ESP32-C3-supermini-dat]] - [[ESP32-C3-NOW-code-1]] - [[ESP-NOW-dat]] |
|
| 12 | + |
|
| 13 | +- [[ESP32-RC-phone-dat]] |
|
| 14 | + |
|
| 11 | 15 | |
| 12 | 16 | |
| 13 | 17 | ## ESP32 x3 |
SDK-dat/ESP-SDK-dat/ESP32-RC-phone-dat/ESP32-RC-phone-dat.ino
| ... | ... | @@ -0,0 +1,201 @@ |
| 1 | + |
|
| 2 | +#include <WiFi.h> |
|
| 3 | +#include <AsyncTCP.h> // Requires installing the AsyncTCP library |
|
| 4 | +#include <ESPAsyncWebServer.h> // Requires installing the ESPAsyncWebServer library |
|
| 5 | + |
|
| 6 | +// --- Wi-Fi Credentials --- |
|
| 7 | +const char* ssid = "ESP32_C3_RC_Car"; |
|
| 8 | +const char* password = "123456789"; // Minimum 8 characters |
|
| 9 | + |
|
| 10 | +// --- Pin Allocations --- |
|
| 11 | +const int M1_PWM = 6; |
|
| 12 | +const int M1_DIR = 7; |
|
| 13 | +const int M2_PWM = 9; |
|
| 14 | +const int M2_DIR = 10; |
|
| 15 | + |
|
| 16 | +// --- PWM Settings --- |
|
| 17 | +const int PWM_FREQ = 5000; |
|
| 18 | +const int PWM_RES = 8; |
|
| 19 | + |
|
| 20 | +// Create AsyncWebServer object on port 80 |
|
| 21 | +AsyncWebServer server(80); |
|
| 22 | +AsyncWebSocket ws("/ws"); |
|
| 23 | + |
|
| 24 | +// --- HTML + JavaScript Interface --- |
|
| 25 | +// This file is stored directly in the program memory and served to your phone |
|
| 26 | +const char index_html[] PROGMEM = R"rawliteral( |
|
| 27 | +<!DOCTYPE html> |
|
| 28 | +<html> |
|
| 29 | +<head> |
|
| 30 | + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
|
| 31 | + <title>ESP32-C3 RC Control</title> |
|
| 32 | + <style> |
|
| 33 | + body { font-family: Arial, sans-serif; text-align: center; background: #222; color: #fff; margin: 0; padding: 0; user-select: none; overflow: hidden;} |
|
| 34 | + h1 { margin-top: 20px; color: #00f3ff; font-size: 24px; } |
|
| 35 | + #container { position: relative; width: 300px; height: 300px; background: #333; border-radius: 50%; margin: 50px auto; border: 4px solid #555; touch-action: none; } |
|
| 36 | + #joystick { position: absolute; width: 80px; height: 80px; background: #00f3ff; border-radius: 50%; top: 110px; left: 110px; box-shadow: 0 0 20px #00f3ff; } |
|
| 37 | + #status { font-size: 18px; color: #aaa; margin-top: 20px; } |
|
| 38 | + </style> |
|
| 39 | +</head> |
|
| 40 | +<body> |
|
| 41 | + <h1>ESP32-C3 Driver</h1> |
|
| 42 | + <div id="container"> |
|
| 43 | + <div id="joystick"></div> |
|
| 44 | + </div> |
|
| 45 | + <div id="status">Status: Disconnected</div> |
|
| 46 | + |
|
| 47 | + <script> |
|
| 48 | + var gateway = `ws://${window.location.hostname}/ws`; |
|
| 49 | + var websocket; |
|
| 50 | + var container = document.getElementById('container'); |
|
| 51 | + var joystick = document.getElementById('joystick'); |
|
| 52 | + var statusText = document.getElementById('status'); |
|
| 53 | + |
|
| 54 | + var centerX = 150 - 40; |
|
| 55 | + var centerY = 150 - 40; |
|
| 56 | + var dragging = false; |
|
| 57 | + |
|
| 58 | + window.addEventListener('load', initWebSocket); |
|
| 59 | + |
|
| 60 | + function initWebSocket() { |
|
| 61 | + websocket = new WebSocket(gateway); |
|
| 62 | + websocket.onopen = function() { statusText.innerText = "Status: Connected"; statusText.style.color = "#00ff00"; }; |
|
| 63 | + websocket.onclose = function() { statusText.innerText = "Status: Disconnected"; statusText.style.color = "#ff0000"; setTimeout(initWebSocket, 2000); }; |
|
| 64 | + } |
|
| 65 | + |
|
| 66 | + container.addEventListener('touchstart', function(e) { dragging = true; handleMove(e.touches[0]); }); |
|
| 67 | + window.addEventListener('touchmove', function(e) { if (dragging) handleMove(e.touches[0]); }, { passive: false }); |
|
| 68 | + window.addEventListener('touchend', function() { |
|
| 69 | + dragging = false; |
|
| 70 | + joystick.style.left = centerX + 'px'; |
|
| 71 | + joystick.style.top = centerY + 'px'; |
|
| 72 | + sendData(0, 0); |
|
| 73 | + }); |
|
| 74 | + |
|
| 75 | + function handleMove(touch) { |
|
| 76 | + var rect = container.getBoundingClientRect(); |
|
| 77 | + var x = touch.clientX - rect.left - 40; |
|
| 78 | + var y = touch.clientY - rect.top - 40; |
|
| 79 | + |
|
| 80 | + // Limit to boundary ring |
|
| 81 | + var dx = x - centerX; |
|
| 82 | + var dy = y - centerY; |
|
| 83 | + var dist = Math.sqrt(dx*dx + dy*dy); |
|
| 84 | + if (dist > 110) { |
|
| 85 | + x = centerX + (dx / dist) * 110; |
|
| 86 | + y = centerY + (dy / dist) * 110; |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + joystick.style.left = x + 'px'; |
|
| 90 | + joystick.style.top = y + 'px'; |
|
| 91 | + |
|
| 92 | + // Map values to standard motor boundaries (-255 to 255) |
|
| 93 | + var throttle = Math.round(((centerY - y) / 110) * 255); |
|
| 94 | + var steering = Math.round(((x - centerX) / 110) * 255); |
|
| 95 | + sendData(throttle, steering); |
|
| 96 | + } |
|
| 97 | + |
|
| 98 | + // Limit transmission frequency to protect the socket buffer |
|
| 99 | + var lastSend = 0; |
|
| 100 | + function sendData(t, s) { |
|
| 101 | + var now = Date.now(); |
|
| 102 | + if (now - lastSend > 40 || (t === 0 && s === 0)) { |
|
| 103 | + if (websocket.readyState === WebSocket.OPEN) { |
|
| 104 | + websocket.send(t + "," + s); |
|
| 105 | + lastSend = now; |
|
| 106 | + } |
|
| 107 | + } |
|
| 108 | + } |
|
| 109 | + </script> |
|
| 110 | +</body> |
|
| 111 | +</html> |
|
| 112 | +)rawliteral"; |
|
| 113 | + |
|
| 114 | +// --- Motor Control Routing Engine --- |
|
| 115 | +void driveMotors(int16_t throttle, int16_t steering) { |
|
| 116 | + int16_t leftSpeed = throttle + steering; |
|
| 117 | + int16_t rightSpeed = throttle - steering; |
|
| 118 | + |
|
| 119 | + leftSpeed = constrain(leftSpeed, -255, 255); |
|
| 120 | + rightSpeed = constrain(rightSpeed, -255, 255); |
|
| 121 | + |
|
| 122 | + // Motor 1 (Left) |
|
| 123 | + if (leftSpeed >= 0) { |
|
| 124 | + digitalWrite(M1_DIR, LOW); |
|
| 125 | + analogWrite(M1_PWM, leftSpeed); |
|
| 126 | + } else { |
|
| 127 | + digitalWrite(M1_DIR, HIGH); |
|
| 128 | + analogWrite(M1_PWM, 255 + leftSpeed); |
|
| 129 | + } |
|
| 130 | + |
|
| 131 | + // Motor 2 (Right) |
|
| 132 | + if (rightSpeed >= 0) { |
|
| 133 | + digitalWrite(M2_DIR, LOW); |
|
| 134 | + analogWrite(M2_PWM, rightSpeed); |
|
| 135 | + } else { |
|
| 136 | + digitalWrite(M2_DIR, HIGH); |
|
| 137 | + analogWrite(M2_PWM, 255 + rightSpeed); |
|
| 138 | + } |
|
| 139 | +} |
|
| 140 | + |
|
| 141 | +// --- WebSocket Event Handler --- |
|
| 142 | +void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { |
|
| 143 | + if (type == WS_EVT_DATA) { |
|
| 144 | + data[len] = '\0'; |
|
| 145 | + char* msg = (char*)data; |
|
| 146 | + |
|
| 147 | + // Parse incoming csv formatting: "throttle,steering" |
|
| 148 | + char* token = strtok(msg, ","); |
|
| 149 | + if (token != NULL) { |
|
| 150 | + int16_t throttle = atoi(token); |
|
| 151 | + token = strtok(NULL, ","); |
|
| 152 | + if (token != NULL) { |
|
| 153 | + int16_t steering = atoi(token); |
|
| 154 | + driveMotors(throttle, steering); |
|
| 155 | + } |
|
| 156 | + } |
|
| 157 | + } else if (type == WS_EVT_DISCONNECT) { |
|
| 158 | + // Safety feature: stop vehicle instantly if phone disconnects or goes out of range |
|
| 159 | + driveMotors(0, 0); |
|
| 160 | + } |
|
| 161 | +} |
|
| 162 | + |
|
| 163 | +void setup() { |
|
| 164 | + Serial.begin(115200); |
|
| 165 | + |
|
| 166 | + // Initialize Motor Control Hardware |
|
| 167 | + pinMode(M1_PWM, OUTPUT); |
|
| 168 | + pinMode(M1_DIR, OUTPUT); |
|
| 169 | + pinMode(M2_PWM, OUTPUT); |
|
| 170 | + pinMode(M2_DIR, OUTPUT); |
|
| 171 | + |
|
| 172 | + analogWriteFrequency(M1_PWM, PWM_FREQ); |
|
| 173 | + analogWriteResolution(M1_RES); |
|
| 174 | + analogWriteFrequency(M2_PWM, PWM_FREQ); |
|
| 175 | + analogWriteResolution(PWM_RES); |
|
| 176 | + |
|
| 177 | + // Turn off driving pins initially |
|
| 178 | + driveMotors(0, 0); |
|
| 179 | + |
|
| 180 | + // Initialize Soft Access Point Mode |
|
| 181 | + WiFi.softAP(ssid, password); |
|
| 182 | + IPAddress IP = WiFi.softAPIP(); |
|
| 183 | + Serial.print("AP IP address: "); |
|
| 184 | + Serial.println(IP); |
|
| 185 | + |
|
| 186 | + // Bind WebSocket handling engine |
|
| 187 | + ws.onEvent(onEvent); |
|
| 188 | + server.addHandler(&ws); |
|
| 189 | + |
|
| 190 | + // Serve HTML page when phone connects to base address |
|
| 191 | + server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ |
|
| 192 | + request->send_P(200, "text/html", index_html); |
|
| 193 | + }); |
|
| 194 | + |
|
| 195 | + server.begin(); |
|
| 196 | + Serial.println("Web server started successfully."); |
|
| 197 | +} |
|
| 198 | + |
|
| 199 | +void loop() { |
|
| 200 | + ws.cleanupClients(); // Clears memory buffers automatically |
|
| 201 | +} |
|
| ... | ... | \ No newline at end of file |
SDK-dat/ESP-SDK-dat/ESP32-RC-phone-dat/ESP32-RC-phone-dat.md
| ... | ... | @@ -0,0 +1,4 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +# ESP32-RC-phone-dat |
|
| 4 | + |
app-dat/RC-apps-dat/RC-apps-dat.md
| ... | ... | @@ -1,7 +1,11 @@ |
| 1 | 1 | |
| 2 | 2 | # RC-apps-dat |
| 3 | 3 | |
| 4 | -- [[RC-dat]] |
|
| 4 | + |
|
| 5 | + |
|
| 6 | + |
|
| 7 | + |
|
| 8 | +- [[RC-dat]] - [[rc-code-dat]] |
|
| 5 | 9 | |
| 6 | 10 | |
| 7 | 11 | - [[UAV-dat]] |
| ... | ... | @@ -72,6 +76,13 @@ but **500 Hz is the highest stable rate** supported by the Mobula8 SPI receiver. |
| 72 | 76 | |
| 73 | 77 | |
| 74 | 78 | |
| 79 | + |
|
| 80 | + |
|
| 81 | +## SDKs |
|
| 82 | + |
|
| 83 | +- [[ESP-NOW-dat]] - [[ESP-SDK-dat]] |
|
| 84 | + |
|
| 85 | + |
|
| 75 | 86 | ## ref |
| 76 | 87 | |
| 77 | 88 | - [[rc-apps]] |
app-dat/RC-apps-dat/rc-Marine-vehicle-dat/rc-boat-dat/rc-boat-dat.md
| ... | ... | @@ -60,6 +60,9 @@ the [[motor-driver-rc-dat]] hack as below: |
| 60 | 60 | |
| 61 | 61 |  |
| 62 | 62 | |
| 63 | + |
|
| 64 | +- [[ESP32-C3-supermini-dat]] - [[rc-code-dat]] |
|
| 65 | + |
|
| 63 | 66 | - [[UTC3361-dat]] - [[UTC358-dat]] - [[LM358-dat]] |
| 64 | 67 | |
| 65 | 68 |  |
code-dat/RC-code-dat/RC-code-dat.md
| ... | ... | @@ -4,6 +4,9 @@ |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | |
| 7 | +- [[ESP32-C3-supermini-dat]] - [[ESP32-C3-NOW-code-1]] - [[ESP-NOW-dat]] |
|
| 8 | + |
|
| 9 | +- [[ESP32-RC-phone-dat]] |
|
| 7 | 10 | |
| 8 | 11 | |
| 9 | 12 |