Add servo controls and spinlock, fix swerve, optimize code

This commit is contained in:
evlryah 2023-09-29 21:08:53 -05:00
parent 55a0b6549f
commit b4bc492f96
9 changed files with 213 additions and 285 deletions

View File

@ -4,6 +4,7 @@
"cmath": "cpp",
"*.tcc": "cpp",
"string": "cpp",
"ranges": "cpp"
"ranges": "cpp",
"numeric": "cpp"
}
}

View File

@ -15,8 +15,8 @@ extern long last_p;
*/
// Loop timing
#define LOOP_DELAY_MS_CORE_0 50 // Minimum milliseconds between the start of each loop, accounting for processing time during each loop
#define LOOP_DELAY_MS_CORE_1 50 // Minimum milliseconds between the start of each loop, accounting for processing time during each loop
#define LOOP_DELAY_MS_CORE_0 50 // Minimum milliseconds between the start of each loop, accounting for processing time during each loop
#define LOOP_DELAY_MS_CORE_1 20 // Minimum milliseconds between the start of each loop, accounting for processing time during each loop
#define LOOP_DELAY_SECONDS ((float)LOOP_DELAY_MS_CORE_0 / 1000.0f) // Previous number expressed in seconds
// Math things
@ -57,8 +57,11 @@ extern long last_p;
// This value must always be at least 2, otherwise the code will break due to there being an array with a zero or negative length or a division by zero
#define ENCODER_BUFFER_ENTRY_COUNT 5
// Number of encoder ticks per full rotation of each swerve drive steering motor
#define STEERING_ENCODER_TICKS_PER_ROTATION (1024.0 * 8.0)
// Number of encoder ticks per degree of rotation for the swerve drive steering motors
#define STEERING_ENCODER_TICKS_PER_DEGREE (1024.0 * 4.0) / 360.0 // TODO check as of 20230927
#define STEERING_ENCODER_TICKS_PER_DEGREE (STEERING_ENCODER_TICKS_PER_ROTATION / 360.0)
// Maximum speed allowed for the steering motors (out of 127.0)
#define STEERING_MOTOR_SPEED_LIMIT 127.0 // TODO as of 20230927, lower this if they're spinning too fast for the robot to handle
@ -78,6 +81,7 @@ extern long last_p;
// #define CLAW_COMMAND_STOP 1 // Stop immediately, no matter the location
#define CLAW_COMMAND_CLOSE 2 // Close the claw
#define CLAW_COMMAND_OPEN 3 // Open the claw
#define CLAW_COMMAND_STAY 4 // Maintain the current position
// Claw things
#define CLAW_OPEN_ANGLE 90.0f // Open position of the claw
@ -85,18 +89,32 @@ extern long last_p;
#define CLAW_DEFAULT_ANGLE 0.0f // Default starting claw position
// Tilt servo control parameters
#define TILT_ANGLE_MIN_UPDATE_INTERVAL 0.2f // Update the tilt servo's target angle only after this many seconds have elapsed since the previous angle update
#define TILT_ANGLE_MIN_UPDATE_LOOPS (TILT_ANGLE_MIN_UPDATE_INTERVAL / LOOP_DELAY_SECONDS) // Previous value expressed as a number of control loops to wait between updates
#define TILT_ANGLE_UPDATE_DISTANCE 10.0f // Distance in degrees to shift the servo angle by each update
#define TILT_MAX_ANGLE 90.0f // Maximum angle allowed for the tilt servo
#define TILT_MIN_ANGLE -90.0f // Minimum angle allowed for the tilt servo
#define TILT_FLAT_ANGLE 0.0f // Default/flat/starting angle for the tilt servo
#define TILT_DEGREES_PER_SECOND 50.0f // Speed in degrees per second that the tilt motor will move up or down (except when resetting to a flat position)
#define TILT_ANGLE_MIN_UPDATE_INTERVAL 0.2f // Update the tilt servo's target angle only after this many seconds have elapsed since the previous angle update
#define TILT_ANGLE_MIN_UPDATE_LOOPS (TILT_ANGLE_MIN_UPDATE_INTERVAL / LOOP_DELAY_SECONDS) // Previous value expressed as a number of control loops to wait between updates
#define TILT_ANGLE_UPDATE_DISTANCE (TILT_DEGREES_PER_SECOND * TILT_ANGLE_MIN_UPDATE_INTERVAL) // Distance in degrees to shift the servo angle by each update
#define TILT_MAX_ANGLE 90.0f // Maximum angle allowed for the tilt servo
#define TILT_MIN_ANGLE -90.0f // Minimum angle allowed for the tilt servo
#define TILT_FLAT_ANGLE 0.0f // Default/flat/starting angle for the tilt servo
// Tilt servo commands
#define TILT_COMMAND_UNSET 0
#define TILT_COMMAND_UP 1
#define TILT_COMMAND_DOWN 2
#define TILT_COMMAND_UNSET 0 // Command not yet set, go to default (flat) position
#define TILT_COMMAND_RESET 1 // Reset the tilt servo to the flat position
#define TILT_COMMAND_UP 2 // Raise the tilt servo
#define TILT_COMMAND_DOWN 3 // Lower the silt servo
// Control parameters, specify which buttons control new_angle actions
#define ARM_UP_BUTTON DPAD_UP
#define ARM_DOWN_BUTTON DPAD_DOWN
#define CLAW_OPEN_BUTTON DPAD_LEFT
#define CLAW_CLOSE_BUTTON DPAD_RIGHT
#define TILT_UP_BUTTON DIAMOND_UP
#define TILT_DOWN_BUTTON DIAMOND_DOWN
#define TILT_RESET_BUTTON DIAMOND_LEFT
// Button definitions
#define SerComm Serial1 //Serial port connected to Xbee
#define DIAMOND_LEFT 0
#define DIAMOND_DOWN 1

View File

@ -15,6 +15,7 @@
#include <107-Arduino-Servo-RP2040.h>
#include "swerve.h"
#include "manipulator.h"
#include "spinlock.h"
const char* ssid = "TEST";
const char* password = "pink4bubble";
@ -43,9 +44,9 @@ PCF8574 ioex2(0x21, 20, 21);
// JANK: soldered to pico or headers
PioEncoder enc1(18); // Front Left
PioEncoder enc2(14); // Front Right
PioEncoder enc3(27); // Back Left
PioEncoder enc4(0); // Back Right
PioEncoder enc2(0); // Front Right // TODO WIRING AND CONFIRMATION 20230929
PioEncoder enc3(27); // Back Left // TODO WIRING AND CONFIRMATION 20230929
PioEncoder enc4(14); // Back Right
@ -68,10 +69,25 @@ int stepperX_pos = 0;
int stepperY_pos = 0;
int stepperZ_pos = 0;
// Loop management
uint64_t previous_loop_start_time_core_0 = 0, previous_loop_start_time_core_1 = 0; // Track the previous loop start time, used to calculate how long to sleep for until the start of the next loop
uint64_t previous_loop_processing_duration_core_0 = 0, previous_loop_processing_duration_core_1 = 0; // Processing time for the previous loop on each core
uint64_t loop_counter_core_0 = 0, loop_counter_core_1 = 0; // Counter for loop() and loop1() respectively, incremented at the end of each loop
// Motor power communication between cores
byte drive_power_command_spinlock_flag = SPINLOCK_UNSET; // Spinlock tracking flag
// Variables used to transfer steering motor power between cores, covered by spinlock
int power_data_transfer_fl = 0;
int power_data_transfer_fr = 0;
int power_data_transfer_bl = 0;
int power_data_transfer_br = 0;
// Variables used to track previous requested motor power, only used by core 1, sabertooth not called if motor power unchanged since previous loop
int power_data_transfer_prev_fl = 0;
int power_data_transfer_prev_fr = 0;
int power_data_transfer_prev_bl = 0;
int power_data_transfer_prev_br = 0;
#define defMaxSpeed 8000
#define defAcceleration 8000
@ -112,14 +128,14 @@ int right_cooldown = 0;
int olddisplay = 99999; // guarantee a change when first value comes in
// motor indeces for set_motor() function
#define FLSTEER 1
#define FRSTEER 2
#define BLSTEER 3
#define BRSTEER 4
#define FRSTEER 1
#define FLSTEER 2
#define BRSTEER 3
#define BLSTEER 4
#define FLDRIVE 5
#define FRDRIVE 6
#define BRDRIVE 6
#define BLDRIVE 7
#define BRDRIVE 8
#define FRDRIVE 8
#define EXTEND1 9
#define EXTEND2 10
#define LIFT1 11
@ -384,8 +400,8 @@ void set_dec(byte num) {
}
void set_motor(byte motor, int speed) {
// 1 - 4 : swivel motors on Sabertooth 1-2
// 5 - 8 : drive motors on Talon SRX
// 1 - 4 : swivel motors on Sabertooth 1-2 (Clockwise: FR, FL, BR, BL)
// 5 - 8 : drive motors on Talon SRX (Forward: FL, BR, BL, FL)
// 9 - 10 : actuators on Sabertooth 3
// 11 - 13 : Steppers on slave board
// 14 : drive 11-13 with identical position & speed
@ -397,6 +413,7 @@ void set_motor(byte motor, int speed) {
Serial.println(speed);
if (motor <= 4) {
// swerve controls
speed *= (((motor % 2) * 2) - 1); // Flip motors 2 and 4
swivel[(motor - 1) / 2].motor((motor - 1) % 2 + 1, speed);
}
else if (motor == 5)
@ -675,7 +692,7 @@ void setup() {
Serial.print("Initializing encoders..");
set_hex(0x5);
enc1.begin();
enc1.flip();
//enc1.flip();
enc2.begin();
enc3.begin();
enc4.begin();
@ -859,7 +876,8 @@ void print_status() {
}
void telemetry(float zeroed_lx_float, float zeroed_ly_float, float zeroed_rx_float, float zeroed_ry_float, int drive_mode, \
float left_joystick_angle, float left_joystick_magnitude, float right_joystick_angle, float right_joystick_magnitude) { // Print encoder positions for steering motors
float left_joystick_angle, float left_joystick_magnitude, float right_joystick_angle, float right_joystick_magnitude, \
uint64_t processing_time) { // Print encoder positions for steering motors
char buffer[300] = "\0";
@ -868,10 +886,11 @@ void telemetry(float zeroed_lx_float, float zeroed_ly_float, float zeroed_rx_flo
//SerComm.println(buffer);
// Encoder data and loop number
sprintf(buffer, "Loop = %llu E1 = %i E2 = %i E3 = %i E4 = %i z_lx = %f z_ly = %f z_rx = %f z_ry = %f mode = %i mag-L = %f ang-L = %f mag-R = %f ang-R = %f", \
sprintf(buffer, "Loop = %llu E1 = %i E2 = %i E3 = %i E4 = %i z_lx = %f z_ly = %f z_rx = %f z_ry = %f mode = %i mag-L = %f ang-L = %f mag-R = %f ang-R = %f proctime = %llu", \
loop_counter_core_0, enc1.getCount(), enc2.getCount(), enc3.getCount(), enc4.getCount(), \
zeroed_lx_float, zeroed_ly_float, zeroed_rx_float, zeroed_ry_float, drive_mode, \
left_joystick_magnitude, left_joystick_angle, right_joystick_magnitude, right_joystick_angle);
left_joystick_magnitude, left_joystick_angle, right_joystick_magnitude, right_joystick_angle, \
processing_time);
Serial.println(buffer);
SerComm.println(buffer);
}
@ -952,36 +971,46 @@ void loop() {
swrv = updateEncoderData(swrv, enc1.getCount(), enc2.getCount(), enc3.getCount(), enc4.getCount()); // Update encoder data in the swerve_drive struct
swrv = updateSwerveCommand(swrv); // Calculate power for each drive and steering motor
// Arm motor control (stepper motors)
float arm_speed = 0.0f; // TODO as of 20230928: PLACEHOLDER for input for arm speed
// Arm motor control (stepper motors), DPAD_UP to move arm up, DPAD_DOWN to move arm down, both or neither being pressed stops the arm
float arm_speed = (float) (((int) getButton(DPAD_UP)) - ((int) getButton(DPAD_DOWN))); // TODO 20230929 confirm speed and polarity
clawarm = setArmSpeed(clawarm, arm_speed);
// Claw servo control
int new_claw_command = CLAW_COMMAND_UNSET;
/*
// TODO select action for claw
*/
int claw_direction = getButton(CLAW_OPEN_BUTTON) - getButton(CLAW_CLOSE_BUTTON);
switch(claw_direction) {
case 0:
new_claw_command = CLAW_COMMAND_STAY;
break;
case 1:
new_claw_command = CLAW_COMMAND_OPEN;
break;
case -1:
new_claw_command = CLAW_COMMAND_CLOSE;
break;
}
clawarm = updateClawCommand(clawarm, new_claw_command);
// Tilt servo control
int new_tilt_command = TILT_COMMAND_UNSET;
/*
// TODO select action for the tilt servo
*/
clawarm = updateTiltCommand(clawarm, new_tilt_command);
telemetry(zeroed_lx_float, zeroed_ly_float, zeroed_rx_float, zeroed_ry_float, loop_drive_mode, left_joystick_angle, left_joystick_magnitude, right_joystick_angle, right_joystick_magnitude); // DEBUG ONLY, print steering motor encoder positions
telemetry(zeroed_lx_float, zeroed_ly_float, zeroed_rx_float, zeroed_ry_float, loop_drive_mode, left_joystick_angle, left_joystick_magnitude, right_joystick_angle, right_joystick_magnitude, previous_loop_processing_duration_core_0); // DEBUG ONLY, telemetry
// update motors after calculation
set_motor(FLSTEER, swrv.front_left_spin_power);
set_motor(BRSTEER, swrv.back_right_spin_power);
set_motor(FRSTEER, swrv.front_right_spin_power);
set_motor(BLSTEER, swrv.back_left_spin_power);
set_motor(FLDRIVE, swrv.front_left_power);
set_motor(BRDRIVE, swrv.back_right_power);
set_motor(FRDRIVE, swrv.front_right_power);
set_motor(BLDRIVE, swrv.back_left_power);
// Lock the spinlock and transfer the steering motor data to core 1, which will send the data to the sabertooth motor controllers
spinlock_lock_core_0(&drive_power_command_spinlock_flag);
power_data_transfer_fl = swrv.front_left_power;
power_data_transfer_fr = swrv.front_right_spin_power;
power_data_transfer_bl = swrv.back_left_spin_power;
power_data_transfer_br = swrv.back_right_spin_power;
spinlock_release(&drive_power_command_spinlock_flag);
// update stepper motors
set_motor(LIFTALL, clawarm.arm_set_motor_int);
@ -994,155 +1023,6 @@ void loop() {
*/
/////////////////////////////////////////////////////////////
// END OF MODULUS PLUS CODE UNTIL THE END OF THIS FUNCTION //
/////////////////////////////////////////////////////////////
// Goliath / 2 side arcade tank drive code below
/*int zeroed_power = -1 * ((int)(astate->stickX) - 127);
int zeroed_turn = ((int)(astate->stickY) - 127);
if (true) { //fb != NULL) {
//int x = fb->x - 127;
//int y = - fb->y + 127;
int x = zeroed_turn;
int y = zeroed_power;
//Serial.print(x);
//Serial.print(" ");
//Serial.println(y);
double rawdriveangle = atan2(x, y);
double driveangle = rawdriveangle * 180 / 3.1415926;
target_left_power = y;
target_right_power = y;
target_left_power += x;
target_right_power += -x;
target_left_power = constrain(target_left_power, -127, 127);
target_right_power = constrain(target_right_power, -127, 127);
if(turbo) {
target_left_power *= 2;
target_right_power *= 2;
}
target_left_power = target_left_power * 0.675;
target_right_power = target_right_power * 0.675;
}
if(turbo)
acceleration = 8;
else
acceleration = 3;
if(left_cooldown > 0)
left_cooldown --;
if(abs(target_left_power) <= 4 && abs(left_power) > 5) {
left_power = 0;
left_cooldown = 2;
}
else if(target_left_power >= left_power + acceleration && left_cooldown == 0)
left_power += acceleration;
else if(acceleration > target_left_power - left_power && left_cooldown == 0)
left_power = target_left_power;
else if(target_left_power <= left_power - acceleration && left_cooldown == 0)
left_power -= acceleration;
else if(acceleration > left_power - target_left_power && left_cooldown == 0)
left_power = target_left_power;
if(right_cooldown > 0)
right_cooldown --;
if(abs(target_right_power) <= 4 && abs(right_power) > 5) {
right_power = 0;
right_cooldown = 2;
}
else if(target_right_power >= right_power + acceleration && right_cooldown == 0)
right_power += acceleration;
else if(acceleration > target_right_power - right_power && right_cooldown == 0)
right_power = target_right_power;
else if(target_right_power <= right_power - acceleration && right_cooldown == 0)
right_power -= acceleration;
else if(acceleration > right_power - target_right_power && right_cooldown == 0)
right_power = target_right_power;
int avg_speed = (abs(right_power) + abs(left_power))/2;
//SerComm.println();
set_hex(avg_speed);
//drive_right(right_enabled, right_power);
//drive_left(left_enabled, -left_power);
SerComm.println(" L: " + String(left_power) + " LT: " + String(target_left_power) + " R: " + String(right_power) + " RT: " + String(target_right_power) + " MEM FREE: "+ String(rp2040.getFreeHeap()));
*/
//if(left_power != target_left_power || right_power != target_right_power)
//delay(1000);
//set_digit(0, 6);
//set_digit(0, 10);
//set_digit(1, 9);
//set_digit(1, 10);
//set_digit(2, 8);
//set_digit(2, 10);
//set_digit(3, 8);
//set_digit(3, 10);
//set_digit(4, 8);
//set_digit(4, 10);
/*if (mode == 0) {
set_raw(count / 8, count % 8);
if (count < 39) {
count ++;
} else {
count = 0;
mode = 1;
delay(100);
}
}*/
//print_status();
//drive_right(right_enabled, 10);
//drive_left(left_enabled, 10);
/*if (millis() % 3000 > 1500) {
set_mosfet(0, LOW);
set_mosfet(1, LOW);
//ioex2.digitalWrite(7, LOW);
}
if (millis() % 3000 < 1500) {
set_mosfet(0, HIGH);
set_mosfet(1, HIGH);
//ioex2.digitalWrite(7, HIGH);
}*/
/*if (mode == 1) {
set_dec(count);
drive_right(right_enabled, count);
//set_hex(count);
if (count < 40) {
count += 5;
} else {
//count = 0;
mode = 2;
}
}
if (mode == 2) {
set_dec(count);
drive_right(right_enabled, count);
//set_hex(count);
if (count > 5) {
count -= 5;
} else {
//count = 0;
mode = 1;
}
}*/
//delay(200);
previous_loop_processing_duration_core_0 = millis() - previous_loop_start_time_core_0;
int64_t delay_time_ms = LOOP_DELAY_MS_CORE_0 - (int64_t) previous_loop_processing_duration_core_0; // Dynamically calculate delay time
if(delay_time_ms > 0 && delay_time_ms < 100) { // Only delay if the processing time has not exceeded LOOP_DELAY_MS_CORE_0
@ -1153,88 +1033,41 @@ void loop() {
}
void drive_control_core_1() { // Control drive motors from core 1 from loop1() function
// Lock the steering motor power data to read it
spinlock_lock_core_1(&drive_power_command_spinlock_flag);
int local_fl = power_data_transfer_fl;
int local_fr = power_data_transfer_fr;
int local_bl = power_data_transfer_bl;
int local_br = power_data_transfer_br;
spinlock_release(&drive_power_command_spinlock_flag); // Release the spinlock
// Set motors if the requested power is different than the previously requested power
if(local_fl != power_data_transfer_prev_fl) {
set_motor(FLSTEER, local_fl);
}
if(local_fr != power_data_transfer_prev_fr) {
set_motor(FRSTEER, local_fr);
}
if(local_bl != power_data_transfer_prev_bl) {
set_motor(BLSTEER, local_bl);
}
if(local_br != power_data_transfer_prev_br) {
set_motor(BRSTEER, local_br);
}
// Set the previously requested power data to the current power data, will be read in the next loop
power_data_transfer_prev_fl = local_fl;
power_data_transfer_prev_fr = local_fr;
power_data_transfer_prev_bl = local_bl;
power_data_transfer_prev_br = local_br;
}
void loop1() {
previous_loop_start_time_core_1 = millis();
rp2040.wdt_reset();
//drive_left(left_enabled, 255);
//digitalWrite(LED_BUILTIN, HIGH);
if(loop_counter_core_1 == 20) {
//print_status();
loop_counter_core_1 = 0;
delay(25);
}
else {
delay(25);
//loop_counter_core_1++;
}
//SerComm.println("update");
//left_enabled = try_enable_left(left_enabled, get_voltage(1));
//right_enabled = try_enable_right(right_enabled, get_voltage(0));
//digitalWrite(LED_BUILTIN, LOW);
/*if (stepperX.distanceToGo() == 0) { // Give stepper something to do...
if (stepperXdir) {
Serial.println("Driving stepper");
stepperX.moveTo(stepsToGo);
} else {
Serial.println("Driving stepper");
stepperX.moveTo(-stepsToGo);
}
stepperX.runState();
stepperXdir = !stepperXdir;
}
if (stepperY.distanceToGo() == 0) { // Give stepper something to do...
if (stepperYdir)
stepperY.moveTo(stepsToGo);
else
stepperY.moveTo(-stepsToGo);
stepperY.runState();
stepperYdir = !stepperYdir;
}
if (stepperZ.distanceToGo() == 0) { // Give stepper something to do...
if (stepperZdir)
stepperZ.moveTo(stepsToGo);
else
stepperZ.moveTo(-stepsToGo);
stepperZ.runState();
stepperZdir = !stepperZdir;
}*/
if (mode == 1) {
//set_hex(count);
if (count < 125) {
count += 1;
} else {
//count = 0;
mode = 2;
}
}
if (mode == 2) {
//set_hex(count);
if (count > -125) {
count -= 1;
} else {
//count = 0;
mode = 1;
}
}
/*for (int x = 5; x < 9; x++) {
set_motor(x, count);
}
swivel[0].motor(0, 127);
swivel[0].motor(1, 127);
swivel[1].motor(0, 127);
swivel[1].motor(1, 127);
set_motor(14, count); // drive all steppers in sync
digitalWrite(0, HIGH);
digitalWrite(1, HIGH);
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);*/
drive_control_core_1();
previous_loop_processing_duration_core_1 = millis() - previous_loop_start_time_core_1;
int64_t delay_time_ms = LOOP_DELAY_MS_CORE_1 - (int64_t) previous_loop_processing_duration_core_1; // Dynamically calculate delay time

View File

@ -39,22 +39,28 @@ manipulator_arm setTiltAngle(manipulator_arm input, float new_tilt_angle) // Int
manipulator_arm updateTiltCommand(manipulator_arm input, int new_tilt_command) // Update the command for the tilt motor
{
manipulator_arm out = input;
if(new_tilt_command != TILT_COMMAND_UNSET && out.tilt_angle_loops_since_update >= TILT_ANGLE_MIN_UPDATE_LOOPS) { // Ignore value of 0, make sure that its been long enough since the last update
float tilt_angle_offset_direction = 0.0f;
if(new_tilt_command != out.tilt_command || out.tilt_angle_loops_since_update >= TILT_ANGLE_MIN_UPDATE_LOOPS) { // Make sure that it's been long enough since the last update to not spam the servo command
float new_angle = out.tilt_target_angle; // Maintain the existing angle by default
switch(new_tilt_command) {
case TILT_COMMAND_UNSET:
new_angle = out.tilt_target_angle; // Maintain the existing angle
case TILT_COMMAND_RESET:
new_angle = TILT_FLAT_ANGLE;
case TILT_COMMAND_UP:
tilt_angle_offset_direction = 1.0f;
new_angle = out.tilt_target_angle + TILT_ANGLE_UPDATE_DISTANCE;
break;
case TILT_COMMAND_DOWN:
tilt_angle_offset_direction = -1.0f;
new_angle = out.tilt_target_angle - TILT_ANGLE_UPDATE_DISTANCE;
break;
}
float angle_offset = TILT_ANGLE_UPDATE_DISTANCE * tilt_angle_offset_direction; // Degrees that the target angle is being changed by
out = setTiltAngle(out, out.tilt_target_angle + angle_offset);
out = setTiltAngle(out, new_angle);
out.tilt_angle_loops_since_update = 0; // Reset the counter tracking loops since the last update, since an update was just performed
} else { // Increment the number of loops since the previous update, since an update was not performed during this loop
out.tilt_angle_loops_since_update++;
}
out.tilt_command = new_tilt_command; // Save the new command to check whether it has changed in the next loop
return out;
}
@ -81,6 +87,9 @@ manipulator_arm updateClawCommand(manipulator_arm input, int new_claw_command) /
case CLAW_COMMAND_CLOSE:
new_claw_angle = CLAW_CLOSED_ANGLE;
break;
case CLAW_COMMAND_STAY:
new_claw_angle = out.claw_position;
break;
default:
new_claw_angle = CLAW_DEFAULT_ANGLE;
}
@ -92,7 +101,7 @@ manipulator_arm updateClawCommand(manipulator_arm input, int new_claw_command) /
// Arm functions (stepper motors)
manipulator_arm setArmSpeed(manipulator_arm input, float arm_speed) // Set the arm's speed
manipulator_arm setArmSpeed(manipulator_arm input, float arm_speed) // Set the arm's speed, must be between -1.0 and 1.0
{
manipulator_arm out = input;
arm_speed = out.arm_speed_coefficient * min(out.arm_speed_limit, max(-out.arm_speed_limit, arm_speed));

View File

@ -51,7 +51,7 @@ manipulator_arm updateClawCommand(manipulator_arm input, int new_claw_command);
// Arm functions (stepper motors)
manipulator_arm setArmSpeed(manipulator_arm input, float arm_speed); // Set the arm's speed
manipulator_arm setArmSpeed(manipulator_arm input, float arm_speed); // Set the arm's speed, must be between -1.0 and 1.0
manipulator_arm setArmSpeedLimit(manipulator_arm input, float arm_speed_limit); // Set the arm's speed limit (applied before coefficient), limit must be between 0.0 and 1.0

34
src/spinlock.cpp Normal file
View File

@ -0,0 +1,34 @@
#include <Arduino.h>
#include "globals.h"
#include "spinlock.h"
void spinlock_lock_core_0(byte* spinlock_flag) // Lock a spinlock from core 0
{
while(*spinlock_flag == SPINLOCK_LOCK_CORE_1) {} // Wait until the data is not locked by the other core
*spinlock_flag = SPINLOCK_LOCK_CORE_0; // Try setting the flag to lock the data
// Wait to see if the memory was overwritten by the other core
delay(1);
if(*spinlock_flag == SPINLOCK_LOCK_CORE_1 || *spinlock_flag == SPINLOCK_OPEN) { // The other core locked the data (and currently holds a lock or has released it), recurse to try again
spinlock_lock_core_0(spinlock_flag);
return;
}
return;
}
void spinlock_lock_core_1(byte* spinlock_flag) // Lock a spinlock from core 1
{
while(*spinlock_flag == SPINLOCK_LOCK_CORE_1) {} // Wait until the data is not locked by the other core
*spinlock_flag = SPINLOCK_LOCK_CORE_0; // Try setting the flag to lock the data
// Wait to see if the memory was overwritten by the other core
delay(1);
if(*spinlock_flag == SPINLOCK_LOCK_CORE_1 || *spinlock_flag == SPINLOCK_OPEN) { // The other core locked the data (and currently holds a lock or has released it), recurse to try again
spinlock_lock_core_0(spinlock_flag);
return;
}
return;
}
void spinlock_release(byte* spinlock_flag) // Release a spinlock
{
*spinlock_flag = SPINLOCK_OPEN;
}

14
src/spinlock.h Normal file
View File

@ -0,0 +1,14 @@
#include "globals.h"
// Spinlock flags
#define SPINLOCK_UNSET 0
#define SPINLOCK_OPEN 1
#define SPINLOCK_LOCK_CORE_0 2
#define SPINLOCK_LOCK_CORE_1 3
void spinlock_lock_core_0(byte* spinlock_flag); // Lock a spinlock from core 0
void spinlock_lock_core_1(byte* spinlock_flag); // Lock a spinlock from core 1
void spinlock_release(byte* spinlock_flag); // Release a spinlock

View File

@ -146,15 +146,27 @@ swerve_drive updateEncoderData(swerve_drive in, int front_left_encoder, int fron
return out;
}
float normalizeAngle(float angle) { // Takes an input angle and normalizes it to an angle between 0.0 and 360.0 degrees, results excluding exactly 360.0 degrees
int normalizeEncoderData(int encoder_data) // Normalize encoder data to a range of [0, STEERING_ENCODER_TICKS_PER_ROTATION)
{
encoder_data %= (int) STEERING_ENCODER_TICKS_PER_ROTATION;
encoder_data += (STEERING_ENCODER_TICKS_PER_ROTATION * (encoder_data < 0));
return encoder_data;
}
float relativeAngleFromEncoder(int encoder_data_relative ) // Calculate the relative angle from the difference between 2 encoder data points
{
return ((float) normalizeEncoderData(encoder_data_relative)) / ((float) STEERING_ENCODER_TICKS_PER_DEGREE);
}
float normalizeAngle(float angle) // Takes an input angle and normalizes it to an angle between 0.0 and 360.0 degrees, results excluding exactly 360.0 degrees
{
angle = fmod(angle, 360);
if(angle < 0.0) {
angle += 360;
}
angle += (360 * (angle < 0.0));
return angle;
}
swerve_drive setMotorCoefficients(swerve_drive input, float front_left, float front_right, float back_left, float back_right) { // Set the motor speed coefficients for each motor
swerve_drive setMotorCoefficients(swerve_drive input, float front_left, float front_right, float back_left, float back_right) // Set the motor speed coefficients for each motor
{
swerve_drive out = input;
out.front_left_coefficient = front_left;
out.front_right_coefficient = front_right;
@ -163,7 +175,8 @@ swerve_drive setMotorCoefficients(swerve_drive input, float front_left, float fr
return out;
}
swerve_drive setTargetSpin(swerve_drive input, float front_left, float front_right, float back_left, float back_right) { // Set the target spin for each wheel
swerve_drive setTargetSpin(swerve_drive input, float front_left, float front_right, float back_left, float back_right) // Set the target spin for each wheel
{
swerve_drive out = input;
out.front_left_target_spin = front_left + input.spin_offset;
out.front_right_target_spin = front_right + input.spin_offset;
@ -172,7 +185,8 @@ swerve_drive setTargetSpin(swerve_drive input, float front_left, float front_rig
return out;
}
swerve_drive setSpinOffset(swerve_drive input, float new_spin_offset) { // Set a new spin offset, and maintain the current target spin on each motor relative to the robot body as the offset is changed
swerve_drive setSpinOffset(swerve_drive input, float new_spin_offset) // Set a new spin offset, and maintain the current target spin on each motor relative to the robot body as the offset is changed
{
swerve_drive out = input;
float delta_spin_offset = new_spin_offset - input.spin_offset;
@ -184,7 +198,8 @@ swerve_drive setSpinOffset(swerve_drive input, float new_spin_offset) { // Set a
return out;
}
swerve_drive setDriveTargetPower(swerve_drive input, float target_drive_power) { // Set a new drive power
swerve_drive setDriveTargetPower(swerve_drive input, float target_drive_power) // Set a new drive power
{
swerve_drive out = input;
out.target_drive_power = target_drive_power;
return out;

View File

@ -85,6 +85,10 @@ float calculateSteeringMotorSpeed(float steering_delta); // Calculate the speed
swerve_drive updateEncoderData(swerve_drive in, int front_left_encoder, int front_right_encoder, int back_left_encoder, int back_right_encoder); // Process new encoder data, calculate the speed and angle of the steering motors
int normalizeEncoderData(int encoder_data); // Normalize encoder data to a range of [0, STEERING_ENCODER_TICKS_PER_ROTATION)
float relativeAngleFromEncoder(int encoder_data_relative ); // Calculate the relative angle from the difference between 2 encoder data points
float normalizeAngle(float angle); // Takes an input angle and normalizes it to an angle between 0.0 and 360.0 degrees, results excluding exactly 360.0 degrees
swerve_drive setMotorCoefficients(swerve_drive input, float front_left, float front_right, float back_left, float back_right); // Set the motor speed coefficients for each motor