upload code. commented. working

main
EmaMaker 2024-03-28 23:34:03 +01:00
commit 557504f87b
5 changed files with 681 additions and 0 deletions

View File

@ -0,0 +1,249 @@
//=============================================================================================
// Madgwick.c
//=============================================================================================
//
// Implementation of Madgwick's IMU and AHRS algorithms.
// See: http://www.x-io.co.uk/open-source-imu-and-ahrs-algorithms/
//
// From the x-io website "Open-source resources available on this website are
// provided under the GNU General Public Licence unless an alternative licence
// is provided in source."
//
// Date Author Notes
// 29/09/2011 SOH Madgwick Initial release
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
// 19/02/2012 SOH Madgwick Magnetometer measurement is normalised
//
//=============================================================================================
//-------------------------------------------------------------------------------------------
// Header files
#include "Madgwick.h"
#include <math.h>
#include <stdint.h>
#include <Arduino.h>
//-------------------------------------------------------------------------------------------
// Definitions
#define sampleFreqDef 512.0f // sample frequency in Hz
//============================================================================================
// Functions
//-------------------------------------------------------------------------------------------
// AHRS algorithm update
Madgwick::Madgwick() {
q0 = 1.0f;
q1 = 0.0f;
q2 = 0.0f;
q3 = 0.0f;
now = micros();
}
void Madgwick::update(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
float recipNorm;
float s0, s1, s2, s3;
float qDot1, qDot2, qDot3, qDot4;
float hx, hy;
float _2q0mx, _2q0my, _2q0mz, _2q1mx, _2bx, _2bz, _4bx, _4bz, _2q0, _2q1, _2q2, _2q3, _2q0q2, _2q2q3, q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation)
if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {
updateIMU(gx, gy, gz, ax, ay, az);
return;
}
now = micros();
// Set integration time by time elapsed since last filter update
delta_t = ((now - last_update) / (float)1000000.0f);
last_update = now;
// Convert gyroscope degrees/sec to radians/sec
gx *= (float)0.0174533f;
gy *= (float)0.0174533f;
gz *= (float)0.0174533f;
// Rate of change of quaternion from gyroscope
qDot1 = (float)0.5f * (-q1 * gx - q2 * gy - q3 * gz);
qDot2 = (float)0.5f * (q0 * gx + q2 * gz - q3 * gy);
qDot3 = (float)0.5f * (q0 * gy - q1 * gz + q3 * gx);
qDot4 = (float)0.5f * (q0 * gz + q1 * gy - q2 * gx);
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
if(!((ax == (float)0.0f) && (ay == (float)0.0f) && (az == (float)0.0f))) {
// Normalise accelerometer measurement
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
ax *= recipNorm;
ay *= recipNorm;
az *= recipNorm;
// Normalise magnetometer measurement
recipNorm = invSqrt(mx * mx + my * my + mz * mz);
mx *= recipNorm;
my *= recipNorm;
mz *= recipNorm;
// Auxiliary variables to avoid repeated arithmetic
_2q0mx = (float)2.0f * q0 * mx;
_2q0my = (float)2.0f * q0 * my;
_2q0mz = (float)2.0f * q0 * mz;
_2q1mx = (float)2.0f * q1 * mx;
_2q0 = (float)2.0f * q0;
_2q1 = (float)2.0f * q1;
_2q2 = (float)2.0f * q2;
_2q3 = (float)2.0f * q3;
_2q0q2 = (float)2.0f * q0 * q2;
_2q2q3 = (float)2.0f * q2 * q3;
q0q0 = q0 * q0;
q0q1 = q0 * q1;
q0q2 = q0 * q2;
q0q3 = q0 * q3;
q1q1 = q1 * q1;
q1q2 = q1 * q2;
q1q3 = q1 * q3;
q2q2 = q2 * q2;
q2q3 = q2 * q3;
q3q3 = q3 * q3;
// Reference direction of Earth's magnetic field
hx = mx * q0q0 - _2q0my * q3 + _2q0mz * q2 + mx * q1q1 + _2q1 * my * q2 + _2q1 * mz * q3 - mx * q2q2 - mx * q3q3;
hy = _2q0mx * q3 + my * q0q0 - _2q0mz * q1 + _2q1mx * q2 - my * q1q1 + my * q2q2 + _2q2 * mz * q3 - my * q3q3;
_2bx = sqrtf(hx * hx + hy * hy);
_2bz = -_2q0mx * q2 + _2q0my * q1 + mz * q0q0 + _2q1mx * q3 - mz * q1q1 + _2q2 * my * q3 - mz * q2q2 + mz * q3q3;
_4bx = (float)2.0f * _2bx;
_4bz = (float)2.0f * _2bz;
// Gradient decent algorithm corrective step
s0 = -_2q2 * ((float)2.0f * q1q3 - _2q0q2 - ax) + _2q1 * ((float)2.0f * q0q1 + _2q2q3 - ay) - _2bz * q2 * (_2bx * ((float)0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q3 + _2bz * q1) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q2 * (_2bx * (q0q2 + q1q3) + _2bz * ((float)0.5f - q1q1 - q2q2) - mz);
s1 = _2q3 * ((float)2.0f * q1q3 - _2q0q2 - ax) + _2q0 * ((float)2.0f * q0q1 + _2q2q3 - ay) - (float)4.0f * q1 * (1 - (float)2.0f * q1q1 - (float)2.0f * q2q2 - az) + _2bz * q3 * (_2bx * ((float)0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q2 + _2bz * q0) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q3 - _4bz * q1) * (_2bx * (q0q2 + q1q3) + _2bz * ((float)0.5f - q1q1 - q2q2) - mz);
s2 = -_2q0 * ((float)2.0f * q1q3 - _2q0q2 - ax) + _2q3 * ((float)2.0f * q0q1 + _2q2q3 - ay) - (float)4.0f * q2 * (1 - (float)2.0f * q1q1 - (float)2.0f * q2q2 - az) + (-_4bx * q2 - _2bz * q0) * (_2bx * ((float)0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (_2bx * q1 + _2bz * q3) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + (_2bx * q0 - _4bz * q2) * (_2bx * (q0q2 + q1q3) + _2bz * ((float)0.5f - q1q1 - q2q2) - mz);
s3 = _2q1 * ((float)2.0f * q1q3 - _2q0q2 - ax) + _2q2 * ((float)2.0f * q0q1 + _2q2q3 - ay) + (-_4bx * q3 + _2bz * q1) * (_2bx * ((float)0.5f - q2q2 - q3q3) + _2bz * (q1q3 - q0q2) - mx) + (-_2bx * q0 + _2bz * q2) * (_2bx * (q1q2 - q0q3) + _2bz * (q0q1 + q2q3) - my) + _2bx * q1 * (_2bx * (q0q2 + q1q3) + _2bz * ((float)0.5f - q1q1 - q2q2) - mz);
recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude
s0 *= recipNorm;
s1 *= recipNorm;
s2 *= recipNorm;
s3 *= recipNorm;
// Apply feedback step
qDot1 -= beta * s0;
qDot2 -= beta * s1;
qDot3 -= beta * s2;
qDot4 -= beta * s3;
}
// Integrate rate of change of quaternion to yield quaternion
q0 += qDot1 * delta_t;
q1 += qDot2 * delta_t;
q2 += qDot3 * delta_t;
q3 += qDot4 * delta_t;
// Normalise quaternion
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
q0 *= recipNorm;
q1 *= recipNorm;
q2 *= recipNorm;
q3 *= recipNorm;
}
//-------------------------------------------------------------------------------------------
// IMU algorithm update
void Madgwick::updateIMU(float gx, float gy, float gz, float ax, float ay, float az) {
float recipNorm;
float s0, s1, s2, s3;
float qDot1, qDot2, qDot3, qDot4;
float _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2 ,_8q1, _8q2, q0q0, q1q1, q2q2, q3q3;
// Convert gyroscope degrees/sec to radians/sec
gx *= (float)0.0174533f;
gy *= (float)0.0174533f;
gz *= (float)0.0174533f;
now = micros();
// Set integration time by time elapsed since last filter update
delta_t = ((now - last_update) / (float)1000000.0f);
last_update = now;
// Rate of change of quaternion from gyroscope
qDot1 = (float)0.5f * (-q1 * gx - q2 * gy - q3 * gz);
qDot2 = (float)0.5f * (q0 * gx + q2 * gz - q3 * gy);
qDot3 = (float)0.5f * (q0 * gy - q1 * gz + q3 * gx);
qDot4 = (float)0.5f * (q0 * gz + q1 * gy - q2 * gx);
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
// Normalise accelerometer measurement
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
ax *= recipNorm;
ay *= recipNorm;
az *= recipNorm;
// Auxiliary variables to avoid repeated arithmetic
_2q0 = (float)2.0f * q0;
_2q1 = (float)2.0f * q1;
_2q2 = (float)2.0f * q2;
_2q3 = (float)2.0f * q3;
_4q0 = (float)4.0f * q0;
_4q1 = (float)4.0f * q1;
_4q2 = (float)4.0f * q2;
_8q1 = (float)8.0f * q1;
_8q2 = (float)8.0f * q2;
q0q0 = q0 * q0;
q1q1 = q1 * q1;
q2q2 = q2 * q2;
q3q3 = q3 * q3;
// Gradient decent algorithm corrective step
s0 = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay;
s1 = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q1 - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az;
s2 = (float)4.0f * q0q0 * q2 + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az;
s3 = (float)4.0f * q1q1 * q3 - _2q1 * ax + 4.0f * q2q2 * q3 - _2q2 * ay;
recipNorm = invSqrt(s0 * s0 + s1 * s1 + s2 * s2 + s3 * s3); // normalise step magnitude
s0 *= recipNorm;
s1 *= recipNorm;
s2 *= recipNorm;
s3 *= recipNorm;
// Apply feedback step
qDot1 -= beta * s0;
qDot2 -= beta * s1;
qDot3 -= beta * s2;
qDot4 -= beta * s3;
}
// Integrate rate of change of quaternion to yield quaternion
q0 += qDot1 * delta_t;
q1 += qDot2 * delta_t;
q2 += qDot3 * delta_t;
q3 += qDot4 * delta_t;
// Normalise quaternion
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
q0 *= recipNorm;
q1 *= recipNorm;
q2 *= recipNorm;
q3 *= recipNorm;
}
//-------------------------------------------------------------------------------------------
// Fast inverse square-root
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
float Madgwick::invSqrt(float x) {
float halfx = 0.5f * x;
float y = x;
long i = *(long*)&y;
i = 0x5f3759df - (i>>1);
y = *(float*)&i;
y = y * (1.5f - (halfx * y * y));
y = y * (1.5f - (halfx * y * y));
return y;
}
//-------------------------------------------------------------------------------------------

View File

@ -0,0 +1,63 @@
//=============================================================================================
// Madgwick.h
//=============================================================================================
//
// Implementation of Madgwick's IMU and AHRS algorithms.
// See: http://www.x-io.co.uk/open-source-imu-and-ahrs-algorithms/
//
// From the x-io website "Open-source resources available on this website are
// provided under the GNU General Public Licence unless an alternative licence
// is provided in source."
//
// Date Author Notes
// 29/09/2011 SOH Madgwick Initial release
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
//
//=============================================================================================
#ifndef __Madgwick_h__
#define __Madgwick_h__
#include <math.h>
#include <stdint.h>
//--------------------------------------------------------------------------------------------
// Variable declaration
class Madgwick {
private:
float delta_t = 0; // Used to control display output rate
uint32_t now = 0; // used to calculate integration interval
uint32_t last_update = 0; // used to calculate integration interval
static float invSqrt(float x);
float beta; // algorithm gain
float q0;
float q1;
float q2;
float q3; // quaternion of sensor frame relative to auxiliary frame
//-------------------------------------------------------------------------------------------
// Function declarations
public:
Madgwick(void);
void changeBeta(float newBeta) { beta = newBeta; }
void begin(float confBeta) { beta = confBeta; }
void update(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
void updateIMU(float gx, float gy, float gz, float ax, float ay, float az);
float getQuatW() {
return q0;
}
float getQuatX() {
return q1;
}
float getQuatY() {
return q2;
}
float getQuatZ() {
return q3;
}
};
#endif

View File

@ -0,0 +1,133 @@
#include "FastIMU.h"
#include "Madgwick.h"
#include <Wire.h>
//#define PRINT_ANGLES
//#define PRINT_QUAT
//#define PERFORM_CALIBRATION //Comment to disable startup calibration
#define IMU_ADDRESS 0x68 //Change to the address of the IMU
MPU6050 IMU; //Change to the name of any supported IMU!
AccelData IMUAccel; //Sensor data
GyroData IMUGyro;
Madgwick filter;
void setup_imu(){
// TODO: write my own kalman filter
Wire.begin();
Wire.setClock(400000); //400khz clock
calData calib;
calib.accelBias[0]=-0.02;
calib.accelBias[1]=-0.01;
calib.accelBias[2]=0.16;
calib.gyroBias[0] = -2.89;
calib.gyroBias[1] = -3.59;
calib.gyroBias[2] = -0.66;
int err = IMU.init(calib, IMU_ADDRESS);
if (err != 0) {
Serial.print("Error initializing IMU: ");
Serial.println(err);
while (true) {
;
}
}
if (err != 0) {
Serial.print("Error Setting range: ");
Serial.println(err);
while (true) {
;
}
}
#ifdef PERFORM_CALIBRATION
Serial.println("Keep IMU level.");
delay(5000);
IMU.calibrateAccelGyro(&calib);
Serial.println("Calibration done!");
Serial.println("Accel biases X/Y/Z: ");
Serial.print(calib.accelBias[0]);
Serial.print(", ");
Serial.print(calib.accelBias[1]);
Serial.print(", ");
Serial.println(calib.accelBias[2]);
Serial.println("Gyro biases X/Y/Z: ");
Serial.print(calib.gyroBias[0]);
Serial.print(", ");
Serial.print(calib.gyroBias[1]);
Serial.print(", ");
Serial.println(calib.gyroBias[2]);
delay(5000);
IMU.init(calib, IMU_ADDRESS);
#endif
filter.begin(0.2f);
Serial.println("IMU up");
}
void update_imu(){
IMU.update();
IMU.getAccel(&IMUAccel);
IMU.getGyro(&IMUGyro);
// MPU6050 has no magnetometer
filter.updateIMU(IMUGyro.gyroX, IMUGyro.gyroY, IMUGyro.gyroZ, IMUAccel.accelX, IMUAccel.accelY, IMUAccel.accelZ);
float qw = filter.getQuatW();
float qx = filter.getQuatX();
float qy = filter.getQuatY();
float qz = filter.getQuatZ();
double heading{0}, bank{0}, attitude{0};
double sqw = qw*qw;
double sqx = qx*qx;
double sqy = qy*qy;
double sqz = qz*qz;
double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
double test = qx*qy + qz*qw;
if (test > 0.499*unit) { // singularity at north pole
heading = 2 * atan2(qx,qw);
attitude = M_PI/2;
bank = 0;
return;
}
if (test < -0.499*unit) { // singularity at south pole
heading = -2 * atan2(qx,qw);
attitude = M_PI/2;
bank = 0;
return;
}
heading = atan2(2*qy*qw-2*qx*qz , sqx - sqy - sqz + sqw);
attitude = asin(2*test/unit);
bank = atan2(2*qx*qw-2*qy*qz , -sqx + sqy - sqz + sqw);
pitch = heading;
roll = bank;
yaw = attitude;
#ifdef PRINT_ANGLES
Serial.print("Roll: ");
Serial.print(roll, 5);
Serial.print("\tPitch: ");
Serial.print(pitch, 5);
Serial.print("\tYaw: ");
Serial.println(yaw, 5);
#endif // PRINT_ANGLES
#ifdef PRINT_QUAT
Serial.print("QW: ");
Serial.print(qw, 5);
Serial.print("\tQX: ");
Serial.print(qx, 5);
Serial.print("\tQY: ");
Serial.print(qy, 5);
Serial.print("\tQZ: ");
Serial.println(qz, 5);
#endif // PRINT_QUAT
}

View File

@ -0,0 +1,92 @@
#define MOT_DX_STEP 19
#define MOT_DX_DIR 18
#define MOT_SX_STEP 17
#define MOT_SX_DIR 16
void setup_motors(){
pinMode(MOT_DX_STEP, OUTPUT);
pinMode(MOT_DX_DIR, OUTPUT);
pinMode(MOT_SX_STEP, OUTPUT);
pinMode(MOT_SX_DIR, OUTPUT);
Serial.println("Motors up");
}
/*
void test_motors(){
while(!Serial) delay(10);
int m = 0;
while(true){
digitalWrite(mot_pins[m][0], LOW);
digitalWrite(mot_pins[m][1], HIGH);
for(int i = 0; i < 255; i++){
Serial.print("PWM: ");
Serial.println(i);
analogWrite(mot_pins[m][2], i);
delay(100);
}
delay(1000);
digitalWrite(mot_pins[m][0], LOW);
digitalWrite(mot_pins[m][1], LOW);
m = 1-m;
}
}
void test_motors_nodeadzone(){
int m = 0;
while(true){
for(int i = 0; i < 100; i++){
Serial.print("Speed: ");
Serial.println(i);
move(m, i);
delay(100);
}
delay(1000);
move(m, 0);
m = 1-m;
}
}
void test_motors_rpm(){
while(!Serial) delay(10);
unsigned long tstart = millis();
while(millis() - tstart < 200) {
move(0, 20);
}
move(0,0);
}
void test_motors_diff(){
move(MOT_SX, 50*MOT_SX_MULT);
move(MOT_DX, 50*MOT_DX_MULT);
}
void test_motors_torque(int motor, int dir){
while(!Serial){;}
while(1){
delay(1000);
Serial.println("Setup, waiting 8 secs");
delay(8000);
for(int i = 0; i <= 255; i+= 15){
digitalWrite(mot_pins[motor][1], dir > 0 ? LOW : HIGH);
digitalWrite(mot_pins[motor][0], dir > 0 ? HIGH : LOW);
Serial.print("PWM: ");
Serial.println(i);
analogWrite(mot_pins[motor][2], i);
delay(8000);
digitalWrite(mot_pins[motor][0], LOW);
digitalWrite(mot_pins[motor][1], LOW);
delay(2000);
}
}
}
*/

View File

@ -0,0 +1,144 @@
#include <ArduPID.h>
ArduPID myController;
#define MOT_DX_STEP 19
#define MOT_DX_DIR 18
#define MOT_SX_STEP 17
#define MOT_SX_DIR 16
// Nema 17 make 1.8° per step. Using A4988 drivers, and 1/16th microstepping, it results in 0.1125° per step
constexpr double ANGLE_PER_STEP = 0.1125;
// Just used a kitchen scale, good enough
constexpr double WEIGHT = 0.961;
constexpr double WHEEL_RADIUS = 0.0475;
// Experimentally, the lowest pulse my steppers can handle without stalling + some leeway
constexpr double MAX_HALF_PERIOD = 75; // in microseconds
// Which means there is a maximum velocity achievable
constexpr double MAX_VELOCITY = 1000000 * WHEEL_RADIUS / (2 * MAX_HALF_PERIOD * ANGLE_PER_STEP) * PI / 180;
// Derived and analytical model, linearized it and simulated in MATLAB.
// PID values are then calculated and verified by simulation in Simulink. I ain't calibrating a PID by hand on this robot
// I modified the ArduPID library to make it accept negative values for the parameters
constexpr double KP = -50;
constexpr double KI = -600;
constexpr double KD = 0.05;
// IMU little bit tilted
// TODO: Implement an outer control loop for angular velocity. But that requires encoders on the motors
// TODO: try to achieve it crudely by just using a PI controller on the velocity given by the PID balance controller
double setpoint = -0.06;
double output = 0;
double input = 0;
double yaw{ 0 }, pitch{ 0 }, roll{ 0 };
void setup() {
Serial.begin(9600);
delay(1000);
setup_imu();
pinMode(MOT_DX_DIR, OUTPUT);
pinMode(MOT_SX_DIR, OUTPUT);
// Just to signal it is working
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
// Let the initial error from madgwick filter discharge without affecting the integral term of the PID
unsigned long t = millis();
while (millis() - t < 2000) {
update_imu();
}
myController.begin(&input, &output, &setpoint, KP, KI, KD, P_ON_E, FORWARD);
myController.setOutputLimits(-MAX_VELOCITY, MAX_VELOCITY); // double of max torque motors can exhert
//myController.setWindUpLimits(-10, 10);
myController.setSampleTime(2);
myController.start();
}
void setup1(){
pinMode(MOT_DX_STEP, OUTPUT);
pinMode(MOT_SX_STEP, OUTPUT);
}
unsigned long last_time_motors = micros(), current_time_motors = micros();
bool b = true;
// Such a long halfperiod means that the motors are not moving
uint32_t halfperiod1 = INT_MAX;
void loop1(){
// TODO: handle the steppers using interrupt timers. The second core could be used for IMU processing, while the first one handles the different control loops
// Retrieve the half period value from core0. Non blocking call
if(rp2040.fifo.available()) rp2040.fifo.pop_nb(&halfperiod1);
current_time_motors = micros();
if(current_time_motors - last_time_motors > halfperiod1){
// Half a pulse. Next cycle will be the rest
digitalWriteFast(MOT_DX_STEP, b);
digitalWriteFast(MOT_SX_STEP, b);
b = !b;
last_time_motors = current_time_motors;
}
}
unsigned long last_time = millis(), current_time = millis(), time_diff;
double frequency = 0;
unsigned long half_period0 = 0;
double velocity = 0;
void loop() {
current_time = millis();
time_diff = current_time - last_time;
update_imu();
// I also modified the ArduPID library to use compute as a boolean. If calculations were done, it returns true. If not enough time has elapsed, it returns false
if(myController.compute()){
input = pitch;
// Keeping it here
/*
double force_per_motor = output / WHEEL_RADIUS;
double accel = force_per_motor / (WEIGHT);
velocity += accel * time_diff * 0.001;
// anti-windup
velocity = constrain(velocity, -MAX_VELOCITY, MAX_VELOCITY);*/
double tvelocity = output;
if(tvelocity < 0){
digitalWriteFast(MOT_DX_DIR, LOW);
digitalWriteFast(MOT_SX_DIR, LOW);
tvelocity = -tvelocity;
}else{
digitalWriteFast(MOT_DX_DIR, HIGH);
digitalWriteFast(MOT_SX_DIR, HIGH);
}
tvelocity = tvelocity * 180 / PI;
frequency = tvelocity * 0.1125 / WHEEL_RADIUS;
half_period0 = 1000000 / (2*frequency);
// Send the half period to core 1. Non blocking
rp2040.fifo.push_nb(half_period0);
// Some ugly logging I used in debugging, keeping in around
/*Serial.println(input);
Serial.print(" | ");
Serial.print(output);
Serial.print(" | ");
Serial.print(accel);
Serial.print(" | ");
Serial.print(velocity);
Serial.print(" | ");
Serial.print(frequency);
Serial.print(" | ");
Serial.println(half_period0);*/
last_time = current_time;
}
}