From 9aa17c4b32a26e7cb15e32a4f3ea82e37a931b5b Mon Sep 17 00:00:00 2001 From: Thorsteinngretar Date: Thu, 17 Sep 2026 22:18:04 +0000 Subject: [PATCH] Complete part 2 code --- .../Part_2_Motor_Response/.gitignore | 5 + .../include/digital_in.h | 20 ++++ .../include/digital_out.h | 20 ++++ .../Part_2_Motor_Response/include/encoder.h | 29 +++++ .../Part_2_Motor_Response/platformio.ini | 15 +++ .../Part_2_Motor_Response/src/digital_in.cpp | 26 +++++ .../Part_2_Motor_Response/src/digital_out.cpp | 27 +++++ .../Part_2_Motor_Response/src/encoder.cpp | 106 ++++++++++++++++++ .../Part_2_Motor_Response/src/main.cpp | 61 ++++++++++ 9 files changed, 309 insertions(+) create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/.gitignore create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/include/digital_in.h create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/include/digital_out.h create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/include/encoder.h create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/platformio.ini create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/src/digital_in.cpp create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/src/digital_out.cpp create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/src/encoder.cpp create mode 100644 Project_2_Speed_Controller/Part_2_Motor_Response/src/main.cpp diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/.gitignore b/Project_2_Speed_Controller/Part_2_Motor_Response/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/include/digital_in.h b/Project_2_Speed_Controller/Part_2_Motor_Response/include/digital_in.h new file mode 100644 index 0000000..a3505c6 --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/include/digital_in.h @@ -0,0 +1,20 @@ +#ifndef DIGITAL_IN_H +#define DIGITAL_IN_H + +#include + +class Digital_in +{ +public: + Digital_in(int pin); + + void init(); + + bool is_hi(); + bool is_lo(); + +private: + uint8_t pinMask; +}; + +#endif \ No newline at end of file diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/include/digital_out.h b/Project_2_Speed_Controller/Part_2_Motor_Response/include/digital_out.h new file mode 100644 index 0000000..dd2b776 --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/include/digital_out.h @@ -0,0 +1,20 @@ +#ifndef DIGITAL_OUT_H +#define DIGITAL_OUT_H + +#include + +class Digital_out +{ +public: + Digital_out(int pin); + + void init(); + void set_hi(); + void set_lo(); + void toggle(); + +private: + uint8_t pinMask; +}; + +#endif \ No newline at end of file diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/include/encoder.h b/Project_2_Speed_Controller/Part_2_Motor_Response/include/encoder.h new file mode 100644 index 0000000..ea9307a --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/include/encoder.h @@ -0,0 +1,29 @@ +#ifndef ENCODER_H +#define ENCODER_H + +#include +#include + +class Encoder +{ +public: + Encoder(int c1Pin, int c2Pin, int ledPin); + + void init(); + void update(); + int position(); + int speed(); + +private: + Digital_in c1; + Digital_in c2; + Digital_out led; + + bool previousC1; + volatile int count; + int pastCount; + uint32_t pastTime; + +}; + +#endif \ No newline at end of file diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/platformio.ini b/Project_2_Speed_Controller/Part_2_Motor_Response/platformio.ini new file mode 100644 index 0000000..4dbfb2f --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/platformio.ini @@ -0,0 +1,15 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:nanoatmega328new] +platform = atmelavr +board = nanoatmega328new +framework = arduino +monitor_speed = 115200 diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/src/digital_in.cpp b/Project_2_Speed_Controller/Part_2_Motor_Response/src/digital_in.cpp new file mode 100644 index 0000000..2bbe6ef --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/src/digital_in.cpp @@ -0,0 +1,26 @@ +#include +#include + +Digital_in::Digital_in(int pin) +{ + pinMask = static_cast(1U << pin); +} + +void Digital_in::init() +{ + // Configure pin as input + DDRB &= static_cast(~pinMask); + + // Enable internal pull-up resistor + PORTB |= pinMask; +} + +bool Digital_in::is_hi() +{ + return (PINB & pinMask) != 0; +} + +bool Digital_in::is_lo() +{ + return (PINB & pinMask) == 0; +} \ No newline at end of file diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/src/digital_out.cpp b/Project_2_Speed_Controller/Part_2_Motor_Response/src/digital_out.cpp new file mode 100644 index 0000000..2ccfa7d --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/src/digital_out.cpp @@ -0,0 +1,27 @@ +#include +#include + +Digital_out::Digital_out(int pin) +{ + pinMask = static_cast(1U << pin); +} + +void Digital_out::init() +{ + DDRB |= pinMask; +} + +void Digital_out::set_hi() +{ + PORTB |= pinMask; +} + +void Digital_out::set_lo() +{ + PORTB &= static_cast(~pinMask); +} + +void Digital_out::toggle() +{ + PORTB ^= pinMask; +} \ No newline at end of file diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/src/encoder.cpp b/Project_2_Speed_Controller/Part_2_Motor_Response/src/encoder.cpp new file mode 100644 index 0000000..471ead2 --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/src/encoder.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include + +static Encoder* activeEncoder = nullptr; + +ISR(PCINT0_vect) +{ + if (activeEncoder != nullptr) + { + activeEncoder->update(); + } +} + +Encoder::Encoder(int c1Pin, int c2Pin, int ledPin) + : c1(c1Pin), c2(c2Pin), led(ledPin), + previousC1(false), count(0) +{ +} + +void Encoder::init() +{ + c1.init(); + c2.init(); + led.init(); + + led.set_lo(); + + activeEncoder = this; + + // Clear any pending PORTB pin-change interrupt + PCIFR |= (1 << PCIF0); + + // Enable pin-change interrupts for PORTB + PCICR |= (1 << PCIE0); + + // Enable interrupt specifically for PB3 / D8 / C1 + PCMSK0 |= (1 << PCINT0); + + + //capture baseline + previousC1 = c1.is_hi(); + count = 0; + + // Enable global interrupts + sei(); + + // Set initial states for speed + pastCount = count; + pastTime = micros(); + +} + +void Encoder::update() +{ + led.set_lo(); + + bool currentC1 = c1.is_hi(); + + if (currentC1 != previousC1) + { + bool currentC2 = c2.is_hi(); + + if (currentC1 == currentC2) + { + count++; + } + else + { + count--; + } + + previousC1 = currentC1; + + led.set_hi(); + } +} + +int Encoder::position() +{ + uint8_t oldSREG = SREG; + + cli(); + int currentCount = count; + SREG = oldSREG; + + return currentCount; +} + + + +int Encoder::speed() +{ + int currentCount = position(); + uint32_t currentTime = micros(); //gives arduino microseconds since program started running + + //from spec sheet we get 1400 counts per revolution from driver + // or from assignment 1: 2100 + int rpm = ((currentCount-pastCount)*6e7)/((currentTime-pastTime)*2100); // we turn counts to rotations by dividing by 1400 and microsecond to minutes by multiplying with 60 and 10^6 + + pastTime = currentTime; + pastCount = currentCount; + + return rpm; +} \ No newline at end of file diff --git a/Project_2_Speed_Controller/Part_2_Motor_Response/src/main.cpp b/Project_2_Speed_Controller/Part_2_Motor_Response/src/main.cpp new file mode 100644 index 0000000..c53e82e --- /dev/null +++ b/Project_2_Speed_Controller/Part_2_Motor_Response/src/main.cpp @@ -0,0 +1,61 @@ +#include +#include +#include + +int main() +{ + init(); + + Encoder encoder(0, 1, 5); + + Digital_out ain1(3); // D11 + Digital_out ain2(4); // D12 + + encoder.init(); + + ain1.init(); + ain2.init(); + + // Motor initially OFF + ain1.set_lo(); + ain2.set_lo(); + + Serial.begin(115200); + + // Give time to open the serial monitor + delay(3000); + + Serial.println("time_ms,rpm"); + + // Fresh baseline for speed calculation + encoder.speed(); + + uint32_t startTime = micros(); + + // Step input: motor OFF -> full voltage + // This direction should give positive RPM + ain1.set_lo(); + ain2.set_hi(); + + while ((micros() - startTime) < 4000000UL) + { + int rpm = encoder.speed(); + uint32_t time_ms = (micros() - startTime) / 1000UL; + + Serial.print(time_ms); + Serial.print(","); + Serial.println(rpm); + + delay(10); + } + + // Stop motor + ain1.set_lo(); + ain2.set_lo(); + + while (1) + { + } + + return 0; +} \ No newline at end of file