@@ -19,14 +19,26 @@ RobotStateService::RobotStateService(AsyncWebServer* server, SecurityManager* se
19
19
}
20
20
21
21
void RobotStateService::begin () {
22
- camXServo.attach (CAM_X_SERVO_PIN, 2 );
23
- camYServo.attach (CAM_Y_SERVO_PIN, 3 );
24
- clawServo.attach (CLAW_SERVO_PIN, 4 );
22
+ camXServo.attach (CAM_X_SERVO_PIN, CAM_X_SERVO_CHANNEL );
23
+ camYServo.attach (CAM_Y_SERVO_PIN, CAM_Y_SERVO_CHANNEL );
24
+ clawServo.attach (CLAW_SERVO_PIN, CLAW_SERVO_CHANNEL );
25
25
26
26
// configure the default state
27
27
_state.camX = DEFAULT_CAM_X;
28
28
_state.camY = DEFAULT_CAM_Y;
29
29
_state.claw = DEFAULT_CLAW;
30
+ _state.driveX = DEFAULT_DRIVE_X;
31
+ _state.driveY = DEFAULT_DRIVE_Y;
32
+
33
+ // configure the PWM pins for both motors
34
+ ledcSetup (LEFT_MOTOR_PWM_CHANNEL, MOTOR_PWM_FREQUENCY, MOTOR_PWM_RESOLUTION);
35
+ ledcAttachPin (LEFT_MOTOR_PWM_PIN, LEFT_MOTOR_PWM_CHANNEL);
36
+ ledcSetup (RIGHT_MOTOR_PWM_CHANNEL, MOTOR_PWM_FREQUENCY, MOTOR_PWM_RESOLUTION);
37
+ ledcAttachPin (RIGHT_MOTOR_PWM_PIN, RIGHT_MOTOR_PWM_CHANNEL);
38
+
39
+ // configure direction pins for both motors
40
+ pinMode (LEFT_MOTOR_DIRECTION_PIN, OUTPUT);
41
+ pinMode (RIGHT_MOTOR_DIRECTION_PIN, OUTPUT);
30
42
31
43
// apply the default state
32
44
onConfigUpdated ();
@@ -36,4 +48,77 @@ void RobotStateService::onConfigUpdated() {
36
48
camXServo.write (_state.camX );
37
49
camYServo.write (_state.camY );
38
50
clawServo.write (_state.claw );
51
+
52
+ // calculate and convert motor outputs to PWM outputs for h-bridge
53
+ struct MotorOutputs outputs = calculateMotorOutputs (_state.driveX , _state.driveY );
54
+ applyMotorOutput (outputs.left , LEFT_MOTOR_DIRECTION_PIN, LEFT_MOTOR_PWM_CHANNEL);
55
+ applyMotorOutput (outputs.right , RIGHT_MOTOR_DIRECTION_PIN, RIGHT_MOTOR_PWM_CHANNEL);
39
56
}
57
+
58
+ void RobotStateService::applyMotorOutput (int32_t output, uint8_t directionPin, uint8_t pwmChan) {
59
+ bool forward = output >= 0 ;
60
+ output = abs (output);
61
+ output = output > DEAD_ZONE ? output : 0 ;
62
+ if (output > 0 ) {
63
+ output = map (output, 0 , 1023 , 600 , 1023 );
64
+ }
65
+ if (forward) {
66
+ digitalWrite (directionPin, HIGH);
67
+ ledcWrite (pwmChan, 1023 - output);
68
+ } else {
69
+ digitalWrite (directionPin, LOW);
70
+ ledcWrite (pwmChan, output);
71
+ }
72
+ }
73
+
74
+ // Wonderful code below borrowed from https://www.impulseadventure.com/elec/robot-differential-steering.html
75
+ struct MotorOutputs RobotStateService::calculateMotorOutputs (int32_t nJoyX, int32_t nJoyY) {
76
+ // OUTPUTS
77
+ int32_t nMotMixL; // Motor (left) mixed output (-1023..+1023)
78
+ int32_t nMotMixR; // Motor (right) mixed output (-1023..+1023)
79
+
80
+ // CONFIG
81
+ // - fPivYLimt : The threshold at which the pivot action starts
82
+ // This threshold is measured in units on the Y-axis
83
+ // away from the X-axis (Y=0). A greater value will assign
84
+ // more of the joystick's range to pivot actions.
85
+ // Allowable range: (0..+1023)
86
+ float fPivYLimit = 255.0 ;
87
+
88
+ // TEMP VARIABLES
89
+ float nMotPremixL; // Motor (left) premixed output (-1023..+1023)
90
+ float nMotPremixR; // Motor (right) premixed output (-1023..+1023)
91
+ int32_t nPivSpeed; // Pivot Speed (-1023..+1023)
92
+ float fPivScale ; // Balance scale b/w drive and pivot ( 0..1 )
93
+
94
+ // Calculate Drive Turn output due to Joystick X input
95
+ if (nJoyY >= 0 ) {
96
+ // Forward
97
+ nMotPremixL = (nJoyX >= 0 ) ? 1023.0 : (1023.0 + nJoyX);
98
+ nMotPremixR = (nJoyX >= 0 ) ? (1023.0 - nJoyX) : 1023.0 ;
99
+ } else {
100
+ // Reverse
101
+ nMotPremixL = (nJoyX >= 0 ) ? (1023.0 - nJoyX) : 1023.0 ;
102
+ nMotPremixR = (nJoyX >= 0 ) ? 1023.0 : (1023.0 + nJoyX);
103
+ }
104
+
105
+ // Scale Drive output due to Joystick Y input (throttle)
106
+ nMotPremixL = nMotPremixL * nJoyY / 1023.0 ;
107
+ nMotPremixR = nMotPremixR * nJoyY / 1023.0 ;
108
+
109
+ // Now calculate pivot amount
110
+ // - Strength of pivot (nPivSpeed) based on Joystick X input
111
+ // - Blending of pivot vs drive (fPivScale) based on Joystick Y input
112
+ nPivSpeed = nJoyX;
113
+ fPivScale = (abs (nJoyY) > fPivYLimit ) ? 0.0 : (1.0 - abs (nJoyY) / fPivYLimit );
114
+
115
+ // Calculate final mix of Drive and Pivot
116
+ nMotMixL = (1.0 - fPivScale ) * nMotPremixL + fPivScale * (nPivSpeed);
117
+ nMotMixR = (1.0 - fPivScale ) * nMotPremixR + fPivScale * (-nPivSpeed);
118
+
119
+ // return as a struct
120
+ struct MotorOutputs outputs {
121
+ nMotMixL, nMotMixR
122
+ };
123
+ return outputs;
124
+ }
0 commit comments