Chip-cn-dat/Espressif-dat/ESP8266-chip-DAT/ESP8266-DAT.md
... ...
@@ -50,6 +50,7 @@ find modules here - [[esp8266-modules-dat]]
50 50
![](15-46-00-28-03-2023.png)
51 51
52 52
53
+
53 54
### programmer and programming
54 55
55 56
- [[DPR1150-dat]] - [[NWI1070-dat]] for ESP-01/01S
Chip-dat/TI-dat/TI-Motor-dat/DRV8871-dat/drv8871-1.ino
... ...
@@ -0,0 +1,130 @@
1
+// NodeMCU (ESP8266) code to drive two DC motors with DRV8871
2
+// Each motor uses a single GPIO:
3
+// Motor 1: IO0 (D3) for IN1, and IN2 driven by IO0 via an inverter.
4
+// Motor 2: IO2 (D4) for IN1, and IN2 driven by IO2 via an inverter.
5
+
6
+// Define the NodeMCU pins
7
+// MOTOR 1
8
+// GPIO0 (D3 on many NodeMCU boards) is used here.
9
+// WARNING: GPIO0 is a boot mode pin. If it's LOW during boot, ESP8266 enters flash mode.
10
+// Ensure your circuit doesn't pull GPIO0 LOW at boot unless intended.
11
+const int MOTOR1_CTRL_PIN = 0; // GPIO0 (D3)
12
+
13
+// MOTOR 2
14
+// GPIO2 (D4 on many NodeMCU boards) is generally safe to use.
15
+const int MOTOR2_CTRL_PIN = 2; // GPIO2 (D4)
16
+
17
+
18
+// DRV8871 connections (repeat for each motor):
19
+// - MOTORx_CTRL_PIN to DRV8871 IN1
20
+// - MOTORx_CTRL_PIN -> Inverter -> DRV8871 IN2
21
+// - Motor to DRV8871 OUT1 and OUT2
22
+// - Motor power supply (6.5V to 45V) to DRV8871 VM and GND
23
+// - NodeMCU GND to DRV8871 GND
24
+// - Optionally, ILIM resistor (refer to DRV8871 datasheet)
25
+
26
+// ESP8266 analogWrite range is 0-1023 by default.
27
+// PWM_STOP is still needed for the active stopMotor function.
28
+const int PWM_MAX = 1023;
29
+const int PWM_STOP = PWM_MAX / 2; // Approx 511 or 512, for 50% duty cycle
30
+
31
+void setup() {
32
+ pinMode(MOTOR1_CTRL_PIN, OUTPUT);
33
+ pinMode(MOTOR2_CTRL_PIN, OUTPUT);
34
+
35
+ Serial.begin(9600);
36
+ Serial.println("DRV8871 Dual Motor Single Pin (IO0/IO2 + Inverters) Control - Digital Direction");
37
+ Serial.println("Note: Stop is an active stop (50% PWM). True coast/brake not available.");
38
+ Serial.print("PWM Stop value for active stop: ");
39
+ Serial.println(PWM_STOP);
40
+
41
+ // Ensure motors are stopped at startup
42
+ stopMotor1();
43
+ stopMotor2();
44
+}
45
+
46
+void loop() {
47
+ // Simple run loop: Both motors Forward, Stop, Reverse, Stop
48
+ Serial.println("Motor 1 & 2 Forward - Full Speed");
49
+ driveMotor1(true); // true for forward
50
+ driveMotor2(true); // true for forward
51
+ delay(2000);
52
+
53
+ Serial.println("Motor 1 & 2 Stop");
54
+ stopMotor1();
55
+ stopMotor2();
56
+ delay(1000);
57
+
58
+ Serial.println("Motor 1 & 2 Reverse - Full Speed");
59
+ driveMotor1(false); // false for reverse
60
+ driveMotor2(false); // false for reverse
61
+ delay(2000);
62
+
63
+ Serial.println("Motor 1 & 2 Stop");
64
+ stopMotor1();
65
+ stopMotor2();
66
+ delay(1000);
67
+
68
+ // Example: Motor 1 Forward, Motor 2 Reverse
69
+ Serial.println("Motor 1 Forward, Motor 2 Reverse");
70
+ driveMotor1(true);
71
+ driveMotor2(false);
72
+ delay(2000);
73
+
74
+ Serial.println("Motor 1 & 2 Stop");
75
+ stopMotor1();
76
+ stopMotor2();
77
+ delay(1000);
78
+}
79
+
80
+// --- Motor 1 Control Functions ---
81
+
82
+// Function to drive Motor 1 with digital control for direction
83
+// forward: true for forward (MOTOR1_CTRL_PIN HIGH), false for reverse (MOTOR1_CTRL_PIN LOW)
84
+void driveMotor1(bool forward) {
85
+ if (forward) {
86
+ digitalWrite(MOTOR1_CTRL_PIN, HIGH);
87
+ // Serial.println("Driving Motor 1: Forward (MOTOR1_CTRL_PIN HIGH)");
88
+ } else {
89
+ digitalWrite(MOTOR1_CTRL_PIN, LOW);
90
+ // Serial.println("Driving Motor 1: Reverse (MOTOR1_CTRL_PIN LOW)");
91
+ }
92
+}
93
+
94
+// Function to stop Motor 1 (active stop by 50% duty cycle on MOTOR1_CTRL_PIN)
95
+void stopMotor1() {
96
+ analogWrite(MOTOR1_CTRL_PIN, PWM_STOP);
97
+ // Serial.println("Motor 1 Stop (Active - 50% PWM on MOTOR1_CTRL_PIN)");
98
+}
99
+
100
+// Function to "brake" Motor 1. Performs an active stop.
101
+void brakeMotor1() {
102
+ stopMotor1();
103
+ // Serial.println("Motor 1 Brake (Performed Active Stop)");
104
+}
105
+
106
+// --- Motor 2 Control Functions ---
107
+
108
+// Function to drive Motor 2 with digital control for direction
109
+// forward: true for forward (MOTOR2_CTRL_PIN HIGH), false for reverse (MOTOR2_CTRL_PIN LOW)
110
+void driveMotor2(bool forward) {
111
+ if (forward) {
112
+ digitalWrite(MOTOR2_CTRL_PIN, HIGH);
113
+ // Serial.println("Driving Motor 2: Forward (MOTOR2_CTRL_PIN HIGH)");
114
+ } else {
115
+ digitalWrite(MOTOR2_CTRL_PIN, LOW);
116
+ // Serial.println("Driving Motor 2: Reverse (MOTOR2_CTRL_PIN LOW)");
117
+ }
118
+}
119
+
120
+// Function to stop Motor 2 (active stop by 50% duty cycle on MOTOR2_CTRL_PIN)
121
+void stopMotor2() {
122
+ analogWrite(MOTOR2_CTRL_PIN, PWM_STOP);
123
+ // Serial.println("Motor 2 Stop (Active - 50% PWM on MOTOR2_CTRL_PIN)");
124
+}
125
+
126
+// Function to "brake" Motor 2. Performs an active stop.
127
+void brakeMotor2() {
128
+ stopMotor2();
129
+ // Serial.println("Motor 2 Brake (Performed Active Stop)");
130
+}
... ...
\ No newline at end of file
app-dat/RC-dat/RC-code-dat/RC-code-dat.md
... ...
@@ -3,12 +3,17 @@
3 3
4 4
## working for
5 5
6
-- [[SDR1064-dat]]
6
+- [[SDR1064-dat]] - [[nodemcu-dat]]
7 7
8 8
## code
9 9
10 10
- [[PWM-1ch.ino]] - [[PWM-2ch.ino]] - [[PWM-2ch-v2.ino]]
11 11
12
+- [[rover-1.ino]] - [[rover-2.ino]]
13
+
14
+- [[DRV8871-dat]]
15
+
16
+
12 17
## ref
13 18
14 19
- [[PWM-dat]]
app-dat/RC-dat/RC-code-dat/rover-2.ino
... ...
@@ -1,18 +1,15 @@
1 1
#include <Adafruit_NeoPixel.h>
2 2
3 3
// Define pins for each RC channel
4
-int aileronPin = 14; // Channel 1 (Throttle)
5
-int elevatorPin = 12; // Channel 2 (Steering)
4
+int aileronPin = 14; // Channel 1 (Throttle) // D5
5
+int elevatorPin = 12; // Channel 2 (Steering) // D6
6 6
7
-const int ENA = 5; // PWM for speed for Motor 1
8
-const int ENB = 4; // PWM for speed for Motor 2
9
-
10
-const int IN1 = 0; // Direction for Motor 1
11
-const int IN2 = 2; // Direction pin 1 for Motor 2
7
+const int IN1 = 0; // Direction for Motor 1 // D3
8
+const int IN2 = 2; // Direction pin 1 for Motor 2 // D4
12 9
13 10
// WS2812 LED Strip Configuration
14 11
#define LED_PIN 15 // nodemcu pin D8
15
-#define LED_COUNT 8
12
+#define LED_COUNT 8
16 13
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
17 14
18 15
long aileronControl; // Mapped value from aileron channel (0-100)
app-dat/RC-dat/RC-code-dat/rover-8871-2.ino
... ...
@@ -0,0 +1,257 @@
1
+// NodeMCU (ESP8266) code to drive two DC motors with DRV8871
2
+// Each motor uses a single GPIO:
3
+// Motor 1: IO0 (D3) for IN1, and IN2 driven by IO0 via an inverter.
4
+// Motor 2: IO2 (D4) for IN1, and IN2 driven by IO2 via an inverter.
5
+
6
+#include <Adafruit_NeoPixel.h>
7
+
8
+// Define pins for each RC channel
9
+int aileronPin = 14; // Channel 1 (Throttle) // D5
10
+int elevatorPin = 12; // Channel 2 (Steering) // D6
11
+
12
+// --- START: Added/Modified from drv8871-rc.ino ---
13
+// Define the NodeMCU pins for motors (consistent with drv8871-rc.ino)
14
+// MOTOR 1
15
+// GPIO0 (D3 on many NodeMCU boards) is used here.
16
+// WARNING: GPIO0 is a boot mode pin. If it's LOW during boot, ESP8266 enters flash mode.
17
+// Ensure your circuit doesn't pull GPIO0 LOW at boot unless intended.
18
+const int MOTOR1_CTRL_PIN = 0; // GPIO0 (D3), replaces IN1
19
+
20
+// MOTOR 2
21
+// GPIO2 (D4 on many NodeMCU boards) is generally safe to use.
22
+const int MOTOR2_CTRL_PIN = 2; // GPIO2 (D4), replaces IN2
23
+
24
+// ESP8266 analogWrite range is 0-1023 by default.
25
+// PWM_STOP is still needed for the active stopMotor function.
26
+const int PWM_MAX = 1023;
27
+const int PWM_STOP = PWM_MAX / 2; // Approx 511 or 512, for 50% duty cycle
28
+// --- END: Added/Modified from drv8871-rc.ino ---
29
+
30
+// WS2812 LED Strip Configuration
31
+#define LED_PIN 15 // nodemcu pin D8
32
+#define LED_COUNT 8
33
+Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
34
+
35
+long aileronControl; // Mapped value from aileron channel (0-100)
36
+long elevatorControl; // Mapped value from elevator channel (0-100)
37
+
38
+// Reads the PWM signal from the aileron channel and maps it to 0-100
39
+long readAileronControlSignal() {
40
+ unsigned long rawPWM = pulseIn(aileronPin, HIGH, 25000);
41
+ // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50)
42
+ // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid.
43
+ if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) {
44
+ return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop
45
+ }
46
+ // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map
47
+ long constrainedPWM = constrain(rawPWM, 1000, 2000);
48
+ return map(constrainedPWM, 1000, 2000, 0, 100);
49
+}
50
+
51
+// Reads the PWM signal from the elevator channel and maps it to 0-100
52
+long readElevatorControlSignal() {
53
+ unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000);
54
+ // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50)
55
+ // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid.
56
+ if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) {
57
+ return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop
58
+ }
59
+ // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map
60
+ long constrainedPWM = constrain(rawPWM, 1000, 2000);
61
+ return map(constrainedPWM, 1000, 2000, 0, 100);
62
+}
63
+
64
+void setup() {
65
+ pinMode(aileronPin, INPUT);
66
+ pinMode(elevatorPin, INPUT); // Initialize elevator pin
67
+
68
+ // --- START: Modified for drv8871-rc.ino motor control ---
69
+ pinMode(MOTOR1_CTRL_PIN, OUTPUT);
70
+ pinMode(MOTOR2_CTRL_PIN, OUTPUT);
71
+ analogWrite(MOTOR2_CTRL_PIN, PWM_STOP);
72
+ // --- END: Modified for drv8871-rc.ino motor control ---
73
+
74
+ Serial.begin(9600);
75
+ // --- START: Added/Modified from drv8871-rc.ino setup ---
76
+ Serial.println("RC Rover with DRV8871 Single Pin Control");
77
+ Serial.println("Note: Stop is an active stop (50% PWM).");
78
+ Serial.print("PWM Stop value for active stop: ");
79
+ Serial.println(PWM_STOP);
80
+
81
+ // Ensure motors are stopped at startup
82
+ stopMotor1();
83
+ stopMotor2();
84
+ // --- END: Added/Modified from drv8871-rc.ino setup ---
85
+
86
+ strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
87
+ strip.show(); // Turn OFF all pixels ASAP
88
+ strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
89
+}
90
+
91
+// --- START: Motor control functions from drv8871-rc.ino ---
92
+// --- Motor 1 Control Functions ---
93
+// Function to drive Motor 1 with digital control for direction
94
+// forward: true for forward (MOTOR1_CTRL_PIN HIGH), false for reverse (MOTOR1_CTRL_PIN LOW)
95
+void driveMotor1(bool forward) {
96
+ if (forward) {
97
+ digitalWrite(MOTOR1_CTRL_PIN, HIGH);
98
+ } else {
99
+ digitalWrite(MOTOR1_CTRL_PIN, LOW);
100
+ }
101
+}
102
+
103
+// Function to stop Motor 1 (active stop by 50% duty cycle on MOTOR1_CTRL_PIN)
104
+void stopMotor1() {
105
+ analogWrite(MOTOR1_CTRL_PIN, PWM_STOP);
106
+}
107
+
108
+// Function to "brake" Motor 1. Performs an active stop.
109
+void brakeMotor1() {
110
+ stopMotor1();
111
+}
112
+
113
+// --- Motor 2 Control Functions ---
114
+// Function to drive Motor 2 with digital control for direction
115
+// forward: true for forward (MOTOR2_CTRL_PIN HIGH), false for reverse (MOTOR2_CTRL_PIN LOW)
116
+void driveMotor2(bool forward) {
117
+ if (forward) {
118
+ digitalWrite(MOTOR2_CTRL_PIN, HIGH);
119
+ } else {
120
+ digitalWrite(MOTOR2_CTRL_PIN, LOW);
121
+ }
122
+}
123
+
124
+// Function to stop Motor 2
125
+void stopMotor2() {
126
+ // Try a different PWM value if 50% doesn't work
127
+ analogWrite(MOTOR2_CTRL_PIN, PWM_STOP); // or try PWM_MAX
128
+ // Alternatively, try digitalWrite
129
+ // digitalWrite(MOTOR2_CTRL_PIN, LOW); // or try HIGH
130
+}
131
+
132
+// Function to "brake" Motor 2. Performs an active stop.
133
+void brakeMotor2() {
134
+ stopMotor2();
135
+}
136
+// --- END: Motor control functions from drv8871-rc.ino ---
137
+
138
+// Helper function to map RC control input (0-100) to an output range (e.g., -255 to 255)
139
+// with a deadband around the center (e.g., 50).
140
+long mapWithDeadband(long rcValue, int rcMin, int rcMax, int rcCenter, int deadbandRadius, int outMin, int outMax) {
141
+ long mappedValue = 0;
142
+ int deadbandLower = rcCenter - deadbandRadius;
143
+ int deadbandUpper = rcCenter + deadbandRadius;
144
+
145
+ if (rcValue < deadbandLower) {
146
+ // Map the range [rcMin, deadbandLower - 1] to [outMin, -1]
147
+ // Ensure deadbandLower - 1 is not less than rcMin
148
+ if (deadbandLower -1 < rcMin) {
149
+ mappedValue = outMin;
150
+ } else {
151
+ mappedValue = map(rcValue, rcMin, deadbandLower - 1, outMin, -1);
152
+ }
153
+ } else if (rcValue > deadbandUpper) {
154
+ // Map the range [deadbandUpper + 1, rcMax] to [1, outMax]
155
+ // Ensure deadbandUpper + 1 is not greater than rcMax
156
+ if (deadbandUpper + 1 > rcMax) {
157
+ mappedValue = outMax;
158
+ } else {
159
+ mappedValue = map(rcValue, deadbandUpper + 1, rcMax, 1, outMax);
160
+ }
161
+ } else {
162
+ // Inside deadband
163
+ mappedValue = 0;
164
+ }
165
+ return constrain(mappedValue, outMin, outMax);
166
+}
167
+
168
+// Function to create a random blinking effect for WS2812 LEDs
169
+void randomBlinkEffect() {
170
+ for (int i = 0; i < LED_COUNT; i++) {
171
+ // Turn on a random LED with a random color
172
+ if (random(0, 2) == 1) { // 50% chance to turn on this LED
173
+ strip.setPixelColor(i, strip.Color(random(0, 256), random(0, 256), random(0, 256)));
174
+ } else {
175
+ strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off
176
+ }
177
+ }
178
+ strip.show(); // Send the updated pixel colors to the hardware.
179
+ delay(100); // Wait a short period
180
+}
181
+
182
+void loop() {
183
+ // Read mapped control signals from each channel
184
+ aileronControl = readAileronControlSignal(); // Throttle (0-100)
185
+ elevatorControl = readElevatorControlSignal(); // Steering (0-100)
186
+
187
+ // Print the mapped control signal values to the Serial Monitor
188
+ Serial.print("Aileron (Throttle): ");
189
+ Serial.print(aileronControl);
190
+ Serial.print(" Elevator (Steering): ");
191
+ Serial.print(elevatorControl);
192
+ // Serial.println(); // Combined with next print
193
+
194
+ // Define deadband radius (e.g., +/- 5 around center of 50 for a 0-100 input)
195
+ // This means input values from 45 to 55 (inclusive if center is 50 and radius is 5) will be treated as 0.
196
+ int deadbandRadius = 15;
197
+ // Factors to adjust how throttle and steering mix.
198
+ // With on/off control, these primarily affect the outcome when throttle and steering have opposing commands.
199
+ float steeringFactor = 1.0; // Start with 1.0, adjust if needed
200
+ float throttleFactor = 1.0; // Start with 1.0, adjust if needed
201
+
202
+ // Map control values with deadband. Output is -255 to 255, or 0 if in deadband.
203
+ long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255);
204
+ long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255);
205
+
206
+ // Apply sensitivity factors
207
+ long throttleValue = rawThrottleValue * throttleFactor;
208
+ long adjustedSteeringValue = rawSteeringValue * steeringFactor;
209
+
210
+ // Mix throttle and steering for differential drive
211
+ // The magnitude of these values will only determine the sign for direction control.
212
+ long motor1MixedOutput = throttleValue + adjustedSteeringValue;
213
+ long motor2MixedOutput = throttleValue - adjustedSteeringValue;
214
+
215
+ // Print mixed output for debugging
216
+ Serial.print(" M1_Mix: ");
217
+ Serial.print(motor1MixedOutput);
218
+ Serial.print(" M2_Mix: ");
219
+ Serial.print(motor2MixedOutput);
220
+ Serial.println();
221
+
222
+
223
+ // --- START: Motor control logic using drv8871 functions ---
224
+ // Motor 1 Control
225
+ if (motor1MixedOutput > 0) { // Any positive value means forward
226
+ driveMotor1(true);
227
+ } else if (motor1MixedOutput < 0) { // Any negative value means reverse
228
+ driveMotor1(false);
229
+ } else { // Zero means stop
230
+ stopMotor1();
231
+ }
232
+
233
+ // Motor 2 Control
234
+ if (motor2MixedOutput > 0) { // Any positive value means forward
235
+ driveMotor2(true);
236
+ } else if (motor2MixedOutput < 0) { // Any negative value means reverse
237
+ driveMotor2(false);
238
+ } else { // Zero means stop
239
+ stopMotor2();
240
+ }
241
+ // --- END: Motor control logic using drv8871 functions ---
242
+
243
+ // Add the LED effect
244
+ randomBlinkEffect(); // This function contains a delay(100)
245
+
246
+ delay(20); // Delay for RC input reading cycle. Total loop delay is this + randomBlinkEffect delay.
247
+
248
+ // At the end of your loop
249
+ Serial.print("Motor2 Output: ");
250
+ if (motor2MixedOutput > 0) {
251
+ Serial.println("FORWARD");
252
+ } else if (motor2MixedOutput < 0) {
253
+ Serial.println("REVERSE");
254
+ } else {
255
+ Serial.println("STOP COMMANDED");
256
+ }
257
+}
... ...
\ No newline at end of file
board-3rd-dat/nodemcu-dat/nodemcu-dat.md
... ...
@@ -32,6 +32,8 @@
32 32
| | 3.3V | | |
33 33
34 34
35
+- [[ESP8266-dat]]
36
+
35 37
## Boards
36 38
37 39
- [[NWI1044-dat]]