Board-dat/SDR/SDR1117-dat/SDR1117-dat.md
... ...
@@ -59,7 +59,7 @@ expanding PCB by [[PCB-accesories-dat]]
59 59
60 60
## setup
61 61
62
-- [[CRSF-dat]]
62
+- [[CRSF-dat]] - [[radiomaster-pocket-dat]]
63 63
64 64
correct to SoftwareSerial soft(13, 12); // RX, TX
65 65
Board-dat/SDR/SDR1125-dat/SDR1125-dat.md
... ...
@@ -2,6 +2,9 @@
2 2
3 3
# SDR1125-dat.md
4 4
5
+
6
+- [[SDR1125-dat]] - [[CRSF-dat]]
7
+
5 8
orange boxes series
6 9
7 10
- [[OPM1153-dat]] - [[MP1584-dat]] == orange middle module
Chip-cn-dat/Espressif-dat/ESP8266-DAT/ESP8266-DAT.md
... ...
@@ -23,33 +23,7 @@ hardware and software - [[ESP8266-HDK-dat]] - [[ESP8266-SDK-dat]]
23 23
debug - [[ESP8266-debug-log-dat]] - [[ESP8266-error-log-dat]] - [[ESP8266-boot-log-dat]]
24 24
25 25
26
-## design
27
-
28
-software serial - can not be more than 115200 baud, otherwise the data will be corrupted.
29
-
30
-The data you shared is raw CRSF binary packets, but they look slightly corrupted or "jittery," which is very common when using SoftwareSerial at 115200 on an ESP8266.
31
-
32
-- [[CRSF-dat]]
33
-
34
- 0B 56 FE D8 10 0B 56 FE D8 10 0B 52 FE 84 D8 10
35
- 0B 52 FE D8 10 0B 56 FE D8 10 0B 52 FF D8 10 0B
36
- 52 FF D9 10 99 FF 44 D8 10 0B 56 FE D8 10 0B 52
37
- FF D8 10 0B 56 FE D8 10 0B 56 FF 25 26 12 4B A2
38
- D8 10 0B 52 FE D8 10 0B 56 FE A6 12 4B D8 10 99
39
- FF D8 10 0B 56 FE E4 26 12 4B A2 A6 12 4B D8 10
40
- 0B 52 FE D8 10 0B 56 FE D8 10 0B 56 FF 84 D8 10
41
- 99 FF D8 10 0B 52 FF D8 10 0B 56 FE A6 12 4B A4
42
- D8 10 0B 56 FE D8 10 FF D8 10 0B 52 FE D8 10 0B
43
- 56 FE D8 10 0B 56 FE 44 12 4B FF D8 10 0B 52 FF
44
- D8 10 0B 56 FF D9 10 FE D8 10 0B 56 FF 80 D8 10
45
- 0B 56 FF D8 10 0B 56 FF 12 4B 54 FF 84 D8 10 0B
46
- 52 FF D8 10 0B 52 FF D8 10 0B 52 FF D8 10 0B 56
47
- FF D9 10 FE C4 D9 10 0B 56 FF D8 10 FE 12 4B 02
48
- 4E D8 10 0B D2 FF D8 10 FE A2 D8 10 0B 52 FF D8
49
- 10 0B 56 FF D8 10 FE D8 10 0B 56 FF 00 80 D8 10
50
- 0B 56 FE D8 10 0B 56 FE D8 10 0B 52 FE D8 10 FF
51
- D8 10 0B 56 FE 80 D8 10 0B 52 FE D8 10 0B 56 FE
52
- D8 10 0B 52 FE D8 10 0B 52 FE D8 10 99 FF 40 D8
26
+
53 27
54 28
## ref
55 29
Network-dat/RC-dat/RC-protocols-dat/CRSF-dat/CRSF-dat.md
... ...
@@ -1,6 +1,10 @@
1 1
2 2
# CRSF-dat
3 3
4
+
5
+
6
+
7
+
4 8
CRSF (Crossfire Serial Protocol) is a low-latency, high-speed serial protocol developed by **Team BlackSheep (TBS)** for communication between radio receivers (like TBS Crossfire Nano RX) and flight controllers.
5 9
6 10
It’s used in RC applications (especially FPV drones) to transmit RC channel data, telemetry, and link status over a compact serial format.
... ...
@@ -8,7 +12,9 @@ It’s used in RC applications (especially FPV drones) to transmit RC channel da
8 12
CRSF packets are binary data. Here's the basic structure of a CRSF packet:
9 13
10 14
15
+## board
11 16
17
+- [[SDR1125-dat]] - [[CRSF-dat]]
12 18
13 19
14 20
SDK-dat/ESP-SDK-dat/ESP8266-SDK-dat/ESP8266-SDK-dat.md
... ...
@@ -1,6 +1,9 @@
1 1
2 2
# ESP8266-SDK-dat
3 3
4
+- [[esp866-code-dat]] - [[ESP8266-SDK-dat]] - [[ESP-dat]]
5
+
6
+
4 7
- [[esp-idf-dat]] - [[ESP-dat]] - [[esp-sdk-dat]] - [[esptool-dat]]
5 8
6 9
- [[ESP8266-HDK-dat]]
code-dat/esp866-code-dat/ESP8266-WIFI-motor-1/ESP8266-WIFI-motor-1.ino
... ...
@@ -0,0 +1,283 @@
1
+#include <ESP8266WiFi.h>
2
+#include <ESP8266WebServer.h>
3
+
4
+// WiFi AP settings (fixed IP)
5
+const char *ssid = "MotorAP";
6
+const char *password = "motorpass"; // set to "" for open AP
7
+IPAddress apIP(192, 168, 4, 1);
8
+IPAddress netMsk(255, 255, 255, 0);
9
+
10
+// Define pins for motor control
11
+// Motor 1 (Left)
12
+const int M1_IN1 = 4;
13
+const int M1_IN2 = 5;
14
+// Motor 2 (Right)
15
+const int M2_IN1 = 0;
16
+const int M2_IN2 = 2;
17
+
18
+int carSpeed = 200; // 0..255 (Base Speed)
19
+int minSpeed = 100; // Minimum speed to avoid stalling
20
+int turnDiff = 85; // Increased for more "agility" (sharper turns)
21
+int carAction = 0; // 0: stop, 1: forward, 2: backward, 3: left, 4: right
22
+unsigned long lastCommandTime = 0;
23
+const unsigned long SAFETY_TIMEOUT = 300; // Even tighter for high responsiveness
24
+
25
+int batteryS = 3; // Default 3S (11.1V)
26
+
27
+ESP8266WebServer server(80);
28
+
29
+int getCompensatedSpeed(int baseSpeed) {
30
+ if (baseSpeed == 0) return 0;
31
+ // Simple inverse scaling:
32
+ // If it's 3S (11.1V), we scale DOWN the speed compared to 2S (7.4V)
33
+ // Scale factor = 7.4 / 11.1 = ~0.66
34
+ if (batteryS == 3) {
35
+ return (int)(baseSpeed * 0.66);
36
+ }
37
+ return baseSpeed; // Use raw speed for 2S
38
+}
39
+
40
+void applyMotorControl()
41
+{
42
+ int leftSpeed = 0;
43
+ int rightSpeed = 0;
44
+
45
+ int compensatedSpeed = getCompensatedSpeed(carSpeed);
46
+ int compensatedTurnDiff = getCompensatedSpeed(turnDiff);
47
+
48
+ // Helper to ensure motor gets enough power or is OFF
49
+ auto normalizeSpeed = [&](int s) {
50
+ if (s <= 0) return 0;
51
+ if (s < minSpeed) return minSpeed;
52
+ if (s > 255) return 255;
53
+ return s;
54
+ };
55
+
56
+ switch (carAction)
57
+ {
58
+ case 0: // Stop
59
+ leftSpeed = rightSpeed = 0;
60
+ break;
61
+ case 1: // Forward
62
+ leftSpeed = rightSpeed = compensatedSpeed;
63
+ break;
64
+ case 2: // Backward
65
+ leftSpeed = rightSpeed = -compensatedSpeed;
66
+ break;
67
+ case 3: // Spin Left
68
+ leftSpeed = -compensatedSpeed;
69
+ rightSpeed = compensatedSpeed;
70
+ break;
71
+ case 4: // Spin Right
72
+ leftSpeed = compensatedSpeed;
73
+ rightSpeed = -compensatedSpeed;
74
+ break;
75
+ case 5: // Forward Left (Curve) - Swapped
76
+ leftSpeed = compensatedSpeed + compensatedTurnDiff;
77
+ rightSpeed = compensatedSpeed - compensatedTurnDiff;
78
+ break;
79
+ case 6: // Forward Right (Curve) - Swapped
80
+ leftSpeed = compensatedSpeed - compensatedTurnDiff;
81
+ rightSpeed = compensatedSpeed + compensatedTurnDiff;
82
+ break;
83
+ case 7: // Backward Left (Curve)
84
+ leftSpeed = -(compensatedSpeed + compensatedTurnDiff);
85
+ rightSpeed = -(compensatedSpeed - compensatedTurnDiff);
86
+ break;
87
+ case 8: // Backward Right (Curve)
88
+ leftSpeed = -(compensatedSpeed - compensatedTurnDiff);
89
+ rightSpeed = -(compensatedSpeed + compensatedTurnDiff);
90
+ break;
91
+ default:
92
+ leftSpeed = rightSpeed = 0;
93
+ break;
94
+ }
95
+
96
+ // Apply Left Motor
97
+ int absL = abs(leftSpeed);
98
+ int finalL = normalizeSpeed(absL);
99
+ if (leftSpeed > 0) {
100
+ analogWrite(M1_IN1, finalL);
101
+ digitalWrite(M1_IN2, LOW);
102
+ } else if (leftSpeed < 0) {
103
+ digitalWrite(M1_IN1, LOW);
104
+ analogWrite(M1_IN2, finalL);
105
+ } else {
106
+ digitalWrite(M1_IN1, LOW);
107
+ digitalWrite(M1_IN2, LOW);
108
+ }
109
+
110
+ // Apply Right Motor
111
+ int absR = abs(rightSpeed);
112
+ int finalR = normalizeSpeed(absR);
113
+ if (rightSpeed > 0) {
114
+ analogWrite(M2_IN1, finalR);
115
+ digitalWrite(M2_IN2, LOW);
116
+ } else if (rightSpeed < 0) {
117
+ digitalWrite(M2_IN1, LOW);
118
+ analogWrite(M2_IN2, finalR);
119
+ } else {
120
+ digitalWrite(M2_IN1, LOW);
121
+ digitalWrite(M2_IN2, LOW);
122
+ }
123
+}
124
+
125
+String pageRoot()
126
+{
127
+ String html = "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">";
128
+ html += "<style>";
129
+ html += "body { font-family: sans-serif; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; background: #f0f0f0; }";
130
+ html += ".btn { width: 80px; height: 80px; margin: 10px; border-radius: 15px; border: none; background: #3498db; color: white; font-size: 24px; font-weight: bold; cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent; box-shadow: 0 4px #2980b9; }";
131
+ html += ".btn:active { background: #2980b9; box-shadow: 0 2px #1c5982; transform: translateY(2px); }";
132
+ html += ".stop-btn { background: #e74c3c; box-shadow: 0 4px #c0392b; }";
133
+ html += ".stop-btn:active { background: #c0392b; box-shadow: 0 2px #962d22; }";
134
+ html += ".row { display: flex; justify-content: center; }";
135
+ html += ".speed-container { margin-top: 20px; width: 80%; }";
136
+ html += "input[type=range] { width: 100%; height: 25px; cursor: pointer; }";
137
+ html += "select { padding: 8px; font-size: 16px; border-radius: 5px; }";
138
+ html += "</style></head><body>";
139
+ html += "<h2>Motor Control</h2>";
140
+
141
+ auto btnHtml = [&](int act, String icon) {
142
+ String s_act = String(act);
143
+ return " <button class='btn' onmousedown=\"setAction(" + s_act + ", event)\" ontouchstart=\"setAction(" + s_act + ", event)\" "
144
+ "onmouseup=\"setAction(0, event)\" onmouseleave=\"setAction(0, event)\" ontouchend=\"setAction(0, event)\" ontouchcancel=\"setAction(0, event)\">" + icon + "</button>";
145
+ };
146
+
147
+ html += "<div class='row'>";
148
+ html += btnHtml(5, "&#8598;");
149
+ html += btnHtml(1, "&#8593;");
150
+ html += btnHtml(6, "&#8599;");
151
+ html += "</div>";
152
+
153
+ html += "<div class='row'>";
154
+ html += btnHtml(3, "&#8592;");
155
+ html += " <button class='btn stop-btn' onclick=\"setAction(0, event)\" ontouchstart=\"setAction(0, event)\">OFF</button>";
156
+ html += btnHtml(4, "&#8594;");
157
+ html += "</div>";
158
+
159
+ html += "<div class='row'>";
160
+ html += btnHtml(7, "&#8601;");
161
+ html += btnHtml(2, "&#8595;");
162
+ html += btnHtml(8, "&#8600;");
163
+ html += "</div>";
164
+
165
+ html += "<div class='speed-container'>";
166
+ html += " Speed: <span id='v'>" + String(carSpeed) + "</span>";
167
+ html += " <input type='range' id='s' min='100' max='255' value='" + String(carSpeed) + "' oninput='setSpeed(this.value)' />";
168
+ html += "</div>";
169
+
170
+ html += "<div class='speed-container'>";
171
+ html += " Battery Mode: <select onchange=\"setBattery(this.value)\">";
172
+ html += " <option value='2'" + String(batteryS == 2 ? " selected" : "") + ">2S (7.4V)</option>";
173
+ html += " <option value='3'" + String(batteryS == 3 ? " selected" : "") + ">3S (11.1V)</option>";
174
+ html += " </select>";
175
+ html += "</div>";
176
+
177
+ html += "<script>";
178
+ html += "let lastA = -1; let lastS = -1;";
179
+ html += "function setAction(a, e, f) { if(e) { e.preventDefault(); } if(!f && a == lastA && a != 0) return; lastA = a; fetch('/set?action=' + a).catch(e => console.error(e)); }";
180
+ html += "function setSpeed(s) { if(s == lastS) return; lastS = s; document.getElementById('v').innerText = s; fetch('/set?speed=' + s).catch(e => console.error(e)); }";
181
+ html += "function setBattery(b) { fetch('/set?batt=' + b); }";
182
+ html += "setInterval(() => { if(lastA > 0) setAction(lastA, null, true); }, 100);"; // "Pro" agility: 100ms heartbeat
183
+ html += "</script></body></html>";
184
+ return html;
185
+}
186
+
187
+void handleRoot()
188
+{
189
+ server.send(200, "text/html", pageRoot());
190
+}
191
+
192
+void handleSet()
193
+{
194
+ server.client().setNoDelay(true); // Disable Nagle's algorithm for faster response
195
+ lastCommandTime = millis(); // Refresh safety watchdog
196
+ if (server.hasArg("action"))
197
+ {
198
+ carAction = server.arg("action").toInt();
199
+ }
200
+ if (server.hasArg("speed"))
201
+ {
202
+ carSpeed = server.arg("speed").toInt();
203
+ carSpeed = constrain(carSpeed, 0, 255);
204
+ }
205
+ if (server.hasArg("batt"))
206
+ {
207
+ batteryS = server.arg("batt").toInt();
208
+ }
209
+ applyMotorControl();
210
+ server.send(200, "text/plain", "OK");
211
+}
212
+
213
+void handleStatus()
214
+{
215
+ String status = "Action: " + String(carAction) + ", Speed: " + String(carSpeed) + ", Batt: " + String(batteryS) + "S";
216
+ server.send(200, "text/plain", status);
217
+}
218
+
219
+void setup()
220
+{
221
+ // Initialize pins
222
+ pinMode(M1_IN1, OUTPUT);
223
+ pinMode(M1_IN2, OUTPUT);
224
+ pinMode(M2_IN1, OUTPUT);
225
+ pinMode(M2_IN2, OUTPUT);
226
+
227
+ // Initialize motors to off
228
+ digitalWrite(M1_IN1, LOW);
229
+ digitalWrite(M1_IN2, LOW);
230
+ digitalWrite(M2_IN1, LOW);
231
+ digitalWrite(M2_IN2, LOW);
232
+
233
+ // Set PWM frequency for DRV8871 (supports up to 200kHz, but 20kHz is standard for silence and efficiency)
234
+ analogWriteFreq(20000);
235
+
236
+ Serial.begin(115200);
237
+ delay(100);
238
+
239
+ Serial.println("Test...");
240
+ delay(1000);
241
+ Serial.println("Test...");
242
+ delay(1000);
243
+ Serial.println("Test...");
244
+ delay(1000);
245
+ // Configure AP with fixed IP
246
+ WiFi.softAPConfig(apIP, apIP, netMsk);
247
+ WiFi.softAP(ssid, password);
248
+
249
+ IPAddress myIP = WiFi.softAPIP();
250
+ Serial.print("AP IP address: ");
251
+ Serial.println(myIP);
252
+
253
+ // Configure server routes
254
+ server.on("/", handleRoot);
255
+ server.on("/set", handleSet);
256
+ server.on("/status", handleStatus);
257
+ server.begin();
258
+ Serial.println("HTTP server started");
259
+
260
+ // Ensure PWM range 0-255
261
+ analogWriteRange(255);
262
+
263
+ // Apply initial motor state
264
+ applyMotorControl();
265
+}
266
+
267
+void loop()
268
+{
269
+ server.handleClient();
270
+
271
+ // Safety Watchdog: Stop motors if no command received for > 1 second
272
+ if (carAction != 0 && (millis() - lastCommandTime > SAFETY_TIMEOUT)) {
273
+ carAction = 0;
274
+ applyMotorControl();
275
+ Serial.println("Safety Timeout: Motors stopped");
276
+ }
277
+
278
+ delay(10);
279
+}
280
+
281
+
282
+
283
+
code-dat/esp866-code-dat/ESP8266-WIFI-motor-1/features.md
... ...
@@ -0,0 +1,32 @@
1
+# ESP8266 WiFi Motor Chassis Features
2
+
3
+## 1. Directional Control (9-Way)
4
+- **8 Directions**: Full support for Forward, Backward, Left, Right, and all four diagonal directions (Forward-Left, Forward-Right, Backward-Left, Backward-Right).
5
+- **Dedicated Stop**: Immediate halt on button release and a centralized "OFF" emergency stop button.
6
+
7
+## 2. Advanced Motor Driving
8
+- **Differential Steering**: Implements $Base \pm Offset$ logic for smooth, proportional turning during diagonal movement and pivot rotation.
9
+- **Stall Protection**: Enforces a `minSpeed` floor (100 PWM) to ensure motors maintain torque at low speeds.
10
+- **PWM Optimization**: Optimized for high-frequency (20kHz) PWM modulation for smooth speed control.
11
+
12
+## 3. Safety & Reliability
13
+- **Software Watchdog**: A hardware-safe timeout system stops the motors if no command is received within **500ms**, preventing runaway cars in case of WiFi disconnect.
14
+- **Active Heartbeat**: The client browser sends a "keep-alive" signal every **200ms** while any button is held, ensuring seamless motion through minor signal jitters.
15
+- **Interface Sanity**: Prevents "ghost" presses with event `preventDefault()` and stops motors automatically if the browser window loses focus (`blur` event).
16
+
17
+## 4. Power Management
18
+- **Battery Compensation**: Selectable modes for **2S (7.4V)** and **3S (11.1V)** battery packs.
19
+- **Voltage Scaling**: Automatically reduces PWM duty cycle in 3S mode (scaling factor $\approx 0.66$) to match 2S speed levels and protect motors from over-voltage.
20
+
21
+## 5. Web Interface & Connectivity
22
+- **Standalone Hotspot**: Creates its own WiFi Access Point (`MotorAP`) for direct control without an external router.
23
+- **Responsive Web UI**: A mobile-first controller interface with large touch-friendly buttons and a real-time speed slider.
24
+- **Low Latency**: Lightweight HTTP GET handlers for near-instant control responses.
25
+
26
+## 6. Technical Specifications (Default)
27
+- **Controller**: ESP8266
28
+- **Motor Pins**:
29
+ - Left (M1): Pins 4, 5
30
+ - Right (M2): Pins 0, 2
31
+- **Default Speed**: 200/255
32
+- **Safety Window**: 500ms
code-dat/esp866-code-dat/esp8266-elrs-drv8871-2-1/esp8266-elrs-drv8871-2-1.ino
... ...
@@ -0,0 +1,138 @@
1
+
2
+#include <SoftwareSerial.h>
3
+
4
+/*
5
+ * ELRS Motor Control Demo for ESP8266
6
+ *
7
+ * Hardware Setup:
8
+ * - ELRS Receiver: RX -> IO13, TX -> IO12 (SoftwareSerial)
9
+ * - Motor 1 (Left): IN1 -> IO4, IN2 -> IO5
10
+ * - Motor 2 (Right): IN1 -> IO0, IN2 -> IO2
11
+ * - DRV8871 pins are externally pulled-up, so active LOW for driving.
12
+ */
13
+
14
+// Motor 1 (Left)
15
+const int M1_IN1 = 4;
16
+const int M1_IN2 = 5;
17
+// Motor 2 (Right)
18
+const int M2_IN1 = 0;
19
+const int M2_IN2 = 2;
20
+
21
+// CRSF Protocol Definitions
22
+#define CRSF_ADDR_MODULE 0xEE
23
+#define CRSF_FRAMETYPE_RC_CHANNELS_PACKED 0x16
24
+
25
+SoftwareSerial elrsSerial(13, 12); // RX, TX
26
+
27
+void setup() {
28
+ Serial.begin(115200);
29
+ elrsSerial.begin(420000); // CRSF standard baud rate is 420k
30
+
31
+ pinMode(M1_IN1, OUTPUT);
32
+ pinMode(M1_IN2, OUTPUT);
33
+ pinMode(M2_IN1, OUTPUT);
34
+ pinMode(M2_IN2, OUTPUT);
35
+
36
+ // Initialize motors to STOP (HIGH because of external pull-up)
37
+ digitalWrite(M1_IN1, HIGH);
38
+ digitalWrite(M1_IN2, HIGH);
39
+ digitalWrite(M2_IN1, HIGH);
40
+ digitalWrite(M2_IN2, HIGH);
41
+
42
+ Serial.println("ELRS DRV8871 Motor Control Initialized.");
43
+}
44
+
45
+void stopMotors() {
46
+ digitalWrite(M1_IN1, HIGH);
47
+ digitalWrite(M1_IN2, HIGH);
48
+ digitalWrite(M2_IN1, HIGH);
49
+ digitalWrite(M2_IN2, HIGH);
50
+}
51
+
52
+void driveMotor(int in1, int in2, int speed) {
53
+ // speed: -100 to 100
54
+ if (speed > 10) {
55
+ // Forward (using PWM for speed control, since pins are pulled up, we pull LOW)
56
+ analogWrite(in1, 255 - map(speed, 0, 100, 0, 255));
57
+ digitalWrite(in2, HIGH);
58
+ } else if (speed < -10) {
59
+ // Reverse
60
+ digitalWrite(in1, HIGH);
61
+ analogWrite(in2, 255 - map(abs(speed), 0, 100, 0, 255));
62
+ } else {
63
+ // Stop
64
+ digitalWrite(in1, HIGH);
65
+ digitalWrite(in2, HIGH);
66
+ }
67
+}
68
+
69
+void loop() {
70
+ // Debug serial input from ELRS even if not a full packet
71
+ static unsigned long lastRawDebug = 0;
72
+ if (elrsSerial.available() && millis() - lastRawDebug > 1000) {
73
+ lastRawDebug = millis();
74
+ Serial.print("ELRS Serial Bytes Available: ");
75
+ Serial.println(elrsSerial.available());
76
+ }
77
+
78
+ if (elrsSerial.available()) {
79
+ uint8_t header = elrsSerial.read();
80
+ if (header == CRSF_ADDR_MODULE) {
81
+ uint8_t len = elrsSerial.read();
82
+ uint8_t type = elrsSerial.read();
83
+
84
+ if (type == CRSF_FRAMETYPE_RC_CHANNELS_PACKED) {
85
+ uint8_t buffer[22];
86
+ elrsSerial.readBytes(buffer, 22);
87
+
88
+ // Debug Raw Packet
89
+ static unsigned long lastHexDebug = 0;
90
+ if (millis() - lastHexDebug > 500) {
91
+ lastHexDebug = millis();
92
+ Serial.print("Raw Hex: ");
93
+ Serial.print(header, HEX); Serial.print(" ");
94
+ Serial.print(len, HEX); Serial.print(" ");
95
+ Serial.print(type, HEX); Serial.print(" ");
96
+ for(int i=0; i<22; i++) {
97
+ if(buffer[i] < 0x10) Serial.print("0");
98
+ Serial.print(buffer[i], HEX); Serial.print(" ");
99
+ }
100
+ Serial.println();
101
+ }
102
+
103
+ // Simple CRSF channel decoding (11 bits per channel)
104
+ // Channel 1: Roll, Channel 2: Pitch, Channel 3: Throttle, Channel 4: Yaw
105
+ int ch1 = (buffer[0] | buffer[1] << 8) & 0x07FF;
106
+ int ch2 = (buffer[1] >> 3 | buffer[2] << 5) & 0x07FF;
107
+ int ch3 = (buffer[2] >> 6 | buffer[3] << 2 | buffer[4] << 10) & 0x07FF;
108
+ int ch4 = (buffer[4] >> 1 | buffer[5] << 7) & 0x07FF;
109
+
110
+ // Map ELRS channels (typically 172-1811, center 992) to -100 to 100
111
+ int throttle = map(ch3, 172, 1811, -100, 100);
112
+ int steering = map(ch1, 172, 1811, -100, 100);
113
+
114
+ // Simple Differential Drive logic
115
+ int leftSpeed = throttle + steering;
116
+ int rightSpeed = throttle - steering;
117
+
118
+ leftSpeed = constrain(leftSpeed, -100, 100);
119
+ rightSpeed = constrain(rightSpeed, -100, 100);
120
+
121
+ // Debugging output
122
+ static unsigned long lastDebug = 0;
123
+ if (millis() - lastDebug > 100) {
124
+ lastDebug = millis();
125
+ Serial.print("CH1: "); Serial.print(ch1);
126
+ Serial.print(" | CH3: "); Serial.print(ch3);
127
+ Serial.print(" | Thr: "); Serial.print(throttle);
128
+ Serial.print(" | Str: "); Serial.print(steering);
129
+ Serial.print(" | L: "); Serial.print(leftSpeed);
130
+ Serial.print(" | R: "); Serial.println(rightSpeed);
131
+ }
132
+
133
+ driveMotor(M1_IN1, M1_IN2, leftSpeed);
134
+ driveMotor(M2_IN1, M2_IN2, rightSpeed);
135
+ }
136
+ }
137
+ }
138
+}
code-dat/esp866-code-dat/esp866-code-dat.md
... ...
@@ -0,0 +1,40 @@
1
+
2
+
3
+# esp866-code-dat
4
+
5
+- [[esp866-code-dat]] - [[ESP8266-SDK-dat]] - [[ESP-dat]]
6
+
7
+- [[CRSF-dat]]
8
+
9
+## design
10
+
11
+slow software serial - can not be more than 115200 baud, otherwise the data will be corrupted.
12
+
13
+The data you shared is raw CRSF binary packets, but they look slightly corrupted or "jittery," which is very common when using SoftwareSerial at 115200 on an ESP8266.
14
+
15
+- [[CRSF-dat]]
16
+
17
+ 0B 56 FE D8 10 0B 56 FE D8 10 0B 52 FE 84 D8 10
18
+ 0B 52 FE D8 10 0B 56 FE D8 10 0B 52 FF D8 10 0B
19
+ 52 FF D9 10 99 FF 44 D8 10 0B 56 FE D8 10 0B 52
20
+ FF D8 10 0B 56 FE D8 10 0B 56 FF 25 26 12 4B A2
21
+ D8 10 0B 52 FE D8 10 0B 56 FE A6 12 4B D8 10 99
22
+ FF D8 10 0B 56 FE E4 26 12 4B A2 A6 12 4B D8 10
23
+ 0B 52 FE D8 10 0B 56 FE D8 10 0B 56 FF 84 D8 10
24
+ 99 FF D8 10 0B 52 FF D8 10 0B 56 FE A6 12 4B A4
25
+ D8 10 0B 56 FE D8 10 FF D8 10 0B 52 FE D8 10 0B
26
+ 56 FE D8 10 0B 56 FE 44 12 4B FF D8 10 0B 52 FF
27
+ D8 10 0B 56 FF D9 10 FE D8 10 0B 56 FF 80 D8 10
28
+ 0B 56 FF D8 10 0B 56 FF 12 4B 54 FF 84 D8 10 0B
29
+ 52 FF D8 10 0B 52 FF D8 10 0B 52 FF D8 10 0B 56
30
+ FF D9 10 FE C4 D9 10 0B 56 FF D8 10 FE 12 4B 02
31
+ 4E D8 10 0B D2 FF D8 10 FE A2 D8 10 0B 52 FF D8
32
+ 10 0B 56 FF D8 10 FE D8 10 0B 56 FF 00 80 D8 10
33
+ 0B 56 FE D8 10 0B 56 FE D8 10 0B 52 FE D8 10 FF
34
+ D8 10 0B 56 FE 80 D8 10 0B 52 FE D8 10 0B 56 FE
35
+ D8 10 0B 52 FE D8 10 0B 52 FE D8 10 99 FF 40 D8
36
+
37
+
38
+## ref
39
+
40
+
code-dat/esp866-code-dat/printAllChannels/printAllChannels.ino
... ...
@@ -0,0 +1,37 @@
1
+#include <AlfredoCRSF.h>
2
+#include <SoftwareSerial.h>
3
+
4
+#define PIN_RX 13
5
+#define PIN_TX 12
6
+
7
+// Set up a new SoftwareSerial object
8
+SoftwareSerial crsfSerial(PIN_RX, PIN_TX);
9
+AlfredoCRSF crsf;
10
+
11
+void setup()
12
+{
13
+ Serial.begin(115200);
14
+ Serial.println("COM Serial initialized");
15
+
16
+ crsfSerial.begin(115200);
17
+
18
+ crsf.begin(crsfSerial);
19
+}
20
+
21
+void loop()
22
+{
23
+ // Must call crsf.update() in loop() to process data
24
+ crsf.update();
25
+ printChannels();
26
+}
27
+
28
+//Use crsf.getChannel(x) to get us channel values (1-16).
29
+void printChannels()
30
+{
31
+ for (int ChannelNum = 1; ChannelNum <= 16; ChannelNum++)
32
+ {
33
+ Serial.print(crsf.getChannel(ChannelNum));
34
+ Serial.print(", ");
35
+ }
36
+ Serial.println(" ");
37
+}
... ...
\ No newline at end of file
code-dat/esp866-code-dat/soft-serial-debug-2/soft-serial-debug-2.ino
... ...
@@ -0,0 +1,37 @@
1
+#include <SoftwareSerial.h>
2
+SoftwareSerial s(13, 12);
3
+uint8_t buffer[64];
4
+int p = 0;
5
+unsigned long t = 0;
6
+void setup() {
7
+ pinMode(13, INPUT_PULLUP); // Enable internal pull-up on RX pin
8
+ Serial.begin(115200);
9
+ s.begin(115200);
10
+ Serial.println("\n--- CRSF V5 Filtered ---");
11
+}
12
+void loop() {
13
+ while (s.available()) {
14
+ uint8_t v = s.read();
15
+ if (p == 0) {
16
+ if (v == 0xC4 || v == 0xC8 || v == 0xEE) p = 1;
17
+ } else {
18
+ buffer[p++] = v;
19
+ if (p >= 26) {
20
+ unsigned int rc[4];
21
+ rc[0] = (buffer[3] | buffer[4] << 8) & 0x7FF;
22
+ rc[1] = (buffer[4] >> 3 | buffer[5] << 5) & 0x7FF;
23
+ rc[2] = (buffer[5] >> 6 | buffer[6] << 2 | buffer[7] << 10) & 0x7FF;
24
+ rc[3] = (buffer[7] >> 1 | buffer[8] << 7) & 0x7FF;
25
+ bool ok = true;
26
+ for(int i=0; i<4; i++) if(rc[i] < 170 || rc[i] > 1820) ok = false;
27
+ if (ok) { // Removed the 100ms delay for faster output
28
+ Serial.print("CH1:"); Serial.print(rc[0]);
29
+ Serial.print(" CH2:"); Serial.print(rc[1]);
30
+ Serial.print(" CH3:"); Serial.print(rc[2]);
31
+ Serial.print(" CH4:"); Serial.println(rc[3]);
32
+ }
33
+ p = 0;
34
+ }
35
+ }
36
+ }
37
+}
code-dat/esp866-code-dat/soft-serial-debug/soft-serial-debug.ino
... ...
@@ -0,0 +1,28 @@
1
+#include <SoftwareSerial.h>
2
+
3
+SoftwareSerial soft(13, 12); // RX, TX
4
+
5
+void setup() {
6
+ Serial.begin(115200);
7
+ soft.begin(115200);
8
+ Serial.println("\n--- CRSF Raw Hex Debugger ---");
9
+}
10
+
11
+void loop() {
12
+ if (soft.available()) {
13
+ uint8_t incomingByte = soft.read();
14
+
15
+ // Print as Hex
16
+ if (incomingByte < 0x10) Serial.print("0");
17
+ Serial.print(incomingByte, HEX);
18
+ Serial.print(" ");
19
+
20
+ // Newline every 16 bytes
21
+ static int byteCount = 0;
22
+ byteCount++;
23
+ if (byteCount >= 16) {
24
+ Serial.println();
25
+ byteCount = 0;
26
+ }
27
+ }
28
+}
... ...
\ No newline at end of file
code-dat/esp866-dat/ESP8266-WIFI-motor-1/ESP8266-WIFI-motor-1.ino
... ...
@@ -1,283 +0,0 @@
1
-#include <ESP8266WiFi.h>
2
-#include <ESP8266WebServer.h>
3
-
4
-// WiFi AP settings (fixed IP)
5
-const char *ssid = "MotorAP";
6
-const char *password = "motorpass"; // set to "" for open AP
7
-IPAddress apIP(192, 168, 4, 1);
8
-IPAddress netMsk(255, 255, 255, 0);
9
-
10
-// Define pins for motor control
11
-// Motor 1 (Left)
12
-const int M1_IN1 = 4;
13
-const int M1_IN2 = 5;
14
-// Motor 2 (Right)
15
-const int M2_IN1 = 0;
16
-const int M2_IN2 = 2;
17
-
18
-int carSpeed = 200; // 0..255 (Base Speed)
19
-int minSpeed = 100; // Minimum speed to avoid stalling
20
-int turnDiff = 85; // Increased for more "agility" (sharper turns)
21
-int carAction = 0; // 0: stop, 1: forward, 2: backward, 3: left, 4: right
22
-unsigned long lastCommandTime = 0;
23
-const unsigned long SAFETY_TIMEOUT = 300; // Even tighter for high responsiveness
24
-
25
-int batteryS = 3; // Default 3S (11.1V)
26
-
27
-ESP8266WebServer server(80);
28
-
29
-int getCompensatedSpeed(int baseSpeed) {
30
- if (baseSpeed == 0) return 0;
31
- // Simple inverse scaling:
32
- // If it's 3S (11.1V), we scale DOWN the speed compared to 2S (7.4V)
33
- // Scale factor = 7.4 / 11.1 = ~0.66
34
- if (batteryS == 3) {
35
- return (int)(baseSpeed * 0.66);
36
- }
37
- return baseSpeed; // Use raw speed for 2S
38
-}
39
-
40
-void applyMotorControl()
41
-{
42
- int leftSpeed = 0;
43
- int rightSpeed = 0;
44
-
45
- int compensatedSpeed = getCompensatedSpeed(carSpeed);
46
- int compensatedTurnDiff = getCompensatedSpeed(turnDiff);
47
-
48
- // Helper to ensure motor gets enough power or is OFF
49
- auto normalizeSpeed = [&](int s) {
50
- if (s <= 0) return 0;
51
- if (s < minSpeed) return minSpeed;
52
- if (s > 255) return 255;
53
- return s;
54
- };
55
-
56
- switch (carAction)
57
- {
58
- case 0: // Stop
59
- leftSpeed = rightSpeed = 0;
60
- break;
61
- case 1: // Forward
62
- leftSpeed = rightSpeed = compensatedSpeed;
63
- break;
64
- case 2: // Backward
65
- leftSpeed = rightSpeed = -compensatedSpeed;
66
- break;
67
- case 3: // Spin Left
68
- leftSpeed = -compensatedSpeed;
69
- rightSpeed = compensatedSpeed;
70
- break;
71
- case 4: // Spin Right
72
- leftSpeed = compensatedSpeed;
73
- rightSpeed = -compensatedSpeed;
74
- break;
75
- case 5: // Forward Left (Curve) - Swapped
76
- leftSpeed = compensatedSpeed + compensatedTurnDiff;
77
- rightSpeed = compensatedSpeed - compensatedTurnDiff;
78
- break;
79
- case 6: // Forward Right (Curve) - Swapped
80
- leftSpeed = compensatedSpeed - compensatedTurnDiff;
81
- rightSpeed = compensatedSpeed + compensatedTurnDiff;
82
- break;
83
- case 7: // Backward Left (Curve)
84
- leftSpeed = -(compensatedSpeed + compensatedTurnDiff);
85
- rightSpeed = -(compensatedSpeed - compensatedTurnDiff);
86
- break;
87
- case 8: // Backward Right (Curve)
88
- leftSpeed = -(compensatedSpeed - compensatedTurnDiff);
89
- rightSpeed = -(compensatedSpeed + compensatedTurnDiff);
90
- break;
91
- default:
92
- leftSpeed = rightSpeed = 0;
93
- break;
94
- }
95
-
96
- // Apply Left Motor
97
- int absL = abs(leftSpeed);
98
- int finalL = normalizeSpeed(absL);
99
- if (leftSpeed > 0) {
100
- analogWrite(M1_IN1, finalL);
101
- digitalWrite(M1_IN2, LOW);
102
- } else if (leftSpeed < 0) {
103
- digitalWrite(M1_IN1, LOW);
104
- analogWrite(M1_IN2, finalL);
105
- } else {
106
- digitalWrite(M1_IN1, LOW);
107
- digitalWrite(M1_IN2, LOW);
108
- }
109
-
110
- // Apply Right Motor
111
- int absR = abs(rightSpeed);
112
- int finalR = normalizeSpeed(absR);
113
- if (rightSpeed > 0) {
114
- analogWrite(M2_IN1, finalR);
115
- digitalWrite(M2_IN2, LOW);
116
- } else if (rightSpeed < 0) {
117
- digitalWrite(M2_IN1, LOW);
118
- analogWrite(M2_IN2, finalR);
119
- } else {
120
- digitalWrite(M2_IN1, LOW);
121
- digitalWrite(M2_IN2, LOW);
122
- }
123
-}
124
-
125
-String pageRoot()
126
-{
127
- String html = "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">";
128
- html += "<style>";
129
- html += "body { font-family: sans-serif; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; background: #f0f0f0; }";
130
- html += ".btn { width: 80px; height: 80px; margin: 10px; border-radius: 15px; border: none; background: #3498db; color: white; font-size: 24px; font-weight: bold; cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent; box-shadow: 0 4px #2980b9; }";
131
- html += ".btn:active { background: #2980b9; box-shadow: 0 2px #1c5982; transform: translateY(2px); }";
132
- html += ".stop-btn { background: #e74c3c; box-shadow: 0 4px #c0392b; }";
133
- html += ".stop-btn:active { background: #c0392b; box-shadow: 0 2px #962d22; }";
134
- html += ".row { display: flex; justify-content: center; }";
135
- html += ".speed-container { margin-top: 20px; width: 80%; }";
136
- html += "input[type=range] { width: 100%; height: 25px; cursor: pointer; }";
137
- html += "select { padding: 8px; font-size: 16px; border-radius: 5px; }";
138
- html += "</style></head><body>";
139
- html += "<h2>Motor Control</h2>";
140
-
141
- auto btnHtml = [&](int act, String icon) {
142
- String s_act = String(act);
143
- return " <button class='btn' onmousedown=\"setAction(" + s_act + ", event)\" ontouchstart=\"setAction(" + s_act + ", event)\" "
144
- "onmouseup=\"setAction(0, event)\" onmouseleave=\"setAction(0, event)\" ontouchend=\"setAction(0, event)\" ontouchcancel=\"setAction(0, event)\">" + icon + "</button>";
145
- };
146
-
147
- html += "<div class='row'>";
148
- html += btnHtml(5, "&#8598;");
149
- html += btnHtml(1, "&#8593;");
150
- html += btnHtml(6, "&#8599;");
151
- html += "</div>";
152
-
153
- html += "<div class='row'>";
154
- html += btnHtml(3, "&#8592;");
155
- html += " <button class='btn stop-btn' onclick=\"setAction(0, event)\" ontouchstart=\"setAction(0, event)\">OFF</button>";
156
- html += btnHtml(4, "&#8594;");
157
- html += "</div>";
158
-
159
- html += "<div class='row'>";
160
- html += btnHtml(7, "&#8601;");
161
- html += btnHtml(2, "&#8595;");
162
- html += btnHtml(8, "&#8600;");
163
- html += "</div>";
164
-
165
- html += "<div class='speed-container'>";
166
- html += " Speed: <span id='v'>" + String(carSpeed) + "</span>";
167
- html += " <input type='range' id='s' min='100' max='255' value='" + String(carSpeed) + "' oninput='setSpeed(this.value)' />";
168
- html += "</div>";
169
-
170
- html += "<div class='speed-container'>";
171
- html += " Battery Mode: <select onchange=\"setBattery(this.value)\">";
172
- html += " <option value='2'" + String(batteryS == 2 ? " selected" : "") + ">2S (7.4V)</option>";
173
- html += " <option value='3'" + String(batteryS == 3 ? " selected" : "") + ">3S (11.1V)</option>";
174
- html += " </select>";
175
- html += "</div>";
176
-
177
- html += "<script>";
178
- html += "let lastA = -1; let lastS = -1;";
179
- html += "function setAction(a, e, f) { if(e) { e.preventDefault(); } if(!f && a == lastA && a != 0) return; lastA = a; fetch('/set?action=' + a).catch(e => console.error(e)); }";
180
- html += "function setSpeed(s) { if(s == lastS) return; lastS = s; document.getElementById('v').innerText = s; fetch('/set?speed=' + s).catch(e => console.error(e)); }";
181
- html += "function setBattery(b) { fetch('/set?batt=' + b); }";
182
- html += "setInterval(() => { if(lastA > 0) setAction(lastA, null, true); }, 100);"; // "Pro" agility: 100ms heartbeat
183
- html += "</script></body></html>";
184
- return html;
185
-}
186
-
187
-void handleRoot()
188
-{
189
- server.send(200, "text/html", pageRoot());
190
-}
191
-
192
-void handleSet()
193
-{
194
- server.client().setNoDelay(true); // Disable Nagle's algorithm for faster response
195
- lastCommandTime = millis(); // Refresh safety watchdog
196
- if (server.hasArg("action"))
197
- {
198
- carAction = server.arg("action").toInt();
199
- }
200
- if (server.hasArg("speed"))
201
- {
202
- carSpeed = server.arg("speed").toInt();
203
- carSpeed = constrain(carSpeed, 0, 255);
204
- }
205
- if (server.hasArg("batt"))
206
- {
207
- batteryS = server.arg("batt").toInt();
208
- }
209
- applyMotorControl();
210
- server.send(200, "text/plain", "OK");
211
-}
212
-
213
-void handleStatus()
214
-{
215
- String status = "Action: " + String(carAction) + ", Speed: " + String(carSpeed) + ", Batt: " + String(batteryS) + "S";
216
- server.send(200, "text/plain", status);
217
-}
218
-
219
-void setup()
220
-{
221
- // Initialize pins
222
- pinMode(M1_IN1, OUTPUT);
223
- pinMode(M1_IN2, OUTPUT);
224
- pinMode(M2_IN1, OUTPUT);
225
- pinMode(M2_IN2, OUTPUT);
226
-
227
- // Initialize motors to off
228
- digitalWrite(M1_IN1, LOW);
229
- digitalWrite(M1_IN2, LOW);
230
- digitalWrite(M2_IN1, LOW);
231
- digitalWrite(M2_IN2, LOW);
232
-
233
- // Set PWM frequency for DRV8871 (supports up to 200kHz, but 20kHz is standard for silence and efficiency)
234
- analogWriteFreq(20000);
235
-
236
- Serial.begin(115200);
237
- delay(100);
238
-
239
- Serial.println("Test...");
240
- delay(1000);
241
- Serial.println("Test...");
242
- delay(1000);
243
- Serial.println("Test...");
244
- delay(1000);
245
- // Configure AP with fixed IP
246
- WiFi.softAPConfig(apIP, apIP, netMsk);
247
- WiFi.softAP(ssid, password);
248
-
249
- IPAddress myIP = WiFi.softAPIP();
250
- Serial.print("AP IP address: ");
251
- Serial.println(myIP);
252
-
253
- // Configure server routes
254
- server.on("/", handleRoot);
255
- server.on("/set", handleSet);
256
- server.on("/status", handleStatus);
257
- server.begin();
258
- Serial.println("HTTP server started");
259
-
260
- // Ensure PWM range 0-255
261
- analogWriteRange(255);
262
-
263
- // Apply initial motor state
264
- applyMotorControl();
265
-}
266
-
267
-void loop()
268
-{
269
- server.handleClient();
270
-
271
- // Safety Watchdog: Stop motors if no command received for > 1 second
272
- if (carAction != 0 && (millis() - lastCommandTime > SAFETY_TIMEOUT)) {
273
- carAction = 0;
274
- applyMotorControl();
275
- Serial.println("Safety Timeout: Motors stopped");
276
- }
277
-
278
- delay(10);
279
-}
280
-
281
-
282
-
283
-
code-dat/esp866-dat/ESP8266-WIFI-motor-1/features.md
... ...
@@ -1,32 +0,0 @@
1
-# ESP8266 WiFi Motor Chassis Features
2
-
3
-## 1. Directional Control (9-Way)
4
-- **8 Directions**: Full support for Forward, Backward, Left, Right, and all four diagonal directions (Forward-Left, Forward-Right, Backward-Left, Backward-Right).
5
-- **Dedicated Stop**: Immediate halt on button release and a centralized "OFF" emergency stop button.
6
-
7
-## 2. Advanced Motor Driving
8
-- **Differential Steering**: Implements $Base \pm Offset$ logic for smooth, proportional turning during diagonal movement and pivot rotation.
9
-- **Stall Protection**: Enforces a `minSpeed` floor (100 PWM) to ensure motors maintain torque at low speeds.
10
-- **PWM Optimization**: Optimized for high-frequency (20kHz) PWM modulation for smooth speed control.
11
-
12
-## 3. Safety & Reliability
13
-- **Software Watchdog**: A hardware-safe timeout system stops the motors if no command is received within **500ms**, preventing runaway cars in case of WiFi disconnect.
14
-- **Active Heartbeat**: The client browser sends a "keep-alive" signal every **200ms** while any button is held, ensuring seamless motion through minor signal jitters.
15
-- **Interface Sanity**: Prevents "ghost" presses with event `preventDefault()` and stops motors automatically if the browser window loses focus (`blur` event).
16
-
17
-## 4. Power Management
18
-- **Battery Compensation**: Selectable modes for **2S (7.4V)** and **3S (11.1V)** battery packs.
19
-- **Voltage Scaling**: Automatically reduces PWM duty cycle in 3S mode (scaling factor $\approx 0.66$) to match 2S speed levels and protect motors from over-voltage.
20
-
21
-## 5. Web Interface & Connectivity
22
-- **Standalone Hotspot**: Creates its own WiFi Access Point (`MotorAP`) for direct control without an external router.
23
-- **Responsive Web UI**: A mobile-first controller interface with large touch-friendly buttons and a real-time speed slider.
24
-- **Low Latency**: Lightweight HTTP GET handlers for near-instant control responses.
25
-
26
-## 6. Technical Specifications (Default)
27
-- **Controller**: ESP8266
28
-- **Motor Pins**:
29
- - Left (M1): Pins 4, 5
30
- - Right (M2): Pins 0, 2
31
-- **Default Speed**: 200/255
32
-- **Safety Window**: 500ms
code-dat/esp866-dat/esp8266-elrs-drv8871-2-1/esp8266-elrs-drv8871-2-1.ino
... ...
@@ -1,138 +0,0 @@
1
-
2
-#include <SoftwareSerial.h>
3
-
4
-/*
5
- * ELRS Motor Control Demo for ESP8266
6
- *
7
- * Hardware Setup:
8
- * - ELRS Receiver: RX -> IO13, TX -> IO12 (SoftwareSerial)
9
- * - Motor 1 (Left): IN1 -> IO4, IN2 -> IO5
10
- * - Motor 2 (Right): IN1 -> IO0, IN2 -> IO2
11
- * - DRV8871 pins are externally pulled-up, so active LOW for driving.
12
- */
13
-
14
-// Motor 1 (Left)
15
-const int M1_IN1 = 4;
16
-const int M1_IN2 = 5;
17
-// Motor 2 (Right)
18
-const int M2_IN1 = 0;
19
-const int M2_IN2 = 2;
20
-
21
-// CRSF Protocol Definitions
22
-#define CRSF_ADDR_MODULE 0xEE
23
-#define CRSF_FRAMETYPE_RC_CHANNELS_PACKED 0x16
24
-
25
-SoftwareSerial elrsSerial(13, 12); // RX, TX
26
-
27
-void setup() {
28
- Serial.begin(115200);
29
- elrsSerial.begin(420000); // CRSF standard baud rate is 420k
30
-
31
- pinMode(M1_IN1, OUTPUT);
32
- pinMode(M1_IN2, OUTPUT);
33
- pinMode(M2_IN1, OUTPUT);
34
- pinMode(M2_IN2, OUTPUT);
35
-
36
- // Initialize motors to STOP (HIGH because of external pull-up)
37
- digitalWrite(M1_IN1, HIGH);
38
- digitalWrite(M1_IN2, HIGH);
39
- digitalWrite(M2_IN1, HIGH);
40
- digitalWrite(M2_IN2, HIGH);
41
-
42
- Serial.println("ELRS DRV8871 Motor Control Initialized.");
43
-}
44
-
45
-void stopMotors() {
46
- digitalWrite(M1_IN1, HIGH);
47
- digitalWrite(M1_IN2, HIGH);
48
- digitalWrite(M2_IN1, HIGH);
49
- digitalWrite(M2_IN2, HIGH);
50
-}
51
-
52
-void driveMotor(int in1, int in2, int speed) {
53
- // speed: -100 to 100
54
- if (speed > 10) {
55
- // Forward (using PWM for speed control, since pins are pulled up, we pull LOW)
56
- analogWrite(in1, 255 - map(speed, 0, 100, 0, 255));
57
- digitalWrite(in2, HIGH);
58
- } else if (speed < -10) {
59
- // Reverse
60
- digitalWrite(in1, HIGH);
61
- analogWrite(in2, 255 - map(abs(speed), 0, 100, 0, 255));
62
- } else {
63
- // Stop
64
- digitalWrite(in1, HIGH);
65
- digitalWrite(in2, HIGH);
66
- }
67
-}
68
-
69
-void loop() {
70
- // Debug serial input from ELRS even if not a full packet
71
- static unsigned long lastRawDebug = 0;
72
- if (elrsSerial.available() && millis() - lastRawDebug > 1000) {
73
- lastRawDebug = millis();
74
- Serial.print("ELRS Serial Bytes Available: ");
75
- Serial.println(elrsSerial.available());
76
- }
77
-
78
- if (elrsSerial.available()) {
79
- uint8_t header = elrsSerial.read();
80
- if (header == CRSF_ADDR_MODULE) {
81
- uint8_t len = elrsSerial.read();
82
- uint8_t type = elrsSerial.read();
83
-
84
- if (type == CRSF_FRAMETYPE_RC_CHANNELS_PACKED) {
85
- uint8_t buffer[22];
86
- elrsSerial.readBytes(buffer, 22);
87
-
88
- // Debug Raw Packet
89
- static unsigned long lastHexDebug = 0;
90
- if (millis() - lastHexDebug > 500) {
91
- lastHexDebug = millis();
92
- Serial.print("Raw Hex: ");
93
- Serial.print(header, HEX); Serial.print(" ");
94
- Serial.print(len, HEX); Serial.print(" ");
95
- Serial.print(type, HEX); Serial.print(" ");
96
- for(int i=0; i<22; i++) {
97
- if(buffer[i] < 0x10) Serial.print("0");
98
- Serial.print(buffer[i], HEX); Serial.print(" ");
99
- }
100
- Serial.println();
101
- }
102
-
103
- // Simple CRSF channel decoding (11 bits per channel)
104
- // Channel 1: Roll, Channel 2: Pitch, Channel 3: Throttle, Channel 4: Yaw
105
- int ch1 = (buffer[0] | buffer[1] << 8) & 0x07FF;
106
- int ch2 = (buffer[1] >> 3 | buffer[2] << 5) & 0x07FF;
107
- int ch3 = (buffer[2] >> 6 | buffer[3] << 2 | buffer[4] << 10) & 0x07FF;
108
- int ch4 = (buffer[4] >> 1 | buffer[5] << 7) & 0x07FF;
109
-
110
- // Map ELRS channels (typically 172-1811, center 992) to -100 to 100
111
- int throttle = map(ch3, 172, 1811, -100, 100);
112
- int steering = map(ch1, 172, 1811, -100, 100);
113
-
114
- // Simple Differential Drive logic
115
- int leftSpeed = throttle + steering;
116
- int rightSpeed = throttle - steering;
117
-
118
- leftSpeed = constrain(leftSpeed, -100, 100);
119
- rightSpeed = constrain(rightSpeed, -100, 100);
120
-
121
- // Debugging output
122
- static unsigned long lastDebug = 0;
123
- if (millis() - lastDebug > 100) {
124
- lastDebug = millis();
125
- Serial.print("CH1: "); Serial.print(ch1);
126
- Serial.print(" | CH3: "); Serial.print(ch3);
127
- Serial.print(" | Thr: "); Serial.print(throttle);
128
- Serial.print(" | Str: "); Serial.print(steering);
129
- Serial.print(" | L: "); Serial.print(leftSpeed);
130
- Serial.print(" | R: "); Serial.println(rightSpeed);
131
- }
132
-
133
- driveMotor(M1_IN1, M1_IN2, leftSpeed);
134
- driveMotor(M2_IN1, M2_IN2, rightSpeed);
135
- }
136
- }
137
- }
138
-}
code-dat/esp866-dat/printAllChannels/printAllChannels.ino
... ...
@@ -1,37 +0,0 @@
1
-#include <AlfredoCRSF.h>
2
-#include <SoftwareSerial.h>
3
-
4
-#define PIN_RX 13
5
-#define PIN_TX 12
6
-
7
-// Set up a new SoftwareSerial object
8
-SoftwareSerial crsfSerial(PIN_RX, PIN_TX);
9
-AlfredoCRSF crsf;
10
-
11
-void setup()
12
-{
13
- Serial.begin(115200);
14
- Serial.println("COM Serial initialized");
15
-
16
- crsfSerial.begin(115200);
17
-
18
- crsf.begin(crsfSerial);
19
-}
20
-
21
-void loop()
22
-{
23
- // Must call crsf.update() in loop() to process data
24
- crsf.update();
25
- printChannels();
26
-}
27
-
28
-//Use crsf.getChannel(x) to get us channel values (1-16).
29
-void printChannels()
30
-{
31
- for (int ChannelNum = 1; ChannelNum <= 16; ChannelNum++)
32
- {
33
- Serial.print(crsf.getChannel(ChannelNum));
34
- Serial.print(", ");
35
- }
36
- Serial.println(" ");
37
-}
... ...
\ No newline at end of file
code-dat/esp866-dat/soft-serial-debug-2/soft-serial-debug-2.ino
... ...
@@ -1,82 +0,0 @@
1
-#include <SoftwareSerial.h>
2
-
3
-// PIN 12 = RX, PIN 13 = TX
4
-SoftwareSerial soft(12, 13);
5
-
6
-uint8_t buffer[64];
7
-int bufPtr = 0;
8
-unsigned long lastByteTime = 0;
9
-unsigned long lastPrintTime = 0;
10
-
11
-void setup() {
12
- Serial.begin(115200);
13
- // Increase SoftwareSerial reliability by sticking to 115200
14
- soft.begin(115200);
15
- Serial.println("\n--- CRSF Debug V2 (Robust) ---");
16
-}
17
-
18
-void loop() {
19
- unsigned long now = millis();
20
-
21
- while (soft.available()) {
22
- uint8_t b = soft.read();
23
- lastByteTime = now;
24
-
25
- // 1. SYNC: Look for 0xC8 (Receiver Address)
26
- if (bufPtr == 0) {
27
- if (b == 0xC8) {
28
- buffer[bufPtr++] = b;
29
- }
30
- }
31
- // 2. LENGTH: Expecting 0x18 (24 bytes payload) for RC Channels
32
- else if (bufPtr == 1) {
33
- if (b == 0x18) {
34
- buffer[bufPtr++] = b;
35
- } else {
36
- bufPtr = 0; // Invalid length for channels, restart
37
- }
38
- }
39
- // 3. TYPE: Expecting 0x16 (RC Channels)
40
- else if (bufPtr == 2) {
41
- if (b == 0x16) {
42
- buffer[bufPtr++] = b;
43
- } else {
44
- bufPtr = 0; // Not a channel frame
45
- }
46
- }
47
- // 4. COLLECT DATA
48
- else {
49
- buffer[bufPtr++] = b;
50
-
51
- // CRSF RC packet is exactly 26 bytes: [Addr][Len][Type][22 bytes channels][CRC]
52
- if (bufPtr >= 26) {
53
- decodeAndPrint(buffer);
54
- bufPtr = 0;
55
- }
56
- }
57
- }
58
-
59
- // RECOVERY: If we got half a packet but no more data for 10ms, reset
60
- if (bufPtr > 0 && (now - lastByteTime > 10)) {
61
- bufPtr = 0;
62
- }
63
-}
64
-
65
-void decodeAndPrint(uint8_t* b) {
66
- // Only print every 100ms to reduce CPU load and let SoftwareSerial run smoothly
67
- if (millis() - lastPrintTime < 100) return;
68
- lastPrintTime = millis();
69
-
70
- unsigned int ch[4];
71
- // 11-bit decoding logic
72
- ch[0] = (b[3] | b[4] << 8) & 0x07FF;
73
- ch[1] = (b[4] >> 3 | b[5] << 5) & 0x07FF;
74
- ch[2] = (b[5] >> 6 | b[6] << 2 | b[7] << 10) & 0x07FF;
75
- ch[3] = (b[7] >> 1 | b[8] << 7) & 0x07FF;
76
-
77
- Serial.print("T:"); Serial.print(ch[2]); // Throttle usually CH3
78
- Serial.print(" R:"); Serial.print(ch[3]); // Yaw/Rudder
79
- Serial.print(" E:"); Serial.print(ch[1]); // Pitch/Elevator
80
- Serial.print(" A:"); Serial.print(ch[0]); // Roll/Aileron
81
- Serial.println();
82
-}
... ...
\ No newline at end of file
code-dat/esp866-dat/soft-serial-debug/soft-serial-debug.ino
... ...
@@ -1,28 +0,0 @@
1
-#include <SoftwareSerial.h>
2
-
3
-SoftwareSerial soft(13, 12); // RX, TX
4
-
5
-void setup() {
6
- Serial.begin(115200);
7
- soft.begin(115200);
8
- Serial.println("\n--- CRSF Raw Hex Debugger ---");
9
-}
10
-
11
-void loop() {
12
- if (soft.available()) {
13
- uint8_t incomingByte = soft.read();
14
-
15
- // Print as Hex
16
- if (incomingByte < 0x10) Serial.print("0");
17
- Serial.print(incomingByte, HEX);
18
- Serial.print(" ");
19
-
20
- // Newline every 16 bytes
21
- static int byteCount = 0;
22
- byteCount++;
23
- if (byteCount >= 16) {
24
- Serial.println();
25
- byteCount = 0;
26
- }
27
- }
28
-}
... ...
\ No newline at end of file