diff --git a/src/include/config.h b/src/include/config.h index 104add0..67bde3b 100644 --- a/src/include/config.h +++ b/src/include/config.h @@ -4,6 +4,26 @@ #include +/* + + Determines if logging over the serial port is enabled. + Uses a baud rate of 115200. + + Verbose logging outputs even more, including logging + every loop. Only turn on when required. + + + At the time of writing, turning both on uses more RAM + than the ATMega328P has. + + Turning DebugLog off saves around 1k of RAM and 3k of flash. + Turning VerboseLog off saves around 300 bytes of RAM and 1k of flash. +*/ +//#define DebugLog +//#define VerboseLog + + + class Config { public: @@ -83,6 +103,10 @@ class Config static const uint8_t MotorPinSleep = 16; static const uint8_t MotorPinCurrentSensing = 17; + static const constexpr float MotorCurrentLimit = 6.0; + static const uint16_t MotorCurrentCheckInterval = 100; + + /* Colors diff --git a/src/include/screenids.h b/src/include/screenids.h index 26bea1e..5c2771d 100644 --- a/src/include/screenids.h +++ b/src/include/screenids.h @@ -3,7 +3,7 @@ enum class ScreenId { - Home, + Home = 1, Calibrate, Move, MoveOvercurrent, diff --git a/src/lib/control.cpp b/src/lib/control.cpp index deeee7c..f8bd02d 100644 --- a/src/lib/control.cpp +++ b/src/lib/control.cpp @@ -49,13 +49,17 @@ ControlUpdateResult ControlManager::update() // Check for over-current - // TODO: don't check current every update - if (moving && motorIsOvercurrent()) + if (moving && CurrentTime - lastCurrentCheck >= Config::MotorCurrentCheckInterval) { - dln("[ CONTROL ] Overcurrent detected!"); - this->moveStop(); + lastCurrentCheck = CurrentTime; - return ControlUpdateResult::Overcurrent; + if (motorIsOvercurrent()) + { + dln("[ CONTROL ] Overcurrent detected!"); + this->moveStop(); + + return ControlUpdateResult::Overcurrent; + } } // Read sensor @@ -83,6 +87,8 @@ ControlUpdateResult ControlManager::update() this->currentMeasurement = measurement; this->lastValidMeasurement = CurrentTime; + // TODO: PWM the motor when we're getting close, if overshoot turns out to be an issue in testing + // Check if target has been reached if (moving && this->targetReached()) { diff --git a/src/lib/control.h b/src/lib/control.h index 2fd4ef9..2d351c0 100644 --- a/src/lib/control.h +++ b/src/lib/control.h @@ -64,6 +64,8 @@ class ControlManager uint16_t lastMeasurement = 0; uint32_t lastValidMeasurement = 0; + uint32_t lastCurrentCheck = 0; + MoveDirection moveDirection; uint16_t moveTargetHeight; diff --git a/src/lib/debug.h b/src/lib/debug.h index b4e19dc..8a3ef3a 100644 --- a/src/lib/debug.h +++ b/src/lib/debug.h @@ -2,9 +2,7 @@ #define __debug #include - -#define DebugLog -//#define VerboseLog +#include "include/config.h" #ifdef DebugLog diff --git a/src/lib/motor.cpp b/src/lib/motor.cpp index 63f1be6..7689df4 100644 --- a/src/lib/motor.cpp +++ b/src/lib/motor.cpp @@ -1,5 +1,6 @@ #include "./motor.h" #include "include/config.h" +#include "./debug.h" #include @@ -13,11 +14,17 @@ void motorInit() pinMode(Config::MotorPinDirection, OUTPUT); pinMode(Config::MotorPinCurrentSensing, INPUT); + + // See motorIsOvercurrent + analogReference(INTERNAL); + delay(10); } void motorStart(MotorDirection direction) { + dl("[ MOTOR ] Starting in direction: "); dln((uint8_t)direction); + digitalWrite(Config::MotorPinDirection, direction == MotorDirection::Up ? HIGH : LOW); digitalWrite(Config::MotorPinSleep, HIGH); digitalWrite(Config::MotorPinPWM, HIGH); @@ -26,6 +33,8 @@ void motorStart(MotorDirection direction) void motorStop() { + dln("[ MOTOR ] Stopping"); + digitalWrite(Config::MotorPinPWM, LOW); digitalWrite(Config::MotorPinSleep, LOW); digitalWrite(Config::MotorPinDirection, LOW); @@ -34,8 +43,15 @@ void motorStop() bool motorIsOvercurrent() { - // TODO: implement motorIsOvercurrent - return false; + // The Polugu G2 module outputs 20 mV/A plus a 50 mV offset + // The analog reference has been set to internal, which is 1.1v for the ATMega328P, + // divided by 1024 units is 1.074mV per unit. This means we can measure up to 52.5A. + // I sure hope we never reach that value :-) + auto value = analogRead(Config::MotorPinCurrentSensing); + float voltage = (float)value * (1100.0 / 1024.0); + float current = (voltage - 50) / 20; + + dl("[ MOTOR ] Measured current: value = "); dl(value); dl(", V = "); dl(voltage); dl(", A = "); dln(current); + + return current >= Config::MotorCurrentLimit; } - - diff --git a/src/lib/screen/home.cpp b/src/lib/screen/home.cpp index 34ff61f..6b90a0e 100644 --- a/src/lib/screen/home.cpp +++ b/src/lib/screen/home.cpp @@ -61,7 +61,9 @@ void HomeScreen::onButton(Button button) if (targetHeight > 0) { + MoveReturnScreen = this->screenId(); Control.moveStart(targetHeight); + this->screenManager->show(); } } diff --git a/src/lib/screen/manual.cpp b/src/lib/screen/manual.cpp index abf5366..a095b93 100644 --- a/src/lib/screen/manual.cpp +++ b/src/lib/screen/manual.cpp @@ -1,17 +1,41 @@ #include "./manual.h" +#include "./home.h" +#include "./move.h" +#include "include/metrics.h" +#include "lib/settings.h" +#include "../state.h" -void ManualScreen::onShow() + +void ManualScreen::initHeights() { - // TODO: implement ManualScreen + this->height = Control.getCurrentHeight(); } -void ManualScreen::onButton(Button button) +bool ManualScreen::nextPage() { + if (this->height == Control.getCurrentHeight()) + { + this->screenManager->show(); + return false; + } + + MoveReturnScreen = this->screenId(); + Control.moveStart(this->height); + + this->screenManager->show(); + return true; } -void ManualScreen::onTick() + +void ManualScreen::setHeight(uint16_t value) { + if (value < Settings.Height.Minimum) + this->height = Settings.Height.Minimum; + else if (value > Settings.Height.Maximum) + this->height = Settings.Height.Maximum; + else + this->height = value; } \ No newline at end of file diff --git a/src/lib/screen/manual.h b/src/lib/screen/manual.h index 627beed..e23b6cc 100644 --- a/src/lib/screen/manual.h +++ b/src/lib/screen/manual.h @@ -2,6 +2,7 @@ #define __screen_manual #include "include/screenids.h" +#include "./baseheightentry.h" #include "../screen.h" #include "../Control.h" @@ -10,18 +11,24 @@ * Manual screen * Allows manual entry of the preferred height. */ -class ManualScreen : public BaseScreen +class ManualScreen : public BaseHeightEntryScreen { public: - ManualScreen(ScreenManager* screenManager, Adafruit_GFX* display) : BaseScreen(screenManager, display) { } - - void onShow(); - void onButton(Button button); - void onTick(); + ManualScreen(ScreenManager* screenManager, Adafruit_GFX* display) : BaseHeightEntryScreen(screenManager, display) { } ScreenId screenId() { return ScreenId::Manual; }; + protected: + void initHeights(); + uint16_t getHeight() { return this->height; } + void setHeight(uint16_t value); + bool nextPage(); + + bool isValidHeight() { return true; } + const char* getTitle() { return "Manual"; } + private: + uint16_t height; }; #endif diff --git a/src/lib/screen/menu.cpp b/src/lib/screen/menu.cpp index e6809bf..4167541 100644 --- a/src/lib/screen/menu.cpp +++ b/src/lib/screen/menu.cpp @@ -94,8 +94,7 @@ void MenuScreen::activateMenuItem(MenuItem item) switch (item) { case MenuItem::Manual: - // TODO: show manual screen - //this->screenManager->show(); + this->screenManager->show(); break; case MenuItem::Presets: diff --git a/src/lib/screen/move-overcurrent.cpp b/src/lib/screen/move-overcurrent.cpp index d71b4f7..97b36c9 100644 --- a/src/lib/screen/move-overcurrent.cpp +++ b/src/lib/screen/move-overcurrent.cpp @@ -1,14 +1,39 @@ #include "./move-overcurrent.h" +#include "./home.h" +#include "include/config.h" +#include "include/metrics.h" +#include "lib/control.h" +#include "lib/state.h" void MoveOvercurrentScreen::onShow() { - // TODO: implement MoveOvercurrentScreen + auto y = Metrics::LargeTextLineHeight + Metrics::LargeTextLineYOffset; + + this->display->fillScreen(Config::ColorErrorBackground); + + + this->display->setFont(Metrics::LargeFont); + this->display->setTextSize(Metrics::LargeFontTextSize); + + this->display->setTextColor(Config::ColorErrorText); + this->printCentered("ERROR", y); + y += Metrics::LargeTextLineHeight; + + this->display->setFont(Metrics::SmallFont); + this->display->setTextSize(Metrics::SmallFontTextSize); + + this->printCentered("motor overcurrent", y); + y += Metrics::SmallTextLineHeight; + + this->printCentered("press any button", y); + y += Metrics::SmallTextLineHeight + Metrics::LargeTextLineHeight; } void MoveOvercurrentScreen::onButton(Button button) { + this->screenManager->show(); } diff --git a/src/lib/state.cpp b/src/lib/state.cpp index 92e1c34..5108308 100644 --- a/src/lib/state.cpp +++ b/src/lib/state.cpp @@ -1,3 +1,4 @@ -#include "Control.h" +#include "state.h" -uint32_t CurrentTime; \ No newline at end of file +uint32_t CurrentTime; +ScreenId MoveReturnScreen = (ScreenId)0; \ No newline at end of file diff --git a/src/lib/state.h b/src/lib/state.h index 6d9aa35..9a63712 100644 --- a/src/lib/state.h +++ b/src/lib/state.h @@ -2,7 +2,9 @@ #define __state #include "stdint.h" +#include "include/screenids.h" extern uint32_t CurrentTime; +extern ScreenId MoveReturnScreen; #endif diff --git a/src/main.cpp b/src/main.cpp index 6c3ec4f..daa6dd3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,7 @@ #include "./lib/state.h" #include "./lib/screen/home.h" #include "./lib/screen/calibrate.h" +#include "./lib/screen/manual.h" #include "./lib/screen/move-overcurrent.h" #include "./lib/screen/move-sensorerror.h" @@ -175,7 +176,16 @@ void loop() switch (Control.update()) { case ControlUpdateResult::TargetReached: - screenManager.show(); + switch (MoveReturnScreen) + { + case ScreenId::Manual: + screenManager.show(); + break; + + default: + screenManager.show(); + break; + } break; case ControlUpdateResult::SensorError: