Commit b9f5394d authored by Mark van Renswoude's avatar Mark van Renswoude

Implemented overcurrent detection

Implemented manual and overcurrent screens
Basically it's ready for a real world test!
parent c8ccd519
......@@ -4,6 +4,26 @@
#include <stdint.h>
/*
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
......
......@@ -3,7 +3,7 @@
enum class ScreenId
{
Home,
Home = 1,
Calibrate,
Move,
MoveOvercurrent,
......
......@@ -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())
{
......
......@@ -64,6 +64,8 @@ class ControlManager
uint16_t lastMeasurement = 0;
uint32_t lastValidMeasurement = 0;
uint32_t lastCurrentCheck = 0;
MoveDirection moveDirection;
uint16_t moveTargetHeight;
......
......@@ -2,9 +2,7 @@
#define __debug
#include <Arduino.h>
#define DebugLog
//#define VerboseLog
#include "include/config.h"
#ifdef DebugLog
......
#include "./motor.h"
#include "include/config.h"
#include "./debug.h"
#include <Arduino.h>
......@@ -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;
}
......@@ -61,7 +61,9 @@ void HomeScreen::onButton(Button button)
if (targetHeight > 0)
{
MoveReturnScreen = this->screenId();
Control.moveStart(targetHeight);
this->screenManager->show<MoveScreen>();
}
}
......
#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<HomeScreen>();
return false;
}
MoveReturnScreen = this->screenId();
Control.moveStart(this->height);
this->screenManager->show<MoveScreen>();
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
......@@ -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
......@@ -94,8 +94,7 @@ void MenuScreen::activateMenuItem(MenuItem item)
switch (item)
{
case MenuItem::Manual:
// TODO: show manual screen
//this->screenManager->show<ManualScreen>();
this->screenManager->show<ManualScreen>();
break;
case MenuItem::Presets:
......
#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<HomeScreen>();
}
......
#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
......@@ -2,7 +2,9 @@
#define __state
#include "stdint.h"
#include "include/screenids.h"
extern uint32_t CurrentTime;
extern ScreenId MoveReturnScreen;
#endif
......@@ -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<HomeScreen>();
switch (MoveReturnScreen)
{
case ScreenId::Manual:
screenManager.show<ManualScreen>();
break;
default:
screenManager.show<HomeScreen>();
break;
}
break;
case ControlUpdateResult::SensorError:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment