193 lines
4.4 KiB
C++
193 lines
4.4 KiB
C++
#include "DriveMotor.h"
|
|
|
|
DriveMotor::DriveMotor () {
|
|
|
|
};
|
|
|
|
void DriveMotor::Setup () {
|
|
pinMode(enable_pin, OUTPUT);
|
|
pinMode(forward_pin, OUTPUT);
|
|
pinMode(backward_pin, OUTPUT);
|
|
|
|
pinMode(encoder_a_pin, INPUT);
|
|
pinMode(encoder_b_pin, INPUT);
|
|
|
|
ledcSetup(pwm_channel, pwm_frequency, pwm_resolution);
|
|
Serial.print("Attaching pin ");
|
|
Serial.print(enable_pin);
|
|
Serial.print(" to ledc channel ");
|
|
Serial.print(pwm_channel);
|
|
Serial.println(" for drive");
|
|
ledcAttachPin(enable_pin, pwm_channel);
|
|
ledcWrite(pwm_channel, pwm_duty_cycle);
|
|
|
|
digitalWrite(forward_pin, LOW);
|
|
digitalWrite(backward_pin, LOW);
|
|
|
|
attachInterrupt(digitalPinToInterrupt(encoder_b_pin), ReadEncoder, RISING);
|
|
}
|
|
|
|
void DriveMotor::Start() {
|
|
pulses = 0;
|
|
fps = 0.0;
|
|
fps_max = -1.0;
|
|
fps_min = 100000.0;
|
|
fps_avg = -1.0;
|
|
rpm = 0.0;
|
|
rpm_max = -1.0;
|
|
rpm_min = 100000.0;
|
|
rpm_avg = -1.0;
|
|
start_frame = frames;
|
|
start_rotation = rotations;
|
|
start_time = millis();
|
|
ledcWrite(pwm_channel, pwm_duty_cycle);
|
|
digitalWrite(forward_pin, HIGH);
|
|
digitalWrite(backward_pin, LOW);
|
|
}
|
|
|
|
void DriveMotor::Stop() {;
|
|
digitalWrite(forward_pin, LOW);
|
|
digitalWrite(backward_pin, LOW);
|
|
ledcWrite(pwm_channel, 0);
|
|
Report();
|
|
}
|
|
|
|
void DriveMotor::SetLoad(uint8_t loadInt) {
|
|
load = loadInt;
|
|
}
|
|
|
|
void DriveMotor::SetSpeed(float speed) {
|
|
pwm_duty_cycle = floor(pwm_maximum * speed);
|
|
Serial.print("Set drive motor PWM = ");
|
|
Serial.print(pwm_duty_cycle);
|
|
Serial.print(" / ");
|
|
Serial.println(pwm_maximum);
|
|
}
|
|
|
|
void DriveMotor::SetPWM(uint32_t pwm) {
|
|
pwm_duty_cycle = pwm;
|
|
Serial.print("Set drive motor PWM = ");
|
|
Serial.print(pwm_duty_cycle);
|
|
Serial.print(" / ");
|
|
Serial.println(pwm_maximum);
|
|
}
|
|
|
|
void DriveMotor::SetFPS(float fps) {
|
|
target_fps = fps;
|
|
Serial.print("FPS = ");
|
|
Serial.println(fps);
|
|
SetPWM(EstimatePWMFromFPS(fps));
|
|
}
|
|
|
|
int32_t DriveMotor::pulses = 0;
|
|
|
|
void DriveMotor::ReadEncoder () {
|
|
int b = digitalRead(encoder_b_pin);
|
|
if (b > 0) {
|
|
pulses++;
|
|
} else {
|
|
pulses--;
|
|
}
|
|
}
|
|
|
|
void DriveMotor::Loop () {
|
|
timer = millis();
|
|
//monitor speed
|
|
frames = (int32_t) floor((float) pulses / pulses_per_frame);
|
|
if (frames != last_frame) {
|
|
last_frame = frames;
|
|
fps = CalculateFPS(timer - start_time, frames - start_frame);
|
|
if (fps < fps_min) { fps_min = fps; }
|
|
if (fps > fps_max) { fps_max = fps; }
|
|
if (fps_avg < 0.0) {
|
|
fps_avg = fps;
|
|
} else {
|
|
fps_avg = (fps_avg + fps) / 2.0;
|
|
}
|
|
Serial.print("Frame: ");
|
|
Serial.println(frames);
|
|
}
|
|
rotations = (int32_t) floor((float) pulses / (float) pulses_per_rotation);
|
|
if (rotations != last_rotation) {
|
|
last_rotation = rotations;
|
|
//correction
|
|
frames = rotations * frames_per_rotation;
|
|
rpm = CalculateRPM(timer - start_time, rotations - start_rotation);
|
|
if (rpm < rpm_min) { rpm_min = rpm; }
|
|
if (rpm > rpm_max) { rpm_max = rpm; }
|
|
if (rpm_avg < 0.0) {
|
|
rpm_avg = rpm;
|
|
} else {
|
|
rpm_avg = (rpm_avg + rpm) / 2.0;
|
|
}
|
|
Serial.print("Rotation: ");
|
|
Serial.println(rotations);
|
|
}
|
|
}
|
|
|
|
|
|
void DriveMotor::Report () {
|
|
fps = CalculateFPS(timer - start_time, frames - start_frame);
|
|
rpm = CalculateRPM(timer - start_time, rotations - start_rotation);
|
|
Serial.print("RPM ");
|
|
Serial.println(rpm);
|
|
Serial.print("RPM avg: ");
|
|
Serial.println(rpm_avg);
|
|
Serial.print("RPM min: ");
|
|
Serial.println(rpm_min);
|
|
Serial.print("RPM max: ");
|
|
Serial.println(rpm_max);
|
|
|
|
Serial.print("FPS ");
|
|
Serial.println(fps);
|
|
Serial.print("FPS avg: ");
|
|
Serial.println(fps_avg);
|
|
Serial.print("FPS min: ");
|
|
Serial.println(fps_min);
|
|
Serial.print("FPS max: ");
|
|
Serial.println(fps_max);
|
|
}
|
|
|
|
/* Helper methods */
|
|
|
|
float DriveMotor::CalculateFPS (long time_length, uint32_t frames) {
|
|
return 1000.0 / ((float) time_length / (float) frames);
|
|
}
|
|
|
|
float DriveMotor::CalculateRPM (long time_length, uint32_t rotations) {
|
|
return 60000.0 / ((float) time_length / (float) rotations);
|
|
}
|
|
|
|
int32_t DriveMotor::GetFrames () {
|
|
return frames;
|
|
}
|
|
|
|
int32_t DriveMotor::GetRotations () {
|
|
return rotations;
|
|
}
|
|
|
|
float DriveMotor::FloatMap (float x, float in_min, float in_max, float out_min, float out_max) {
|
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
|
}
|
|
|
|
uint16_t DriveMotor::EstimatePWMFromFPS (float fps) {
|
|
float min, max;
|
|
float max_pwm = pwm_range[0];
|
|
float min_pwm = pwm_range[1];
|
|
switch (load) {
|
|
case 0 :
|
|
max = load_none[0];
|
|
min = load_none[1];
|
|
break;
|
|
case 1 :
|
|
max = load_one[0];
|
|
min = load_one[1];
|
|
break;
|
|
case 2 :
|
|
max = load_two[0];
|
|
min = load_two[1];
|
|
break;
|
|
}
|
|
return (uint16_t) floor(FloatMap(fps, min, max, (float) min_pwm, (float) max_pwm));
|
|
}
|