Completed final part 4 code
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef P_CONTROLLER_H
|
||||||
|
#define P_CONTROLLER_H
|
||||||
|
|
||||||
|
class P_controller
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
P_controller(double kp);
|
||||||
|
double update(double ref, double actual);
|
||||||
|
|
||||||
|
private:
|
||||||
|
double kp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,57 +1,168 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
#include <encoder.h>
|
#include <encoder.h>
|
||||||
#include <digital_out.h>
|
#include <p_controller.h>
|
||||||
|
|
||||||
|
Encoder encoder(0, 1, 5);
|
||||||
|
P_controller controller(40.0);
|
||||||
|
|
||||||
|
volatile bool updateFlag = false;
|
||||||
|
|
||||||
|
ISR(TIMER1_COMPA_vect)
|
||||||
|
{
|
||||||
|
updateFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
Encoder encoder(0, 1, 5);
|
|
||||||
|
|
||||||
Digital_out ain1(3); // D11
|
|
||||||
Digital_out ain2(4); // D12
|
|
||||||
|
|
||||||
encoder.init();
|
encoder.init();
|
||||||
|
|
||||||
ain1.init();
|
|
||||||
ain2.init();
|
|
||||||
|
|
||||||
// Motor initially OFF
|
|
||||||
ain1.set_lo();
|
|
||||||
ain2.set_lo();
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
// Give time to open the serial monitor
|
// D11 / PB3 -> AIN1
|
||||||
delay(3000);
|
DDRB |= (1 << PB3);
|
||||||
|
PORTB &= ~(1 << PB3);
|
||||||
|
|
||||||
Serial.println("time_ms,rpm");
|
// D3 / PD3 / OC2B -> AIN2 PWM
|
||||||
|
DDRD |= (1 << PD3);
|
||||||
|
|
||||||
// Fresh baseline for speed calculation
|
// Timer1: 250 Hz
|
||||||
encoder.speed();
|
TCCR1A = 0;
|
||||||
|
TCCR1B = 0;
|
||||||
|
TCNT1 = 0;
|
||||||
|
|
||||||
uint32_t startTime = micros();
|
OCR1A = 999;
|
||||||
|
|
||||||
// Step input: motor OFF -> full voltage
|
TCCR1B |= (1 << WGM12);
|
||||||
// This direction should give positive RPM
|
TCCR1B |= (1 << CS11) | (1 << CS10);
|
||||||
ain1.set_lo();
|
|
||||||
ain2.set_hi();
|
|
||||||
|
|
||||||
while ((micros() - startTime) < 4000000UL)
|
TIMSK1 |= (1 << OCIE1A);
|
||||||
|
|
||||||
|
// Timer2: 7.8 kHz PWM
|
||||||
|
TCCR2A = 0;
|
||||||
|
TCCR2B = 0;
|
||||||
|
TCNT2 = 0;
|
||||||
|
|
||||||
|
OCR2B = 0;
|
||||||
|
|
||||||
|
TCCR2A =
|
||||||
|
(1 << COM2B1) |
|
||||||
|
(1 << WGM21) |
|
||||||
|
(1 << WGM20);
|
||||||
|
|
||||||
|
TCCR2B = (1 << CS21);
|
||||||
|
|
||||||
|
sei();
|
||||||
|
|
||||||
|
Serial.println("Load test starting in 2 seconds...");
|
||||||
|
|
||||||
|
uint16_t waitCount = 0;
|
||||||
|
|
||||||
|
while (waitCount < 500)
|
||||||
{
|
{
|
||||||
int rpm = encoder.speed();
|
if (updateFlag)
|
||||||
uint32_t time_ms = (micros() - startTime) / 1000UL;
|
{
|
||||||
|
updateFlag = false;
|
||||||
Serial.print(time_ms);
|
waitCount++;
|
||||||
Serial.print(",");
|
}
|
||||||
Serial.println(rpm);
|
|
||||||
|
|
||||||
delay(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop motor
|
int previousCount = encoder.position();
|
||||||
ain1.set_lo();
|
|
||||||
ain2.set_lo();
|
int countHistory[10] = {0};
|
||||||
|
int rollingCounts = 0;
|
||||||
|
|
||||||
|
uint8_t historyIndex = 0;
|
||||||
|
uint8_t samplesFilled = 0;
|
||||||
|
|
||||||
|
uint32_t updateCount = 0;
|
||||||
|
|
||||||
|
const double reference = 50.0;
|
||||||
|
|
||||||
|
Serial.println("time_ms,reference_rpm,actual_rpm,pwm");
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (updateFlag)
|
||||||
|
{
|
||||||
|
updateFlag = false;
|
||||||
|
updateCount++;
|
||||||
|
|
||||||
|
uint32_t time_ms = updateCount * 4;
|
||||||
|
|
||||||
|
int currentCount = encoder.position();
|
||||||
|
|
||||||
|
int deltaCount = currentCount - previousCount;
|
||||||
|
previousCount = currentCount;
|
||||||
|
|
||||||
|
rollingCounts -= countHistory[historyIndex];
|
||||||
|
|
||||||
|
countHistory[historyIndex] = deltaCount;
|
||||||
|
rollingCounts += deltaCount;
|
||||||
|
|
||||||
|
historyIndex++;
|
||||||
|
|
||||||
|
if (historyIndex >= 10)
|
||||||
|
{
|
||||||
|
historyIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samplesFilled < 10)
|
||||||
|
{
|
||||||
|
samplesFilled++;
|
||||||
|
}
|
||||||
|
|
||||||
|
double windowTime = samplesFilled * 0.004;
|
||||||
|
|
||||||
|
double rpm =
|
||||||
|
(rollingCounts * 60.0) /
|
||||||
|
(2100.0 * windowTime);
|
||||||
|
|
||||||
|
double output =
|
||||||
|
controller.update(reference, rpm);
|
||||||
|
|
||||||
|
if (output < 0.0)
|
||||||
|
{
|
||||||
|
output = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output > 255.0)
|
||||||
|
{
|
||||||
|
output = 255.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t pwm = (uint8_t)output;
|
||||||
|
|
||||||
|
OCR2B = pwm;
|
||||||
|
|
||||||
|
if ((updateCount % 10) == 0)
|
||||||
|
{
|
||||||
|
Serial.print(time_ms);
|
||||||
|
Serial.print(",");
|
||||||
|
|
||||||
|
Serial.print(reference);
|
||||||
|
Serial.print(",");
|
||||||
|
|
||||||
|
Serial.print(rpm);
|
||||||
|
Serial.print(",");
|
||||||
|
|
||||||
|
Serial.println(pwm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_ms >= 10000)
|
||||||
|
{
|
||||||
|
OCR2B = 0;
|
||||||
|
|
||||||
|
Serial.println("TEST COMPLETE");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#include <p_controller.h>
|
||||||
|
|
||||||
|
P_controller::P_controller(double kp)
|
||||||
|
: kp(kp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
double P_controller::update(double ref, double actual)
|
||||||
|
{
|
||||||
|
return kp * (ref - actual);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user