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
+