ebc4433e6135a3a0e785174c571352519b3cf7c5
Board-dat/SDR/SDR1060-dat/SDR1060-dat.md
| ... | ... | @@ -63,6 +63,9 @@ Schematic |
| 63 | 63 | |
| 64 | 64 | ## Demo Code and Video |
| 65 | 65 | |
| 66 | +somewhere here: https://github.com/Edragon/arduino-esp8266/tree/master/BSP/SDR/SDR1060-M4 |
|
| 67 | + |
|
| 68 | + |
|
| 66 | 69 | ## ref |
| 67 | 70 | |
| 68 | 71 | - [[SDR1060]] - [[L293-dat]] |
Board-dat/SDR/SDR1064-dat/SDR1064-dat.md
| ... | ... | @@ -9,7 +9,9 @@ |
| 9 | 9 | |
| 10 | 10 | ## Applications, category, tags, etc. |
| 11 | 11 | |
| 12 | -- [[ESP32-rc-car-dat]] - [[nodemcu-dat]] |
|
| 12 | +- [[ESP32-rc-car-dat]] - [[nodemcu-dat]] - [[RC-code-dat]] |
|
| 13 | + |
|
| 14 | + |
|
| 13 | 15 | |
| 14 | 16 | ## Board map |
| 15 | 17 | |
| ... | ... | @@ -27,8 +29,8 @@ Motor Control: Phase_A, Phase_B, VIN, V_Motor |
| 27 | 29 | | nodemcu | right | func1 | func2 | [[SDR1064-dat]] | |
| 28 | 30 | | ------- | ----- | ----- | ----- | --------------- | |
| 29 | 31 | | D0 | I016 | USER | WAKE | | |
| 30 | -| D1 | I05 | | | PWM_A | |
|
| 31 | -| D2 | I04 | | | PWM_B | |
|
| 32 | +| D1 | I05 | | | PWM_ A | |
|
| 33 | +| D2 | I04 | | | PWM_B | |
|
| 32 | 34 | | D3 | I00 | FLASH | | Motor_1 | |
| 33 | 35 | | D4 | I02 | TXD1 | | Motor_2 | |
| 34 | 36 | | | 3.3V | | | | |
| ... | ... | @@ -71,8 +73,12 @@ Motor Control: Phase_A, Phase_B, VIN, V_Motor |
| 71 | 73 | |
| 72 | 74 | [ESP8266: NodeMCU Motor Shield Review](http://blog.squix.ch/2015/09/esp8266-nodemcu-motor-shield-review.html) |
| 73 | 75 | |
| 76 | + |
|
| 77 | +https://github.com/Edragon/arduino-esp8266/tree/master/BSP/SDR/SDR1064-wifi-car |
|
| 78 | + |
|
| 74 | 79 | ### Demo code JS Web Control |
| 75 | 80 | |
| 81 | +https://github.com/Edragon/arduino-esp8266/tree/master/BSP/SDR/SDR1064-wifi-car |
|
| 76 | 82 | |
| 77 | 83 | It is not simple to setup the WiFiCar with the provided software. You should have good knowledge of network handling, and Arduino and C programming. |
| 78 | 84 | |
| ... | ... | @@ -93,7 +99,7 @@ It is not simple to setup the WiFiCar with the provided software. You should hav |
| 93 | 99 | |
| 94 | 100 | - [[SDR1064]] |
| 95 | 101 | |
| 96 | -- [[L293-dat]] - [[dc-motor-dat]] |
|
| 102 | +- [[L293-dat]] - [[dc-motor-dat]] - [[wifi-dat]] - [[rover-dat]] |
|
| 97 | 103 | |
| 98 | 104 | - [legacy wiki page ](https://www.electrodragon.com/w/WifiCar) |
| 99 | 105 | |
| ... | ... | \ No newline at end of file |
Tech-dat/PWM-dat/PWM-1ch.ino
| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | +// Define pins for each RC channel |
|
| 2 | +int aileronPin = 2; // Channel 1 |
|
| 3 | + |
|
| 4 | +const int ENA = 5; // PWM for speed for Motor 1 |
|
| 5 | +const int IN1 = 0; // Direction for Motor 1 (IN2_Motor1 is inverted in hardware) |
|
| 6 | + |
|
| 7 | +long aileronControl; |
|
| 8 | + |
|
| 9 | +long readAileronControlSignal() { |
|
| 10 | + unsigned long rawPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 11 | + if (rawPWM == 0) { // Timeout or no signal |
|
| 12 | + return 50; // Mid-point for 0-100 scale (1500us equivalent) |
|
| 13 | + } |
|
| 14 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 15 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 16 | +} |
|
| 17 | + |
|
| 18 | + |
|
| 19 | + |
|
| 20 | +void setup() { |
|
| 21 | + pinMode(aileronPin, INPUT); |
|
| 22 | + |
|
| 23 | + Serial.begin(9600); |
|
| 24 | +} |
|
| 25 | + |
|
| 26 | +void loop() { |
|
| 27 | + // Read mapped control signals from each channel |
|
| 28 | + aileronControl = readAileronControlSignal(); |
|
| 29 | + |
|
| 30 | + // Print the mapped control signal values to the Serial Monitor |
|
| 31 | + Serial.print("Aileron: "); |
|
| 32 | + Serial.print(aileronControl); |
|
| 33 | + Serial.println(); // Newline for better readability |
|
| 34 | + |
|
| 35 | + delay(100); // Limit output rate |
|
| 36 | +} |
|
| ... | ... | \ No newline at end of file |
Tech-dat/PWM-dat/PWM-4ch.ino
| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | + // Define pins for each RC channel |
|
| 2 | + int aileronPin = 2; // Channel 1 |
|
| 3 | + int elevatorPin = 3; // Channel 2 |
|
| 4 | + int throttlePin = 4; // Channel 3 |
|
| 5 | + int rudderPin = 5; // Channel 4 |
|
| 6 | + |
|
| 7 | + // Variables to store PWM values |
|
| 8 | + unsigned long aileronPWM; |
|
| 9 | + unsigned long elevatorPWM; |
|
| 10 | + unsigned long throttlePWM; |
|
| 11 | + unsigned long rudderPWM; |
|
| 12 | + |
|
| 13 | + void setup() { |
|
| 14 | + pinMode(aileronPin, INPUT); |
|
| 15 | + pinMode(elevatorPin, INPUT); |
|
| 16 | + pinMode(throttlePin, INPUT); |
|
| 17 | + pinMode(rudderPin, INPUT); |
|
| 18 | + |
|
| 19 | + Serial.begin(9600); |
|
| 20 | + } |
|
| 21 | + |
|
| 22 | + void loop() { |
|
| 23 | + // Read PWM signal for each channel |
|
| 24 | + // Timeout of 25000 microseconds (25ms) to prevent lockup if a signal is lost |
|
| 25 | + aileronPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 26 | + elevatorPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 27 | + throttlePWM = pulseIn(throttlePin, HIGH, 25000); |
|
| 28 | + rudderPWM = pulseIn(rudderPin, HIGH, 25000); |
|
| 29 | + |
|
| 30 | + // Print the values to the Serial Monitor |
|
| 31 | + Serial.print("Aileron: "); |
|
| 32 | + Serial.print(aileronPWM); |
|
| 33 | + Serial.print(" us, Elevator: "); |
|
| 34 | + Serial.print(elevatorPWM); |
|
| 35 | + Serial.print(" us, Throttle: "); |
|
| 36 | + Serial.print(throttlePWM); |
|
| 37 | + Serial.print(" us, Rudder: "); |
|
| 38 | + Serial.print(rudderPWM); |
|
| 39 | + Serial.print(" us"); |
|
| 40 | + |
|
| 41 | + |
|
| 42 | + delay(100); // Limit output rate to make it readable |
|
| 43 | + } |
|
| ... | ... | \ No newline at end of file |
Tech-dat/PWM-dat/PWM-dat.md
| ... | ... | @@ -6,6 +6,8 @@ |
| 6 | 6 | |
| 7 | 7 | - [[RC-link-dat]] - [[PPM-dat]] |
| 8 | 8 | |
| 9 | +- [[PWM-1ch.ino]] - [[PWM-4ch.ino]] |
|
| 10 | + |
|
| 9 | 11 | Basic setup: |
| 10 | 12 | |
| 11 | 13 | Connect the signal wire of each channel (e.g., throttle and elevator) to two digital pins on the Arduino (e.g., D2 and D3). |
| ... | ... | @@ -36,7 +38,7 @@ Use pulseIn() to read the high-pulse duration. |
| 36 | 38 | delay(100); // Limit output rate |
| 37 | 39 | } |
| 38 | 40 | |
| 39 | -update into four channels, and add timeout to prevent lockup if a signal is lost. |
|
| 41 | +update into **four channels**, and add timeout to prevent lockup if a signal is lost. |
|
| 40 | 42 | |
| 41 | 43 | // Define pins for each RC channel |
| 42 | 44 | int aileronPin = 2; // Channel 1 |
app-dat/RC-dat/RC-code-dat/PWM-1ch.ino
| ... | ... | @@ -0,0 +1,74 @@ |
| 1 | +// Define pins for each RC channel |
|
| 2 | +int aileronPin = 2; // Channel 1 |
|
| 3 | + |
|
| 4 | +const int ENA = 5; // PWM for speed for Motor 1 |
|
| 5 | +const int ENB = 4; // PWM for speed for Motor 2 |
|
| 6 | + |
|
| 7 | +const int IN1 = 0; // Direction for Motor 1 (IN2_Motor1 is inverted in hardware) |
|
| 8 | +const int IN2 = 2; // Direction pin 1 for Motor 2 |
|
| 9 | + |
|
| 10 | +long aileronControl; |
|
| 11 | + |
|
| 12 | +long readAileronControlSignal() { |
|
| 13 | + unsigned long rawPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 14 | + if (rawPWM == 0) { // Timeout or no signal |
|
| 15 | + return 50; // Mid-point for 0-100 scale (1500us equivalent) |
|
| 16 | + } |
|
| 17 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 18 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 19 | +} |
|
| 20 | + |
|
| 21 | +void setup() { |
|
| 22 | + pinMode(aileronPin, INPUT); |
|
| 23 | + |
|
| 24 | + pinMode(ENA, OUTPUT); |
|
| 25 | + pinMode(ENB, OUTPUT); |
|
| 26 | + pinMode(IN1, OUTPUT); |
|
| 27 | + pinMode(IN2, OUTPUT); |
|
| 28 | + |
|
| 29 | + // Initialize motors to off |
|
| 30 | + digitalWrite(IN1, LOW); |
|
| 31 | + digitalWrite(IN2, LOW); |
|
| 32 | + analogWrite(ENA, 0); |
|
| 33 | + analogWrite(ENB, 0); |
|
| 34 | + |
|
| 35 | + Serial.begin(9600); |
|
| 36 | +} |
|
| 37 | + |
|
| 38 | +void loop() { |
|
| 39 | + // Read mapped control signals from each channel |
|
| 40 | + aileronControl = readAileronControlSignal(); |
|
| 41 | + |
|
| 42 | + // Print the mapped control signal values to the Serial Monitor |
|
| 43 | + Serial.print("Aileron: "); |
|
| 44 | + Serial.print(aileronControl); |
|
| 45 | + Serial.println(); // Newline for better readability |
|
| 46 | + |
|
| 47 | + if (aileronControl > 70) { |
|
| 48 | + // Forward |
|
| 49 | + digitalWrite(IN1, HIGH); // Motor 1 forward |
|
| 50 | + digitalWrite(IN2, HIGH); // Motor 2 forward |
|
| 51 | + |
|
| 52 | + // Map aileronControl (61-100) to PWM speed (e.g., 100-255) |
|
| 53 | + int motorSpeed = map(aileronControl, 61, 100, 100, 255); |
|
| 54 | + analogWrite(ENA, motorSpeed); |
|
| 55 | + analogWrite(ENB, motorSpeed); |
|
| 56 | + } else if (aileronControl < 30) { |
|
| 57 | + // Backward |
|
| 58 | + digitalWrite(IN1, LOW); // Motor 1 backward |
|
| 59 | + digitalWrite(IN2, LOW); // Motor 2 backward |
|
| 60 | + |
|
| 61 | + // Map aileronControl (0-39) to PWM speed (e.g., 255-100, reversing the range for backward) |
|
| 62 | + int motorSpeed = map(aileronControl, 0, 39, 255, 100); |
|
| 63 | + analogWrite(ENA, motorSpeed); |
|
| 64 | + analogWrite(ENB, motorSpeed); |
|
| 65 | + } else { |
|
| 66 | + // Stop motors (aileronControl is between 40 and 60 inclusive) |
|
| 67 | + digitalWrite(IN1, LOW); |
|
| 68 | + digitalWrite(IN2, LOW); |
|
| 69 | + analogWrite(ENA, 0); |
|
| 70 | + analogWrite(ENB, 0); |
|
| 71 | + } |
|
| 72 | + |
|
| 73 | + delay(100); // Limit output rate |
|
| 74 | +} |
|
| ... | ... | \ No newline at end of file |
app-dat/RC-dat/RC-code-dat/PWM-2ch.ino
| ... | ... | @@ -0,0 +1,140 @@ |
| 1 | +// Define pins for each RC channel |
|
| 2 | +int aileronPin = 14; // Channel 1 (Throttle) |
|
| 3 | +int elevatorPin = 12; // Channel 2 (Steering) |
|
| 4 | + |
|
| 5 | +const int ENA = 5; // PWM for speed for Motor 1 |
|
| 6 | +const int ENB = 4; // PWM for speed for Motor 2 |
|
| 7 | + |
|
| 8 | +const int IN1 = 0; // Direction for Motor 1 |
|
| 9 | +const int IN2 = 2; // Direction pin 1 for Motor 2 |
|
| 10 | + |
|
| 11 | +long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 12 | +long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 13 | + |
|
| 14 | +// Reads the PWM signal from the aileron channel and maps it to 0-100 |
|
| 15 | +long readAileronControlSignal() { |
|
| 16 | + unsigned long rawPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 17 | + if (rawPWM == 0) { // Timeout or no signal |
|
| 18 | + return 50; // Mid-point for 0-100 scale (1500us equivalent) |
|
| 19 | + } |
|
| 20 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 21 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 22 | +} |
|
| 23 | + |
|
| 24 | +// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 25 | +long readElevatorControlSignal() { |
|
| 26 | + unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 27 | + if (rawPWM == 0) { // Timeout or no signal |
|
| 28 | + return 50; // Mid-point for 0-100 scale (1500us equivalent) |
|
| 29 | + } |
|
| 30 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 31 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 32 | +} |
|
| 33 | + |
|
| 34 | +void setup() { |
|
| 35 | + pinMode(aileronPin, INPUT); |
|
| 36 | + pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 37 | + |
|
| 38 | + pinMode(ENA, OUTPUT); |
|
| 39 | + pinMode(ENB, OUTPUT); |
|
| 40 | + pinMode(IN1, OUTPUT); |
|
| 41 | + pinMode(IN2, OUTPUT); |
|
| 42 | + |
|
| 43 | + // Initialize motors to off |
|
| 44 | + digitalWrite(IN1, LOW); |
|
| 45 | + digitalWrite(IN2, LOW); |
|
| 46 | + analogWrite(ENA, 0); |
|
| 47 | + analogWrite(ENB, 0); |
|
| 48 | + |
|
| 49 | + Serial.begin(9600); |
|
| 50 | +} |
|
| 51 | + |
|
| 52 | +// Helper function to control a single motor |
|
| 53 | +// pwmVal: -255 (full backward) to 255 (full forward) |
|
| 54 | +void setMotorOutput(int dirPin, int speedPin, int pwmVal) { |
|
| 55 | + if (pwmVal > 0) { // Forward |
|
| 56 | + digitalWrite(dirPin, HIGH); |
|
| 57 | + analogWrite(speedPin, pwmVal); |
|
| 58 | + } else if (pwmVal < 0) { // Backward |
|
| 59 | + digitalWrite(dirPin, LOW); |
|
| 60 | + analogWrite(speedPin, -pwmVal); // Speed is positive |
|
| 61 | + } else { // Stop |
|
| 62 | + digitalWrite(dirPin, LOW); // Or HIGH, doesn't matter much if speed is 0 |
|
| 63 | + analogWrite(speedPin, 0); |
|
| 64 | + } |
|
| 65 | +} |
|
| 66 | + |
|
| 67 | +// Helper function to map RC control input (0-100) to an output range (e.g., -255 to 255) |
|
| 68 | +// with a deadband around the center (e.g., 50). |
|
| 69 | +long mapWithDeadband(long rcValue, int rcMin, int rcMax, int rcCenter, int deadbandRadius, int outMin, int outMax) { |
|
| 70 | + long mappedValue = 0; |
|
| 71 | + int deadbandLower = rcCenter - deadbandRadius; |
|
| 72 | + int deadbandUpper = rcCenter + deadbandRadius; |
|
| 73 | + |
|
| 74 | + if (rcValue < deadbandLower) { |
|
| 75 | + // Map the range [rcMin, deadbandLower - 1] to [outMin, -1] |
|
| 76 | + // Ensure deadbandLower - 1 is not less than rcMin |
|
| 77 | + if (deadbandLower -1 < rcMin) { |
|
| 78 | + mappedValue = outMin; |
|
| 79 | + } else { |
|
| 80 | + mappedValue = map(rcValue, rcMin, deadbandLower - 1, outMin, -1); |
|
| 81 | + } |
|
| 82 | + } else if (rcValue > deadbandUpper) { |
|
| 83 | + // Map the range [deadbandUpper + 1, rcMax] to [1, outMax] |
|
| 84 | + // Ensure deadbandUpper + 1 is not greater than rcMax |
|
| 85 | + if (deadbandUpper + 1 > rcMax) { |
|
| 86 | + mappedValue = outMax; |
|
| 87 | + } else { |
|
| 88 | + mappedValue = map(rcValue, deadbandUpper + 1, rcMax, 1, outMax); |
|
| 89 | + } |
|
| 90 | + } else { |
|
| 91 | + // Inside deadband |
|
| 92 | + mappedValue = 0; |
|
| 93 | + } |
|
| 94 | + return constrain(mappedValue, outMin, outMax); |
|
| 95 | +} |
|
| 96 | + |
|
| 97 | +void loop() { |
|
| 98 | + // Read mapped control signals from each channel |
|
| 99 | + aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 100 | + elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 101 | + |
|
| 102 | + // Print the mapped control signal values to the Serial Monitor |
|
| 103 | + Serial.print("Aileron (Throttle): "); |
|
| 104 | + Serial.print(aileronControl); |
|
| 105 | + Serial.print(" Elevator (Steering): "); |
|
| 106 | + Serial.print(elevatorControl); |
|
| 107 | + Serial.println(); |
|
| 108 | + |
|
| 109 | + // Define deadband radius (e.g., +/- 5 around center of 50 for a 0-100 input) |
|
| 110 | + // This means input values from 45 to 55 (inclusive if center is 50 and radius is 5) will be treated as 0. |
|
| 111 | + int deadbandRadius = 5; |
|
| 112 | + |
|
| 113 | + // Map control values with deadband |
|
| 114 | + // Throttle: aileronControl (0-100) -> throttleValue (-255 to 255) |
|
| 115 | + long throttleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 116 | + // Steering: elevatorControl (0-100) -> steeringValue (-255 to 255) |
|
| 117 | + long steeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 118 | + |
|
| 119 | + // The previous deadband logic is now incorporated into mapWithDeadband: |
|
| 120 | + // if (aileronControl > 45 && aileronControl < 55) { |
|
| 121 | + // throttleValue = 0; |
|
| 122 | + // } |
|
| 123 | + // if (elevatorControl > 45 && elevatorControl < 55) { |
|
| 124 | + // steeringValue = 0; |
|
| 125 | + // } |
|
| 126 | + |
|
| 127 | + // Mix throttle and steering for differential drive |
|
| 128 | + long motor1Pwm = throttleValue + steeringValue; |
|
| 129 | + long motor2Pwm = throttleValue - steeringValue; |
|
| 130 | + |
|
| 131 | + // Constrain PWM values to the valid range [-255, 255] |
|
| 132 | + motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 133 | + motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 134 | + |
|
| 135 | + // Set motor speeds and directions |
|
| 136 | + setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 137 | + setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 138 | + |
|
| 139 | + delay(20); // Shorter delay for better responsiveness |
|
| 140 | +} |
|
| ... | ... | \ No newline at end of file |
app-dat/RC-dat/RC-code-dat/RC-code-dat.md
| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | + |
|
| 2 | +# RC-code-dat |
|
| 3 | + |
|
| 4 | +## working for |
|
| 5 | + |
|
| 6 | +- [[SDR1064-dat]] |
|
| 7 | + |
|
| 8 | +## ref |
|
| 9 | + |
|
| 10 | +- [[PWM-dat]] |
|
| ... | ... | \ No newline at end of file |
app-dat/RC-dat/rover-dat/rover-dat.md
| ... | ... | @@ -1,12 +1,14 @@ |
| 1 | 1 | |
| 2 | 2 | # rover-dat |
| 3 | 3 | |
| 4 | -- [[ardupilot-dat]] |
|
| 4 | +- [[ardupilot-dat]] - [[rc-dat]] |
|
| 5 | 5 | |
| 6 | 6 | https://ardupilot.org/rover/index.html |
| 7 | 7 | |
| 8 | 8 | - [[RC-car-dat]] - [[rover-dat]] - [[RC-car-hack-dat]] |
| 9 | 9 | |
| 10 | +- [[rc-protocols-dat]] |
|
| 11 | + |
|
| 10 | 12 | - ARKV6X Flight Controller Overview |
| 11 | 13 | - ARK FPV Flight Controller Overview == STM32H743IIK6 MCU |
| 12 | 14 | - CUAV V5 Plus Overview == STM32F765 |
| ... | ... | @@ -17,4 +19,4 @@ https://ardupilot.org/rover/index.html |
| 17 | 19 | |
| 18 | 20 | ## board |
| 19 | 21 | |
| 20 | -- [[SDR1064-dat]] |
|
| ... | ... | \ No newline at end of file |
| 0 | +- [[SDR1064-dat]] |
|
| ... | ... | \ No newline at end of file |