Initial commit

Fully operational
This commit is contained in:
Mark van Renswoude 2017-11-26 20:22:15 +01:00
commit 392bb997ef
15 changed files with 672 additions and 0 deletions

53
Buzzer.cpp Normal file
View File

@ -0,0 +1,53 @@
#include "Buzzer.h"
#include <Arduino.h>
#include "Config.h"
void buzzStartup()
{
tone(PinBuzzer, 1000);
delay(50);
noTone(PinBuzzer);
}
void buzzSelect()
{
tone(PinBuzzer, 1000);
delay(1);
noTone(PinBuzzer);
}
void buzzClick()
{
tone(PinBuzzer, 1000);
delay(25);
noTone(PinBuzzer);
}
void buzzCompleted()
{
for (int i = 0; i < 3; i++)
{
tone(PinBuzzer, 1000);
delay(250);
noTone(PinBuzzer);
delay(500);
}
}
void buzzMemoryCleared()
{
for (int i = 0; i < 5; i++)
{
tone(PinBuzzer, 1000);
delay(25);
noTone(PinBuzzer);
delay(250);
}
}

10
Buzzer.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __Buzzer
#define __Buzzer
void buzzStartup();
void buzzSelect();
void buzzClick();
void buzzCompleted();
void buzzMemoryCleared();
#endif

12
Config.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "Config.h"
byte LCDCharArrow[8] = {
B00000,
B01000,
B01100,
B01110,
B01100,
B01000,
B00000,
};

33
Config.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef __Config
#define __Config
#include "Arduino.h"
static const int PinLCDRS = 7;
static const int PinLCDEN = 8;
static const int PinLCDDB4 = 9;
static const int PinLCDDB5 = 10;
static const int PinLCDDB6 = 11;
static const int PinLCDDB7 = 12;
static const int PinEncoderClock = 2;
static const int PinEncoderData = 3;
static const int PinButton = 4;
static const int PinBuzzer = 5;
static const int PinLED = 6;
// You probably don't wanna change these without a proper review of the code, since most of it assumes 16x2 anyways
static const int LCDWidth = 16;
static const int LCDHeight = 2;
static const int EncoderSensitivity = 4;
static const int SmallStep = 1;
static const int LargeStepTreshold = 60;
static const int LargeStep = 10;
static const int MenuTimeout = 2000;
extern byte LCDCharArrow[8];
#endif

18
ExposureTimer.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "ExposureTimer.h"
#include <EEPROM.h>
unsigned int ExposureTime = 0;
unsigned long ExposureTimerStart = 0;
void ResetExposureTime()
{
EEPROM.get(0, ExposureTime);
}
void StartExposureTimer(unsigned long currentTime)
{
EEPROM.put(0, ExposureTime);
ExposureTimerStart = currentTime;
}

13
ExposureTimer.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef __ExposureTimer
#define __ExposureTimer
#include "Arduino.h"
extern unsigned int ExposureTime;
extern unsigned long ExposureTimerStart;
void ResetExposureTime();
void StartExposureTimer(unsigned long currentTime);
#endif

70
ScreenCountdown.cpp Normal file
View File

@ -0,0 +1,70 @@
#include "ScreenCountdown.h"
#include "ScreenSetTime.h"
#include "ExposureTimer.h"
#include "Config.h"
#include "Buzzer.h"
void ScreenCountdown::printRemainingTime()
{
getDisplay()->setCursor(0, 1);
printTime(ExposureTime - ((getCurrentTime() - ExposureTimerStart) / 1000));
}
void ScreenCountdown::onShow()
{
mLastDisplayed = -1;
getDisplay()->setCursor(0, 0);
getDisplay()->print("Exposing... ");
printRemainingTime();
digitalWrite(PinLED, HIGH);
}
void ScreenCountdown::onHide()
{
digitalWrite(PinLED, LOW);
}
void ScreenCountdown::onButton()
{
// TODO Confirmation?
buzzClick();
getScreenManager()->show<ScreenSetTime>();
}
void ScreenCountdown::onEncoder(long lastPosition, long newPosition)
{
// TODO Allow adding / removing time?
}
void ScreenCountdown::onTick()
{
int elapsed = (getCurrentTime() - ExposureTimerStart) / 1000;
if (elapsed >= ExposureTime)
{
getDisplay()->setCursor(0, 0);
getDisplay()->print("Done! ");
printRemainingTime();
digitalWrite(PinLED, LOW);
buzzCompleted();
ExposureTimerStart = 0;
getScreenManager()->show<ScreenSetTime>();
}
else if (elapsed != mLastDisplayed)
{
printRemainingTime();
mLastDisplayed = elapsed;
}
}

29
ScreenCountdown.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __ScreenCountdown
#define __ScreenCountdown
#include "ScreenManager.h"
/*
* Countdown screen
* Shows the remaining time.
*/
class ScreenCountdown : public BaseScreen
{
private:
int mLastDisplayed;
protected:
void printRemainingTime();
public:
ScreenCountdown(ScreenManager* screenManager) : BaseScreen(screenManager) { }
void onShow();
void onHide();
void onButton();
void onEncoder(long lastPosition, long newPosition);
void onTick();
};
#endif

38
ScreenManager.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "ScreenManager.h"
#include "Config.h"
ScreenManager* BaseScreen::getScreenManager()
{
return mScreenManager;
}
unsigned long BaseScreen::getCurrentTime()
{
return mScreenManager->getCurrentTime();
}
LiquidCrystal* BaseScreen::getDisplay()
{
return mScreenManager->getDisplay();
}
void BaseScreen::printTime(int value)
{
String minutes = String(value / 60);
String seconds = String(value % 60);
int textLength = minutes.length() + 1 + 2;
getDisplay()->print(minutes);
getDisplay()->print(":");
if (seconds.length() == 1)
getDisplay()->print("0");
getDisplay()->print(seconds);
for (int space = textLength + 1; space < LCDWidth; space++)
getDisplay()->print(" ");
}

85
ScreenManager.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef __ScreenManager
#define __ScreenManager
#include <LiquidCrystal.h>
class ScreenManager;
class BaseScreen
{
private:
ScreenManager* mScreenManager;
protected:
ScreenManager* getScreenManager();
unsigned long getCurrentTime();
LiquidCrystal* getDisplay();
void printTime(int value);
public:
BaseScreen(ScreenManager* screenManager)
{
mScreenManager = screenManager;
}
virtual void onShow() = 0;
virtual void onHide() = 0;
virtual void onButton() = 0;
virtual void onEncoder(long lastPosition, long newPosition) = 0;
virtual void onTick() = 0;
};
class ScreenManager
{
private:
LiquidCrystal* mDisplay;
unsigned long* mCurrentTime;
BaseScreen* mCurrent = NULL;
public:
ScreenManager(LiquidCrystal* display, unsigned long* currentTime)
{
mDisplay = display;
mCurrentTime = currentTime;
}
inline BaseScreen* getCurrent()
{
return mCurrent;
}
inline unsigned long getCurrentTime()
{
return *mCurrentTime;
}
inline LiquidCrystal* getDisplay()
{
return mDisplay;
}
template<class T> void ScreenManager::show()
{
if (mCurrent != NULL)
{
mCurrent->onHide();
delete(mCurrent);
}
mCurrent = new T(this);
mCurrent->onShow();
}
};
#endif

100
ScreenMenu.cpp Normal file
View File

@ -0,0 +1,100 @@
#include "ScreenMenu.h"
#include "ScreenSetTime.h"
#include "ScreenCountdown.h"
#include "ExposureTimer.h"
#include "Config.h"
#include "Buzzer.h"
void ScreenMenu::updateLastActivity()
{
mLastActivity = getCurrentTime();
}
void ScreenMenu::printExposureTime()
{
getDisplay()->setCursor(0, 1);
printTime(ExposureTime);
}
void ScreenMenu::printMenuCursor()
{
getDisplay()->setCursor(0, 0);
getDisplay()->write(mSelected == 0 ? (byte)0 : ' ');
getDisplay()->setCursor(9, 0);
getDisplay()->write(mSelected == 1 ? (byte)0 : ' ');
}
void ScreenMenu::onShow()
{
updateLastActivity();
mSelected = 0;
getDisplay()->setCursor(0, 0);
getDisplay()->print(" Start Reset ");
printMenuCursor();
printExposureTime();
}
void ScreenMenu::onHide()
{
}
void ScreenMenu::onButton()
{
buzzClick();
switch (mSelected)
{
case 0:
digitalWrite(PinLED, HIGH);
StartExposureTimer(getCurrentTime());
getScreenManager()->show<ScreenCountdown>();
break;
case 1:
ResetExposureTime();
getScreenManager()->show<ScreenSetTime>();
}
}
void ScreenMenu::onEncoder(long lastPosition, long newPosition)
{
updateLastActivity();
if (newPosition > lastPosition)
{
if (mSelected < 1)
{
buzzSelect();
mSelected++;
printMenuCursor();
}
}
else
{
if (mSelected > 0)
{
buzzSelect();
mSelected--;
printMenuCursor();
}
}
}
void ScreenMenu::onTick()
{
if (getCurrentTime() - mLastActivity >= MenuTimeout)
getScreenManager()->show<ScreenSetTime>();
}

33
ScreenMenu.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef __ScreenMenu
#define __ScreenMenu
#include "ScreenManager.h"
/*
* Menu screen
* Allows starting the timer or resetting the time to the last used value.
*/
class ScreenMenu : public BaseScreen
{
private:
int mSelected;
unsigned long mLastActivity;
protected:
void updateLastActivity();
void printExposureTime();
void printMenuCursor();
public:
ScreenMenu(ScreenManager* screenManager) : BaseScreen(screenManager) { }
void onShow();
void onHide();
void onButton();
void onEncoder(long lastPosition, long newPosition);
void onTick();
};
#endif

52
ScreenSetTime.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "ScreenSetTime.h"
#include "ScreenMenu.h"
#include "ExposureTimer.h"
#include "Buzzer.h"
#include "Config.h"
void ScreenSetTime::printExposureTime()
{
getDisplay()->setCursor(0, 1);
printTime(ExposureTime);
}
void ScreenSetTime::onShow()
{
getDisplay()->setCursor(0, 0);
getDisplay()->print("Exposure time: ");
printExposureTime();
}
void ScreenSetTime::onHide()
{
}
void ScreenSetTime::onButton()
{
buzzClick();
getScreenManager()->show<ScreenMenu>();
}
void ScreenSetTime::onEncoder(long lastPosition, long newPosition)
{
buzzSelect();
if (newPosition > lastPosition)
ExposureTime += ExposureTime >= LargeStepTreshold ? LargeStep : SmallStep;
else if (ExposureTime > 0)
ExposureTime -= ExposureTime > LargeStepTreshold ? LargeStep : SmallStep;
printExposureTime();
}
void ScreenSetTime::onTick()
{
}

26
ScreenSetTime.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef __ScreenSetTime
#define __ScreenSetTime
#include "ScreenManager.h"
/*
* Time screen
* Allows changing of the exposure time. Pressing the button will switch to the menu.
*/
class ScreenSetTime : public BaseScreen
{
protected:
void printExposureTime();
public:
ScreenSetTime(ScreenManager* screenManager) : BaseScreen(screenManager) { }
void onShow();
void onHide();
void onButton();
void onEncoder(long lastPosition, long newPosition);
void onTick();
};
#endif

100
UVControl.ino Normal file
View File

@ -0,0 +1,100 @@
#include <Bounce2.h>
#include <Encoder.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include "Config.h"
#include "ScreenManager.h"
#include "ScreenSetTime.h"
#include "Buzzer.h"
#include "ExposureTimer.h"
LiquidCrystal lcd(PinLCDRS, PinLCDEN, PinLCDDB4, PinLCDDB5, PinLCDDB6, PinLCDDB7);
// Before uploading the sketch, upload it once with ClearEEPROM defined to
// zero out the memory.
//#define ClearEEPROM
#ifndef ClearEEPROM
ScreenManager* screenManager;
unsigned long currentTime;
Encoder encoder(PinEncoderData, PinEncoderClock);
Bounce button = Bounce();
void setup()
{
pinMode(PinButton, INPUT_PULLUP);
pinMode(PinBuzzer, OUTPUT);
pinMode(PinLED, OUTPUT);
button.attach(PinButton);
button.interval(5);
ResetExposureTime();
lcd.createChar(0, LCDCharArrow);
lcd.begin(LCDWidth, LCDHeight);
screenManager = new ScreenManager(&lcd, &currentTime);
screenManager->show<ScreenSetTime>();
buzzStartup();
}
long lastPosition = 0;
bool isPressed = false;
void loop()
{
currentTime = millis();
button.update();
long newPosition = encoder.read();
if (abs(newPosition - lastPosition) >= EncoderSensitivity)
{
screenManager->getCurrent()->onEncoder(lastPosition, newPosition);
lastPosition = newPosition;
}
if (button.read() == LOW)
{
if (!isPressed)
{
screenManager->getCurrent()->onButton();
isPressed = true;
}
}
else if (isPressed)
isPressed = false;
screenManager->getCurrent()->onTick();
}
#else
void setup()
{
pinMode(PinBuzzer, OUTPUT);
lcd.begin(LCDWidth, LCDHeight);
for (int i = 0 ; i < EEPROM.length() ; i++)
{
EEPROM.write(i, 0);
}
lcd.setCursor(0, 0);
lcd.print("Memory cleared");
buzzMemoryCleared();
}
void loop()
{
}
#endif