89bb8b5c3161c046c841b41e6c5e9b66279f28d6
Network-dat/RC-dat/RC-code-dat/PWM-1ch.ino
| ... | ... | @@ -1,74 +0,0 @@ |
| 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 |
Network-dat/RC-dat/RC-code-dat/PWM-2ch-2.ino
| ... | ... | @@ -1,142 +0,0 @@ |
| 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 signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 18 | - // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 19 | - if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 20 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 21 | - } |
|
| 22 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 23 | - long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 24 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 25 | -} |
|
| 26 | - |
|
| 27 | -// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 28 | -long readElevatorControlSignal() { |
|
| 29 | - unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 30 | - // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 31 | - // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 32 | - if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 33 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 34 | - } |
|
| 35 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 36 | - long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 37 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 38 | -} |
|
| 39 | - |
|
| 40 | -void setup() { |
|
| 41 | - pinMode(aileronPin, INPUT); |
|
| 42 | - pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 43 | - |
|
| 44 | - pinMode(ENA, OUTPUT); |
|
| 45 | - pinMode(ENB, OUTPUT); |
|
| 46 | - pinMode(IN1, OUTPUT); |
|
| 47 | - pinMode(IN2, OUTPUT); |
|
| 48 | - |
|
| 49 | - // Initialize motors to off |
|
| 50 | - digitalWrite(IN1, LOW); |
|
| 51 | - digitalWrite(IN2, LOW); |
|
| 52 | - analogWrite(ENA, 0); |
|
| 53 | - analogWrite(ENB, 0); |
|
| 54 | - |
|
| 55 | - Serial.begin(9600); |
|
| 56 | -} |
|
| 57 | - |
|
| 58 | -// Helper function to control a single motor |
|
| 59 | -// pwmVal: -255 (full backward) to 255 (full forward) |
|
| 60 | -void setMotorOutput(int dirPin, int speedPin, int pwmVal) { |
|
| 61 | - if (pwmVal > 0) { // Forward |
|
| 62 | - digitalWrite(dirPin, HIGH); |
|
| 63 | - analogWrite(speedPin, pwmVal); |
|
| 64 | - } else if (pwmVal < 0) { // Backward |
|
| 65 | - digitalWrite(dirPin, LOW); |
|
| 66 | - analogWrite(speedPin, -pwmVal); // Speed is positive |
|
| 67 | - } else { // Stop |
|
| 68 | - digitalWrite(dirPin, LOW); // Or HIGH, doesn't matter much if speed is 0 |
|
| 69 | - analogWrite(speedPin, 0); |
|
| 70 | - } |
|
| 71 | -} |
|
| 72 | - |
|
| 73 | -// Helper function to map RC control input (0-100) to an output range (e.g., -255 to 255) |
|
| 74 | -// with a deadband around the center (e.g., 50). |
|
| 75 | -long mapWithDeadband(long rcValue, int rcMin, int rcMax, int rcCenter, int deadbandRadius, int outMin, int outMax) { |
|
| 76 | - long mappedValue = 0; |
|
| 77 | - int deadbandLower = rcCenter - deadbandRadius; |
|
| 78 | - int deadbandUpper = rcCenter + deadbandRadius; |
|
| 79 | - |
|
| 80 | - if (rcValue < deadbandLower) { |
|
| 81 | - // Map the range [rcMin, deadbandLower - 1] to [outMin, -1] |
|
| 82 | - // Ensure deadbandLower - 1 is not less than rcMin |
|
| 83 | - if (deadbandLower -1 < rcMin) { |
|
| 84 | - mappedValue = outMin; |
|
| 85 | - } else { |
|
| 86 | - mappedValue = map(rcValue, rcMin, deadbandLower - 1, outMin, -1); |
|
| 87 | - } |
|
| 88 | - } else if (rcValue > deadbandUpper) { |
|
| 89 | - // Map the range [deadbandUpper + 1, rcMax] to [1, outMax] |
|
| 90 | - // Ensure deadbandUpper + 1 is not greater than rcMax |
|
| 91 | - if (deadbandUpper + 1 > rcMax) { |
|
| 92 | - mappedValue = outMax; |
|
| 93 | - } else { |
|
| 94 | - mappedValue = map(rcValue, deadbandUpper + 1, rcMax, 1, outMax); |
|
| 95 | - } |
|
| 96 | - } else { |
|
| 97 | - // Inside deadband |
|
| 98 | - mappedValue = 0; |
|
| 99 | - } |
|
| 100 | - return constrain(mappedValue, outMin, outMax); |
|
| 101 | -} |
|
| 102 | - |
|
| 103 | -void loop() { |
|
| 104 | - // Read mapped control signals from each channel |
|
| 105 | - aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 106 | - elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 107 | - |
|
| 108 | - // Print the mapped control signal values to the Serial Monitor |
|
| 109 | - Serial.print("Aileron (Throttle): "); |
|
| 110 | - Serial.print(aileronControl); |
|
| 111 | - Serial.print(" Elevator (Steering): "); |
|
| 112 | - Serial.print(elevatorControl); |
|
| 113 | - Serial.println(); |
|
| 114 | - |
|
| 115 | - // Define deadband radius (e.g., +/- 5 around center of 50 for a 0-100 input) |
|
| 116 | - // This means input values from 45 to 55 (inclusive if center is 50 and radius is 5) will be treated as 0. |
|
| 117 | - int deadbandRadius = 10; |
|
| 118 | - float steeringFactor = 3; // Adjust this value to change steering sensitivity |
|
| 119 | - float throttleFactor = 3; // Adjust this value to change throttle sensitivity (e.g., 1.2 for 20% stronger throttle) |
|
| 120 | - |
|
| 121 | - // Map control values with deadband |
|
| 122 | - long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 123 | - long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 124 | - |
|
| 125 | - // Apply sensitivity factors |
|
| 126 | - long throttleValue = rawThrottleValue * throttleFactor; |
|
| 127 | - long adjustedSteeringValue = rawSteeringValue * steeringFactor; |
|
| 128 | - |
|
| 129 | - // Mix throttle and steering for differential drive |
|
| 130 | - long motor1Pwm = throttleValue + adjustedSteeringValue; |
|
| 131 | - long motor2Pwm = throttleValue - adjustedSteeringValue; |
|
| 132 | - |
|
| 133 | - // Constrain PWM values to the valid range [-255, 255] |
|
| 134 | - motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 135 | - motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 136 | - |
|
| 137 | - // Set motor speeds and directions |
|
| 138 | - setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 139 | - setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 140 | - |
|
| 141 | - delay(20); // Shorter delay for better responsiveness |
|
| 142 | -} |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/PWM-2ch-v2.ino
| ... | ... | @@ -1,68 +0,0 @@ |
| 1 | -// RC signal input pins |
|
| 2 | -#define THROTTLE_PIN 2 // Channel 1 (forward/back) |
|
| 3 | -#define STEERING_PIN 3 // Channel 2 (left/right) |
|
| 4 | - |
|
| 5 | -// Motor control pins (L298N) |
|
| 6 | -#define LEFT_ENA 9 |
|
| 7 | -#define LEFT_IN1 4 |
|
| 8 | -#define LEFT_IN2 5 |
|
| 9 | - |
|
| 10 | -#define RIGHT_ENB 10 |
|
| 11 | -#define RIGHT_IN3 6 |
|
| 12 | -#define RIGHT_IN4 7 |
|
| 13 | - |
|
| 14 | -int throttle, steering; |
|
| 15 | - |
|
| 16 | -void setup() { |
|
| 17 | - pinMode(THROTTLE_PIN, INPUT); |
|
| 18 | - pinMode(STEERING_PIN, INPUT); |
|
| 19 | - |
|
| 20 | - pinMode(LEFT_IN1, OUTPUT); |
|
| 21 | - pinMode(LEFT_IN2, OUTPUT); |
|
| 22 | - pinMode(LEFT_ENA, OUTPUT); |
|
| 23 | - |
|
| 24 | - pinMode(RIGHT_IN3, OUTPUT); |
|
| 25 | - pinMode(RIGHT_IN4, OUTPUT); |
|
| 26 | - pinMode(RIGHT_ENB, OUTPUT); |
|
| 27 | - |
|
| 28 | - Serial.begin(9600); |
|
| 29 | -} |
|
| 30 | - |
|
| 31 | -void loop() { |
|
| 32 | - // Read PWM input |
|
| 33 | - throttle = pulseIn(THROTTLE_PIN, HIGH, 25000); |
|
| 34 | - steering = pulseIn(STEERING_PIN, HIGH, 25000); |
|
| 35 | - |
|
| 36 | - // Center = 1500, range = 1000–2000 |
|
| 37 | - int throttleVal = map(throttle, 1000, 2000, -255, 255); |
|
| 38 | - int steeringVal = map(steering, 1000, 2000, -100, 100); // less aggressive |
|
| 39 | - |
|
| 40 | - // Motor mixing (differential drive) |
|
| 41 | - int leftSpeed = constrain(throttleVal + steeringVal, -255, 255); |
|
| 42 | - int rightSpeed = constrain(throttleVal - steeringVal, -255, 255); |
|
| 43 | - |
|
| 44 | - setMotor(LEFT_IN1, LEFT_IN2, LEFT_ENA, leftSpeed); |
|
| 45 | - setMotor(RIGHT_IN3, RIGHT_IN4, RIGHT_ENB, rightSpeed); |
|
| 46 | - |
|
| 47 | - // Debug |
|
| 48 | - Serial.print("Throttle: "); Serial.print(throttleVal); |
|
| 49 | - Serial.print(" Steering: "); Serial.print(steeringVal); |
|
| 50 | - Serial.print(" L: "); Serial.print(leftSpeed); |
|
| 51 | - Serial.print(" R: "); Serial.println(rightSpeed); |
|
| 52 | - |
|
| 53 | - delay(20); |
|
| 54 | -} |
|
| 55 | - |
|
| 56 | -void setMotor(int in1, int in2, int ena, int speed) { |
|
| 57 | - if (speed > 0) { |
|
| 58 | - digitalWrite(in1, HIGH); |
|
| 59 | - digitalWrite(in2, LOW); |
|
| 60 | - } else if (speed < 0) { |
|
| 61 | - digitalWrite(in1, LOW); |
|
| 62 | - digitalWrite(in2, HIGH); |
|
| 63 | - } else { |
|
| 64 | - digitalWrite(in1, LOW); |
|
| 65 | - digitalWrite(in2, LOW); |
|
| 66 | - } |
|
| 67 | - analogWrite(ena, abs(speed)); |
|
| 68 | -} |
Network-dat/RC-dat/RC-code-dat/PWM-2ch.ino
| ... | ... | @@ -1,136 +0,0 @@ |
| 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 | - float steeringFactor = 1.5; // Adjust this value to change steering sensitivity |
|
| 113 | - float throttleFactor = 1.3; // Adjust this value to change throttle sensitivity (e.g., 1.2 for 20% stronger throttle) |
|
| 114 | - |
|
| 115 | - // Map control values with deadband |
|
| 116 | - long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 117 | - long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 118 | - |
|
| 119 | - // Apply sensitivity factors |
|
| 120 | - long throttleValue = rawThrottleValue * throttleFactor; |
|
| 121 | - long adjustedSteeringValue = rawSteeringValue * steeringFactor; |
|
| 122 | - |
|
| 123 | - // Mix throttle and steering for differential drive |
|
| 124 | - long motor1Pwm = throttleValue + adjustedSteeringValue; |
|
| 125 | - long motor2Pwm = throttleValue - adjustedSteeringValue; |
|
| 126 | - |
|
| 127 | - // Constrain PWM values to the valid range [-255, 255] |
|
| 128 | - motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 129 | - motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 130 | - |
|
| 131 | - // Set motor speeds and directions |
|
| 132 | - setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 133 | - setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 134 | - |
|
| 135 | - delay(20); // Shorter delay for better responsiveness |
|
| 136 | -} |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/RC-code-dat.md
| ... | ... | @@ -1,25 +0,0 @@ |
| 1 | - |
|
| 2 | -# RC-code-dat |
|
| 3 | - |
|
| 4 | - |
|
| 5 | -basic code == [[basic-code-1.ino]], or [[ultrasonic car-1602.pde]] |
|
| 6 | - |
|
| 7 | - |
|
| 8 | -## working for |
|
| 9 | - |
|
| 10 | -- [[SDR1064-dat]] - [[nodemcu-dat]] |
|
| 11 | - |
|
| 12 | -## code |
|
| 13 | - |
|
| 14 | -- [[PWM-1ch.ino]] - [[PWM-2ch.ino]] - [[PWM-2ch-v2.ino]] |
|
| 15 | - |
|
| 16 | -- [[rover-1.ino]] - [[rover-2.ino]] |
|
| 17 | - |
|
| 18 | -- [[DRV8871-dat]] |
|
| 19 | - |
|
| 20 | - |
|
| 21 | -## ref |
|
| 22 | - |
|
| 23 | -- [[PWM-dat]] |
|
| 24 | - |
|
| 25 | -- [[RC-dat]] |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/basic-code-1.ino
| ... | ... | @@ -1,403 +0,0 @@ |
| 1 | - |
|
| 2 | - |
|
| 3 | -******************************************************************************* |
|
| 4 | -遥控超声波测距智能车程序(ARDUINO) |
|
| 5 | -#include <IRremote.h> |
|
| 6 | -#include <Servo.h> |
|
| 7 | -#include <Wire.h> |
|
| 8 | -#include <LiquidCrystal_I2C.h> |
|
| 9 | -//***********************定義馬達腳位************************* |
|
| 10 | -int MotorRight1=6; |
|
| 11 | -int MotorRight2=9; |
|
| 12 | -int MotorLeft1=10; |
|
| 13 | -int MotorLeft2=11; |
|
| 14 | - |
|
| 15 | -int counter=0; |
|
| 16 | -const int irReceiverPin = 3; //紅外線接收器 OUTPUT 訊號接在 pin 3 |
|
| 17 | -//***********************設定所偵測到的 IRcode************************* |
|
| 18 | -long IRfront= 0x00FF629D; //前進碼 |
|
| 19 | -long IRback=0x00FFA857; //後退 |
|
| 20 | -long IRturnright=0x00FF22DD; //右轉 |
|
| 21 | -long IRturnleft= 0x00FFC23D; //左轉 |
|
| 22 | -long IRstop=0x00FF02FD; //停止 |
|
| 23 | -long IRAutorun=0x00FF6897; //超音波自走模式 |
|
| 24 | -long IRturnsmallleft= 0x00FFB04F; |
|
| 25 | -IRrecv irrecv(irReceiverPin); // 定義 IRrecv 物件來接收紅外線訊號 |
|
| 26 | -decode_results results; |
|
| 27 | -//*************************定義超音波腳位****************************** |
|
| 28 | -int inputPin =A0 ; // 定義超音波信號接收腳位 rx |
|
| 29 | -int outputPin =A1; // 定義超音波信號發射腳位'tx |
|
| 30 | -int Fspeedd = 0; // 前方距離 |
|
| 31 | -int Rspeedd = 0; // 右方距離 |
|
| 32 | -int Lspeedd = 0; // 左方距離 |
|
| 33 | -int directionn = 0; // 前=8 後=2 左=4 右=6 |
|
| 34 | -Servo myservo; // 設 myservo |
|
| 35 | -int delay_time = 250; // 伺服馬達轉向後的穩定時間 |
|
| 36 | -int Fgo = 8; // 前進 |
|
| 37 | -int Rgo = 6; // 右轉 |
|
| 38 | -int Lgo = 4; // 左轉 |
|
| 39 | -int Bgo = 2; // 倒車 |
|
| 40 | -//********************************************************************(SETUP) |
|
| 41 | -LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line |
|
| 42 | -display |
|
| 43 | -void setup() |
|
| 44 | -{ |
|
| 45 | - Serial.begin(9600); |
|
| 46 | - pinMode(MotorRight1, OUTPUT); // 腳位 8 (PWM) |
|
| 47 | - pinMode(MotorRight2, OUTPUT); // 腳位 9 (PWM) |
|
| 48 | - pinMode(MotorLeft1, OUTPUT); // 腳位 10 (PWM) |
|
| 49 | - pinMode(MotorLeft2, OUTPUT); // 腳位 11 (PWM) |
|
| 50 | - irrecv.enableIRIn(); // 啟動紅外線解碼 |
|
| 51 | - digitalWrite(3,HIGH); |
|
| 52 | - pinMode(inputPin, INPUT); // 定義超音波輸入腳位 |
|
| 53 | - pinMode(outputPin, OUTPUT); // 定義超音波輸出腳位 |
|
| 54 | - myservo.attach(5); // 定義伺服馬達輸出第 5 腳位(PWM) |
|
| 55 | - lcd.init(); // initialize the lcd |
|
| 56 | - lcd.init(); |
|
| 57 | - // Print a message to the LCD. |
|
| 58 | - |
|
| 59 | - lcd.backlight(); |
|
| 60 | - } |
|
| 61 | -//******************************************************************(Void) |
|
| 62 | -void advance(int a) // 前進 |
|
| 63 | -{ |
|
| 64 | - digitalWrite(MotorRight1,LOW); |
|
| 65 | - digitalWrite(MotorRight2,HIGH); |
|
| 66 | - digitalWrite(MotorLeft1,LOW); |
|
| 67 | - digitalWrite(MotorLeft2,HIGH); |
|
| 68 | - delay(a * 100); |
|
| 69 | -} |
|
| 70 | -void right(int b) //右轉(單輪) |
|
| 71 | -{ |
|
| 72 | - digitalWrite(MotorLeft1,LOW); |
|
| 73 | - digitalWrite(MotorLeft2,HIGH); |
|
| 74 | - digitalWrite(MotorRight1,LOW); |
|
| 75 | - digitalWrite(MotorRight2,LOW); |
|
| 76 | - delay(b * 100); |
|
| 77 | -} |
|
| 78 | -void left(int c) //左轉(單輪) |
|
| 79 | -{ |
|
| 80 | - digitalWrite(MotorRight1,LOW); |
|
| 81 | - digitalWrite(MotorRight2,HIGH); |
|
| 82 | - digitalWrite(MotorLeft1,LOW); |
|
| 83 | - digitalWrite(MotorLeft2,LOW); |
|
| 84 | - delay(c * 100); |
|
| 85 | -} |
|
| 86 | -void turnR(int d) //右轉(雙輪) |
|
| 87 | -{ |
|
| 88 | - digitalWrite(MotorRight1,HIGH); |
|
| 89 | - digitalWrite(MotorRight2,LOW); |
|
| 90 | - digitalWrite(MotorLeft1,LOW); |
|
| 91 | - digitalWrite(MotorLeft2,HIGH); |
|
| 92 | - delay(d * 100); |
|
| 93 | -} |
|
| 94 | -void turnL(int e) //左轉(雙輪) |
|
| 95 | -{ |
|
| 96 | - digitalWrite(MotorRight1,LOW); |
|
| 97 | - digitalWrite(MotorRight2,HIGH); |
|
| 98 | - digitalWrite(MotorLeft1,HIGH); |
|
| 99 | - digitalWrite(MotorLeft2,LOW); |
|
| 100 | - |
|
| 101 | - delay(e * 100); |
|
| 102 | -} |
|
| 103 | -void stopp(int f) //停止 |
|
| 104 | -{ |
|
| 105 | - digitalWrite(MotorRight1,LOW); |
|
| 106 | - digitalWrite(MotorRight2,LOW); |
|
| 107 | - digitalWrite(MotorLeft1,LOW); |
|
| 108 | - digitalWrite(MotorLeft2,LOW); |
|
| 109 | - delay(f * 100); |
|
| 110 | -} |
|
| 111 | -void back(int g) //後退 |
|
| 112 | -{ |
|
| 113 | - digitalWrite(MotorRight1,HIGH); |
|
| 114 | - digitalWrite(MotorRight2,LOW); |
|
| 115 | - digitalWrite(MotorLeft1,HIGH); |
|
| 116 | - digitalWrite(MotorLeft2,LOW);; |
|
| 117 | - delay(g * 100); |
|
| 118 | -} |
|
| 119 | -void detection() //測量 3 個角度(前.左.右) |
|
| 120 | -{ |
|
| 121 | - int delay_time = 250; // 伺服馬達轉向後的穩定時間 |
|
| 122 | - ask_pin_F(); // 讀取前方距離 |
|
| 123 | - if(Fspeedd < 10) // 假如前方距離小於 10 公分 |
|
| 124 | - { |
|
| 125 | - stopp(1); // 清除輸出資料 |
|
| 126 | - back(2); // 後退 0.2 秒 |
|
| 127 | - |
|
| 128 | - } |
|
| 129 | - if(Fspeedd < 25) // 假如前方距離小於 25 公分 |
|
| 130 | - { |
|
| 131 | - stopp(1); // 清除輸出資料 |
|
| 132 | - ask_pin_L(); // 讀取左方距離 |
|
| 133 | - delay(delay_time); // 等待伺服馬達穩定 |
|
| 134 | - ask_pin_R(); // 讀取右方距離 |
|
| 135 | - delay(delay_time); // 等待伺服馬達穩定 |
|
| 136 | - if(Lspeedd > Rspeedd) //假如 左邊距離大於右邊距離 |
|
| 137 | - { |
|
| 138 | - directionn = Lgo; //向左走 |
|
| 139 | - } |
|
| 140 | - if(Lspeedd <= Rspeedd) //假如 左邊距離小於或等於右邊距離 |
|
| 141 | - |
|
| 142 | - { |
|
| 143 | - directionn = Rgo; //向右走 |
|
| 144 | - } |
|
| 145 | - if (Lspeedd < 15 && Rspeedd < 15) //假如 左邊距離和右邊距離皆小於 10 公分 |
|
| 146 | - { |
|
| 147 | - directionn = Bgo; //向後走 |
|
| 148 | - } |
|
| 149 | - } |
|
| 150 | - else //加如前方大於 25 公分 |
|
| 151 | - { |
|
| 152 | - directionn = Fgo; //向前走 |
|
| 153 | - } |
|
| 154 | -} |
|
| 155 | -//***************************************************************************** |
|
| 156 | -**** |
|
| 157 | -void ask_pin_F() // 量出前方距離 |
|
| 158 | -{ |
|
| 159 | -myservo.write(90); |
|
| 160 | -digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓 2μs |
|
| 161 | -delayMicroseconds(2); |
|
| 162 | -digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓 10μs,這裡至少是 10μs |
|
| 163 | -delayMicroseconds(10); |
|
| 164 | -digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 165 | -float Fdistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 166 | -Fdistance= Fdistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 167 | -Fspeedd = Fdistance; // 將距離 讀入 Fspeedd(前速) |
|
| 168 | -} |
|
| 169 | -//***************************************************************************** |
|
| 170 | -*** |
|
| 171 | -void ask_pin_L() // 量出左邊距離 |
|
| 172 | -{ |
|
| 173 | -myservo.write(177); |
|
| 174 | -delay(delay_time); |
|
| 175 | -digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓 2μs |
|
| 176 | -delayMicroseconds(2); |
|
| 177 | -digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓 10μs,這裡至少是 10μs |
|
| 178 | -delayMicroseconds(10); |
|
| 179 | -digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 180 | -float Ldistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 181 | -Ldistance= Ldistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 182 | -Lspeedd = Ldistance; // 將距離 讀入 Lspeedd(左速) |
|
| 183 | - |
|
| 184 | -} |
|
| 185 | -//***************************************************************************** |
|
| 186 | -* |
|
| 187 | -void ask_pin_R() // 量出右邊距離 |
|
| 188 | -{ |
|
| 189 | -myservo.write(5); |
|
| 190 | -delay(delay_time); |
|
| 191 | -digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓 2μs |
|
| 192 | -delayMicroseconds(2); |
|
| 193 | -digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓 10μs,這裡至少是 10μs |
|
| 194 | -delayMicroseconds(10); |
|
| 195 | -digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 196 | -float Rdistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 197 | -Rdistance= Rdistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 198 | -Rspeedd = Rdistance; // 將距離 讀入 Rspeedd(右速) |
|
| 199 | -} |
|
| 200 | -//***************************************************************************** |
|
| 201 | -*(LOOP) |
|
| 202 | -void loop() |
|
| 203 | -{ |
|
| 204 | - |
|
| 205 | -//***************************************************************************正 |
|
| 206 | -常遙控模式 |
|
| 207 | - if (irrecv.decode(&results)) |
|
| 208 | - { // 解碼成功,收到一組紅外線訊號 |
|
| 209 | -/***********************************************************************/ |
|
| 210 | - if (results.value == IRfront)//前進 |
|
| 211 | - { |
|
| 212 | - |
|
| 213 | - lcd.setCursor(0,0); |
|
| 214 | - lcd.print(" IR mode"); |
|
| 215 | - lcd.setCursor(0,1); |
|
| 216 | - lcd.print(" advance "); |
|
| 217 | - advance(20);//前進 |
|
| 218 | - } |
|
| 219 | -/***********************************************************************/ |
|
| 220 | - if (results.value == IRback)//後退 |
|
| 221 | - { |
|
| 222 | - |
|
| 223 | - lcd.setCursor(0,0); |
|
| 224 | - lcd.print(" IR mode"); |
|
| 225 | - lcd.setCursor(0,1); |
|
| 226 | - lcd.print(" back "); |
|
| 227 | - |
|
| 228 | - back(20);//後退 |
|
| 229 | - } |
|
| 230 | -/***********************************************************************/ |
|
| 231 | - if (results.value == IRturnright)//右轉 |
|
| 232 | - { |
|
| 233 | - |
|
| 234 | - lcd.setCursor(0,0); |
|
| 235 | - lcd.print(" IR mode"); |
|
| 236 | - lcd.setCursor(0,1); |
|
| 237 | - lcd.print(" right "); |
|
| 238 | - right(10); // 右轉 |
|
| 239 | - |
|
| 240 | - } |
|
| 241 | -/***********************************************************************/ |
|
| 242 | - if (results.value == IRturnleft)//左轉 |
|
| 243 | - { |
|
| 244 | - |
|
| 245 | - lcd.setCursor(0,0); |
|
| 246 | - lcd.print(" IR mode"); |
|
| 247 | - lcd.setCursor(0,1); |
|
| 248 | - lcd.print(" left "); |
|
| 249 | - left(10); // 左轉); |
|
| 250 | - } |
|
| 251 | -/***********************************************************************/ |
|
| 252 | - if (results.value == IRstop)//停止 |
|
| 253 | - { |
|
| 254 | - lcd.setCursor(0,0); |
|
| 255 | - lcd.print(" IR mode"); |
|
| 256 | - lcd.setCursor(0,1); |
|
| 257 | - lcd.print(" stop "); |
|
| 258 | - digitalWrite(MotorRight1,LOW); |
|
| 259 | - digitalWrite(MotorRight2,LOW); |
|
| 260 | - digitalWrite(MotorLeft1,LOW); |
|
| 261 | - digitalWrite(MotorLeft2,LOW); |
|
| 262 | - |
|
| 263 | - |
|
| 264 | - } |
|
| 265 | -//***********************************************************************超音波 |
|
| 266 | -自走模式 |
|
| 267 | - if (results.value ==IRAutorun ) |
|
| 268 | - { |
|
| 269 | - while(IRAutorun) |
|
| 270 | - { |
|
| 271 | - |
|
| 272 | - myservo.write(90); //讓伺服馬達回歸 預備位置 準備下一次的測量 |
|
| 273 | - detection(); //測量角度 並且判斷要往哪一方向移動 |
|
| 274 | - if(directionn == 8) //假如 directionn(方向) = 8(前進) |
|
| 275 | - { |
|
| 276 | - if (irrecv.decode(&results)) |
|
| 277 | - { |
|
| 278 | - irrecv.resume(); |
|
| 279 | - Serial.println(results.value,HEX); |
|
| 280 | - if(results.value ==IRstop) |
|
| 281 | - { |
|
| 282 | - digitalWrite(MotorRight1,LOW); |
|
| 283 | - digitalWrite(MotorRight2,LOW); |
|
| 284 | - digitalWrite(MotorLeft1,LOW); |
|
| 285 | - digitalWrite(MotorLeft2,LOW); |
|
| 286 | - break; |
|
| 287 | - } |
|
| 288 | - } |
|
| 289 | - results.value=0; |
|
| 290 | - |
|
| 291 | - |
|
| 292 | - lcd.setCursor(0,0); |
|
| 293 | - lcd.print(" aoto mode"); |
|
| 294 | - lcd.setCursor(0,1); |
|
| 295 | - lcd.print(" Advance "); |
|
| 296 | - advance(1); // 正常前進 |
|
| 297 | - } |
|
| 298 | - if(directionn == 2) //假如 directionn(方向) = 2(倒車) |
|
| 299 | - { |
|
| 300 | - if (irrecv.decode(&results)) |
|
| 301 | - { |
|
| 302 | - irrecv.resume(); |
|
| 303 | - Serial.println(results.value,HEX); |
|
| 304 | - if(results.value ==IRstop) |
|
| 305 | - { |
|
| 306 | - digitalWrite(MotorRight1,LOW); |
|
| 307 | - digitalWrite(MotorRight2,LOW); |
|
| 308 | - digitalWrite(MotorLeft1,LOW); |
|
| 309 | - digitalWrite(MotorLeft2,LOW); |
|
| 310 | - break; |
|
| 311 | - } |
|
| 312 | - } |
|
| 313 | - results.value=0; |
|
| 314 | - |
|
| 315 | - lcd.setCursor(0,0); |
|
| 316 | - lcd.print(" aoto mode"); |
|
| 317 | - lcd.setCursor(0,1); |
|
| 318 | - lcd.print(" Reverse "); |
|
| 319 | - back(8); // 倒退(車) |
|
| 320 | - turnL(3); //些微向左方移動(防止卡在死巷裡) |
|
| 321 | - } |
|
| 322 | - if(directionn == 6) //假如 directionn(方向) = 6(右轉) |
|
| 323 | - { |
|
| 324 | - if (irrecv.decode(&results)) |
|
| 325 | - { |
|
| 326 | - irrecv.resume(); |
|
| 327 | - Serial.println(results.value,HEX); |
|
| 328 | - if(results.value ==IRstop) |
|
| 329 | - { |
|
| 330 | - digitalWrite(MotorRight1,LOW); |
|
| 331 | - digitalWrite(MotorRight2,LOW); |
|
| 332 | - digitalWrite(MotorLeft1,LOW); |
|
| 333 | - digitalWrite(MotorLeft2,LOW); |
|
| 334 | - break; |
|
| 335 | - } |
|
| 336 | - } |
|
| 337 | - results.value=0; |
|
| 338 | - |
|
| 339 | - |
|
| 340 | - lcd.setCursor(0,0); |
|
| 341 | - lcd.print(" aoto mode"); |
|
| 342 | - lcd.setCursor(0,1); |
|
| 343 | - lcd.print(" Right "); |
|
| 344 | - back(1); |
|
| 345 | - turnR(3); // 右轉 |
|
| 346 | - } |
|
| 347 | - if(directionn == 4) //假如 directionn(方向) = 4(左轉) |
|
| 348 | - { |
|
| 349 | - if (irrecv.decode(&results)) |
|
| 350 | - { |
|
| 351 | - irrecv.resume(); |
|
| 352 | - Serial.println(results.value,HEX); |
|
| 353 | - if(results.value ==IRstop) |
|
| 354 | - { |
|
| 355 | - digitalWrite(MotorRight1,LOW); |
|
| 356 | - digitalWrite(MotorRight2,LOW); |
|
| 357 | - digitalWrite(MotorLeft1,LOW); |
|
| 358 | - digitalWrite(MotorLeft2,LOW); |
|
| 359 | - |
|
| 360 | - break; |
|
| 361 | - } |
|
| 362 | - } |
|
| 363 | - results.value=0; |
|
| 364 | - |
|
| 365 | - lcd.setCursor(0,0); |
|
| 366 | - lcd.print(" aoto mode"); |
|
| 367 | - lcd.setCursor(0,1); |
|
| 368 | - lcd.print(" Left "); |
|
| 369 | - back(1); |
|
| 370 | - turnL(3); // 左轉 |
|
| 371 | - |
|
| 372 | - } |
|
| 373 | - |
|
| 374 | - if (irrecv.decode(&results)) |
|
| 375 | - { |
|
| 376 | - irrecv.resume(); |
|
| 377 | - Serial.println(results.value,HEX); |
|
| 378 | - if(results.value ==IRstop) |
|
| 379 | - { |
|
| 380 | - digitalWrite(MotorRight1,LOW); |
|
| 381 | - digitalWrite(MotorRight2,LOW); |
|
| 382 | - digitalWrite(MotorLeft1,LOW); |
|
| 383 | - digitalWrite(MotorLeft2,LOW); |
|
| 384 | - break; |
|
| 385 | - } |
|
| 386 | - } |
|
| 387 | - } |
|
| 388 | - results.value=0; |
|
| 389 | - } |
|
| 390 | -/***********************************************************************/ |
|
| 391 | - else |
|
| 392 | - { |
|
| 393 | - digitalWrite(MotorRight1,LOW); |
|
| 394 | - digitalWrite(MotorRight2,LOW); |
|
| 395 | - digitalWrite(MotorLeft1,LOW); |
|
| 396 | - digitalWrite(MotorLeft2,LOW); |
|
| 397 | - } |
|
| 398 | - |
|
| 399 | - irrecv.resume(); // 繼續收下一組紅外線訊號 |
|
| 400 | - } |
|
| 401 | -} |
|
| 402 | - |
|
| 403 | -******************************************************************************* |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/rover-1.ino
| ... | ... | @@ -1,94 +0,0 @@ |
| 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 signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 18 | - if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 19 | - return 50; // Mid-point for 0-100 scale |
|
| 20 | - } |
|
| 21 | - long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 22 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 23 | -} |
|
| 24 | - |
|
| 25 | -// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 26 | -long readElevatorControlSignal() { |
|
| 27 | - unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 28 | - // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 29 | - if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 30 | - return 50; // Mid-point for 0-100 scale |
|
| 31 | - } |
|
| 32 | - long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 33 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 34 | -} |
|
| 35 | - |
|
| 36 | -void setup() { |
|
| 37 | - pinMode(aileronPin, INPUT); |
|
| 38 | - pinMode(elevatorPin, INPUT); |
|
| 39 | - |
|
| 40 | - pinMode(ENA, OUTPUT); |
|
| 41 | - pinMode(ENB, OUTPUT); |
|
| 42 | - pinMode(IN1, OUTPUT); |
|
| 43 | - pinMode(IN2, OUTPUT); |
|
| 44 | - |
|
| 45 | - // Initialize motors to off |
|
| 46 | - digitalWrite(IN1, LOW); |
|
| 47 | - digitalWrite(IN2, LOW); |
|
| 48 | - analogWrite(ENA, 0); |
|
| 49 | - analogWrite(ENB, 0); |
|
| 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); |
|
| 63 | - analogWrite(speedPin, 0); |
|
| 64 | - } |
|
| 65 | -} |
|
| 66 | - |
|
| 67 | -void loop() { |
|
| 68 | - // Read mapped control signals from each channel |
|
| 69 | - aileronControl = readAileronControlSignal(); // Throttle (0-100, 50 is neutral) |
|
| 70 | - elevatorControl = readElevatorControlSignal(); // Steering (0-100, 50 is neutral) |
|
| 71 | - |
|
| 72 | - // Map control values directly |
|
| 73 | - // aileronControl (0-100) to throttleValue (-255 to 255) |
|
| 74 | - // 0 -> -255 (full reverse), 50 -> 0 (stop), 100 -> 255 (full forward) |
|
| 75 | - long throttleValue = map(aileronControl, 0, 100, -255, 255); |
|
| 76 | - |
|
| 77 | - // elevatorControl (0-100) to steeringValue (-255 to 255) |
|
| 78 | - // 0 -> -255 (full left turn effect), 50 -> 0 (straight), 100 -> 255 (full right turn effect) |
|
| 79 | - long steeringValue = map(elevatorControl, 0, 100, -255, 255); |
|
| 80 | - |
|
| 81 | - // Mix throttle and steering for differential drive |
|
| 82 | - long motor1Pwm = throttleValue + steeringValue; |
|
| 83 | - long motor2Pwm = throttleValue - steeringValue; |
|
| 84 | - |
|
| 85 | - // Constrain PWM values to the valid range [-255, 255] |
|
| 86 | - motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 87 | - motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 88 | - |
|
| 89 | - // Set motor speeds and directions |
|
| 90 | - setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 91 | - setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 92 | - |
|
| 93 | - delay(20); // Delay for responsiveness |
|
| 94 | -} |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/rover-2.ino
| ... | ... | @@ -1,167 +0,0 @@ |
| 1 | -#include <Adafruit_NeoPixel.h> |
|
| 2 | - |
|
| 3 | -// Define pins for each RC channel |
|
| 4 | -int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 5 | -int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 6 | - |
|
| 7 | -const int IN1 = 0; // Direction for Motor 1 // D3 |
|
| 8 | -const int IN2 = 2; // Direction pin 1 for Motor 2 // D4 |
|
| 9 | - |
|
| 10 | -// WS2812 LED Strip Configuration |
|
| 11 | -#define LED_PIN 15 // nodemcu pin D8 |
|
| 12 | -#define LED_COUNT 8 |
|
| 13 | -Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); |
|
| 14 | - |
|
| 15 | -long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 16 | -long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 17 | - |
|
| 18 | -// Reads the PWM signal from the aileron channel and maps it to 0-100 |
|
| 19 | -long readAileronControlSignal() { |
|
| 20 | - unsigned long rawPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 21 | - // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 22 | - // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 23 | - if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 24 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 25 | - } |
|
| 26 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 27 | - long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 28 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 29 | -} |
|
| 30 | - |
|
| 31 | -// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 32 | -long readElevatorControlSignal() { |
|
| 33 | - unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 34 | - // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 35 | - // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 36 | - if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 37 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 38 | - } |
|
| 39 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 40 | - long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 41 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 42 | -} |
|
| 43 | - |
|
| 44 | -void setup() { |
|
| 45 | - pinMode(aileronPin, INPUT); |
|
| 46 | - pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 47 | - |
|
| 48 | - pinMode(ENA, OUTPUT); |
|
| 49 | - pinMode(ENB, OUTPUT); |
|
| 50 | - pinMode(IN1, OUTPUT); |
|
| 51 | - pinMode(IN2, OUTPUT); |
|
| 52 | - |
|
| 53 | - // Initialize motors to off |
|
| 54 | - digitalWrite(IN1, LOW); |
|
| 55 | - digitalWrite(IN2, LOW); |
|
| 56 | - analogWrite(ENA, 0); |
|
| 57 | - analogWrite(ENB, 0); |
|
| 58 | - |
|
| 59 | - Serial.begin(9600); |
|
| 60 | - |
|
| 61 | - strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) |
|
| 62 | - strip.show(); // Turn OFF all pixels ASAP |
|
| 63 | - strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255) |
|
| 64 | -} |
|
| 65 | - |
|
| 66 | -// Helper function to control a single motor |
|
| 67 | -// pwmVal: -255 (full backward) to 255 (full forward) |
|
| 68 | -void setMotorOutput(int dirPin, int speedPin, int pwmVal) { |
|
| 69 | - if (pwmVal > 0) { // Forward |
|
| 70 | - digitalWrite(dirPin, HIGH); |
|
| 71 | - analogWrite(speedPin, pwmVal); |
|
| 72 | - } else if (pwmVal < 0) { // Backward |
|
| 73 | - digitalWrite(dirPin, LOW); |
|
| 74 | - analogWrite(speedPin, -pwmVal); // Speed is positive |
|
| 75 | - } else { // Stop |
|
| 76 | - digitalWrite(dirPin, LOW); // Or HIGH, doesn't matter much if speed is 0 |
|
| 77 | - analogWrite(speedPin, 0); |
|
| 78 | - } |
|
| 79 | -} |
|
| 80 | - |
|
| 81 | -// Helper function to map RC control input (0-100) to an output range (e.g., -255 to 255) |
|
| 82 | -// with a deadband around the center (e.g., 50). |
|
| 83 | -long mapWithDeadband(long rcValue, int rcMin, int rcMax, int rcCenter, int deadbandRadius, int outMin, int outMax) { |
|
| 84 | - long mappedValue = 0; |
|
| 85 | - int deadbandLower = rcCenter - deadbandRadius; |
|
| 86 | - int deadbandUpper = rcCenter + deadbandRadius; |
|
| 87 | - |
|
| 88 | - if (rcValue < deadbandLower) { |
|
| 89 | - // Map the range [rcMin, deadbandLower - 1] to [outMin, -1] |
|
| 90 | - // Ensure deadbandLower - 1 is not less than rcMin |
|
| 91 | - if (deadbandLower -1 < rcMin) { |
|
| 92 | - mappedValue = outMin; |
|
| 93 | - } else { |
|
| 94 | - mappedValue = map(rcValue, rcMin, deadbandLower - 1, outMin, -1); |
|
| 95 | - } |
|
| 96 | - } else if (rcValue > deadbandUpper) { |
|
| 97 | - // Map the range [deadbandUpper + 1, rcMax] to [1, outMax] |
|
| 98 | - // Ensure deadbandUpper + 1 is not greater than rcMax |
|
| 99 | - if (deadbandUpper + 1 > rcMax) { |
|
| 100 | - mappedValue = outMax; |
|
| 101 | - } else { |
|
| 102 | - mappedValue = map(rcValue, deadbandUpper + 1, rcMax, 1, outMax); |
|
| 103 | - } |
|
| 104 | - } else { |
|
| 105 | - // Inside deadband |
|
| 106 | - mappedValue = 0; |
|
| 107 | - } |
|
| 108 | - return constrain(mappedValue, outMin, outMax); |
|
| 109 | -} |
|
| 110 | - |
|
| 111 | -// Function to create a random blinking effect for WS2812 LEDs |
|
| 112 | -void randomBlinkEffect() { |
|
| 113 | - for (int i = 0; i < LED_COUNT; i++) { |
|
| 114 | - // Turn on a random LED with a random color |
|
| 115 | - if (random(0, 2) == 1) { // 50% chance to turn on this LED |
|
| 116 | - strip.setPixelColor(i, strip.Color(random(0, 256), random(0, 256), random(0, 256))); |
|
| 117 | - } else { |
|
| 118 | - strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off |
|
| 119 | - } |
|
| 120 | - } |
|
| 121 | - strip.show(); // Send the updated pixel colors to the hardware. |
|
| 122 | - delay(100); // Wait a short period |
|
| 123 | -} |
|
| 124 | - |
|
| 125 | -void loop() { |
|
| 126 | - // Read mapped control signals from each channel |
|
| 127 | - aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 128 | - elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 129 | - |
|
| 130 | - // Print the mapped control signal values to the Serial Monitor |
|
| 131 | - Serial.print("Aileron (Throttle): "); |
|
| 132 | - Serial.print(aileronControl); |
|
| 133 | - Serial.print(" Elevator (Steering): "); |
|
| 134 | - Serial.print(elevatorControl); |
|
| 135 | - Serial.println(); |
|
| 136 | - |
|
| 137 | - // Define deadband radius (e.g., +/- 5 around center of 50 for a 0-100 input) |
|
| 138 | - // This means input values from 45 to 55 (inclusive if center is 50 and radius is 5) will be treated as 0. |
|
| 139 | - int deadbandRadius = 15; |
|
| 140 | - float steeringFactor = 3; // Adjust this value to change steering sensitivity |
|
| 141 | - float throttleFactor = 3; // Adjust this value to change throttle sensitivity (e.g., 1.2 for 20% stronger throttle) |
|
| 142 | - |
|
| 143 | - // Map control values with deadband |
|
| 144 | - long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 145 | - long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 146 | - |
|
| 147 | - // Apply sensitivity factors |
|
| 148 | - long throttleValue = rawThrottleValue * throttleFactor; |
|
| 149 | - long adjustedSteeringValue = rawSteeringValue * steeringFactor; |
|
| 150 | - |
|
| 151 | - // Mix throttle and steering for differential drive |
|
| 152 | - long motor1Pwm = throttleValue + adjustedSteeringValue; |
|
| 153 | - long motor2Pwm = throttleValue - adjustedSteeringValue; |
|
| 154 | - |
|
| 155 | - // Constrain PWM values to the valid range [-255, 255] |
|
| 156 | - motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 157 | - motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 158 | - |
|
| 159 | - // Set motor speeds and directions |
|
| 160 | - setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 161 | - setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 162 | - |
|
| 163 | - // Add the LED effect |
|
| 164 | - randomBlinkEffect(); |
|
| 165 | - |
|
| 166 | - delay(20); // Shorter delay for better responsiveness |
|
| 167 | -} |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/rover-8871-2.ino
| ... | ... | @@ -1,126 +0,0 @@ |
| 1 | -// Define pins for each RC channel |
|
| 2 | -int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 3 | -int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 4 | - |
|
| 5 | -const int MOTOR1_CTRL_PIN = 4; // GPIO4 (D2) |
|
| 6 | -const int MOTOR2_CTRL_PIN = 5; // GPIO5 (D1) |
|
| 7 | - |
|
| 8 | -long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 9 | -long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 10 | - |
|
| 11 | -unsigned long rawAileronPWM = 0; |
|
| 12 | -unsigned long rawElevatorPWM = 0; |
|
| 13 | - |
|
| 14 | -const int PWM_MAX = 255; // ESP8266 PWM range is 0-1023 |
|
| 15 | -const int PWM_STOP = PWM_MAX / 2; // ~511 or 512 |
|
| 16 | - |
|
| 17 | -long readAileronControlSignal() { |
|
| 18 | - rawAileronPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 19 | - if (rawAileronPWM == 0 || rawAileronPWM < 900 || rawAileronPWM > 2100) { |
|
| 20 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 21 | - } |
|
| 22 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 23 | - long constrainedPWM = constrain(rawAileronPWM, 1000, 2000); |
|
| 24 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 25 | -} |
|
| 26 | - |
|
| 27 | -long readElevatorControlSignal() { |
|
| 28 | - rawElevatorPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 29 | - if (rawElevatorPWM == 0 || rawElevatorPWM < 900 || rawElevatorPWM > 2100) { |
|
| 30 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 31 | - } |
|
| 32 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 33 | - long constrainedPWM = constrain(rawElevatorPWM, 1000, 2000); |
|
| 34 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 35 | -} |
|
| 36 | - |
|
| 37 | -void setup() { |
|
| 38 | - pinMode(aileronPin, INPUT); |
|
| 39 | - pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 40 | - |
|
| 41 | - pinMode(MOTOR1_CTRL_PIN, OUTPUT); |
|
| 42 | - pinMode(MOTOR2_CTRL_PIN, OUTPUT); |
|
| 43 | - |
|
| 44 | - Serial.begin(9600); |
|
| 45 | - brakeMotor1(); |
|
| 46 | - brakeMotor2(); |
|
| 47 | -} |
|
| 48 | - |
|
| 49 | -void driveMotor1(bool forward) { |
|
| 50 | - if (forward) { |
|
| 51 | - digitalWrite(MOTOR1_CTRL_PIN, HIGH); |
|
| 52 | - } else { |
|
| 53 | - digitalWrite(MOTOR1_CTRL_PIN, LOW); |
|
| 54 | - } |
|
| 55 | -} |
|
| 56 | - |
|
| 57 | -void brakeMotor1() { |
|
| 58 | - analogWrite(MOTOR1_CTRL_PIN, PWM_STOP); |
|
| 59 | -} |
|
| 60 | - |
|
| 61 | -void driveMotor2(bool forward) { |
|
| 62 | - if (forward) { |
|
| 63 | - digitalWrite(MOTOR2_CTRL_PIN, HIGH); |
|
| 64 | - } else { |
|
| 65 | - digitalWrite(MOTOR2_CTRL_PIN, LOW); |
|
| 66 | - } |
|
| 67 | -} |
|
| 68 | - |
|
| 69 | -void brakeMotor2() { |
|
| 70 | - analogWrite(MOTOR2_CTRL_PIN, PWM_STOP); |
|
| 71 | -} |
|
| 72 | - |
|
| 73 | -void loop() { |
|
| 74 | - // Read mapped control signals from each channel |
|
| 75 | - aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 76 | - elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 77 | - |
|
| 78 | - // Simplified driving approach - no mixing |
|
| 79 | - String motor1Command = "STOP"; |
|
| 80 | - String motor2Command = "STOP"; |
|
| 81 | - |
|
| 82 | - // Handle throttle control (forward/reverse) |
|
| 83 | - if (aileronControl > 60) { |
|
| 84 | - // Forward |
|
| 85 | - driveMotor1(true); |
|
| 86 | - driveMotor2(true); |
|
| 87 | - motor1Command = "FORWARD"; |
|
| 88 | - motor2Command = "FORWARD"; |
|
| 89 | - } else if (aileronControl < 40) { |
|
| 90 | - // Reverse |
|
| 91 | - driveMotor1(false); |
|
| 92 | - driveMotor2(false); |
|
| 93 | - motor1Command = "REVERSE"; |
|
| 94 | - motor2Command = "REVERSE"; |
|
| 95 | - } else if (elevatorControl > 60) { |
|
| 96 | - // Turn right (M1 forward, M2 reverse) |
|
| 97 | - driveMotor1(true); |
|
| 98 | - driveMotor2(false); |
|
| 99 | - motor1Command = "FORWARD"; |
|
| 100 | - motor2Command = "REVERSE"; |
|
| 101 | - } else if (elevatorControl < 40) { |
|
| 102 | - // Turn left (M1 reverse, M2 forward) |
|
| 103 | - driveMotor1(false); |
|
| 104 | - driveMotor2(true); |
|
| 105 | - motor1Command = "REVERSE"; |
|
| 106 | - motor2Command = "FORWARD"; |
|
| 107 | - } else { |
|
| 108 | - // Stop |
|
| 109 | - brakeMotor1(); |
|
| 110 | - brakeMotor2(); |
|
| 111 | - } |
|
| 112 | - |
|
| 113 | - // 1. RC INPUTS |
|
| 114 | - Serial.print("RC INPUT: "); |
|
| 115 | - Serial.print("Aileron="); Serial.print(rawAileronPWM); Serial.print("us ("); Serial.print(aileronControl); Serial.print("%), "); |
|
| 116 | - Serial.print("Elevator="); Serial.print(rawElevatorPWM); Serial.print("us ("); Serial.print(elevatorControl); Serial.println("%)"); |
|
| 117 | - |
|
| 118 | - // 2. COMMANDS |
|
| 119 | - Serial.print("MOTORS: "); |
|
| 120 | - Serial.print("M1="); Serial.print(motor1Command); Serial.print(", "); |
|
| 121 | - Serial.print("M2="); Serial.println(motor2Command); |
|
| 122 | - |
|
| 123 | - Serial.println(); |
|
| 124 | - |
|
| 125 | - delay(20); // Delay for RC input reading cycle |
|
| 126 | -} |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/rover-8871-3.ino
| ... | ... | @@ -1,132 +0,0 @@ |
| 1 | -// Define pins for each RC channel |
|
| 2 | -int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 3 | -int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 4 | - |
|
| 5 | -const int MOTOR1_CTRL_PIN = 4; // GPIO4 (D2) |
|
| 6 | -const int MOTOR2_CTRL_PIN = 5; // GPIO5 (D1) |
|
| 7 | - |
|
| 8 | -long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 9 | -long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 10 | - |
|
| 11 | -unsigned long rawAileronPWM = 0; |
|
| 12 | -unsigned long rawElevatorPWM = 0; |
|
| 13 | - |
|
| 14 | -const int PWM_MAX = 255; // ESP8266 PWM range is 0-255 for analogWrite |
|
| 15 | -const int PWM_STOP = PWM_MAX / 2; // Approx. 127, this is brake/neutral for DRV8871 single-pin |
|
| 16 | -const int PWM_MIN_MOVING = 10; // Minimum offset from PWM_STOP to ensure movement |
|
| 17 | - |
|
| 18 | -// Add these global variables for current speeds and ramp step |
|
| 19 | -int currentMotor1Speed = PWM_STOP; |
|
| 20 | -int currentMotor2Speed = PWM_STOP; |
|
| 21 | -const int RAMP_STEP = 5; // Adjust for desired smoothness. Smaller is smoother. |
|
| 22 | - |
|
| 23 | -long readAileronControlSignal() { |
|
| 24 | - rawAileronPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 25 | - if (rawAileronPWM == 0 || rawAileronPWM < 900 || rawAileronPWM > 2100) { |
|
| 26 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 27 | - } |
|
| 28 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 29 | - long constrainedPWM = constrain(rawAileronPWM, 1000, 2000); |
|
| 30 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 31 | -} |
|
| 32 | - |
|
| 33 | -long readElevatorControlSignal() { |
|
| 34 | - rawElevatorPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 35 | - if (rawElevatorPWM == 0 || rawElevatorPWM < 900 || rawElevatorPWM > 2100) { |
|
| 36 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 37 | - } |
|
| 38 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 39 | - long constrainedPWM = constrain(rawElevatorPWM, 1000, 2000); |
|
| 40 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 41 | -} |
|
| 42 | - |
|
| 43 | -void setup() { |
|
| 44 | - pinMode(aileronPin, INPUT); |
|
| 45 | - pinMode(elevatorPin, INPUT); |
|
| 46 | - |
|
| 47 | - pinMode(MOTOR1_CTRL_PIN, OUTPUT); |
|
| 48 | - pinMode(MOTOR2_CTRL_PIN, OUTPUT); |
|
| 49 | - |
|
| 50 | - Serial.begin(9600); |
|
| 51 | - |
|
| 52 | - // Initialize motors to braked state using currentSpeed variables |
|
| 53 | - currentMotor1Speed = PWM_STOP; |
|
| 54 | - currentMotor2Speed = PWM_STOP; |
|
| 55 | - analogWrite(MOTOR1_CTRL_PIN, currentMotor1Speed); |
|
| 56 | - analogWrite(MOTOR2_CTRL_PIN, currentMotor2Speed); |
|
| 57 | -} |
|
| 58 | - |
|
| 59 | -void loop() { |
|
| 60 | - // Read mapped control signals from each channel |
|
| 61 | - aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 62 | - elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 63 | - |
|
| 64 | - String motor1TargetCommand = "BRAKE"; // Command based on stick input |
|
| 65 | - String motor2TargetCommand = "BRAKE"; |
|
| 66 | - int targetMotor1Speed = PWM_STOP; // Target speed for this loop iteration |
|
| 67 | - int targetMotor2Speed = PWM_STOP; // Target speed for this loop iteration |
|
| 68 | - |
|
| 69 | - // Handle throttle control (forward/reverse) |
|
| 70 | - if (aileronControl > 55) { |
|
| 71 | - // Forward |
|
| 72 | - int speed = map(aileronControl, 61, 100, PWM_STOP + PWM_MIN_MOVING, PWM_MAX); |
|
| 73 | - speed = constrain(speed, PWM_STOP + PWM_MIN_MOVING, PWM_MAX); |
|
| 74 | - targetMotor1Speed = speed; |
|
| 75 | - targetMotor2Speed = speed; |
|
| 76 | - motor1TargetCommand = "FORWARD"; |
|
| 77 | - motor2TargetCommand = "FORWARD"; |
|
| 78 | - } else if (aileronControl < 45) { |
|
| 79 | - // Reverse |
|
| 80 | - int speed = map(aileronControl, 39, 0, PWM_STOP - PWM_MIN_MOVING, 0); |
|
| 81 | - speed = constrain(speed, 0, PWM_STOP - PWM_MIN_MOVING); |
|
| 82 | - targetMotor1Speed = speed; |
|
| 83 | - targetMotor2Speed = speed; |
|
| 84 | - motor1TargetCommand = "REVERSE"; |
|
| 85 | - motor2TargetCommand = "REVERSE"; |
|
| 86 | - } else if (elevatorControl > 55) { |
|
| 87 | - // Turn right (throttle is neutral) |
|
| 88 | - int turnOffset = map(elevatorControl, 61, 100, PWM_MIN_MOVING, (PWM_MAX - PWM_STOP)); |
|
| 89 | - targetMotor1Speed = constrain(PWM_STOP + turnOffset, 0, PWM_MAX); |
|
| 90 | - targetMotor2Speed = constrain(PWM_STOP - turnOffset, 0, PWM_MAX); |
|
| 91 | - motor1TargetCommand = "TURN_R_M1"; |
|
| 92 | - motor2TargetCommand = "TURN_R_M2"; |
|
| 93 | - } else if (elevatorControl < 45) { |
|
| 94 | - // Turn left (throttle is neutral) |
|
| 95 | - int turnOffset = map(elevatorControl, 39, 0, PWM_MIN_MOVING, (PWM_MAX - PWM_STOP)); |
|
| 96 | - targetMotor1Speed = constrain(PWM_STOP - turnOffset, 0, PWM_MAX); |
|
| 97 | - targetMotor2Speed = constrain(PWM_STOP + turnOffset, 0, PWM_MAX); |
|
| 98 | - motor1TargetCommand = "TURN_L_M1"; |
|
| 99 | - motor2TargetCommand = "TURN_L_M2"; |
|
| 100 | - } else { |
|
| 101 | - // All sticks neutral - Target speeds remain PWM_STOP (Brake) |
|
| 102 | - // motor1TargetCommand and motor2TargetCommand remain "BRAKE" |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - // Ramping logic for Motor 1 |
|
| 106 | - if (currentMotor1Speed < targetMotor1Speed) { |
|
| 107 | - currentMotor1Speed = min(currentMotor1Speed + RAMP_STEP, targetMotor1Speed); |
|
| 108 | - } else if (currentMotor1Speed > targetMotor1Speed) { |
|
| 109 | - currentMotor1Speed = max(currentMotor1Speed - RAMP_STEP, targetMotor1Speed); |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - // Ramping logic for Motor 2 |
|
| 113 | - if (currentMotor2Speed < targetMotor2Speed) { |
|
| 114 | - currentMotor2Speed = min(currentMotor2Speed + RAMP_STEP, targetMotor2Speed); |
|
| 115 | - } else if (currentMotor2Speed > targetMotor2Speed) { |
|
| 116 | - currentMotor2Speed = max(currentMotor2Speed - RAMP_STEP, targetMotor2Speed); |
|
| 117 | - } |
|
| 118 | - |
|
| 119 | - // Apply the ramped speeds |
|
| 120 | - analogWrite(MOTOR1_CTRL_PIN, currentMotor1Speed); |
|
| 121 | - analogWrite(MOTOR2_CTRL_PIN, currentMotor2Speed); |
|
| 122 | - |
|
| 123 | - Serial.print("RC INPUT: "); |
|
| 124 | - Serial.print("Aileron="); Serial.print(rawAileronPWM); Serial.print("us ("); Serial.print(aileronControl); Serial.print("%), "); |
|
| 125 | - Serial.print("Elevator="); Serial.print(rawElevatorPWM); Serial.print("us ("); Serial.print(elevatorControl); Serial.print("%)"); |
|
| 126 | - Serial.print("MOTORS: "); |
|
| 127 | - Serial.print("M1_Cmd="); Serial.print(motor1TargetCommand); Serial.print(" (CurPWM:"); Serial.print(currentMotor1Speed); Serial.print(" TgtPWM:"); Serial.print(targetMotor1Speed); Serial.print("), "); |
|
| 128 | - Serial.print("M2_Cmd="); Serial.print(motor2TargetCommand); Serial.print(" (CurPWM:"); Serial.print(currentMotor2Speed); Serial.print(" TgtPWM:"); Serial.print(targetMotor2Speed); Serial.print(")"); |
|
| 129 | - |
|
| 130 | - Serial.println(); |
|
| 131 | - delay(20); // Delay for RC input reading cycle & ramping interval |
|
| 132 | -} |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/rover-8871-4.ino
| ... | ... | @@ -1,180 +0,0 @@ |
| 1 | -#include <Adafruit_NeoPixel.h> |
|
| 2 | - |
|
| 3 | -// Define pins for each RC channel |
|
| 4 | -int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 5 | -int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 6 | - |
|
| 7 | -// WS2812 LED Strip Configuration |
|
| 8 | -#define LED_PIN 15 // nodemcu pin D8 |
|
| 9 | -#define LED_COUNT 8 |
|
| 10 | -Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); |
|
| 11 | - |
|
| 12 | -// Updated comments for IN1 and IN2 to reflect their role as single control pins |
|
| 13 | -const int IN1 = 4; // Control pin for Motor 1 // D3 (was GPIO2 on NodeMCU D4, now D2/GPIO4) |
|
| 14 | -const int IN2 = 5; // Control pin for Motor 2 // D4 (was GPIO0 on NodeMCU D3, now D1/GPIO5) |
|
| 15 | - |
|
| 16 | -const int PWM_MAX = 255; // ESP8266 PWM range is 0-255 for analogWrite. |
|
| 17 | - // Note: Default ESP8266 analogWrite range is 0-1023. |
|
| 18 | - // Call analogWriteRange(255) in setup if 0-255 is desired. |
|
| 19 | -const int PWM_STOP = PWM_MAX / 2; // Approx. 127, this is brake/neutral for DRV8871 single-pin |
|
| 20 | -const int PWM_MIN_MOVING = 10; // Minimum offset from PWM_STOP to ensure movement |
|
| 21 | - |
|
| 22 | - |
|
| 23 | -long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 24 | -long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 25 | - |
|
| 26 | -// Reads the PWM signal from the aileron channel and maps it to 0-100 |
|
| 27 | -long readAileronControlSignal() { |
|
| 28 | - unsigned long rawPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 29 | - // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 30 | - // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 31 | - if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 32 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 33 | - } |
|
| 34 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 35 | - long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 36 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 37 | -} |
|
| 38 | - |
|
| 39 | -// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 40 | -long readElevatorControlSignal() { |
|
| 41 | - unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 42 | - // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 43 | - // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 44 | - if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 45 | - return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 46 | - } |
|
| 47 | - // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 48 | - long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 49 | - return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 50 | -} |
|
| 51 | - |
|
| 52 | -void setup() { |
|
| 53 | - pinMode(aileronPin, INPUT); |
|
| 54 | - pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 55 | - |
|
| 56 | - pinMode(IN1, OUTPUT); |
|
| 57 | - pinMode(IN2, OUTPUT); |
|
| 58 | - |
|
| 59 | - // Initialize motors to brake state |
|
| 60 | - analogWrite(IN1, PWM_STOP); |
|
| 61 | - analogWrite(IN2, PWM_STOP); |
|
| 62 | - |
|
| 63 | - Serial.begin(9600); |
|
| 64 | - // If you intend PWM_MAX to be 255, you might need to call: |
|
| 65 | - // analogWriteRange(255); |
|
| 66 | - // Otherwise, analogWrite will use a 0-1023 range by default on ESP8266. |
|
| 67 | - |
|
| 68 | - strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) |
|
| 69 | - strip.show(); // Turn OFF all pixels ASAP |
|
| 70 | - strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255) |
|
| 71 | -} |
|
| 72 | - |
|
| 73 | -// Updated helper function to control a single motor using one control pin |
|
| 74 | -// motorCtrlPin: The pin connected to the motor driver's input (e.g., IN1 for motor 1) |
|
| 75 | -// pwmVal: -255 (full backward) to 255 (full forward), 0 for brake |
|
| 76 | -void setMotorOutput(int motorCtrlPin, int pwmVal) { |
|
| 77 | - int actualPwm; |
|
| 78 | - if (pwmVal == 0) { |
|
| 79 | - actualPwm = PWM_STOP; // Brake |
|
| 80 | - } else if (pwmVal > 0) { // Forward |
|
| 81 | - // Map pwmVal from (1 to 255) to (PWM_STOP + PWM_MIN_MOVING to PWM_MAX) |
|
| 82 | - actualPwm = map(pwmVal, 1, 255, PWM_STOP + PWM_MIN_MOVING, PWM_MAX); |
|
| 83 | - // Ensure the value is within the defined forward motion range |
|
| 84 | - actualPwm = constrain(actualPwm, PWM_STOP + PWM_MIN_MOVING, PWM_MAX); |
|
| 85 | - } else { // Backward (pwmVal < 0) |
|
| 86 | - // Map abs(pwmVal) from (1 to 255) to (PWM_STOP - PWM_MIN_MOVING to 0) |
|
| 87 | - actualPwm = map(abs(pwmVal), 1, 255, PWM_STOP - PWM_MIN_MOVING, 0); |
|
| 88 | - // Ensure the value is within the defined reverse motion range |
|
| 89 | - actualPwm = constrain(actualPwm, 0, PWM_STOP - PWM_MIN_MOVING); |
|
| 90 | - } |
|
| 91 | - analogWrite(motorCtrlPin, actualPwm); |
|
| 92 | -} |
|
| 93 | - |
|
| 94 | -// Helper function to map RC control input (0-100) to an output range (e.g., -255 to 255) |
|
| 95 | -// with a deadband around the center (e.g., 50). |
|
| 96 | -long mapWithDeadband(long rcValue, int rcMin, int rcMax, int rcCenter, int deadbandRadius, int outMin, int outMax) { |
|
| 97 | - long mappedValue = 0; |
|
| 98 | - int deadbandLower = rcCenter - deadbandRadius; |
|
| 99 | - int deadbandUpper = rcCenter + deadbandRadius; |
|
| 100 | - |
|
| 101 | - if (rcValue < deadbandLower) { |
|
| 102 | - // Map the range [rcMin, deadbandLower - 1] to [outMin, -1] |
|
| 103 | - // Ensure deadbandLower - 1 is not less than rcMin |
|
| 104 | - if (deadbandLower -1 < rcMin) { |
|
| 105 | - mappedValue = outMin; |
|
| 106 | - } else { |
|
| 107 | - mappedValue = map(rcValue, rcMin, deadbandLower - 1, outMin, -1); |
|
| 108 | - } |
|
| 109 | - } else if (rcValue > deadbandUpper) { |
|
| 110 | - // Map the range [deadbandUpper + 1, rcMax] to [1, outMax] |
|
| 111 | - // Ensure deadbandUpper + 1 is not greater than rcMax |
|
| 112 | - if (deadbandUpper + 1 > rcMax) { |
|
| 113 | - mappedValue = outMax; |
|
| 114 | - } else { |
|
| 115 | - mappedValue = map(rcValue, deadbandUpper + 1, rcMax, 1, outMax); |
|
| 116 | - } |
|
| 117 | - } else { |
|
| 118 | - // Inside deadband |
|
| 119 | - mappedValue = 0; |
|
| 120 | - } |
|
| 121 | - return constrain(mappedValue, outMin, outMax); |
|
| 122 | -} |
|
| 123 | - |
|
| 124 | -// Function to create a random blinking effect for WS2812 LEDs |
|
| 125 | -void randomBlinkEffect() { |
|
| 126 | - for (int i = 0; i < LED_COUNT; i++) { |
|
| 127 | - // Turn on a random LED with a random color |
|
| 128 | - if (random(0, 2) == 1) { // 50% chance to turn on this LED |
|
| 129 | - strip.setPixelColor(i, strip.Color(random(0, 256), random(0, 256), random(0, 256))); |
|
| 130 | - } else { |
|
| 131 | - strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off |
|
| 132 | - } |
|
| 133 | - } |
|
| 134 | - strip.show(); // Send the updated pixel colors to the hardware. |
|
| 135 | - delay(100); // Wait a short period |
|
| 136 | -} |
|
| 137 | - |
|
| 138 | -void loop() { |
|
| 139 | - // Read mapped control signals from each channel |
|
| 140 | - aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 141 | - elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 142 | - |
|
| 143 | - // Print the mapped control signal values to the Serial Monitor |
|
| 144 | - Serial.print("Aileron (Throttle): "); |
|
| 145 | - Serial.print(aileronControl); |
|
| 146 | - Serial.print(" Elevator (Steering): "); |
|
| 147 | - Serial.print(elevatorControl); |
|
| 148 | - Serial.println(); |
|
| 149 | - |
|
| 150 | - // Define deadband radius (e.g., +/- 5 around center of 50 for a 0-100 input) |
|
| 151 | - // This means input values from 45 to 55 (inclusive if center is 50 and radius is 5) will be treated as 0. |
|
| 152 | - int deadbandRadius = 15; |
|
| 153 | - float steeringFactor = 1; // Adjust this value to change steering sensitivity |
|
| 154 | - float throttleFactor = 1; // Adjust this value to change throttle sensitivity (e.g., 1.2 for 20% stronger throttle) |
|
| 155 | - |
|
| 156 | - // Map control values with deadband |
|
| 157 | - long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 158 | - long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 159 | - |
|
| 160 | - // Apply sensitivity factors |
|
| 161 | - long throttleValue = rawThrottleValue * throttleFactor; |
|
| 162 | - long adjustedSteeringValue = rawSteeringValue * steeringFactor; |
|
| 163 | - |
|
| 164 | - // Mix throttle and steering for differential drive |
|
| 165 | - long motor1Pwm = throttleValue + adjustedSteeringValue; |
|
| 166 | - long motor2Pwm = throttleValue - adjustedSteeringValue; |
|
| 167 | - |
|
| 168 | - // Constrain PWM values to the valid range [-255, 255] |
|
| 169 | - motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 170 | - motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 171 | - |
|
| 172 | - // Set motor speeds and directions using the updated function |
|
| 173 | - setMotorOutput(IN1, motor1Pwm); // Motor 1 |
|
| 174 | - setMotorOutput(IN2, motor2Pwm); // Motor 2 |
|
| 175 | - |
|
| 176 | - // Add the LED effect |
|
| 177 | - randomBlinkEffect(); |
|
| 178 | - |
|
| 179 | - delay(20); // Shorter delay for better responsiveness |
|
| 180 | -} |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/rover-8871-test.ino
| ... | ... | @@ -1,29 +0,0 @@ |
| 1 | -// Define pins for each RC channel |
|
| 2 | -int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 3 | -int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 4 | - |
|
| 5 | -// Motor control pins |
|
| 6 | -const int MOTOR1_CTRL_PIN = 4; // GPIO4 (D2) |
|
| 7 | -const int MOTOR2_CTRL_PIN = 5; // GPIO5 (D1) |
|
| 8 | - |
|
| 9 | -const int PWM_MAX = 1023; // ESP8266 PWM range is 0-1023 |
|
| 10 | -const int PWM_STOP = PWM_MAX / 2; // ~511 or 512 |
|
| 11 | - |
|
| 12 | -void setup() { |
|
| 13 | - pinMode(MOTOR1_CTRL_PIN, OUTPUT); |
|
| 14 | - pinMode(MOTOR2_CTRL_PIN, OUTPUT); |
|
| 15 | - Serial.begin(9600); |
|
| 16 | -} |
|
| 17 | - |
|
| 18 | - |
|
| 19 | -void loop() { |
|
| 20 | - for (int pwm = 0; pwm <= PWM_MAX; pwm += 50) { |
|
| 21 | - |
|
| 22 | - // Apply the PWM value to both motors |
|
| 23 | - analogWrite(MOTOR1_CTRL_PIN, pwm); |
|
| 24 | - analogWrite(MOTOR2_CTRL_PIN, pwm); |
|
| 25 | - |
|
| 26 | - // Wait a moment at this PWM value |
|
| 27 | - delay(500); |
|
| 28 | - } |
|
| 29 | -} |
|
| ... | ... | \ No newline at end of file |
Network-dat/RC-dat/RC-code-dat/ultrasonic car-1602.pde
| ... | ... | @@ -1,399 +0,0 @@ |
| 1 | -#include <IRremote.h> |
|
| 2 | -#include <Servo.h> |
|
| 3 | -#include <Wire.h> |
|
| 4 | -#include <LiquidCrystal_I2C.h> |
|
| 5 | - |
|
| 6 | -//***********************定義馬達腳位************************* |
|
| 7 | -int MotorRight1=6; |
|
| 8 | -int MotorRight2=9; |
|
| 9 | -int MotorLeft1=10; |
|
| 10 | -int MotorLeft2=11; |
|
| 11 | -int counter=0; |
|
| 12 | -const int irReceiverPin = 3; //紅外線接收器 OUTPUT 訊號接在 pin 2 |
|
| 13 | - |
|
| 14 | -//***********************設定所偵測到的IRcode************************* |
|
| 15 | -long IRfront= 0x00FF629D; //前進碼 |
|
| 16 | -long IRback=0x00FFA857; //後退 |
|
| 17 | -long IRturnright=0x00FF22DD; //右轉 |
|
| 18 | -long IRturnleft= 0x00FFC23D; //左轉 |
|
| 19 | -long IRstop=0x00FF02FD; //停止 |
|
| 20 | -long IRAutorun=0x00FF6897; //超音波自走模式 |
|
| 21 | -long IRturnsmallleft= 0x00FFB04F; |
|
| 22 | -IRrecv irrecv(irReceiverPin); // 定義 IRrecv 物件來接收紅外線訊號 |
|
| 23 | -decode_results results; |
|
| 24 | -//*************************定義超音波腳位****************************** |
|
| 25 | -int inputPin =A0 ; // 定義超音波信號接收腳位rx |
|
| 26 | -int outputPin =A1; // 定義超音波信號發射腳位'tx |
|
| 27 | -int Fspeedd = 0; // 前方距離 |
|
| 28 | -int Rspeedd = 0; // 右方距離 |
|
| 29 | -int Lspeedd = 0; // 左方距離 |
|
| 30 | -int directionn = 0; // 前=8 後=2 左=4 右=6 |
|
| 31 | -Servo myservo; // 設 myservo |
|
| 32 | -int delay_time = 250; // 伺服馬達轉向後的穩定時間 |
|
| 33 | -int Fgo = 8; // 前進 |
|
| 34 | -int Rgo = 6; // 右轉 |
|
| 35 | -int Lgo = 4; // 左轉 |
|
| 36 | -int Bgo = 2; // 倒車 |
|
| 37 | -//********************************************************************(SETUP) |
|
| 38 | -LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display |
|
| 39 | -void setup() |
|
| 40 | -{ |
|
| 41 | - Serial.begin(9600); |
|
| 42 | - pinMode(MotorRight1, OUTPUT); // 腳位 8 (PWM) |
|
| 43 | - pinMode(MotorRight2, OUTPUT); // 腳位 9 (PWM) |
|
| 44 | - pinMode(MotorLeft1, OUTPUT); // 腳位 10 (PWM) |
|
| 45 | - pinMode(MotorLeft2, OUTPUT); // 腳位 11 (PWM) |
|
| 46 | - irrecv.enableIRIn(); // 啟動紅外線解碼 |
|
| 47 | - digitalWrite(3,HIGH); |
|
| 48 | - pinMode(inputPin, INPUT); // 定義超音波輸入腳位 |
|
| 49 | - pinMode(outputPin, OUTPUT); // 定義超音波輸出腳位 |
|
| 50 | - myservo.attach(5); // 定義伺服馬達輸出第5腳位(PWM) |
|
| 51 | - lcd.init(); // initialize the lcd |
|
| 52 | - lcd.init(); |
|
| 53 | - // Print a message to the LCD. |
|
| 54 | - lcd.backlight(); |
|
| 55 | - |
|
| 56 | - |
|
| 57 | - |
|
| 58 | - } |
|
| 59 | -//******************************************************************(Void) |
|
| 60 | -void advance(int a) // 前進 |
|
| 61 | -{ |
|
| 62 | - digitalWrite(MotorRight1,LOW); |
|
| 63 | - digitalWrite(MotorRight2,HIGH); |
|
| 64 | - digitalWrite(MotorLeft1,LOW); |
|
| 65 | - digitalWrite(MotorLeft2,HIGH); |
|
| 66 | - delay(a * 100); |
|
| 67 | -} |
|
| 68 | -void right(int b) //右轉(單輪) |
|
| 69 | -{ |
|
| 70 | - digitalWrite(MotorLeft1,LOW); |
|
| 71 | - digitalWrite(MotorLeft2,HIGH); |
|
| 72 | - digitalWrite(MotorRight1,LOW); |
|
| 73 | - digitalWrite(MotorRight2,LOW); |
|
| 74 | - delay(b * 100); |
|
| 75 | -} |
|
| 76 | -void left(int c) //左轉(單輪) |
|
| 77 | -{ |
|
| 78 | - digitalWrite(MotorRight1,LOW); |
|
| 79 | - digitalWrite(MotorRight2,HIGH); |
|
| 80 | - digitalWrite(MotorLeft1,LOW); |
|
| 81 | - digitalWrite(MotorLeft2,LOW); |
|
| 82 | - delay(c * 100); |
|
| 83 | -} |
|
| 84 | -void turnR(int d) //右轉(雙輪) |
|
| 85 | -{ |
|
| 86 | - digitalWrite(MotorRight1,HIGH); |
|
| 87 | - digitalWrite(MotorRight2,LOW); |
|
| 88 | - digitalWrite(MotorLeft1,LOW); |
|
| 89 | - digitalWrite(MotorLeft2,HIGH); |
|
| 90 | - delay(d * 100); |
|
| 91 | -} |
|
| 92 | -void turnL(int e) //左轉(雙輪) |
|
| 93 | -{ |
|
| 94 | - digitalWrite(MotorRight1,LOW); |
|
| 95 | - digitalWrite(MotorRight2,HIGH); |
|
| 96 | - digitalWrite(MotorLeft1,HIGH); |
|
| 97 | - digitalWrite(MotorLeft2,LOW); |
|
| 98 | - delay(e * 100); |
|
| 99 | -} |
|
| 100 | -void stopp(int f) //停止 |
|
| 101 | -{ |
|
| 102 | - digitalWrite(MotorRight1,LOW); |
|
| 103 | - digitalWrite(MotorRight2,LOW); |
|
| 104 | - digitalWrite(MotorLeft1,LOW); |
|
| 105 | - digitalWrite(MotorLeft2,LOW); |
|
| 106 | - delay(f * 100); |
|
| 107 | -} |
|
| 108 | -void back(int g) //後退 |
|
| 109 | -{ |
|
| 110 | - digitalWrite(MotorRight1,HIGH); |
|
| 111 | - digitalWrite(MotorRight2,LOW); |
|
| 112 | - digitalWrite(MotorLeft1,HIGH); |
|
| 113 | - digitalWrite(MotorLeft2,LOW);; |
|
| 114 | - delay(g * 100); |
|
| 115 | -} |
|
| 116 | -void detection() //測量3個角度(前.左.右) |
|
| 117 | -{ |
|
| 118 | - int delay_time = 250; // 伺服馬達轉向後的穩定時間 |
|
| 119 | - ask_pin_F(); // 讀取前方距離 |
|
| 120 | - |
|
| 121 | - if(Fspeedd < 10) // 假如前方距離小於10公分 |
|
| 122 | - { |
|
| 123 | - stopp(1); // 清除輸出資料 |
|
| 124 | - back(2); // 後退 0.2秒 |
|
| 125 | - |
|
| 126 | - |
|
| 127 | - } |
|
| 128 | - if(Fspeedd < 25) // 假如前方距離小於25公分 |
|
| 129 | - { |
|
| 130 | - stopp(1); // 清除輸出資料 |
|
| 131 | - ask_pin_L(); // 讀取左方距離 |
|
| 132 | - delay(delay_time); // 等待伺服馬達穩定 |
|
| 133 | - ask_pin_R(); // 讀取右方距離 |
|
| 134 | - delay(delay_time); // 等待伺服馬達穩定 |
|
| 135 | - |
|
| 136 | - if(Lspeedd > Rspeedd) //假如 左邊距離大於右邊距離 |
|
| 137 | - { |
|
| 138 | - directionn = Lgo; //向左走 |
|
| 139 | - } |
|
| 140 | - |
|
| 141 | - if(Lspeedd <= Rspeedd) //假如 左邊距離小於或等於右邊距離 |
|
| 142 | - { |
|
| 143 | - directionn = Rgo; //向右走 |
|
| 144 | - } |
|
| 145 | - |
|
| 146 | - if (Lspeedd < 15 && Rspeedd < 15) //假如 左邊距離和右邊距離皆小於10公分 |
|
| 147 | - { |
|
| 148 | - directionn = Bgo; //向後走 |
|
| 149 | - } |
|
| 150 | - } |
|
| 151 | - else //加如前方大於25公分 |
|
| 152 | - { |
|
| 153 | - directionn = Fgo; //向前走 |
|
| 154 | - } |
|
| 155 | -} |
|
| 156 | -//********************************************************************************* |
|
| 157 | -void ask_pin_F() // 量出前方距離 |
|
| 158 | -{ |
|
| 159 | -myservo.write(90); |
|
| 160 | -digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs |
|
| 161 | -delayMicroseconds(2); |
|
| 162 | -digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓10μs,這裡至少是10μs |
|
| 163 | -delayMicroseconds(10); |
|
| 164 | -digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 165 | -float Fdistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 166 | -Fdistance= Fdistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 167 | - |
|
| 168 | -Fspeedd = Fdistance; // 將距離 讀入Fspeedd(前速) |
|
| 169 | -} |
|
| 170 | -//******************************************************************************** |
|
| 171 | -void ask_pin_L() // 量出左邊距離 |
|
| 172 | -{ |
|
| 173 | -myservo.write(177); |
|
| 174 | -delay(delay_time); |
|
| 175 | -digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs |
|
| 176 | -delayMicroseconds(2); |
|
| 177 | -digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓10μs,這裡至少是10μs |
|
| 178 | -delayMicroseconds(10); |
|
| 179 | -digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 180 | -float Ldistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 181 | -Ldistance= Ldistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 182 | - |
|
| 183 | -Lspeedd = Ldistance; // 將距離 讀入Lspeedd(左速) |
|
| 184 | -} |
|
| 185 | -//****************************************************************************** |
|
| 186 | -void ask_pin_R() // 量出右邊距離 |
|
| 187 | -{ |
|
| 188 | -myservo.write(5); |
|
| 189 | -delay(delay_time); |
|
| 190 | -digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs |
|
| 191 | -delayMicroseconds(2); |
|
| 192 | -digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓10μs,這裡至少是10μs |
|
| 193 | -delayMicroseconds(10); |
|
| 194 | -digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 195 | -float Rdistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 196 | -Rdistance= Rdistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 197 | - |
|
| 198 | -Rspeedd = Rdistance; // 將距離 讀入Rspeedd(右速) |
|
| 199 | -} |
|
| 200 | -//******************************************************************************(LOOP) |
|
| 201 | -void loop() |
|
| 202 | -{ |
|
| 203 | - |
|
| 204 | -//***************************************************************************正常遙控模式 |
|
| 205 | - if (irrecv.decode(&results)) |
|
| 206 | - { // 解碼成功,收到一組紅外線訊號 |
|
| 207 | -/***********************************************************************/ |
|
| 208 | - if (results.value == IRfront)//前進 |
|
| 209 | - { |
|
| 210 | - |
|
| 211 | - lcd.setCursor(0,0); |
|
| 212 | - lcd.print(" IR mode"); |
|
| 213 | - lcd.setCursor(0,1); |
|
| 214 | - lcd.print(" advance "); |
|
| 215 | - advance(20);//前進 |
|
| 216 | - } |
|
| 217 | -/***********************************************************************/ |
|
| 218 | - if (results.value == IRback)//後退 |
|
| 219 | - { |
|
| 220 | - |
|
| 221 | - lcd.setCursor(0,0); |
|
| 222 | - lcd.print(" IR mode"); |
|
| 223 | - lcd.setCursor(0,1); |
|
| 224 | - lcd.print(" back "); |
|
| 225 | - back(20);//後退 |
|
| 226 | - } |
|
| 227 | -/***********************************************************************/ |
|
| 228 | - if (results.value == IRturnright)//右轉 |
|
| 229 | - { |
|
| 230 | - |
|
| 231 | - lcd.setCursor(0,0); |
|
| 232 | - lcd.print(" IR mode"); |
|
| 233 | - lcd.setCursor(0,1); |
|
| 234 | - lcd.print(" right "); |
|
| 235 | - right(10); // 右轉 |
|
| 236 | - |
|
| 237 | - } |
|
| 238 | -/***********************************************************************/ |
|
| 239 | - if (results.value == IRturnleft)//左轉 |
|
| 240 | - { |
|
| 241 | - |
|
| 242 | - lcd.setCursor(0,0); |
|
| 243 | - lcd.print(" IR mode"); |
|
| 244 | - lcd.setCursor(0,1); |
|
| 245 | - lcd.print(" left "); |
|
| 246 | - left(10); // 左轉); |
|
| 247 | - } |
|
| 248 | -/***********************************************************************/ |
|
| 249 | - if (results.value == IRstop)//停止 |
|
| 250 | - { |
|
| 251 | - lcd.setCursor(0,0); |
|
| 252 | - lcd.print(" IR mode"); |
|
| 253 | - lcd.setCursor(0,1); |
|
| 254 | - lcd.print(" stop "); |
|
| 255 | - digitalWrite(MotorRight1,LOW); |
|
| 256 | - digitalWrite(MotorRight2,LOW); |
|
| 257 | - digitalWrite(MotorLeft1,LOW); |
|
| 258 | - digitalWrite(MotorLeft2,LOW); |
|
| 259 | - |
|
| 260 | - |
|
| 261 | - } |
|
| 262 | - |
|
| 263 | -//***********************************************************************超音波自走模式 |
|
| 264 | - if (results.value ==IRAutorun ) |
|
| 265 | - { |
|
| 266 | - while(IRAutorun) |
|
| 267 | - { |
|
| 268 | - myservo.write(90); //讓伺服馬達回歸 預備位置 準備下一次的測量 |
|
| 269 | - detection(); //測量角度 並且判斷要往哪一方向移動 |
|
| 270 | - if(directionn == 8) //假如directionn(方向) = 8(前進) |
|
| 271 | - { |
|
| 272 | - if (irrecv.decode(&results)) |
|
| 273 | - { |
|
| 274 | - irrecv.resume(); |
|
| 275 | - Serial.println(results.value,HEX); |
|
| 276 | - if(results.value ==IRstop) |
|
| 277 | - { |
|
| 278 | - digitalWrite(MotorRight1,LOW); |
|
| 279 | - digitalWrite(MotorRight2,LOW); |
|
| 280 | - digitalWrite(MotorLeft1,LOW); |
|
| 281 | - digitalWrite(MotorLeft2,LOW); |
|
| 282 | - break; |
|
| 283 | - } |
|
| 284 | - } |
|
| 285 | - results.value=0; |
|
| 286 | - |
|
| 287 | - |
|
| 288 | - lcd.setCursor(0,0); |
|
| 289 | - lcd.print(" aoto mode"); |
|
| 290 | - lcd.setCursor(0,1); |
|
| 291 | - lcd.print(" Advance "); |
|
| 292 | - advance(1); // 正常前進 |
|
| 293 | - } |
|
| 294 | - if(directionn == 2) //假如directionn(方向) = 2(倒車) |
|
| 295 | - { |
|
| 296 | - if (irrecv.decode(&results)) |
|
| 297 | - { |
|
| 298 | - irrecv.resume(); |
|
| 299 | - Serial.println(results.value,HEX); |
|
| 300 | - if(results.value ==IRstop) |
|
| 301 | - { |
|
| 302 | - digitalWrite(MotorRight1,LOW); |
|
| 303 | - digitalWrite(MotorRight2,LOW); |
|
| 304 | - digitalWrite(MotorLeft1,LOW); |
|
| 305 | - digitalWrite(MotorLeft2,LOW); |
|
| 306 | - break; |
|
| 307 | - } |
|
| 308 | - } |
|
| 309 | - results.value=0; |
|
| 310 | - |
|
| 311 | - |
|
| 312 | - lcd.setCursor(0,0); |
|
| 313 | - lcd.print(" aoto mode"); |
|
| 314 | - lcd.setCursor(0,1); |
|
| 315 | - lcd.print(" Reverse "); |
|
| 316 | - back(8); // 倒退(車) |
|
| 317 | - turnL(3); //些微向左方移動(防止卡在死巷裡) |
|
| 318 | - } |
|
| 319 | - if(directionn == 6) //假如directionn(方向) = 6(右轉) |
|
| 320 | - { |
|
| 321 | - if (irrecv.decode(&results)) |
|
| 322 | - { |
|
| 323 | - irrecv.resume(); |
|
| 324 | - Serial.println(results.value,HEX); |
|
| 325 | - if(results.value ==IRstop) |
|
| 326 | - { |
|
| 327 | - digitalWrite(MotorRight1,LOW); |
|
| 328 | - digitalWrite(MotorRight2,LOW); |
|
| 329 | - digitalWrite(MotorLeft1,LOW); |
|
| 330 | - digitalWrite(MotorLeft2,LOW); |
|
| 331 | - break; |
|
| 332 | - } |
|
| 333 | - } |
|
| 334 | - results.value=0; |
|
| 335 | - |
|
| 336 | - |
|
| 337 | - lcd.setCursor(0,0); |
|
| 338 | - lcd.print(" aoto mode"); |
|
| 339 | - lcd.setCursor(0,1); |
|
| 340 | - lcd.print(" Right "); |
|
| 341 | - back(1); |
|
| 342 | - turnR(3); // 右轉 |
|
| 343 | - } |
|
| 344 | - if(directionn == 4) //假如directionn(方向) = 4(左轉) |
|
| 345 | - { |
|
| 346 | - if (irrecv.decode(&results)) |
|
| 347 | - { |
|
| 348 | - irrecv.resume(); |
|
| 349 | - Serial.println(results.value,HEX); |
|
| 350 | - if(results.value ==IRstop) |
|
| 351 | - { |
|
| 352 | - digitalWrite(MotorRight1,LOW); |
|
| 353 | - digitalWrite(MotorRight2,LOW); |
|
| 354 | - digitalWrite(MotorLeft1,LOW); |
|
| 355 | - digitalWrite(MotorLeft2,LOW); |
|
| 356 | - break; |
|
| 357 | - } |
|
| 358 | - } |
|
| 359 | - results.value=0; |
|
| 360 | - |
|
| 361 | - lcd.setCursor(0,0); |
|
| 362 | - lcd.print(" aoto mode"); |
|
| 363 | - lcd.setCursor(0,1); |
|
| 364 | - lcd.print(" Left "); |
|
| 365 | - back(1); |
|
| 366 | - turnL(3); // 左轉 |
|
| 367 | - |
|
| 368 | - } |
|
| 369 | - |
|
| 370 | - if (irrecv.decode(&results)) |
|
| 371 | - { |
|
| 372 | - irrecv.resume(); |
|
| 373 | - Serial.println(results.value,HEX); |
|
| 374 | - if(results.value ==IRstop) |
|
| 375 | - { |
|
| 376 | - digitalWrite(MotorRight1,LOW); |
|
| 377 | - digitalWrite(MotorRight2,LOW); |
|
| 378 | - digitalWrite(MotorLeft1,LOW); |
|
| 379 | - digitalWrite(MotorLeft2,LOW); |
|
| 380 | - break; |
|
| 381 | - } |
|
| 382 | - } |
|
| 383 | - } |
|
| 384 | - results.value=0; |
|
| 385 | - } |
|
| 386 | -/***********************************************************************/ |
|
| 387 | - else |
|
| 388 | - { |
|
| 389 | - digitalWrite(MotorRight1,LOW); |
|
| 390 | - digitalWrite(MotorRight2,LOW); |
|
| 391 | - digitalWrite(MotorLeft1,LOW); |
|
| 392 | - digitalWrite(MotorLeft2,LOW); |
|
| 393 | - } |
|
| 394 | - |
|
| 395 | - |
|
| 396 | - irrecv.resume(); // 繼續收下一組紅外線訊號 |
|
| 397 | - } |
|
| 398 | -} |
|
| 399 | - |
code-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 |
code-dat/RC-code-dat/PWM-2ch-2.ino
| ... | ... | @@ -0,0 +1,142 @@ |
| 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 signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 18 | + // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 19 | + if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 20 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 21 | + } |
|
| 22 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 23 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 24 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 25 | +} |
|
| 26 | + |
|
| 27 | +// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 28 | +long readElevatorControlSignal() { |
|
| 29 | + unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 30 | + // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 31 | + // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 32 | + if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 33 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 34 | + } |
|
| 35 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 36 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 37 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 38 | +} |
|
| 39 | + |
|
| 40 | +void setup() { |
|
| 41 | + pinMode(aileronPin, INPUT); |
|
| 42 | + pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 43 | + |
|
| 44 | + pinMode(ENA, OUTPUT); |
|
| 45 | + pinMode(ENB, OUTPUT); |
|
| 46 | + pinMode(IN1, OUTPUT); |
|
| 47 | + pinMode(IN2, OUTPUT); |
|
| 48 | + |
|
| 49 | + // Initialize motors to off |
|
| 50 | + digitalWrite(IN1, LOW); |
|
| 51 | + digitalWrite(IN2, LOW); |
|
| 52 | + analogWrite(ENA, 0); |
|
| 53 | + analogWrite(ENB, 0); |
|
| 54 | + |
|
| 55 | + Serial.begin(9600); |
|
| 56 | +} |
|
| 57 | + |
|
| 58 | +// Helper function to control a single motor |
|
| 59 | +// pwmVal: -255 (full backward) to 255 (full forward) |
|
| 60 | +void setMotorOutput(int dirPin, int speedPin, int pwmVal) { |
|
| 61 | + if (pwmVal > 0) { // Forward |
|
| 62 | + digitalWrite(dirPin, HIGH); |
|
| 63 | + analogWrite(speedPin, pwmVal); |
|
| 64 | + } else if (pwmVal < 0) { // Backward |
|
| 65 | + digitalWrite(dirPin, LOW); |
|
| 66 | + analogWrite(speedPin, -pwmVal); // Speed is positive |
|
| 67 | + } else { // Stop |
|
| 68 | + digitalWrite(dirPin, LOW); // Or HIGH, doesn't matter much if speed is 0 |
|
| 69 | + analogWrite(speedPin, 0); |
|
| 70 | + } |
|
| 71 | +} |
|
| 72 | + |
|
| 73 | +// Helper function to map RC control input (0-100) to an output range (e.g., -255 to 255) |
|
| 74 | +// with a deadband around the center (e.g., 50). |
|
| 75 | +long mapWithDeadband(long rcValue, int rcMin, int rcMax, int rcCenter, int deadbandRadius, int outMin, int outMax) { |
|
| 76 | + long mappedValue = 0; |
|
| 77 | + int deadbandLower = rcCenter - deadbandRadius; |
|
| 78 | + int deadbandUpper = rcCenter + deadbandRadius; |
|
| 79 | + |
|
| 80 | + if (rcValue < deadbandLower) { |
|
| 81 | + // Map the range [rcMin, deadbandLower - 1] to [outMin, -1] |
|
| 82 | + // Ensure deadbandLower - 1 is not less than rcMin |
|
| 83 | + if (deadbandLower -1 < rcMin) { |
|
| 84 | + mappedValue = outMin; |
|
| 85 | + } else { |
|
| 86 | + mappedValue = map(rcValue, rcMin, deadbandLower - 1, outMin, -1); |
|
| 87 | + } |
|
| 88 | + } else if (rcValue > deadbandUpper) { |
|
| 89 | + // Map the range [deadbandUpper + 1, rcMax] to [1, outMax] |
|
| 90 | + // Ensure deadbandUpper + 1 is not greater than rcMax |
|
| 91 | + if (deadbandUpper + 1 > rcMax) { |
|
| 92 | + mappedValue = outMax; |
|
| 93 | + } else { |
|
| 94 | + mappedValue = map(rcValue, deadbandUpper + 1, rcMax, 1, outMax); |
|
| 95 | + } |
|
| 96 | + } else { |
|
| 97 | + // Inside deadband |
|
| 98 | + mappedValue = 0; |
|
| 99 | + } |
|
| 100 | + return constrain(mappedValue, outMin, outMax); |
|
| 101 | +} |
|
| 102 | + |
|
| 103 | +void loop() { |
|
| 104 | + // Read mapped control signals from each channel |
|
| 105 | + aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 106 | + elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 107 | + |
|
| 108 | + // Print the mapped control signal values to the Serial Monitor |
|
| 109 | + Serial.print("Aileron (Throttle): "); |
|
| 110 | + Serial.print(aileronControl); |
|
| 111 | + Serial.print(" Elevator (Steering): "); |
|
| 112 | + Serial.print(elevatorControl); |
|
| 113 | + Serial.println(); |
|
| 114 | + |
|
| 115 | + // Define deadband radius (e.g., +/- 5 around center of 50 for a 0-100 input) |
|
| 116 | + // This means input values from 45 to 55 (inclusive if center is 50 and radius is 5) will be treated as 0. |
|
| 117 | + int deadbandRadius = 10; |
|
| 118 | + float steeringFactor = 3; // Adjust this value to change steering sensitivity |
|
| 119 | + float throttleFactor = 3; // Adjust this value to change throttle sensitivity (e.g., 1.2 for 20% stronger throttle) |
|
| 120 | + |
|
| 121 | + // Map control values with deadband |
|
| 122 | + long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 123 | + long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 124 | + |
|
| 125 | + // Apply sensitivity factors |
|
| 126 | + long throttleValue = rawThrottleValue * throttleFactor; |
|
| 127 | + long adjustedSteeringValue = rawSteeringValue * steeringFactor; |
|
| 128 | + |
|
| 129 | + // Mix throttle and steering for differential drive |
|
| 130 | + long motor1Pwm = throttleValue + adjustedSteeringValue; |
|
| 131 | + long motor2Pwm = throttleValue - adjustedSteeringValue; |
|
| 132 | + |
|
| 133 | + // Constrain PWM values to the valid range [-255, 255] |
|
| 134 | + motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 135 | + motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 136 | + |
|
| 137 | + // Set motor speeds and directions |
|
| 138 | + setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 139 | + setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 140 | + |
|
| 141 | + delay(20); // Shorter delay for better responsiveness |
|
| 142 | +} |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/PWM-2ch-v2.ino
| ... | ... | @@ -0,0 +1,68 @@ |
| 1 | +// RC signal input pins |
|
| 2 | +#define THROTTLE_PIN 2 // Channel 1 (forward/back) |
|
| 3 | +#define STEERING_PIN 3 // Channel 2 (left/right) |
|
| 4 | + |
|
| 5 | +// Motor control pins (L298N) |
|
| 6 | +#define LEFT_ENA 9 |
|
| 7 | +#define LEFT_IN1 4 |
|
| 8 | +#define LEFT_IN2 5 |
|
| 9 | + |
|
| 10 | +#define RIGHT_ENB 10 |
|
| 11 | +#define RIGHT_IN3 6 |
|
| 12 | +#define RIGHT_IN4 7 |
|
| 13 | + |
|
| 14 | +int throttle, steering; |
|
| 15 | + |
|
| 16 | +void setup() { |
|
| 17 | + pinMode(THROTTLE_PIN, INPUT); |
|
| 18 | + pinMode(STEERING_PIN, INPUT); |
|
| 19 | + |
|
| 20 | + pinMode(LEFT_IN1, OUTPUT); |
|
| 21 | + pinMode(LEFT_IN2, OUTPUT); |
|
| 22 | + pinMode(LEFT_ENA, OUTPUT); |
|
| 23 | + |
|
| 24 | + pinMode(RIGHT_IN3, OUTPUT); |
|
| 25 | + pinMode(RIGHT_IN4, OUTPUT); |
|
| 26 | + pinMode(RIGHT_ENB, OUTPUT); |
|
| 27 | + |
|
| 28 | + Serial.begin(9600); |
|
| 29 | +} |
|
| 30 | + |
|
| 31 | +void loop() { |
|
| 32 | + // Read PWM input |
|
| 33 | + throttle = pulseIn(THROTTLE_PIN, HIGH, 25000); |
|
| 34 | + steering = pulseIn(STEERING_PIN, HIGH, 25000); |
|
| 35 | + |
|
| 36 | + // Center = 1500, range = 1000–2000 |
|
| 37 | + int throttleVal = map(throttle, 1000, 2000, -255, 255); |
|
| 38 | + int steeringVal = map(steering, 1000, 2000, -100, 100); // less aggressive |
|
| 39 | + |
|
| 40 | + // Motor mixing (differential drive) |
|
| 41 | + int leftSpeed = constrain(throttleVal + steeringVal, -255, 255); |
|
| 42 | + int rightSpeed = constrain(throttleVal - steeringVal, -255, 255); |
|
| 43 | + |
|
| 44 | + setMotor(LEFT_IN1, LEFT_IN2, LEFT_ENA, leftSpeed); |
|
| 45 | + setMotor(RIGHT_IN3, RIGHT_IN4, RIGHT_ENB, rightSpeed); |
|
| 46 | + |
|
| 47 | + // Debug |
|
| 48 | + Serial.print("Throttle: "); Serial.print(throttleVal); |
|
| 49 | + Serial.print(" Steering: "); Serial.print(steeringVal); |
|
| 50 | + Serial.print(" L: "); Serial.print(leftSpeed); |
|
| 51 | + Serial.print(" R: "); Serial.println(rightSpeed); |
|
| 52 | + |
|
| 53 | + delay(20); |
|
| 54 | +} |
|
| 55 | + |
|
| 56 | +void setMotor(int in1, int in2, int ena, int speed) { |
|
| 57 | + if (speed > 0) { |
|
| 58 | + digitalWrite(in1, HIGH); |
|
| 59 | + digitalWrite(in2, LOW); |
|
| 60 | + } else if (speed < 0) { |
|
| 61 | + digitalWrite(in1, LOW); |
|
| 62 | + digitalWrite(in2, HIGH); |
|
| 63 | + } else { |
|
| 64 | + digitalWrite(in1, LOW); |
|
| 65 | + digitalWrite(in2, LOW); |
|
| 66 | + } |
|
| 67 | + analogWrite(ena, abs(speed)); |
|
| 68 | +} |
code-dat/RC-code-dat/RC-code-dat.md
| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | + |
|
| 2 | +# RC-code-dat |
|
| 3 | + |
|
| 4 | + |
|
| 5 | +basic code == [[basic-code-1.ino]], or [[ultrasonic car-1602.pde]] |
|
| 6 | + |
|
| 7 | + |
|
| 8 | +## working for |
|
| 9 | + |
|
| 10 | +- [[SDR1064-dat]] - [[nodemcu-dat]] |
|
| 11 | + |
|
| 12 | +## code |
|
| 13 | + |
|
| 14 | +- [[PWM-1ch.ino]] - [[PWM-2ch.ino]] - [[PWM-2ch-v2.ino]] |
|
| 15 | + |
|
| 16 | +- [[rover-1.ino]] - [[rover-2.ino]] |
|
| 17 | + |
|
| 18 | +- [[DRV8871-dat]] |
|
| 19 | + |
|
| 20 | + |
|
| 21 | +## ref |
|
| 22 | + |
|
| 23 | +- [[PWM-dat]] |
|
| 24 | + |
|
| 25 | +- [[RC-dat]] |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/SDR1064-1.ino
| ... | ... | @@ -0,0 +1,94 @@ |
| 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 signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 18 | + if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 19 | + return 50; // Mid-point for 0-100 scale |
|
| 20 | + } |
|
| 21 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 22 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 23 | +} |
|
| 24 | + |
|
| 25 | +// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 26 | +long readElevatorControlSignal() { |
|
| 27 | + unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 28 | + // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 29 | + if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 30 | + return 50; // Mid-point for 0-100 scale |
|
| 31 | + } |
|
| 32 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 33 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 34 | +} |
|
| 35 | + |
|
| 36 | +void setup() { |
|
| 37 | + pinMode(aileronPin, INPUT); |
|
| 38 | + pinMode(elevatorPin, INPUT); |
|
| 39 | + |
|
| 40 | + pinMode(ENA, OUTPUT); |
|
| 41 | + pinMode(ENB, OUTPUT); |
|
| 42 | + pinMode(IN1, OUTPUT); |
|
| 43 | + pinMode(IN2, OUTPUT); |
|
| 44 | + |
|
| 45 | + // Initialize motors to off |
|
| 46 | + digitalWrite(IN1, LOW); |
|
| 47 | + digitalWrite(IN2, LOW); |
|
| 48 | + analogWrite(ENA, 0); |
|
| 49 | + analogWrite(ENB, 0); |
|
| 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); |
|
| 63 | + analogWrite(speedPin, 0); |
|
| 64 | + } |
|
| 65 | +} |
|
| 66 | + |
|
| 67 | +void loop() { |
|
| 68 | + // Read mapped control signals from each channel |
|
| 69 | + aileronControl = readAileronControlSignal(); // Throttle (0-100, 50 is neutral) |
|
| 70 | + elevatorControl = readElevatorControlSignal(); // Steering (0-100, 50 is neutral) |
|
| 71 | + |
|
| 72 | + // Map control values directly |
|
| 73 | + // aileronControl (0-100) to throttleValue (-255 to 255) |
|
| 74 | + // 0 -> -255 (full reverse), 50 -> 0 (stop), 100 -> 255 (full forward) |
|
| 75 | + long throttleValue = map(aileronControl, 0, 100, -255, 255); |
|
| 76 | + |
|
| 77 | + // elevatorControl (0-100) to steeringValue (-255 to 255) |
|
| 78 | + // 0 -> -255 (full left turn effect), 50 -> 0 (straight), 100 -> 255 (full right turn effect) |
|
| 79 | + long steeringValue = map(elevatorControl, 0, 100, -255, 255); |
|
| 80 | + |
|
| 81 | + // Mix throttle and steering for differential drive |
|
| 82 | + long motor1Pwm = throttleValue + steeringValue; |
|
| 83 | + long motor2Pwm = throttleValue - steeringValue; |
|
| 84 | + |
|
| 85 | + // Constrain PWM values to the valid range [-255, 255] |
|
| 86 | + motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 87 | + motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 88 | + |
|
| 89 | + // Set motor speeds and directions |
|
| 90 | + setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 91 | + setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 92 | + |
|
| 93 | + delay(20); // Delay for responsiveness |
|
| 94 | +} |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/SDR1064-2.ino
| ... | ... | @@ -0,0 +1,167 @@ |
| 1 | +#include <Adafruit_NeoPixel.h> |
|
| 2 | + |
|
| 3 | +// Define pins for each RC channel |
|
| 4 | +int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 5 | +int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 6 | + |
|
| 7 | +const int IN1 = 0; // Direction for Motor 1 // D3 |
|
| 8 | +const int IN2 = 2; // Direction pin 1 for Motor 2 // D4 |
|
| 9 | + |
|
| 10 | +// WS2812 LED Strip Configuration |
|
| 11 | +#define LED_PIN 15 // nodemcu pin D8 |
|
| 12 | +#define LED_COUNT 8 |
|
| 13 | +Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); |
|
| 14 | + |
|
| 15 | +long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 16 | +long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 17 | + |
|
| 18 | +// Reads the PWM signal from the aileron channel and maps it to 0-100 |
|
| 19 | +long readAileronControlSignal() { |
|
| 20 | + unsigned long rawPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 21 | + // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 22 | + // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 23 | + if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 24 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 25 | + } |
|
| 26 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 27 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 28 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 29 | +} |
|
| 30 | + |
|
| 31 | +// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 32 | +long readElevatorControlSignal() { |
|
| 33 | + unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 34 | + // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 35 | + // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 36 | + if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 37 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 38 | + } |
|
| 39 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 40 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 41 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 42 | +} |
|
| 43 | + |
|
| 44 | +void setup() { |
|
| 45 | + pinMode(aileronPin, INPUT); |
|
| 46 | + pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 47 | + |
|
| 48 | + pinMode(ENA, OUTPUT); |
|
| 49 | + pinMode(ENB, OUTPUT); |
|
| 50 | + pinMode(IN1, OUTPUT); |
|
| 51 | + pinMode(IN2, OUTPUT); |
|
| 52 | + |
|
| 53 | + // Initialize motors to off |
|
| 54 | + digitalWrite(IN1, LOW); |
|
| 55 | + digitalWrite(IN2, LOW); |
|
| 56 | + analogWrite(ENA, 0); |
|
| 57 | + analogWrite(ENB, 0); |
|
| 58 | + |
|
| 59 | + Serial.begin(9600); |
|
| 60 | + |
|
| 61 | + strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) |
|
| 62 | + strip.show(); // Turn OFF all pixels ASAP |
|
| 63 | + strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255) |
|
| 64 | +} |
|
| 65 | + |
|
| 66 | +// Helper function to control a single motor |
|
| 67 | +// pwmVal: -255 (full backward) to 255 (full forward) |
|
| 68 | +void setMotorOutput(int dirPin, int speedPin, int pwmVal) { |
|
| 69 | + if (pwmVal > 0) { // Forward |
|
| 70 | + digitalWrite(dirPin, HIGH); |
|
| 71 | + analogWrite(speedPin, pwmVal); |
|
| 72 | + } else if (pwmVal < 0) { // Backward |
|
| 73 | + digitalWrite(dirPin, LOW); |
|
| 74 | + analogWrite(speedPin, -pwmVal); // Speed is positive |
|
| 75 | + } else { // Stop |
|
| 76 | + digitalWrite(dirPin, LOW); // Or HIGH, doesn't matter much if speed is 0 |
|
| 77 | + analogWrite(speedPin, 0); |
|
| 78 | + } |
|
| 79 | +} |
|
| 80 | + |
|
| 81 | +// Helper function to map RC control input (0-100) to an output range (e.g., -255 to 255) |
|
| 82 | +// with a deadband around the center (e.g., 50). |
|
| 83 | +long mapWithDeadband(long rcValue, int rcMin, int rcMax, int rcCenter, int deadbandRadius, int outMin, int outMax) { |
|
| 84 | + long mappedValue = 0; |
|
| 85 | + int deadbandLower = rcCenter - deadbandRadius; |
|
| 86 | + int deadbandUpper = rcCenter + deadbandRadius; |
|
| 87 | + |
|
| 88 | + if (rcValue < deadbandLower) { |
|
| 89 | + // Map the range [rcMin, deadbandLower - 1] to [outMin, -1] |
|
| 90 | + // Ensure deadbandLower - 1 is not less than rcMin |
|
| 91 | + if (deadbandLower -1 < rcMin) { |
|
| 92 | + mappedValue = outMin; |
|
| 93 | + } else { |
|
| 94 | + mappedValue = map(rcValue, rcMin, deadbandLower - 1, outMin, -1); |
|
| 95 | + } |
|
| 96 | + } else if (rcValue > deadbandUpper) { |
|
| 97 | + // Map the range [deadbandUpper + 1, rcMax] to [1, outMax] |
|
| 98 | + // Ensure deadbandUpper + 1 is not greater than rcMax |
|
| 99 | + if (deadbandUpper + 1 > rcMax) { |
|
| 100 | + mappedValue = outMax; |
|
| 101 | + } else { |
|
| 102 | + mappedValue = map(rcValue, deadbandUpper + 1, rcMax, 1, outMax); |
|
| 103 | + } |
|
| 104 | + } else { |
|
| 105 | + // Inside deadband |
|
| 106 | + mappedValue = 0; |
|
| 107 | + } |
|
| 108 | + return constrain(mappedValue, outMin, outMax); |
|
| 109 | +} |
|
| 110 | + |
|
| 111 | +// Function to create a random blinking effect for WS2812 LEDs |
|
| 112 | +void randomBlinkEffect() { |
|
| 113 | + for (int i = 0; i < LED_COUNT; i++) { |
|
| 114 | + // Turn on a random LED with a random color |
|
| 115 | + if (random(0, 2) == 1) { // 50% chance to turn on this LED |
|
| 116 | + strip.setPixelColor(i, strip.Color(random(0, 256), random(0, 256), random(0, 256))); |
|
| 117 | + } else { |
|
| 118 | + strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off |
|
| 119 | + } |
|
| 120 | + } |
|
| 121 | + strip.show(); // Send the updated pixel colors to the hardware. |
|
| 122 | + delay(100); // Wait a short period |
|
| 123 | +} |
|
| 124 | + |
|
| 125 | +void loop() { |
|
| 126 | + // Read mapped control signals from each channel |
|
| 127 | + aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 128 | + elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 129 | + |
|
| 130 | + // Print the mapped control signal values to the Serial Monitor |
|
| 131 | + Serial.print("Aileron (Throttle): "); |
|
| 132 | + Serial.print(aileronControl); |
|
| 133 | + Serial.print(" Elevator (Steering): "); |
|
| 134 | + Serial.print(elevatorControl); |
|
| 135 | + Serial.println(); |
|
| 136 | + |
|
| 137 | + // Define deadband radius (e.g., +/- 5 around center of 50 for a 0-100 input) |
|
| 138 | + // This means input values from 45 to 55 (inclusive if center is 50 and radius is 5) will be treated as 0. |
|
| 139 | + int deadbandRadius = 15; |
|
| 140 | + float steeringFactor = 3; // Adjust this value to change steering sensitivity |
|
| 141 | + float throttleFactor = 3; // Adjust this value to change throttle sensitivity (e.g., 1.2 for 20% stronger throttle) |
|
| 142 | + |
|
| 143 | + // Map control values with deadband |
|
| 144 | + long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 145 | + long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 146 | + |
|
| 147 | + // Apply sensitivity factors |
|
| 148 | + long throttleValue = rawThrottleValue * throttleFactor; |
|
| 149 | + long adjustedSteeringValue = rawSteeringValue * steeringFactor; |
|
| 150 | + |
|
| 151 | + // Mix throttle and steering for differential drive |
|
| 152 | + long motor1Pwm = throttleValue + adjustedSteeringValue; |
|
| 153 | + long motor2Pwm = throttleValue - adjustedSteeringValue; |
|
| 154 | + |
|
| 155 | + // Constrain PWM values to the valid range [-255, 255] |
|
| 156 | + motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 157 | + motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 158 | + |
|
| 159 | + // Set motor speeds and directions |
|
| 160 | + setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 161 | + setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 162 | + |
|
| 163 | + // Add the LED effect |
|
| 164 | + randomBlinkEffect(); |
|
| 165 | + |
|
| 166 | + delay(20); // Shorter delay for better responsiveness |
|
| 167 | +} |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/SDR1064-3.ino
| ... | ... | @@ -0,0 +1,136 @@ |
| 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 | + float steeringFactor = 1.5; // Adjust this value to change steering sensitivity |
|
| 113 | + float throttleFactor = 1.3; // Adjust this value to change throttle sensitivity (e.g., 1.2 for 20% stronger throttle) |
|
| 114 | + |
|
| 115 | + // Map control values with deadband |
|
| 116 | + long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 117 | + long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 118 | + |
|
| 119 | + // Apply sensitivity factors |
|
| 120 | + long throttleValue = rawThrottleValue * throttleFactor; |
|
| 121 | + long adjustedSteeringValue = rawSteeringValue * steeringFactor; |
|
| 122 | + |
|
| 123 | + // Mix throttle and steering for differential drive |
|
| 124 | + long motor1Pwm = throttleValue + adjustedSteeringValue; |
|
| 125 | + long motor2Pwm = throttleValue - adjustedSteeringValue; |
|
| 126 | + |
|
| 127 | + // Constrain PWM values to the valid range [-255, 255] |
|
| 128 | + motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 129 | + motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 130 | + |
|
| 131 | + // Set motor speeds and directions |
|
| 132 | + setMotorOutput(IN1, ENA, motor1Pwm); // Motor 1 |
|
| 133 | + setMotorOutput(IN2, ENB, motor2Pwm); // Motor 2 |
|
| 134 | + |
|
| 135 | + delay(20); // Shorter delay for better responsiveness |
|
| 136 | +} |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/basic-code-1.ino
| ... | ... | @@ -0,0 +1,403 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +******************************************************************************* |
|
| 4 | +遥控超声波测距智能车程序(ARDUINO) |
|
| 5 | +#include <IRremote.h> |
|
| 6 | +#include <Servo.h> |
|
| 7 | +#include <Wire.h> |
|
| 8 | +#include <LiquidCrystal_I2C.h> |
|
| 9 | +//***********************定義馬達腳位************************* |
|
| 10 | +int MotorRight1=6; |
|
| 11 | +int MotorRight2=9; |
|
| 12 | +int MotorLeft1=10; |
|
| 13 | +int MotorLeft2=11; |
|
| 14 | + |
|
| 15 | +int counter=0; |
|
| 16 | +const int irReceiverPin = 3; //紅外線接收器 OUTPUT 訊號接在 pin 3 |
|
| 17 | +//***********************設定所偵測到的 IRcode************************* |
|
| 18 | +long IRfront= 0x00FF629D; //前進碼 |
|
| 19 | +long IRback=0x00FFA857; //後退 |
|
| 20 | +long IRturnright=0x00FF22DD; //右轉 |
|
| 21 | +long IRturnleft= 0x00FFC23D; //左轉 |
|
| 22 | +long IRstop=0x00FF02FD; //停止 |
|
| 23 | +long IRAutorun=0x00FF6897; //超音波自走模式 |
|
| 24 | +long IRturnsmallleft= 0x00FFB04F; |
|
| 25 | +IRrecv irrecv(irReceiverPin); // 定義 IRrecv 物件來接收紅外線訊號 |
|
| 26 | +decode_results results; |
|
| 27 | +//*************************定義超音波腳位****************************** |
|
| 28 | +int inputPin =A0 ; // 定義超音波信號接收腳位 rx |
|
| 29 | +int outputPin =A1; // 定義超音波信號發射腳位'tx |
|
| 30 | +int Fspeedd = 0; // 前方距離 |
|
| 31 | +int Rspeedd = 0; // 右方距離 |
|
| 32 | +int Lspeedd = 0; // 左方距離 |
|
| 33 | +int directionn = 0; // 前=8 後=2 左=4 右=6 |
|
| 34 | +Servo myservo; // 設 myservo |
|
| 35 | +int delay_time = 250; // 伺服馬達轉向後的穩定時間 |
|
| 36 | +int Fgo = 8; // 前進 |
|
| 37 | +int Rgo = 6; // 右轉 |
|
| 38 | +int Lgo = 4; // 左轉 |
|
| 39 | +int Bgo = 2; // 倒車 |
|
| 40 | +//********************************************************************(SETUP) |
|
| 41 | +LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line |
|
| 42 | +display |
|
| 43 | +void setup() |
|
| 44 | +{ |
|
| 45 | + Serial.begin(9600); |
|
| 46 | + pinMode(MotorRight1, OUTPUT); // 腳位 8 (PWM) |
|
| 47 | + pinMode(MotorRight2, OUTPUT); // 腳位 9 (PWM) |
|
| 48 | + pinMode(MotorLeft1, OUTPUT); // 腳位 10 (PWM) |
|
| 49 | + pinMode(MotorLeft2, OUTPUT); // 腳位 11 (PWM) |
|
| 50 | + irrecv.enableIRIn(); // 啟動紅外線解碼 |
|
| 51 | + digitalWrite(3,HIGH); |
|
| 52 | + pinMode(inputPin, INPUT); // 定義超音波輸入腳位 |
|
| 53 | + pinMode(outputPin, OUTPUT); // 定義超音波輸出腳位 |
|
| 54 | + myservo.attach(5); // 定義伺服馬達輸出第 5 腳位(PWM) |
|
| 55 | + lcd.init(); // initialize the lcd |
|
| 56 | + lcd.init(); |
|
| 57 | + // Print a message to the LCD. |
|
| 58 | + |
|
| 59 | + lcd.backlight(); |
|
| 60 | + } |
|
| 61 | +//******************************************************************(Void) |
|
| 62 | +void advance(int a) // 前進 |
|
| 63 | +{ |
|
| 64 | + digitalWrite(MotorRight1,LOW); |
|
| 65 | + digitalWrite(MotorRight2,HIGH); |
|
| 66 | + digitalWrite(MotorLeft1,LOW); |
|
| 67 | + digitalWrite(MotorLeft2,HIGH); |
|
| 68 | + delay(a * 100); |
|
| 69 | +} |
|
| 70 | +void right(int b) //右轉(單輪) |
|
| 71 | +{ |
|
| 72 | + digitalWrite(MotorLeft1,LOW); |
|
| 73 | + digitalWrite(MotorLeft2,HIGH); |
|
| 74 | + digitalWrite(MotorRight1,LOW); |
|
| 75 | + digitalWrite(MotorRight2,LOW); |
|
| 76 | + delay(b * 100); |
|
| 77 | +} |
|
| 78 | +void left(int c) //左轉(單輪) |
|
| 79 | +{ |
|
| 80 | + digitalWrite(MotorRight1,LOW); |
|
| 81 | + digitalWrite(MotorRight2,HIGH); |
|
| 82 | + digitalWrite(MotorLeft1,LOW); |
|
| 83 | + digitalWrite(MotorLeft2,LOW); |
|
| 84 | + delay(c * 100); |
|
| 85 | +} |
|
| 86 | +void turnR(int d) //右轉(雙輪) |
|
| 87 | +{ |
|
| 88 | + digitalWrite(MotorRight1,HIGH); |
|
| 89 | + digitalWrite(MotorRight2,LOW); |
|
| 90 | + digitalWrite(MotorLeft1,LOW); |
|
| 91 | + digitalWrite(MotorLeft2,HIGH); |
|
| 92 | + delay(d * 100); |
|
| 93 | +} |
|
| 94 | +void turnL(int e) //左轉(雙輪) |
|
| 95 | +{ |
|
| 96 | + digitalWrite(MotorRight1,LOW); |
|
| 97 | + digitalWrite(MotorRight2,HIGH); |
|
| 98 | + digitalWrite(MotorLeft1,HIGH); |
|
| 99 | + digitalWrite(MotorLeft2,LOW); |
|
| 100 | + |
|
| 101 | + delay(e * 100); |
|
| 102 | +} |
|
| 103 | +void stopp(int f) //停止 |
|
| 104 | +{ |
|
| 105 | + digitalWrite(MotorRight1,LOW); |
|
| 106 | + digitalWrite(MotorRight2,LOW); |
|
| 107 | + digitalWrite(MotorLeft1,LOW); |
|
| 108 | + digitalWrite(MotorLeft2,LOW); |
|
| 109 | + delay(f * 100); |
|
| 110 | +} |
|
| 111 | +void back(int g) //後退 |
|
| 112 | +{ |
|
| 113 | + digitalWrite(MotorRight1,HIGH); |
|
| 114 | + digitalWrite(MotorRight2,LOW); |
|
| 115 | + digitalWrite(MotorLeft1,HIGH); |
|
| 116 | + digitalWrite(MotorLeft2,LOW);; |
|
| 117 | + delay(g * 100); |
|
| 118 | +} |
|
| 119 | +void detection() //測量 3 個角度(前.左.右) |
|
| 120 | +{ |
|
| 121 | + int delay_time = 250; // 伺服馬達轉向後的穩定時間 |
|
| 122 | + ask_pin_F(); // 讀取前方距離 |
|
| 123 | + if(Fspeedd < 10) // 假如前方距離小於 10 公分 |
|
| 124 | + { |
|
| 125 | + stopp(1); // 清除輸出資料 |
|
| 126 | + back(2); // 後退 0.2 秒 |
|
| 127 | + |
|
| 128 | + } |
|
| 129 | + if(Fspeedd < 25) // 假如前方距離小於 25 公分 |
|
| 130 | + { |
|
| 131 | + stopp(1); // 清除輸出資料 |
|
| 132 | + ask_pin_L(); // 讀取左方距離 |
|
| 133 | + delay(delay_time); // 等待伺服馬達穩定 |
|
| 134 | + ask_pin_R(); // 讀取右方距離 |
|
| 135 | + delay(delay_time); // 等待伺服馬達穩定 |
|
| 136 | + if(Lspeedd > Rspeedd) //假如 左邊距離大於右邊距離 |
|
| 137 | + { |
|
| 138 | + directionn = Lgo; //向左走 |
|
| 139 | + } |
|
| 140 | + if(Lspeedd <= Rspeedd) //假如 左邊距離小於或等於右邊距離 |
|
| 141 | + |
|
| 142 | + { |
|
| 143 | + directionn = Rgo; //向右走 |
|
| 144 | + } |
|
| 145 | + if (Lspeedd < 15 && Rspeedd < 15) //假如 左邊距離和右邊距離皆小於 10 公分 |
|
| 146 | + { |
|
| 147 | + directionn = Bgo; //向後走 |
|
| 148 | + } |
|
| 149 | + } |
|
| 150 | + else //加如前方大於 25 公分 |
|
| 151 | + { |
|
| 152 | + directionn = Fgo; //向前走 |
|
| 153 | + } |
|
| 154 | +} |
|
| 155 | +//***************************************************************************** |
|
| 156 | +**** |
|
| 157 | +void ask_pin_F() // 量出前方距離 |
|
| 158 | +{ |
|
| 159 | +myservo.write(90); |
|
| 160 | +digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓 2μs |
|
| 161 | +delayMicroseconds(2); |
|
| 162 | +digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓 10μs,這裡至少是 10μs |
|
| 163 | +delayMicroseconds(10); |
|
| 164 | +digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 165 | +float Fdistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 166 | +Fdistance= Fdistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 167 | +Fspeedd = Fdistance; // 將距離 讀入 Fspeedd(前速) |
|
| 168 | +} |
|
| 169 | +//***************************************************************************** |
|
| 170 | +*** |
|
| 171 | +void ask_pin_L() // 量出左邊距離 |
|
| 172 | +{ |
|
| 173 | +myservo.write(177); |
|
| 174 | +delay(delay_time); |
|
| 175 | +digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓 2μs |
|
| 176 | +delayMicroseconds(2); |
|
| 177 | +digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓 10μs,這裡至少是 10μs |
|
| 178 | +delayMicroseconds(10); |
|
| 179 | +digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 180 | +float Ldistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 181 | +Ldistance= Ldistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 182 | +Lspeedd = Ldistance; // 將距離 讀入 Lspeedd(左速) |
|
| 183 | + |
|
| 184 | +} |
|
| 185 | +//***************************************************************************** |
|
| 186 | +* |
|
| 187 | +void ask_pin_R() // 量出右邊距離 |
|
| 188 | +{ |
|
| 189 | +myservo.write(5); |
|
| 190 | +delay(delay_time); |
|
| 191 | +digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓 2μs |
|
| 192 | +delayMicroseconds(2); |
|
| 193 | +digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓 10μs,這裡至少是 10μs |
|
| 194 | +delayMicroseconds(10); |
|
| 195 | +digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 196 | +float Rdistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 197 | +Rdistance= Rdistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 198 | +Rspeedd = Rdistance; // 將距離 讀入 Rspeedd(右速) |
|
| 199 | +} |
|
| 200 | +//***************************************************************************** |
|
| 201 | +*(LOOP) |
|
| 202 | +void loop() |
|
| 203 | +{ |
|
| 204 | + |
|
| 205 | +//***************************************************************************正 |
|
| 206 | +常遙控模式 |
|
| 207 | + if (irrecv.decode(&results)) |
|
| 208 | + { // 解碼成功,收到一組紅外線訊號 |
|
| 209 | +/***********************************************************************/ |
|
| 210 | + if (results.value == IRfront)//前進 |
|
| 211 | + { |
|
| 212 | + |
|
| 213 | + lcd.setCursor(0,0); |
|
| 214 | + lcd.print(" IR mode"); |
|
| 215 | + lcd.setCursor(0,1); |
|
| 216 | + lcd.print(" advance "); |
|
| 217 | + advance(20);//前進 |
|
| 218 | + } |
|
| 219 | +/***********************************************************************/ |
|
| 220 | + if (results.value == IRback)//後退 |
|
| 221 | + { |
|
| 222 | + |
|
| 223 | + lcd.setCursor(0,0); |
|
| 224 | + lcd.print(" IR mode"); |
|
| 225 | + lcd.setCursor(0,1); |
|
| 226 | + lcd.print(" back "); |
|
| 227 | + |
|
| 228 | + back(20);//後退 |
|
| 229 | + } |
|
| 230 | +/***********************************************************************/ |
|
| 231 | + if (results.value == IRturnright)//右轉 |
|
| 232 | + { |
|
| 233 | + |
|
| 234 | + lcd.setCursor(0,0); |
|
| 235 | + lcd.print(" IR mode"); |
|
| 236 | + lcd.setCursor(0,1); |
|
| 237 | + lcd.print(" right "); |
|
| 238 | + right(10); // 右轉 |
|
| 239 | + |
|
| 240 | + } |
|
| 241 | +/***********************************************************************/ |
|
| 242 | + if (results.value == IRturnleft)//左轉 |
|
| 243 | + { |
|
| 244 | + |
|
| 245 | + lcd.setCursor(0,0); |
|
| 246 | + lcd.print(" IR mode"); |
|
| 247 | + lcd.setCursor(0,1); |
|
| 248 | + lcd.print(" left "); |
|
| 249 | + left(10); // 左轉); |
|
| 250 | + } |
|
| 251 | +/***********************************************************************/ |
|
| 252 | + if (results.value == IRstop)//停止 |
|
| 253 | + { |
|
| 254 | + lcd.setCursor(0,0); |
|
| 255 | + lcd.print(" IR mode"); |
|
| 256 | + lcd.setCursor(0,1); |
|
| 257 | + lcd.print(" stop "); |
|
| 258 | + digitalWrite(MotorRight1,LOW); |
|
| 259 | + digitalWrite(MotorRight2,LOW); |
|
| 260 | + digitalWrite(MotorLeft1,LOW); |
|
| 261 | + digitalWrite(MotorLeft2,LOW); |
|
| 262 | + |
|
| 263 | + |
|
| 264 | + } |
|
| 265 | +//***********************************************************************超音波 |
|
| 266 | +自走模式 |
|
| 267 | + if (results.value ==IRAutorun ) |
|
| 268 | + { |
|
| 269 | + while(IRAutorun) |
|
| 270 | + { |
|
| 271 | + |
|
| 272 | + myservo.write(90); //讓伺服馬達回歸 預備位置 準備下一次的測量 |
|
| 273 | + detection(); //測量角度 並且判斷要往哪一方向移動 |
|
| 274 | + if(directionn == 8) //假如 directionn(方向) = 8(前進) |
|
| 275 | + { |
|
| 276 | + if (irrecv.decode(&results)) |
|
| 277 | + { |
|
| 278 | + irrecv.resume(); |
|
| 279 | + Serial.println(results.value,HEX); |
|
| 280 | + if(results.value ==IRstop) |
|
| 281 | + { |
|
| 282 | + digitalWrite(MotorRight1,LOW); |
|
| 283 | + digitalWrite(MotorRight2,LOW); |
|
| 284 | + digitalWrite(MotorLeft1,LOW); |
|
| 285 | + digitalWrite(MotorLeft2,LOW); |
|
| 286 | + break; |
|
| 287 | + } |
|
| 288 | + } |
|
| 289 | + results.value=0; |
|
| 290 | + |
|
| 291 | + |
|
| 292 | + lcd.setCursor(0,0); |
|
| 293 | + lcd.print(" aoto mode"); |
|
| 294 | + lcd.setCursor(0,1); |
|
| 295 | + lcd.print(" Advance "); |
|
| 296 | + advance(1); // 正常前進 |
|
| 297 | + } |
|
| 298 | + if(directionn == 2) //假如 directionn(方向) = 2(倒車) |
|
| 299 | + { |
|
| 300 | + if (irrecv.decode(&results)) |
|
| 301 | + { |
|
| 302 | + irrecv.resume(); |
|
| 303 | + Serial.println(results.value,HEX); |
|
| 304 | + if(results.value ==IRstop) |
|
| 305 | + { |
|
| 306 | + digitalWrite(MotorRight1,LOW); |
|
| 307 | + digitalWrite(MotorRight2,LOW); |
|
| 308 | + digitalWrite(MotorLeft1,LOW); |
|
| 309 | + digitalWrite(MotorLeft2,LOW); |
|
| 310 | + break; |
|
| 311 | + } |
|
| 312 | + } |
|
| 313 | + results.value=0; |
|
| 314 | + |
|
| 315 | + lcd.setCursor(0,0); |
|
| 316 | + lcd.print(" aoto mode"); |
|
| 317 | + lcd.setCursor(0,1); |
|
| 318 | + lcd.print(" Reverse "); |
|
| 319 | + back(8); // 倒退(車) |
|
| 320 | + turnL(3); //些微向左方移動(防止卡在死巷裡) |
|
| 321 | + } |
|
| 322 | + if(directionn == 6) //假如 directionn(方向) = 6(右轉) |
|
| 323 | + { |
|
| 324 | + if (irrecv.decode(&results)) |
|
| 325 | + { |
|
| 326 | + irrecv.resume(); |
|
| 327 | + Serial.println(results.value,HEX); |
|
| 328 | + if(results.value ==IRstop) |
|
| 329 | + { |
|
| 330 | + digitalWrite(MotorRight1,LOW); |
|
| 331 | + digitalWrite(MotorRight2,LOW); |
|
| 332 | + digitalWrite(MotorLeft1,LOW); |
|
| 333 | + digitalWrite(MotorLeft2,LOW); |
|
| 334 | + break; |
|
| 335 | + } |
|
| 336 | + } |
|
| 337 | + results.value=0; |
|
| 338 | + |
|
| 339 | + |
|
| 340 | + lcd.setCursor(0,0); |
|
| 341 | + lcd.print(" aoto mode"); |
|
| 342 | + lcd.setCursor(0,1); |
|
| 343 | + lcd.print(" Right "); |
|
| 344 | + back(1); |
|
| 345 | + turnR(3); // 右轉 |
|
| 346 | + } |
|
| 347 | + if(directionn == 4) //假如 directionn(方向) = 4(左轉) |
|
| 348 | + { |
|
| 349 | + if (irrecv.decode(&results)) |
|
| 350 | + { |
|
| 351 | + irrecv.resume(); |
|
| 352 | + Serial.println(results.value,HEX); |
|
| 353 | + if(results.value ==IRstop) |
|
| 354 | + { |
|
| 355 | + digitalWrite(MotorRight1,LOW); |
|
| 356 | + digitalWrite(MotorRight2,LOW); |
|
| 357 | + digitalWrite(MotorLeft1,LOW); |
|
| 358 | + digitalWrite(MotorLeft2,LOW); |
|
| 359 | + |
|
| 360 | + break; |
|
| 361 | + } |
|
| 362 | + } |
|
| 363 | + results.value=0; |
|
| 364 | + |
|
| 365 | + lcd.setCursor(0,0); |
|
| 366 | + lcd.print(" aoto mode"); |
|
| 367 | + lcd.setCursor(0,1); |
|
| 368 | + lcd.print(" Left "); |
|
| 369 | + back(1); |
|
| 370 | + turnL(3); // 左轉 |
|
| 371 | + |
|
| 372 | + } |
|
| 373 | + |
|
| 374 | + if (irrecv.decode(&results)) |
|
| 375 | + { |
|
| 376 | + irrecv.resume(); |
|
| 377 | + Serial.println(results.value,HEX); |
|
| 378 | + if(results.value ==IRstop) |
|
| 379 | + { |
|
| 380 | + digitalWrite(MotorRight1,LOW); |
|
| 381 | + digitalWrite(MotorRight2,LOW); |
|
| 382 | + digitalWrite(MotorLeft1,LOW); |
|
| 383 | + digitalWrite(MotorLeft2,LOW); |
|
| 384 | + break; |
|
| 385 | + } |
|
| 386 | + } |
|
| 387 | + } |
|
| 388 | + results.value=0; |
|
| 389 | + } |
|
| 390 | +/***********************************************************************/ |
|
| 391 | + else |
|
| 392 | + { |
|
| 393 | + digitalWrite(MotorRight1,LOW); |
|
| 394 | + digitalWrite(MotorRight2,LOW); |
|
| 395 | + digitalWrite(MotorLeft1,LOW); |
|
| 396 | + digitalWrite(MotorLeft2,LOW); |
|
| 397 | + } |
|
| 398 | + |
|
| 399 | + irrecv.resume(); // 繼續收下一組紅外線訊號 |
|
| 400 | + } |
|
| 401 | +} |
|
| 402 | + |
|
| 403 | +******************************************************************************* |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/rover-8871-2.ino
| ... | ... | @@ -0,0 +1,126 @@ |
| 1 | +// Define pins for each RC channel |
|
| 2 | +int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 3 | +int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 4 | + |
|
| 5 | +const int MOTOR1_CTRL_PIN = 4; // GPIO4 (D2) |
|
| 6 | +const int MOTOR2_CTRL_PIN = 5; // GPIO5 (D1) |
|
| 7 | + |
|
| 8 | +long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 9 | +long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 10 | + |
|
| 11 | +unsigned long rawAileronPWM = 0; |
|
| 12 | +unsigned long rawElevatorPWM = 0; |
|
| 13 | + |
|
| 14 | +const int PWM_MAX = 255; // ESP8266 PWM range is 0-1023 |
|
| 15 | +const int PWM_STOP = PWM_MAX / 2; // ~511 or 512 |
|
| 16 | + |
|
| 17 | +long readAileronControlSignal() { |
|
| 18 | + rawAileronPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 19 | + if (rawAileronPWM == 0 || rawAileronPWM < 900 || rawAileronPWM > 2100) { |
|
| 20 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 21 | + } |
|
| 22 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 23 | + long constrainedPWM = constrain(rawAileronPWM, 1000, 2000); |
|
| 24 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 25 | +} |
|
| 26 | + |
|
| 27 | +long readElevatorControlSignal() { |
|
| 28 | + rawElevatorPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 29 | + if (rawElevatorPWM == 0 || rawElevatorPWM < 900 || rawElevatorPWM > 2100) { |
|
| 30 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 31 | + } |
|
| 32 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 33 | + long constrainedPWM = constrain(rawElevatorPWM, 1000, 2000); |
|
| 34 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 35 | +} |
|
| 36 | + |
|
| 37 | +void setup() { |
|
| 38 | + pinMode(aileronPin, INPUT); |
|
| 39 | + pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 40 | + |
|
| 41 | + pinMode(MOTOR1_CTRL_PIN, OUTPUT); |
|
| 42 | + pinMode(MOTOR2_CTRL_PIN, OUTPUT); |
|
| 43 | + |
|
| 44 | + Serial.begin(9600); |
|
| 45 | + brakeMotor1(); |
|
| 46 | + brakeMotor2(); |
|
| 47 | +} |
|
| 48 | + |
|
| 49 | +void driveMotor1(bool forward) { |
|
| 50 | + if (forward) { |
|
| 51 | + digitalWrite(MOTOR1_CTRL_PIN, HIGH); |
|
| 52 | + } else { |
|
| 53 | + digitalWrite(MOTOR1_CTRL_PIN, LOW); |
|
| 54 | + } |
|
| 55 | +} |
|
| 56 | + |
|
| 57 | +void brakeMotor1() { |
|
| 58 | + analogWrite(MOTOR1_CTRL_PIN, PWM_STOP); |
|
| 59 | +} |
|
| 60 | + |
|
| 61 | +void driveMotor2(bool forward) { |
|
| 62 | + if (forward) { |
|
| 63 | + digitalWrite(MOTOR2_CTRL_PIN, HIGH); |
|
| 64 | + } else { |
|
| 65 | + digitalWrite(MOTOR2_CTRL_PIN, LOW); |
|
| 66 | + } |
|
| 67 | +} |
|
| 68 | + |
|
| 69 | +void brakeMotor2() { |
|
| 70 | + analogWrite(MOTOR2_CTRL_PIN, PWM_STOP); |
|
| 71 | +} |
|
| 72 | + |
|
| 73 | +void loop() { |
|
| 74 | + // Read mapped control signals from each channel |
|
| 75 | + aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 76 | + elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 77 | + |
|
| 78 | + // Simplified driving approach - no mixing |
|
| 79 | + String motor1Command = "STOP"; |
|
| 80 | + String motor2Command = "STOP"; |
|
| 81 | + |
|
| 82 | + // Handle throttle control (forward/reverse) |
|
| 83 | + if (aileronControl > 60) { |
|
| 84 | + // Forward |
|
| 85 | + driveMotor1(true); |
|
| 86 | + driveMotor2(true); |
|
| 87 | + motor1Command = "FORWARD"; |
|
| 88 | + motor2Command = "FORWARD"; |
|
| 89 | + } else if (aileronControl < 40) { |
|
| 90 | + // Reverse |
|
| 91 | + driveMotor1(false); |
|
| 92 | + driveMotor2(false); |
|
| 93 | + motor1Command = "REVERSE"; |
|
| 94 | + motor2Command = "REVERSE"; |
|
| 95 | + } else if (elevatorControl > 60) { |
|
| 96 | + // Turn right (M1 forward, M2 reverse) |
|
| 97 | + driveMotor1(true); |
|
| 98 | + driveMotor2(false); |
|
| 99 | + motor1Command = "FORWARD"; |
|
| 100 | + motor2Command = "REVERSE"; |
|
| 101 | + } else if (elevatorControl < 40) { |
|
| 102 | + // Turn left (M1 reverse, M2 forward) |
|
| 103 | + driveMotor1(false); |
|
| 104 | + driveMotor2(true); |
|
| 105 | + motor1Command = "REVERSE"; |
|
| 106 | + motor2Command = "FORWARD"; |
|
| 107 | + } else { |
|
| 108 | + // Stop |
|
| 109 | + brakeMotor1(); |
|
| 110 | + brakeMotor2(); |
|
| 111 | + } |
|
| 112 | + |
|
| 113 | + // 1. RC INPUTS |
|
| 114 | + Serial.print("RC INPUT: "); |
|
| 115 | + Serial.print("Aileron="); Serial.print(rawAileronPWM); Serial.print("us ("); Serial.print(aileronControl); Serial.print("%), "); |
|
| 116 | + Serial.print("Elevator="); Serial.print(rawElevatorPWM); Serial.print("us ("); Serial.print(elevatorControl); Serial.println("%)"); |
|
| 117 | + |
|
| 118 | + // 2. COMMANDS |
|
| 119 | + Serial.print("MOTORS: "); |
|
| 120 | + Serial.print("M1="); Serial.print(motor1Command); Serial.print(", "); |
|
| 121 | + Serial.print("M2="); Serial.println(motor2Command); |
|
| 122 | + |
|
| 123 | + Serial.println(); |
|
| 124 | + |
|
| 125 | + delay(20); // Delay for RC input reading cycle |
|
| 126 | +} |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/rover-8871-3.ino
| ... | ... | @@ -0,0 +1,132 @@ |
| 1 | +// Define pins for each RC channel |
|
| 2 | +int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 3 | +int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 4 | + |
|
| 5 | +const int MOTOR1_CTRL_PIN = 4; // GPIO4 (D2) |
|
| 6 | +const int MOTOR2_CTRL_PIN = 5; // GPIO5 (D1) |
|
| 7 | + |
|
| 8 | +long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 9 | +long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 10 | + |
|
| 11 | +unsigned long rawAileronPWM = 0; |
|
| 12 | +unsigned long rawElevatorPWM = 0; |
|
| 13 | + |
|
| 14 | +const int PWM_MAX = 255; // ESP8266 PWM range is 0-255 for analogWrite |
|
| 15 | +const int PWM_STOP = PWM_MAX / 2; // Approx. 127, this is brake/neutral for DRV8871 single-pin |
|
| 16 | +const int PWM_MIN_MOVING = 10; // Minimum offset from PWM_STOP to ensure movement |
|
| 17 | + |
|
| 18 | +// Add these global variables for current speeds and ramp step |
|
| 19 | +int currentMotor1Speed = PWM_STOP; |
|
| 20 | +int currentMotor2Speed = PWM_STOP; |
|
| 21 | +const int RAMP_STEP = 5; // Adjust for desired smoothness. Smaller is smoother. |
|
| 22 | + |
|
| 23 | +long readAileronControlSignal() { |
|
| 24 | + rawAileronPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 25 | + if (rawAileronPWM == 0 || rawAileronPWM < 900 || rawAileronPWM > 2100) { |
|
| 26 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 27 | + } |
|
| 28 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 29 | + long constrainedPWM = constrain(rawAileronPWM, 1000, 2000); |
|
| 30 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 31 | +} |
|
| 32 | + |
|
| 33 | +long readElevatorControlSignal() { |
|
| 34 | + rawElevatorPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 35 | + if (rawElevatorPWM == 0 || rawElevatorPWM < 900 || rawElevatorPWM > 2100) { |
|
| 36 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 37 | + } |
|
| 38 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 39 | + long constrainedPWM = constrain(rawElevatorPWM, 1000, 2000); |
|
| 40 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 41 | +} |
|
| 42 | + |
|
| 43 | +void setup() { |
|
| 44 | + pinMode(aileronPin, INPUT); |
|
| 45 | + pinMode(elevatorPin, INPUT); |
|
| 46 | + |
|
| 47 | + pinMode(MOTOR1_CTRL_PIN, OUTPUT); |
|
| 48 | + pinMode(MOTOR2_CTRL_PIN, OUTPUT); |
|
| 49 | + |
|
| 50 | + Serial.begin(9600); |
|
| 51 | + |
|
| 52 | + // Initialize motors to braked state using currentSpeed variables |
|
| 53 | + currentMotor1Speed = PWM_STOP; |
|
| 54 | + currentMotor2Speed = PWM_STOP; |
|
| 55 | + analogWrite(MOTOR1_CTRL_PIN, currentMotor1Speed); |
|
| 56 | + analogWrite(MOTOR2_CTRL_PIN, currentMotor2Speed); |
|
| 57 | +} |
|
| 58 | + |
|
| 59 | +void loop() { |
|
| 60 | + // Read mapped control signals from each channel |
|
| 61 | + aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 62 | + elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 63 | + |
|
| 64 | + String motor1TargetCommand = "BRAKE"; // Command based on stick input |
|
| 65 | + String motor2TargetCommand = "BRAKE"; |
|
| 66 | + int targetMotor1Speed = PWM_STOP; // Target speed for this loop iteration |
|
| 67 | + int targetMotor2Speed = PWM_STOP; // Target speed for this loop iteration |
|
| 68 | + |
|
| 69 | + // Handle throttle control (forward/reverse) |
|
| 70 | + if (aileronControl > 55) { |
|
| 71 | + // Forward |
|
| 72 | + int speed = map(aileronControl, 61, 100, PWM_STOP + PWM_MIN_MOVING, PWM_MAX); |
|
| 73 | + speed = constrain(speed, PWM_STOP + PWM_MIN_MOVING, PWM_MAX); |
|
| 74 | + targetMotor1Speed = speed; |
|
| 75 | + targetMotor2Speed = speed; |
|
| 76 | + motor1TargetCommand = "FORWARD"; |
|
| 77 | + motor2TargetCommand = "FORWARD"; |
|
| 78 | + } else if (aileronControl < 45) { |
|
| 79 | + // Reverse |
|
| 80 | + int speed = map(aileronControl, 39, 0, PWM_STOP - PWM_MIN_MOVING, 0); |
|
| 81 | + speed = constrain(speed, 0, PWM_STOP - PWM_MIN_MOVING); |
|
| 82 | + targetMotor1Speed = speed; |
|
| 83 | + targetMotor2Speed = speed; |
|
| 84 | + motor1TargetCommand = "REVERSE"; |
|
| 85 | + motor2TargetCommand = "REVERSE"; |
|
| 86 | + } else if (elevatorControl > 55) { |
|
| 87 | + // Turn right (throttle is neutral) |
|
| 88 | + int turnOffset = map(elevatorControl, 61, 100, PWM_MIN_MOVING, (PWM_MAX - PWM_STOP)); |
|
| 89 | + targetMotor1Speed = constrain(PWM_STOP + turnOffset, 0, PWM_MAX); |
|
| 90 | + targetMotor2Speed = constrain(PWM_STOP - turnOffset, 0, PWM_MAX); |
|
| 91 | + motor1TargetCommand = "TURN_R_M1"; |
|
| 92 | + motor2TargetCommand = "TURN_R_M2"; |
|
| 93 | + } else if (elevatorControl < 45) { |
|
| 94 | + // Turn left (throttle is neutral) |
|
| 95 | + int turnOffset = map(elevatorControl, 39, 0, PWM_MIN_MOVING, (PWM_MAX - PWM_STOP)); |
|
| 96 | + targetMotor1Speed = constrain(PWM_STOP - turnOffset, 0, PWM_MAX); |
|
| 97 | + targetMotor2Speed = constrain(PWM_STOP + turnOffset, 0, PWM_MAX); |
|
| 98 | + motor1TargetCommand = "TURN_L_M1"; |
|
| 99 | + motor2TargetCommand = "TURN_L_M2"; |
|
| 100 | + } else { |
|
| 101 | + // All sticks neutral - Target speeds remain PWM_STOP (Brake) |
|
| 102 | + // motor1TargetCommand and motor2TargetCommand remain "BRAKE" |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + // Ramping logic for Motor 1 |
|
| 106 | + if (currentMotor1Speed < targetMotor1Speed) { |
|
| 107 | + currentMotor1Speed = min(currentMotor1Speed + RAMP_STEP, targetMotor1Speed); |
|
| 108 | + } else if (currentMotor1Speed > targetMotor1Speed) { |
|
| 109 | + currentMotor1Speed = max(currentMotor1Speed - RAMP_STEP, targetMotor1Speed); |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + // Ramping logic for Motor 2 |
|
| 113 | + if (currentMotor2Speed < targetMotor2Speed) { |
|
| 114 | + currentMotor2Speed = min(currentMotor2Speed + RAMP_STEP, targetMotor2Speed); |
|
| 115 | + } else if (currentMotor2Speed > targetMotor2Speed) { |
|
| 116 | + currentMotor2Speed = max(currentMotor2Speed - RAMP_STEP, targetMotor2Speed); |
|
| 117 | + } |
|
| 118 | + |
|
| 119 | + // Apply the ramped speeds |
|
| 120 | + analogWrite(MOTOR1_CTRL_PIN, currentMotor1Speed); |
|
| 121 | + analogWrite(MOTOR2_CTRL_PIN, currentMotor2Speed); |
|
| 122 | + |
|
| 123 | + Serial.print("RC INPUT: "); |
|
| 124 | + Serial.print("Aileron="); Serial.print(rawAileronPWM); Serial.print("us ("); Serial.print(aileronControl); Serial.print("%), "); |
|
| 125 | + Serial.print("Elevator="); Serial.print(rawElevatorPWM); Serial.print("us ("); Serial.print(elevatorControl); Serial.print("%)"); |
|
| 126 | + Serial.print("MOTORS: "); |
|
| 127 | + Serial.print("M1_Cmd="); Serial.print(motor1TargetCommand); Serial.print(" (CurPWM:"); Serial.print(currentMotor1Speed); Serial.print(" TgtPWM:"); Serial.print(targetMotor1Speed); Serial.print("), "); |
|
| 128 | + Serial.print("M2_Cmd="); Serial.print(motor2TargetCommand); Serial.print(" (CurPWM:"); Serial.print(currentMotor2Speed); Serial.print(" TgtPWM:"); Serial.print(targetMotor2Speed); Serial.print(")"); |
|
| 129 | + |
|
| 130 | + Serial.println(); |
|
| 131 | + delay(20); // Delay for RC input reading cycle & ramping interval |
|
| 132 | +} |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/rover-8871-4.ino
| ... | ... | @@ -0,0 +1,180 @@ |
| 1 | +#include <Adafruit_NeoPixel.h> |
|
| 2 | + |
|
| 3 | +// Define pins for each RC channel |
|
| 4 | +int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 5 | +int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 6 | + |
|
| 7 | +// WS2812 LED Strip Configuration |
|
| 8 | +#define LED_PIN 15 // nodemcu pin D8 |
|
| 9 | +#define LED_COUNT 8 |
|
| 10 | +Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); |
|
| 11 | + |
|
| 12 | +// Updated comments for IN1 and IN2 to reflect their role as single control pins |
|
| 13 | +const int IN1 = 4; // Control pin for Motor 1 // D3 (was GPIO2 on NodeMCU D4, now D2/GPIO4) |
|
| 14 | +const int IN2 = 5; // Control pin for Motor 2 // D4 (was GPIO0 on NodeMCU D3, now D1/GPIO5) |
|
| 15 | + |
|
| 16 | +const int PWM_MAX = 255; // ESP8266 PWM range is 0-255 for analogWrite. |
|
| 17 | + // Note: Default ESP8266 analogWrite range is 0-1023. |
|
| 18 | + // Call analogWriteRange(255) in setup if 0-255 is desired. |
|
| 19 | +const int PWM_STOP = PWM_MAX / 2; // Approx. 127, this is brake/neutral for DRV8871 single-pin |
|
| 20 | +const int PWM_MIN_MOVING = 10; // Minimum offset from PWM_STOP to ensure movement |
|
| 21 | + |
|
| 22 | + |
|
| 23 | +long aileronControl; // Mapped value from aileron channel (0-100) |
|
| 24 | +long elevatorControl; // Mapped value from elevator channel (0-100) |
|
| 25 | + |
|
| 26 | +// Reads the PWM signal from the aileron channel and maps it to 0-100 |
|
| 27 | +long readAileronControlSignal() { |
|
| 28 | + unsigned long rawPWM = pulseIn(aileronPin, HIGH, 25000); |
|
| 29 | + // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 30 | + // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 31 | + if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 32 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 33 | + } |
|
| 34 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 35 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 36 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 37 | +} |
|
| 38 | + |
|
| 39 | +// Reads the PWM signal from the elevator channel and maps it to 0-100 |
|
| 40 | +long readElevatorControlSignal() { |
|
| 41 | + unsigned long rawPWM = pulseIn(elevatorPin, HIGH, 25000); |
|
| 42 | + // If signal is lost (timeout) or clearly out of valid RC pulse range, return neutral (50) |
|
| 43 | + // Valid RC pulses are typically 1000-2000us. Values outside ~900-2100us are treated as invalid. |
|
| 44 | + if (rawPWM == 0 || rawPWM < 900 || rawPWM > 2100) { |
|
| 45 | + return 50; // Mid-point for 0-100 scale (1500us equivalent), results in stop |
|
| 46 | + } |
|
| 47 | + // Otherwise, the signal is likely valid; constrain it to the standard 1000-2000us range and map |
|
| 48 | + long constrainedPWM = constrain(rawPWM, 1000, 2000); |
|
| 49 | + return map(constrainedPWM, 1000, 2000, 0, 100); |
|
| 50 | +} |
|
| 51 | + |
|
| 52 | +void setup() { |
|
| 53 | + pinMode(aileronPin, INPUT); |
|
| 54 | + pinMode(elevatorPin, INPUT); // Initialize elevator pin |
|
| 55 | + |
|
| 56 | + pinMode(IN1, OUTPUT); |
|
| 57 | + pinMode(IN2, OUTPUT); |
|
| 58 | + |
|
| 59 | + // Initialize motors to brake state |
|
| 60 | + analogWrite(IN1, PWM_STOP); |
|
| 61 | + analogWrite(IN2, PWM_STOP); |
|
| 62 | + |
|
| 63 | + Serial.begin(9600); |
|
| 64 | + // If you intend PWM_MAX to be 255, you might need to call: |
|
| 65 | + // analogWriteRange(255); |
|
| 66 | + // Otherwise, analogWrite will use a 0-1023 range by default on ESP8266. |
|
| 67 | + |
|
| 68 | + strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) |
|
| 69 | + strip.show(); // Turn OFF all pixels ASAP |
|
| 70 | + strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255) |
|
| 71 | +} |
|
| 72 | + |
|
| 73 | +// Updated helper function to control a single motor using one control pin |
|
| 74 | +// motorCtrlPin: The pin connected to the motor driver's input (e.g., IN1 for motor 1) |
|
| 75 | +// pwmVal: -255 (full backward) to 255 (full forward), 0 for brake |
|
| 76 | +void setMotorOutput(int motorCtrlPin, int pwmVal) { |
|
| 77 | + int actualPwm; |
|
| 78 | + if (pwmVal == 0) { |
|
| 79 | + actualPwm = PWM_STOP; // Brake |
|
| 80 | + } else if (pwmVal > 0) { // Forward |
|
| 81 | + // Map pwmVal from (1 to 255) to (PWM_STOP + PWM_MIN_MOVING to PWM_MAX) |
|
| 82 | + actualPwm = map(pwmVal, 1, 255, PWM_STOP + PWM_MIN_MOVING, PWM_MAX); |
|
| 83 | + // Ensure the value is within the defined forward motion range |
|
| 84 | + actualPwm = constrain(actualPwm, PWM_STOP + PWM_MIN_MOVING, PWM_MAX); |
|
| 85 | + } else { // Backward (pwmVal < 0) |
|
| 86 | + // Map abs(pwmVal) from (1 to 255) to (PWM_STOP - PWM_MIN_MOVING to 0) |
|
| 87 | + actualPwm = map(abs(pwmVal), 1, 255, PWM_STOP - PWM_MIN_MOVING, 0); |
|
| 88 | + // Ensure the value is within the defined reverse motion range |
|
| 89 | + actualPwm = constrain(actualPwm, 0, PWM_STOP - PWM_MIN_MOVING); |
|
| 90 | + } |
|
| 91 | + analogWrite(motorCtrlPin, actualPwm); |
|
| 92 | +} |
|
| 93 | + |
|
| 94 | +// Helper function to map RC control input (0-100) to an output range (e.g., -255 to 255) |
|
| 95 | +// with a deadband around the center (e.g., 50). |
|
| 96 | +long mapWithDeadband(long rcValue, int rcMin, int rcMax, int rcCenter, int deadbandRadius, int outMin, int outMax) { |
|
| 97 | + long mappedValue = 0; |
|
| 98 | + int deadbandLower = rcCenter - deadbandRadius; |
|
| 99 | + int deadbandUpper = rcCenter + deadbandRadius; |
|
| 100 | + |
|
| 101 | + if (rcValue < deadbandLower) { |
|
| 102 | + // Map the range [rcMin, deadbandLower - 1] to [outMin, -1] |
|
| 103 | + // Ensure deadbandLower - 1 is not less than rcMin |
|
| 104 | + if (deadbandLower -1 < rcMin) { |
|
| 105 | + mappedValue = outMin; |
|
| 106 | + } else { |
|
| 107 | + mappedValue = map(rcValue, rcMin, deadbandLower - 1, outMin, -1); |
|
| 108 | + } |
|
| 109 | + } else if (rcValue > deadbandUpper) { |
|
| 110 | + // Map the range [deadbandUpper + 1, rcMax] to [1, outMax] |
|
| 111 | + // Ensure deadbandUpper + 1 is not greater than rcMax |
|
| 112 | + if (deadbandUpper + 1 > rcMax) { |
|
| 113 | + mappedValue = outMax; |
|
| 114 | + } else { |
|
| 115 | + mappedValue = map(rcValue, deadbandUpper + 1, rcMax, 1, outMax); |
|
| 116 | + } |
|
| 117 | + } else { |
|
| 118 | + // Inside deadband |
|
| 119 | + mappedValue = 0; |
|
| 120 | + } |
|
| 121 | + return constrain(mappedValue, outMin, outMax); |
|
| 122 | +} |
|
| 123 | + |
|
| 124 | +// Function to create a random blinking effect for WS2812 LEDs |
|
| 125 | +void randomBlinkEffect() { |
|
| 126 | + for (int i = 0; i < LED_COUNT; i++) { |
|
| 127 | + // Turn on a random LED with a random color |
|
| 128 | + if (random(0, 2) == 1) { // 50% chance to turn on this LED |
|
| 129 | + strip.setPixelColor(i, strip.Color(random(0, 256), random(0, 256), random(0, 256))); |
|
| 130 | + } else { |
|
| 131 | + strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off |
|
| 132 | + } |
|
| 133 | + } |
|
| 134 | + strip.show(); // Send the updated pixel colors to the hardware. |
|
| 135 | + delay(100); // Wait a short period |
|
| 136 | +} |
|
| 137 | + |
|
| 138 | +void loop() { |
|
| 139 | + // Read mapped control signals from each channel |
|
| 140 | + aileronControl = readAileronControlSignal(); // Throttle (0-100) |
|
| 141 | + elevatorControl = readElevatorControlSignal(); // Steering (0-100) |
|
| 142 | + |
|
| 143 | + // Print the mapped control signal values to the Serial Monitor |
|
| 144 | + Serial.print("Aileron (Throttle): "); |
|
| 145 | + Serial.print(aileronControl); |
|
| 146 | + Serial.print(" Elevator (Steering): "); |
|
| 147 | + Serial.print(elevatorControl); |
|
| 148 | + Serial.println(); |
|
| 149 | + |
|
| 150 | + // Define deadband radius (e.g., +/- 5 around center of 50 for a 0-100 input) |
|
| 151 | + // This means input values from 45 to 55 (inclusive if center is 50 and radius is 5) will be treated as 0. |
|
| 152 | + int deadbandRadius = 15; |
|
| 153 | + float steeringFactor = 1; // Adjust this value to change steering sensitivity |
|
| 154 | + float throttleFactor = 1; // Adjust this value to change throttle sensitivity (e.g., 1.2 for 20% stronger throttle) |
|
| 155 | + |
|
| 156 | + // Map control values with deadband |
|
| 157 | + long rawThrottleValue = mapWithDeadband(aileronControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 158 | + long rawSteeringValue = mapWithDeadband(elevatorControl, 0, 100, 50, deadbandRadius, -255, 255); |
|
| 159 | + |
|
| 160 | + // Apply sensitivity factors |
|
| 161 | + long throttleValue = rawThrottleValue * throttleFactor; |
|
| 162 | + long adjustedSteeringValue = rawSteeringValue * steeringFactor; |
|
| 163 | + |
|
| 164 | + // Mix throttle and steering for differential drive |
|
| 165 | + long motor1Pwm = throttleValue + adjustedSteeringValue; |
|
| 166 | + long motor2Pwm = throttleValue - adjustedSteeringValue; |
|
| 167 | + |
|
| 168 | + // Constrain PWM values to the valid range [-255, 255] |
|
| 169 | + motor1Pwm = constrain(motor1Pwm, -255, 255); |
|
| 170 | + motor2Pwm = constrain(motor2Pwm, -255, 255); |
|
| 171 | + |
|
| 172 | + // Set motor speeds and directions using the updated function |
|
| 173 | + setMotorOutput(IN1, motor1Pwm); // Motor 1 |
|
| 174 | + setMotorOutput(IN2, motor2Pwm); // Motor 2 |
|
| 175 | + |
|
| 176 | + // Add the LED effect |
|
| 177 | + randomBlinkEffect(); |
|
| 178 | + |
|
| 179 | + delay(20); // Shorter delay for better responsiveness |
|
| 180 | +} |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/rover-8871-test.ino
| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | +// Define pins for each RC channel |
|
| 2 | +int aileronPin = 14; // Channel 1 (Throttle) // D5 |
|
| 3 | +int elevatorPin = 12; // Channel 2 (Steering) // D6 |
|
| 4 | + |
|
| 5 | +// Motor control pins |
|
| 6 | +const int MOTOR1_CTRL_PIN = 4; // GPIO4 (D2) |
|
| 7 | +const int MOTOR2_CTRL_PIN = 5; // GPIO5 (D1) |
|
| 8 | + |
|
| 9 | +const int PWM_MAX = 1023; // ESP8266 PWM range is 0-1023 |
|
| 10 | +const int PWM_STOP = PWM_MAX / 2; // ~511 or 512 |
|
| 11 | + |
|
| 12 | +void setup() { |
|
| 13 | + pinMode(MOTOR1_CTRL_PIN, OUTPUT); |
|
| 14 | + pinMode(MOTOR2_CTRL_PIN, OUTPUT); |
|
| 15 | + Serial.begin(9600); |
|
| 16 | +} |
|
| 17 | + |
|
| 18 | + |
|
| 19 | +void loop() { |
|
| 20 | + for (int pwm = 0; pwm <= PWM_MAX; pwm += 50) { |
|
| 21 | + |
|
| 22 | + // Apply the PWM value to both motors |
|
| 23 | + analogWrite(MOTOR1_CTRL_PIN, pwm); |
|
| 24 | + analogWrite(MOTOR2_CTRL_PIN, pwm); |
|
| 25 | + |
|
| 26 | + // Wait a moment at this PWM value |
|
| 27 | + delay(500); |
|
| 28 | + } |
|
| 29 | +} |
|
| ... | ... | \ No newline at end of file |
code-dat/RC-code-dat/ultrasonic car-1602.pde
| ... | ... | @@ -0,0 +1,399 @@ |
| 1 | +#include <IRremote.h> |
|
| 2 | +#include <Servo.h> |
|
| 3 | +#include <Wire.h> |
|
| 4 | +#include <LiquidCrystal_I2C.h> |
|
| 5 | + |
|
| 6 | +//***********************定義馬達腳位************************* |
|
| 7 | +int MotorRight1=6; |
|
| 8 | +int MotorRight2=9; |
|
| 9 | +int MotorLeft1=10; |
|
| 10 | +int MotorLeft2=11; |
|
| 11 | +int counter=0; |
|
| 12 | +const int irReceiverPin = 3; //紅外線接收器 OUTPUT 訊號接在 pin 2 |
|
| 13 | + |
|
| 14 | +//***********************設定所偵測到的IRcode************************* |
|
| 15 | +long IRfront= 0x00FF629D; //前進碼 |
|
| 16 | +long IRback=0x00FFA857; //後退 |
|
| 17 | +long IRturnright=0x00FF22DD; //右轉 |
|
| 18 | +long IRturnleft= 0x00FFC23D; //左轉 |
|
| 19 | +long IRstop=0x00FF02FD; //停止 |
|
| 20 | +long IRAutorun=0x00FF6897; //超音波自走模式 |
|
| 21 | +long IRturnsmallleft= 0x00FFB04F; |
|
| 22 | +IRrecv irrecv(irReceiverPin); // 定義 IRrecv 物件來接收紅外線訊號 |
|
| 23 | +decode_results results; |
|
| 24 | +//*************************定義超音波腳位****************************** |
|
| 25 | +int inputPin =A0 ; // 定義超音波信號接收腳位rx |
|
| 26 | +int outputPin =A1; // 定義超音波信號發射腳位'tx |
|
| 27 | +int Fspeedd = 0; // 前方距離 |
|
| 28 | +int Rspeedd = 0; // 右方距離 |
|
| 29 | +int Lspeedd = 0; // 左方距離 |
|
| 30 | +int directionn = 0; // 前=8 後=2 左=4 右=6 |
|
| 31 | +Servo myservo; // 設 myservo |
|
| 32 | +int delay_time = 250; // 伺服馬達轉向後的穩定時間 |
|
| 33 | +int Fgo = 8; // 前進 |
|
| 34 | +int Rgo = 6; // 右轉 |
|
| 35 | +int Lgo = 4; // 左轉 |
|
| 36 | +int Bgo = 2; // 倒車 |
|
| 37 | +//********************************************************************(SETUP) |
|
| 38 | +LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display |
|
| 39 | +void setup() |
|
| 40 | +{ |
|
| 41 | + Serial.begin(9600); |
|
| 42 | + pinMode(MotorRight1, OUTPUT); // 腳位 8 (PWM) |
|
| 43 | + pinMode(MotorRight2, OUTPUT); // 腳位 9 (PWM) |
|
| 44 | + pinMode(MotorLeft1, OUTPUT); // 腳位 10 (PWM) |
|
| 45 | + pinMode(MotorLeft2, OUTPUT); // 腳位 11 (PWM) |
|
| 46 | + irrecv.enableIRIn(); // 啟動紅外線解碼 |
|
| 47 | + digitalWrite(3,HIGH); |
|
| 48 | + pinMode(inputPin, INPUT); // 定義超音波輸入腳位 |
|
| 49 | + pinMode(outputPin, OUTPUT); // 定義超音波輸出腳位 |
|
| 50 | + myservo.attach(5); // 定義伺服馬達輸出第5腳位(PWM) |
|
| 51 | + lcd.init(); // initialize the lcd |
|
| 52 | + lcd.init(); |
|
| 53 | + // Print a message to the LCD. |
|
| 54 | + lcd.backlight(); |
|
| 55 | + |
|
| 56 | + |
|
| 57 | + |
|
| 58 | + } |
|
| 59 | +//******************************************************************(Void) |
|
| 60 | +void advance(int a) // 前進 |
|
| 61 | +{ |
|
| 62 | + digitalWrite(MotorRight1,LOW); |
|
| 63 | + digitalWrite(MotorRight2,HIGH); |
|
| 64 | + digitalWrite(MotorLeft1,LOW); |
|
| 65 | + digitalWrite(MotorLeft2,HIGH); |
|
| 66 | + delay(a * 100); |
|
| 67 | +} |
|
| 68 | +void right(int b) //右轉(單輪) |
|
| 69 | +{ |
|
| 70 | + digitalWrite(MotorLeft1,LOW); |
|
| 71 | + digitalWrite(MotorLeft2,HIGH); |
|
| 72 | + digitalWrite(MotorRight1,LOW); |
|
| 73 | + digitalWrite(MotorRight2,LOW); |
|
| 74 | + delay(b * 100); |
|
| 75 | +} |
|
| 76 | +void left(int c) //左轉(單輪) |
|
| 77 | +{ |
|
| 78 | + digitalWrite(MotorRight1,LOW); |
|
| 79 | + digitalWrite(MotorRight2,HIGH); |
|
| 80 | + digitalWrite(MotorLeft1,LOW); |
|
| 81 | + digitalWrite(MotorLeft2,LOW); |
|
| 82 | + delay(c * 100); |
|
| 83 | +} |
|
| 84 | +void turnR(int d) //右轉(雙輪) |
|
| 85 | +{ |
|
| 86 | + digitalWrite(MotorRight1,HIGH); |
|
| 87 | + digitalWrite(MotorRight2,LOW); |
|
| 88 | + digitalWrite(MotorLeft1,LOW); |
|
| 89 | + digitalWrite(MotorLeft2,HIGH); |
|
| 90 | + delay(d * 100); |
|
| 91 | +} |
|
| 92 | +void turnL(int e) //左轉(雙輪) |
|
| 93 | +{ |
|
| 94 | + digitalWrite(MotorRight1,LOW); |
|
| 95 | + digitalWrite(MotorRight2,HIGH); |
|
| 96 | + digitalWrite(MotorLeft1,HIGH); |
|
| 97 | + digitalWrite(MotorLeft2,LOW); |
|
| 98 | + delay(e * 100); |
|
| 99 | +} |
|
| 100 | +void stopp(int f) //停止 |
|
| 101 | +{ |
|
| 102 | + digitalWrite(MotorRight1,LOW); |
|
| 103 | + digitalWrite(MotorRight2,LOW); |
|
| 104 | + digitalWrite(MotorLeft1,LOW); |
|
| 105 | + digitalWrite(MotorLeft2,LOW); |
|
| 106 | + delay(f * 100); |
|
| 107 | +} |
|
| 108 | +void back(int g) //後退 |
|
| 109 | +{ |
|
| 110 | + digitalWrite(MotorRight1,HIGH); |
|
| 111 | + digitalWrite(MotorRight2,LOW); |
|
| 112 | + digitalWrite(MotorLeft1,HIGH); |
|
| 113 | + digitalWrite(MotorLeft2,LOW);; |
|
| 114 | + delay(g * 100); |
|
| 115 | +} |
|
| 116 | +void detection() //測量3個角度(前.左.右) |
|
| 117 | +{ |
|
| 118 | + int delay_time = 250; // 伺服馬達轉向後的穩定時間 |
|
| 119 | + ask_pin_F(); // 讀取前方距離 |
|
| 120 | + |
|
| 121 | + if(Fspeedd < 10) // 假如前方距離小於10公分 |
|
| 122 | + { |
|
| 123 | + stopp(1); // 清除輸出資料 |
|
| 124 | + back(2); // 後退 0.2秒 |
|
| 125 | + |
|
| 126 | + |
|
| 127 | + } |
|
| 128 | + if(Fspeedd < 25) // 假如前方距離小於25公分 |
|
| 129 | + { |
|
| 130 | + stopp(1); // 清除輸出資料 |
|
| 131 | + ask_pin_L(); // 讀取左方距離 |
|
| 132 | + delay(delay_time); // 等待伺服馬達穩定 |
|
| 133 | + ask_pin_R(); // 讀取右方距離 |
|
| 134 | + delay(delay_time); // 等待伺服馬達穩定 |
|
| 135 | + |
|
| 136 | + if(Lspeedd > Rspeedd) //假如 左邊距離大於右邊距離 |
|
| 137 | + { |
|
| 138 | + directionn = Lgo; //向左走 |
|
| 139 | + } |
|
| 140 | + |
|
| 141 | + if(Lspeedd <= Rspeedd) //假如 左邊距離小於或等於右邊距離 |
|
| 142 | + { |
|
| 143 | + directionn = Rgo; //向右走 |
|
| 144 | + } |
|
| 145 | + |
|
| 146 | + if (Lspeedd < 15 && Rspeedd < 15) //假如 左邊距離和右邊距離皆小於10公分 |
|
| 147 | + { |
|
| 148 | + directionn = Bgo; //向後走 |
|
| 149 | + } |
|
| 150 | + } |
|
| 151 | + else //加如前方大於25公分 |
|
| 152 | + { |
|
| 153 | + directionn = Fgo; //向前走 |
|
| 154 | + } |
|
| 155 | +} |
|
| 156 | +//********************************************************************************* |
|
| 157 | +void ask_pin_F() // 量出前方距離 |
|
| 158 | +{ |
|
| 159 | +myservo.write(90); |
|
| 160 | +digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs |
|
| 161 | +delayMicroseconds(2); |
|
| 162 | +digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓10μs,這裡至少是10μs |
|
| 163 | +delayMicroseconds(10); |
|
| 164 | +digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 165 | +float Fdistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 166 | +Fdistance= Fdistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 167 | + |
|
| 168 | +Fspeedd = Fdistance; // 將距離 讀入Fspeedd(前速) |
|
| 169 | +} |
|
| 170 | +//******************************************************************************** |
|
| 171 | +void ask_pin_L() // 量出左邊距離 |
|
| 172 | +{ |
|
| 173 | +myservo.write(177); |
|
| 174 | +delay(delay_time); |
|
| 175 | +digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs |
|
| 176 | +delayMicroseconds(2); |
|
| 177 | +digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓10μs,這裡至少是10μs |
|
| 178 | +delayMicroseconds(10); |
|
| 179 | +digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 180 | +float Ldistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 181 | +Ldistance= Ldistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 182 | + |
|
| 183 | +Lspeedd = Ldistance; // 將距離 讀入Lspeedd(左速) |
|
| 184 | +} |
|
| 185 | +//****************************************************************************** |
|
| 186 | +void ask_pin_R() // 量出右邊距離 |
|
| 187 | +{ |
|
| 188 | +myservo.write(5); |
|
| 189 | +delay(delay_time); |
|
| 190 | +digitalWrite(outputPin, LOW); // 讓超聲波發射低電壓2μs |
|
| 191 | +delayMicroseconds(2); |
|
| 192 | +digitalWrite(outputPin, HIGH); // 讓超聲波發射高電壓10μs,這裡至少是10μs |
|
| 193 | +delayMicroseconds(10); |
|
| 194 | +digitalWrite(outputPin, LOW); // 維持超聲波發射低電壓 |
|
| 195 | +float Rdistance = pulseIn(inputPin, HIGH); // 讀差相差時間 |
|
| 196 | +Rdistance= Rdistance/5.8/10; // 將時間轉為距離距离(單位:公分) |
|
| 197 | + |
|
| 198 | +Rspeedd = Rdistance; // 將距離 讀入Rspeedd(右速) |
|
| 199 | +} |
|
| 200 | +//******************************************************************************(LOOP) |
|
| 201 | +void loop() |
|
| 202 | +{ |
|
| 203 | + |
|
| 204 | +//***************************************************************************正常遙控模式 |
|
| 205 | + if (irrecv.decode(&results)) |
|
| 206 | + { // 解碼成功,收到一組紅外線訊號 |
|
| 207 | +/***********************************************************************/ |
|
| 208 | + if (results.value == IRfront)//前進 |
|
| 209 | + { |
|
| 210 | + |
|
| 211 | + lcd.setCursor(0,0); |
|
| 212 | + lcd.print(" IR mode"); |
|
| 213 | + lcd.setCursor(0,1); |
|
| 214 | + lcd.print(" advance "); |
|
| 215 | + advance(20);//前進 |
|
| 216 | + } |
|
| 217 | +/***********************************************************************/ |
|
| 218 | + if (results.value == IRback)//後退 |
|
| 219 | + { |
|
| 220 | + |
|
| 221 | + lcd.setCursor(0,0); |
|
| 222 | + lcd.print(" IR mode"); |
|
| 223 | + lcd.setCursor(0,1); |
|
| 224 | + lcd.print(" back "); |
|
| 225 | + back(20);//後退 |
|
| 226 | + } |
|
| 227 | +/***********************************************************************/ |
|
| 228 | + if (results.value == IRturnright)//右轉 |
|
| 229 | + { |
|
| 230 | + |
|
| 231 | + lcd.setCursor(0,0); |
|
| 232 | + lcd.print(" IR mode"); |
|
| 233 | + lcd.setCursor(0,1); |
|
| 234 | + lcd.print(" right "); |
|
| 235 | + right(10); // 右轉 |
|
| 236 | + |
|
| 237 | + } |
|
| 238 | +/***********************************************************************/ |
|
| 239 | + if (results.value == IRturnleft)//左轉 |
|
| 240 | + { |
|
| 241 | + |
|
| 242 | + lcd.setCursor(0,0); |
|
| 243 | + lcd.print(" IR mode"); |
|
| 244 | + lcd.setCursor(0,1); |
|
| 245 | + lcd.print(" left "); |
|
| 246 | + left(10); // 左轉); |
|
| 247 | + } |
|
| 248 | +/***********************************************************************/ |
|
| 249 | + if (results.value == IRstop)//停止 |
|
| 250 | + { |
|
| 251 | + lcd.setCursor(0,0); |
|
| 252 | + lcd.print(" IR mode"); |
|
| 253 | + lcd.setCursor(0,1); |
|
| 254 | + lcd.print(" stop "); |
|
| 255 | + digitalWrite(MotorRight1,LOW); |
|
| 256 | + digitalWrite(MotorRight2,LOW); |
|
| 257 | + digitalWrite(MotorLeft1,LOW); |
|
| 258 | + digitalWrite(MotorLeft2,LOW); |
|
| 259 | + |
|
| 260 | + |
|
| 261 | + } |
|
| 262 | + |
|
| 263 | +//***********************************************************************超音波自走模式 |
|
| 264 | + if (results.value ==IRAutorun ) |
|
| 265 | + { |
|
| 266 | + while(IRAutorun) |
|
| 267 | + { |
|
| 268 | + myservo.write(90); //讓伺服馬達回歸 預備位置 準備下一次的測量 |
|
| 269 | + detection(); //測量角度 並且判斷要往哪一方向移動 |
|
| 270 | + if(directionn == 8) //假如directionn(方向) = 8(前進) |
|
| 271 | + { |
|
| 272 | + if (irrecv.decode(&results)) |
|
| 273 | + { |
|
| 274 | + irrecv.resume(); |
|
| 275 | + Serial.println(results.value,HEX); |
|
| 276 | + if(results.value ==IRstop) |
|
| 277 | + { |
|
| 278 | + digitalWrite(MotorRight1,LOW); |
|
| 279 | + digitalWrite(MotorRight2,LOW); |
|
| 280 | + digitalWrite(MotorLeft1,LOW); |
|
| 281 | + digitalWrite(MotorLeft2,LOW); |
|
| 282 | + break; |
|
| 283 | + } |
|
| 284 | + } |
|
| 285 | + results.value=0; |
|
| 286 | + |
|
| 287 | + |
|
| 288 | + lcd.setCursor(0,0); |
|
| 289 | + lcd.print(" aoto mode"); |
|
| 290 | + lcd.setCursor(0,1); |
|
| 291 | + lcd.print(" Advance "); |
|
| 292 | + advance(1); // 正常前進 |
|
| 293 | + } |
|
| 294 | + if(directionn == 2) //假如directionn(方向) = 2(倒車) |
|
| 295 | + { |
|
| 296 | + if (irrecv.decode(&results)) |
|
| 297 | + { |
|
| 298 | + irrecv.resume(); |
|
| 299 | + Serial.println(results.value,HEX); |
|
| 300 | + if(results.value ==IRstop) |
|
| 301 | + { |
|
| 302 | + digitalWrite(MotorRight1,LOW); |
|
| 303 | + digitalWrite(MotorRight2,LOW); |
|
| 304 | + digitalWrite(MotorLeft1,LOW); |
|
| 305 | + digitalWrite(MotorLeft2,LOW); |
|
| 306 | + break; |
|
| 307 | + } |
|
| 308 | + } |
|
| 309 | + results.value=0; |
|
| 310 | + |
|
| 311 | + |
|
| 312 | + lcd.setCursor(0,0); |
|
| 313 | + lcd.print(" aoto mode"); |
|
| 314 | + lcd.setCursor(0,1); |
|
| 315 | + lcd.print(" Reverse "); |
|
| 316 | + back(8); // 倒退(車) |
|
| 317 | + turnL(3); //些微向左方移動(防止卡在死巷裡) |
|
| 318 | + } |
|
| 319 | + if(directionn == 6) //假如directionn(方向) = 6(右轉) |
|
| 320 | + { |
|
| 321 | + if (irrecv.decode(&results)) |
|
| 322 | + { |
|
| 323 | + irrecv.resume(); |
|
| 324 | + Serial.println(results.value,HEX); |
|
| 325 | + if(results.value ==IRstop) |
|
| 326 | + { |
|
| 327 | + digitalWrite(MotorRight1,LOW); |
|
| 328 | + digitalWrite(MotorRight2,LOW); |
|
| 329 | + digitalWrite(MotorLeft1,LOW); |
|
| 330 | + digitalWrite(MotorLeft2,LOW); |
|
| 331 | + break; |
|
| 332 | + } |
|
| 333 | + } |
|
| 334 | + results.value=0; |
|
| 335 | + |
|
| 336 | + |
|
| 337 | + lcd.setCursor(0,0); |
|
| 338 | + lcd.print(" aoto mode"); |
|
| 339 | + lcd.setCursor(0,1); |
|
| 340 | + lcd.print(" Right "); |
|
| 341 | + back(1); |
|
| 342 | + turnR(3); // 右轉 |
|
| 343 | + } |
|
| 344 | + if(directionn == 4) //假如directionn(方向) = 4(左轉) |
|
| 345 | + { |
|
| 346 | + if (irrecv.decode(&results)) |
|
| 347 | + { |
|
| 348 | + irrecv.resume(); |
|
| 349 | + Serial.println(results.value,HEX); |
|
| 350 | + if(results.value ==IRstop) |
|
| 351 | + { |
|
| 352 | + digitalWrite(MotorRight1,LOW); |
|
| 353 | + digitalWrite(MotorRight2,LOW); |
|
| 354 | + digitalWrite(MotorLeft1,LOW); |
|
| 355 | + digitalWrite(MotorLeft2,LOW); |
|
| 356 | + break; |
|
| 357 | + } |
|
| 358 | + } |
|
| 359 | + results.value=0; |
|
| 360 | + |
|
| 361 | + lcd.setCursor(0,0); |
|
| 362 | + lcd.print(" aoto mode"); |
|
| 363 | + lcd.setCursor(0,1); |
|
| 364 | + lcd.print(" Left "); |
|
| 365 | + back(1); |
|
| 366 | + turnL(3); // 左轉 |
|
| 367 | + |
|
| 368 | + } |
|
| 369 | + |
|
| 370 | + if (irrecv.decode(&results)) |
|
| 371 | + { |
|
| 372 | + irrecv.resume(); |
|
| 373 | + Serial.println(results.value,HEX); |
|
| 374 | + if(results.value ==IRstop) |
|
| 375 | + { |
|
| 376 | + digitalWrite(MotorRight1,LOW); |
|
| 377 | + digitalWrite(MotorRight2,LOW); |
|
| 378 | + digitalWrite(MotorLeft1,LOW); |
|
| 379 | + digitalWrite(MotorLeft2,LOW); |
|
| 380 | + break; |
|
| 381 | + } |
|
| 382 | + } |
|
| 383 | + } |
|
| 384 | + results.value=0; |
|
| 385 | + } |
|
| 386 | +/***********************************************************************/ |
|
| 387 | + else |
|
| 388 | + { |
|
| 389 | + digitalWrite(MotorRight1,LOW); |
|
| 390 | + digitalWrite(MotorRight2,LOW); |
|
| 391 | + digitalWrite(MotorLeft1,LOW); |
|
| 392 | + digitalWrite(MotorLeft2,LOW); |
|
| 393 | + } |
|
| 394 | + |
|
| 395 | + |
|
| 396 | + irrecv.resume(); // 繼續收下一組紅外線訊號 |
|
| 397 | + } |
|
| 398 | +} |
|
| 399 | + |