Implemented overcurrent detection
Implemented manual and overcurrent screens Basically it's ready for a real world test!
This commit is contained in:
parent
c8ccd519fc
commit
b9f5394d53
@ -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,14 +49,18 @@ ControlUpdateResult ControlManager::update()
|
||||
|
||||
|
||||
// Check for over-current
|
||||
// TODO: don't check current every update
|
||||
if (moving && motorIsOvercurrent())
|
||||
if (moving && CurrentTime - lastCurrentCheck >= Config::MotorCurrentCheckInterval)
|
||||
{
|
||||
lastCurrentCheck = CurrentTime;
|
||||
|
||||
if (motorIsOvercurrent())
|
||||
{
|
||||
dln("[ CONTROL ] Overcurrent detected!");
|
||||
this->moveStop();
|
||||
|
||||
return ControlUpdateResult::Overcurrent;
|
||||
}
|
||||
}
|
||||
|
||||
// Read sensor
|
||||
if (!asyncReading)
|
||||
@ -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
|
||||
|
@ -1,5 +1,6 @@
|
||||
#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>();
|
||||
}
|
||||
}
|
||||
|
@ -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<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;
|
||||
}
|
@ -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:
|
||||
|
@ -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<HomeScreen>();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "Control.h"
|
||||
#include "state.h"
|
||||
|
||||
uint32_t CurrentTime;
|
||||
ScreenId MoveReturnScreen = (ScreenId)0;
|
@ -2,7 +2,9 @@
|
||||
#define __state
|
||||
|
||||
#include "stdint.h"
|
||||
#include "include/screenids.h"
|
||||
|
||||
extern uint32_t CurrentTime;
|
||||
extern ScreenId MoveReturnScreen;
|
||||
|
||||
#endif
|
||||
|
10
src/main.cpp
10
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,8 +176,17 @@ void loop()
|
||||
switch (Control.update())
|
||||
{
|
||||
case ControlUpdateResult::TargetReached:
|
||||
switch (MoveReturnScreen)
|
||||
{
|
||||
case ScreenId::Manual:
|
||||
screenManager.show<ManualScreen>();
|
||||
break;
|
||||
|
||||
default:
|
||||
screenManager.show<HomeScreen>();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ControlUpdateResult::SensorError:
|
||||
screenManager.show<MoveSensorErrorScreen>(ScreenId::MoveSensorError);
|
||||
|
Loading…
Reference in New Issue
Block a user