6 Commits
Author SHA1 Message Date
isakg22 7ca9c51268 fjarlæfði LED úr rotary_encoder 2026-09-28 10:35:30 +00:00
isakg22 52f0d2052a Breytt í main system --> motor_controller 2026-09-28 10:33:27 +00:00
isakg22 937ca7df1b Nýtt diagram og lagað pio drasl 2026-09-24 12:06:40 +00:00
isakg22 5c68fb7722 Lagaði initialization steit 2026-09-24 11:35:02 +00:00
isakg22 ca41322d52 meira nýtt 2026-09-24 11:27:56 +00:00
isakg22 00c251b26d Nýtt branch og kóðar/files fyrir part 1 2026-09-24 11:20:26 +00:00
15 changed files with 543 additions and 179 deletions
+19 -19
View File
@@ -8,29 +8,29 @@
{
"name": "PlatformIO",
"includePath": [
"C:/Users/helgi/H26/ESP/Projects/ESP_Project3_H26/include",
"C:/Users/helgi/H26/ESP/Projects/ESP_Project3_H26/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/cores/arduino",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/variants/eightanaloginputs",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/EEPROM/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/HID/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/SPI/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/SoftwareSerial/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/Wire/src",
"C:/Users/isakt/Embedded/ESP_Project3_H26/include",
"C:/Users/isakt/Embedded/ESP_Project3_H26/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/cores/arduino",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/variants/eightanaloginputs",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/EEPROM/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/HID/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/SPI/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/SoftwareSerial/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/Wire/src",
""
],
"browse": {
"limitSymbolsToIncludedHeaders": true,
"path": [
"C:/Users/helgi/H26/ESP/Projects/ESP_Project3_H26/include",
"C:/Users/helgi/H26/ESP/Projects/ESP_Project3_H26/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/cores/arduino",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/variants/eightanaloginputs",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/EEPROM/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/HID/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/SPI/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/SoftwareSerial/src",
"C:/Users/helgi/.platformio/packages/framework-arduino-avr/libraries/Wire/src",
"C:/Users/isakt/Embedded/ESP_Project3_H26/include",
"C:/Users/isakt/Embedded/ESP_Project3_H26/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/cores/arduino",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/variants/eightanaloginputs",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/EEPROM/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/HID/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/SPI/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/SoftwareSerial/src",
"C:/Users/isakt/.platformio/packages/framework-arduino-avr/libraries/Wire/src",
""
]
},
@@ -45,7 +45,7 @@
],
"cStandard": "gnu11",
"cppStandard": "gnu++11",
"compilerPath": "C:/Users/helgi/.platformio/packages/toolchain-atmelavr/bin/avr-gcc.exe",
"compilerPath": "C:/Users/isakt/.platformio/packages/toolchain-atmelavr/bin/avr-gcc.exe",
"compilerArgs": [
"-mmcu=atmega328p",
""
+6 -6
View File
@@ -12,9 +12,9 @@
"type": "platformio-debug",
"request": "launch",
"name": "PIO Debug",
"executable": "C:/Users/helgi/H26/ESP/Projects/ESP_Project3_H26/.pio/build/nanoatmega328new/firmware.elf",
"executable": "C:/Users/isakt/Embedded/ESP_Project3_H26/.pio/build/nanoatmega328new/firmware.elf",
"projectEnvName": "nanoatmega328new",
"toolchainBinDir": "C:/Users/helgi/.platformio/packages/toolchain-atmelavr/bin",
"toolchainBinDir": "C:/Users/isakt/.platformio/packages/toolchain-atmelavr/bin",
"internalConsoleOptions": "openOnSessionStart",
"preLaunchTask": {
"type": "PlatformIO",
@@ -25,18 +25,18 @@
"type": "platformio-debug",
"request": "launch",
"name": "PIO Debug (skip Pre-Debug)",
"executable": "C:/Users/helgi/H26/ESP/Projects/ESP_Project3_H26/.pio/build/nanoatmega328new/firmware.elf",
"executable": "C:/Users/isakt/Embedded/ESP_Project3_H26/.pio/build/nanoatmega328new/firmware.elf",
"projectEnvName": "nanoatmega328new",
"toolchainBinDir": "C:/Users/helgi/.platformio/packages/toolchain-atmelavr/bin",
"toolchainBinDir": "C:/Users/isakt/.platformio/packages/toolchain-atmelavr/bin",
"internalConsoleOptions": "openOnSessionStart"
},
{
"type": "platformio-debug",
"request": "launch",
"name": "PIO Debug (without uploading)",
"executable": "C:/Users/helgi/H26/ESP/Projects/ESP_Project3_H26/.pio/build/nanoatmega328new/firmware.elf",
"executable": "C:/Users/isakt/Embedded/ESP_Project3_H26/.pio/build/nanoatmega328new/firmware.elf",
"projectEnvName": "nanoatmega328new",
"toolchainBinDir": "C:/Users/helgi/.platformio/packages/toolchain-atmelavr/bin",
"toolchainBinDir": "C:/Users/isakt/.platformio/packages/toolchain-atmelavr/bin",
"internalConsoleOptions": "openOnSessionStart",
"loadMode": "manual"
}
+28
View File
@@ -0,0 +1,28 @@
@startuml
skinparam state {
BackgroundColor LightBlue
}
[*] --> Initialization
state Initialization
Initialization : Entry / Stop motor
Initialization : Do / Initialize internal parameters
Initialization : Do / Reset speed measurement
Initialization : Exit / Send Boot-up message
state Operational
Operational : Entry / LED on
Operational : Do / Run speed controller
Operational : Exit / Stop motor
Operational : Exit / LED off
Initialization --> Operational : initialization complete
Operational --> Initialization : reset
@enduml
+19
View File
@@ -0,0 +1,19 @@
#ifndef INITIALIZATION_STATE_H
#define INITIALIZATION_STATE_H
#include "state.h"
class InitializationState : public State
{
public:
void enter() override;
void update() override;
void command(char c) override;
void exit() override;
};
#endif
+61
View File
@@ -0,0 +1,61 @@
#ifndef MOTOR_CONTROLLER_H
#define MOTOR_CONTROLLER_H
#include "rotary_encoder_driver.h"
#include "motor_driver.h"
#include "p_controller.h"
class State;
class MotorController
{
private:
State* current_state;
State* initialization_state;
State* operational_state;
RotaryEncoderDriver& encoder;
MotorDriver& motor;
P_controller& controller;
double reference_rpm;
public:
MotorController(
RotaryEncoderDriver& encoder,
MotorDriver& motor,
P_controller& controller
);
void set_states(
State* initialization,
State* operational
);
void begin();
void update();
void command(char c);
void transition_to(State* new_state);
void to_initialization();
void to_operational();
void run_speed_controller();
void stop_motor();
void reset_speed_measurement();
};
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef OPERATIONAL_STATE_H
#define OPERATIONAL_STATE_H
#include "state.h"
class OperationalState : public State
{
public:
void enter() override;
void update() override;
void command(char c) override;
void exit() override;
};
#endif
+10 -3
View File
@@ -4,11 +4,11 @@
#include <stdint.h>
#include "digital_in.h"
#include "digital_out.h"
//#include "digital_out.h"
#include "timer_usec.h"
class RotaryEncoderDriver {
static const uint8_t HIST_LEN = 4; // 8 x 5 ms = 40 ms gluggi fyrir rpm-utreikning
static const uint8_t HIST_LEN = 4; // 4 x 4 ms = 16 ms gluggi fyrir rpm-utreikning
volatile uint8_t cycle;
volatile int16_t count;
@@ -18,7 +18,7 @@ class RotaryEncoderDriver {
volatile int16_t history[HIST_LEN];
volatile uint8_t hist_idx;
Digital_out led;
//Digital_out led;
Digital_in eA;
Digital_in eB;
@@ -29,14 +29,21 @@ public:
volatile int16_t delta;
RotaryEncoderDriver();
void begin();
void update();
int position();
void update_delta();
float count_per_sec();
float rpm();
bool new_speed_available();
void reset_speed_measurement();
};
+32
View File
@@ -0,0 +1,32 @@
#ifndef STATE_H
#define STATE_H
class MotorController;
class State
{
protected:
MotorController* context;
public:
virtual ~State()
{
}
void set_context(MotorController* context)
{
this->context = context;
}
virtual void enter() = 0; // LED ON
virtual void update() = 0; // run motor controller
virtual void command(char c) = 0; // Listen for reset
virtual void exit() = 0; // Stop motor
};
#endif
+1
View File
@@ -14,3 +14,4 @@ board = nanoatmega328new
framework = arduino
monitor_speed = 115200
+35
View File
@@ -0,0 +1,35 @@
#include "initialization_state.h"
#include "motor_controller.h"
#include <Arduino.h>
void InitializationState::enter()
{
Serial.println();
Serial.println("State: Initialization");
digitalWrite(LED_BUILTIN, LOW);
context->stop_motor();
context->reset_speed_measurement();
Serial.println("Boot-up");
}
void InitializationState::update()
{
context->to_operational();
}
void InitializationState::command(char c)
{
}
void InitializationState::exit()
{
}
+49 -134
View File
@@ -1,5 +1,3 @@
#include <avr/io.h>
#include <util/delay.h>
#include <Arduino.h>
#include <avr/interrupt.h>
@@ -7,160 +5,77 @@
#include "motor_driver.h"
#include "p_controller.h"
// RotaryEncoderDriver encoder;
// MotorDriver motor;
#include "motor_controller.h"
// P_controller controller(12.5);
#include "initialization_state.h"
#include "operational_state.h"
// const double REF_RPM1 = 30.0;
// const double REF_RPM2 = 50.0;
// const uint16_t STEP1_AT_SAMPLE = 50;
// const uint16_t STEP2_AT_SAMPLE = 500;
RotaryEncoderDriver encoder;
// const uint16_t STOP_AT_SAMPLE = 1000;
MotorDriver motor;
unsigned long state_entry_time;
P_controller controller(12.5);
unsigned long time_in_state()
MotorController motor_controller(
encoder,
motor,
controller
);
InitializationState initialization_state;
OperationalState operational_state;
int main()
{
return millis() - state_entry_time;
}
int main() {
init();
Serial.begin(115200);
// Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
cli();
encoder.begin();
motor.begin();
sei();
enum State
{
Initialization,
Operational,
Pre_Operational,
Stopped
};
State state = State::Initialization; // Define state variable and set the initial state
motor_controller.set_states(
&initialization_state,
&operational_state
);
// cli();
// encoder.begin();
// motor.begin();
// sei();
// Mótor stopp og smá bið svo kerfið sé í kyrrstöðu áður en mælingin hefst
// motor.stop();
// _delay_ms(2000);
motor_controller.begin();
// Serial.println("time_ms,ref_rpm,actual_rpm,pwm_requested,pwm_actual");
// Serial.println("0.0,0.0,0.0,0.0,0.0");
// encoder.reset_speed_measurement();
// uint16_t sample = 0;
// double ref = 0.0;
while (1) {
int c = 0; // for incoming serial data
while (true)
{
if (Serial.available() > 0)
{
c = Serial.read();
Serial.print("I received: ");
Serial.println(c, DEC);
char c = Serial.read();
if (c != '\n' && c != '\r')
{
motor_controller.command(c);
}
}
switch (state)
{
case State::Initialization:
if (c == 'p')
{
state_entry_time = millis();
// State::Idle exit action
// event1 transition action
Serial.println("Initialization finished");
// set new target state
state = State::Pre_Operational;
// target state entry action
Serial.println("Going into Pre Operation");
}
if (c == 'o')
{
state_entry_time = millis();
// State::Idle exit action
// event2 transition action
Serial.println("Initialization finished");
// set new target state
state = State::Operational;
// target state entry action
Serial.println("Going straight to Operation");
}
break;
case State::Operational:
if (c == 'i')
{
state_entry_time = millis();
// State::Cooling exit action
Serial.println("Operation over");
// event3 transition action
// set new target state
state = State::Initialization;
// target state entry action
Serial.println("Initialization state");
}
if (c == 's')
{
state_entry_time = millis();
// State::Cooling exit action
Serial.println("Operation over");
// event4 transition action
// set new target state
state = State::Stopped;
// target state entry action
Serial.println("Stopping");
}
break;
motor_controller.update();
}
case State::Pre_Operational:
if (c == 'o')
{
state_entry_time = millis();
// State::Heating exit action
Serial.println("Pre Operation over");
// event3 transition action
// set new target state
state = State::Operational;
// target state entry action
Serial.println("Going to Operation");
}
if (c == 's')
{
state_entry_time = millis();
// State::Heating exit action
Serial.println("Pre Operation over");
// event4 transition action
// set new target state
state = State::Stopped;
// target state entry action
Serial.println("Stopping");
}
break;
case State::Stopped:
if (c == 'i')
{
state_entry_time = millis();
// State::Failure exit action
Serial.println("Stop over");
// event3 transition action
// set new target state
state = State::Initialization;
// target state entry action
Serial.println("Initialization state");
}
}
}
return 0;
}
+88
View File
@@ -0,0 +1,88 @@
/* #include <avr/io.h>
#include <util/delay.h>
#include <Arduino.h>
#include "rotary_encoder_driver.h"
#include "motor_driver.h"
#include "p_controller.h"
RotaryEncoderDriver encoder;
MotorDriver motor;
P_controller controller(12.5);
const double REF_RPM1 = 30.0;
const double REF_RPM2 = 50.0;
const uint16_t STEP1_AT_SAMPLE = 50;
const uint16_t STEP2_AT_SAMPLE = 500;
const uint16_t STOP_AT_SAMPLE = 1000;
int main() {
init();
Serial.begin(115200);
cli();
encoder.begin();
motor.begin();
sei();
// Mótor stopp og smá bið svo kerfið sé í kyrrstöðu áður en mælingin hefst
motor.stop();
_delay_ms(2000);
Serial.println("time_ms,ref_rpm,actual_rpm,pwm_requested,pwm_actual");
Serial.println("0.0,0.0,0.0,0.0,0.0");
encoder.reset_speed_measurement();
uint16_t sample = 0;
double ref = 0.0;
while (true) {
if (encoder.new_speed_available()) {
sample++;
float time_ms = sample * 4.0f;
// Step-inntak: viðmiðið hoppar úr 0 í REF_RPM á STEP_AT_SAMPLE
if (sample == STEP1_AT_SAMPLE) {
ref = REF_RPM1;
}
if (sample == STEP2_AT_SAMPLE) {
ref = REF_RPM2;
}
double actual = encoder.rpm();
double pwm_percent = controller.update(ref, actual);
double pwm_requested = pwm_percent * 2.55;
double pwm_actual = pwm_requested;
if (pwm_actual > 255.0) pwm_actual = 255.0;
if (pwm_actual < -255.0) pwm_actual = -255.0;
motor.set(pwm_actual);
Serial.print(time_ms, 1);
Serial.print(",");
Serial.print(ref, 1);
Serial.print(",");
Serial.print(actual, 2);
Serial.print(",");
Serial.print(pwm_requested, 1);
Serial.print(",");
Serial.println(pwm_actual, 1);
if (sample >= STOP_AT_SAMPLE) {
motor.stop();
while (true) {
}
}
}
}
return 0;
}
*/
+110
View File
@@ -0,0 +1,110 @@
#include "motor_controller.h"
#include "state.h"
#include <Arduino.h>
MotorController::MotorController(
RotaryEncoderDriver& encoder,
MotorDriver& motor,
P_controller& controller
)
: current_state(nullptr),
initialization_state(nullptr),
operational_state(nullptr),
encoder(encoder),
motor(motor),
controller(controller),
reference_rpm(30.0)
{
}
void MotorController::set_states(
State* initialization,
State* operational
)
{
initialization_state = initialization;
operational_state = operational;
}
void MotorController::begin()
{
transition_to(initialization_state);
}
void MotorController::transition_to(State* new_state)
{
if (current_state != nullptr)
{
current_state->exit();
}
current_state = new_state;
current_state->set_context(this);
current_state->enter();
}
void MotorController::update()
{
if (current_state != nullptr)
{
current_state->update();
}
}
void MotorController::command(char c)
{
if (current_state != nullptr)
{
current_state->command(c);
}
}
void MotorController::to_initialization()
{
transition_to(initialization_state);
}
void MotorController::to_operational()
{
transition_to(operational_state);
}
void MotorController::run_speed_controller()
{
if (encoder.new_speed_available())
{
double actual = encoder.rpm();
double pwm_percent =
controller.update(reference_rpm, actual);
double pwm =
pwm_percent * 2.55;
motor.set(pwm);
}
}
void MotorController::stop_motor()
{
motor.stop();
}
void MotorController::reset_speed_measurement()
{
encoder.reset_speed_measurement();
}
+37
View File
@@ -0,0 +1,37 @@
#include "operational_state.h"
#include "motor_controller.h"
#include <Arduino.h>
void OperationalState::enter()
{
Serial.println("State: Operational");
digitalWrite(LED_BUILTIN, HIGH);
}
void OperationalState::update()
{
context->run_speed_controller();
}
void OperationalState::command(char c)
{
if (c == 'r' || c == 'R')
{
Serial.println("Command: reset");
context->to_initialization();
}
}
void OperationalState::exit()
{
context->stop_motor();
digitalWrite(LED_BUILTIN, LOW);
}
+27 -15
View File
@@ -9,20 +9,22 @@ RotaryEncoderDriver::RotaryEncoderDriver()
, prev_count(0)
, speed_ready(false)
, hist_idx(0)
, led(5)
, eA(2)
, eB(5)
, delta(0)
{
for (uint8_t i = 0; i < HIST_LEN; i++) {
for (uint8_t i = 0; i < HIST_LEN; i++)
{
history[i] = 0;
}
}
void RotaryEncoderDriver::begin() {
void RotaryEncoderDriver::begin()
{
driver = this;
led.init();
//led.init();
eA.init();
eB.init();
@@ -32,12 +34,14 @@ void RotaryEncoderDriver::begin() {
timer.init(4000);
}
void RotaryEncoderDriver::update() {
void RotaryEncoderDriver::update()
{
count += eB.is_hi() ? 1 : -1;
led.set_hi();
//led.set_hi();
}
int RotaryEncoderDriver::position() {
int RotaryEncoderDriver::position()
{
uint8_t oldSREG = SREG;
@@ -47,27 +51,31 @@ int RotaryEncoderDriver::position() {
SREG = oldSREG;
led.set_lo();
//led.set_lo();
return local_count;
}
void RotaryEncoderDriver::update_delta() {
void RotaryEncoderDriver::update_delta()
{
int16_t oldest = history[hist_idx];
history[hist_idx] = count;
hist_idx = (hist_idx + 1) % HIST_LEN;
delta = count - oldest; // breyting yfir HIST_LEN * Ts (40 ms) glugga
delta = count - oldest; // breyting yfir HIST_LEN * Ts (16 ms) glugga
prev_count = count;
speed_ready = true;
led.set_lo();
//led.set_lo();
}
float RotaryEncoderDriver::count_per_sec() {
float RotaryEncoderDriver::count_per_sec()
{
uint8_t oldSREG = SREG;
@@ -118,18 +126,22 @@ void RotaryEncoderDriver::reset_speed_measurement()
delta = 0;
speed_ready = false;
for (uint8_t i = 0; i < HIST_LEN; i++) {
for (uint8_t i = 0; i < HIST_LEN; i++)
{
history[i] = count;
}
hist_idx = 0;
SREG = oldSREG;
}
ISR(INT0_vect) {
ISR(INT0_vect)
{
driver->update();
}
ISR(TIMER1_COMPA_vect) {
ISR(TIMER1_COMPA_vect)
{
driver->update_delta();
}