summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTito Jankowski <tito@openpcr.org>2011-06-25 17:32:49 -0700
committerTito Jankowski <tito@openpcr.org>2011-06-25 17:32:49 -0700
commitc7a5a692bdea54ccb1bcefc8b144cca6230453de (patch)
tree487ab709c0f46950d549bf3aeefceff675e268b0
parent5ae054e52ea096c6539e2dcc7efd86b9577803d7 (diff)
parentb69dcd175e3b45edc13b08b7400b642834dda786 (diff)
downloadopenpcr-c7a5a692bdea54ccb1bcefc8b144cca6230453de.tar.gz
openpcr-c7a5a692bdea54ccb1bcefc8b144cca6230453de.zip
Merge branch 'master' of github.com:jperfetto/OpenPCR
-rw-r--r--arduino/OpenPCR/Makefile2
-rw-r--r--arduino/OpenPCR/display.cpp45
-rw-r--r--arduino/OpenPCR/pcr_includes.h1
-rw-r--r--arduino/OpenPCR/serialcontrol.cpp104
-rw-r--r--arduino/OpenPCR/serialcontrol.h9
-rw-r--r--arduino/OpenPCR/thermocycler.cpp27
-rw-r--r--arduino/OpenPCR/thermocycler.h1
-rw-r--r--arduino/OpenPCR/util.cpp4
8 files changed, 126 insertions, 67 deletions
diff --git a/arduino/OpenPCR/Makefile b/arduino/OpenPCR/Makefile
index 4bdfd28..8a6857d 100644
--- a/arduino/OpenPCR/Makefile
+++ b/arduino/OpenPCR/Makefile
@@ -18,6 +18,6 @@
# Where to find header files and libraries.
INC_DIRS = ./inc
LIB_DIRS = $(addprefix $(ARD_HOME)/libraries/, $(LIBS))
- LIBS = LiquidCrystal Wire Wire/utility
+ LIBS = LiquidCrystal EEPROM Wire Wire/utility
include ./Makefile.master \ No newline at end of file
diff --git a/arduino/OpenPCR/display.cpp b/arduino/OpenPCR/display.cpp
index 46578ab..3e858b8 100644
--- a/arduino/OpenPCR/display.cpp
+++ b/arduino/OpenPCR/display.cpp
@@ -29,7 +29,18 @@ const char HEATING_STR[] PROGMEM = "Heating";
const char COOLING_STR[] PROGMEM = "Cooling";
const char LIDWAIT_STR[] PROGMEM = "Heating Lid";
const char STOPPED_STR[] PROGMEM = "Ready";
-const char LID_FORM_STR[] PROGMEM = "Lid: %3d C";
+const char RUN_COMPLETE_STR[] PROGMEM = "*** Run Complete ***";
+const char OPENPCR_STR[] PROGMEM = "OpenPCR";
+const char POWERED_OFF_STR[] PROGMEM = "Powered Off";
+const char VERSION_STR[] PROGMEM = "Firmware v1.0";
+const char ETA_OVER_10H_STR[] PROGMEM = "ETA: >10h";
+
+const char LID_FORM_STR[] PROGMEM = "Lid: %3d C";
+const char CYCLE_FORM_STR[] PROGMEM = "%d of %d";
+const char ETA_HOURMIN_FORM_STR[] PROGMEM = "ETA: %d:%02d";
+const char ETA_SEC_FORM_STR[] PROGMEM = "ETA: %2ds";
+const char BLOCK_TEMP_FORM_STR[] PROGMEM = "%s C";
+const char STATE_FORM_STR[] PROGMEM = "%-13s";
Display::Display():
iLcd(6, 7, 8, A5, 16, 17),
@@ -93,16 +104,22 @@ void Display::Update() {
DisplayEta();
} else if (state == Thermocycler::EComplete) {
iLcd.setCursor(0, 3);
- iLcd.print("*** Run Complete ***");
+ iLcd.print(rps(RUN_COMPLETE_STR));
}
break;
case Thermocycler::EOff:
+ case Thermocycler::EStartup:
iLcd.setCursor(6, 1);
- iLcd.print("OpenPCR");
-
- iLcd.setCursor(4, 2);
- iLcd.print("Powered Off");
+ iLcd.print(rps(OPENPCR_STR));
+
+ if (state == Thermocycler::EOff) {
+ iLcd.setCursor(4, 2);
+ iLcd.print(rps(POWERED_OFF_STR));
+ } else {
+ iLcd.setCursor(3, 2);
+ iLcd.print(rps(VERSION_STR));
+ }
break;
}
}
@@ -115,21 +132,19 @@ void Display::DisplayEta() {
int secs = timeRemaining % 60;
if (hours >= 10)
- strcpy(timeString, "ETA: >10h");
+ strcpy_P(timeString, ETA_OVER_10H_STR);
else if (mins >= 1 || hours >= 1)
- sprintf(timeString, "ETA: %d:%02d", hours, mins);
+ sprintf_P(timeString, ETA_HOURMIN_FORM_STR, hours, mins);
else
- sprintf(timeString, "ETA: %2ds", secs);
+ sprintf_P(timeString, ETA_SEC_FORM_STR, secs);
iLcd.setCursor(11, 3);
iLcd.print(timeString);
}
void Display::DisplayLidTemp() {
- char pbuf[16];
char buf[16];
- strcpy_P(pbuf, LID_FORM_STR);
- sprintf(buf, pbuf, (int)(GetThermocycler().GetLidTemp() + 0.5));
+ sprintf_P(buf, LID_FORM_STR, (int)(GetThermocycler().GetLidTemp() + 0.5));
iLcd.setCursor(10, 2);
iLcd.print(buf);
@@ -140,7 +155,7 @@ void Display::DisplayBlockTemp() {
char floatStr[16];
sprintFloat(floatStr, GetThermocycler().GetPlateTemp(), 1, true);
- sprintf(buf, "%s C", floatStr);
+ sprintf_P(buf, BLOCK_TEMP_FORM_STR, floatStr);
iLcd.setCursor(13, 0);
iLcd.print(buf);
@@ -150,7 +165,7 @@ void Display::DisplayCycle() {
char buf[16];
iLcd.setCursor(0, 3);
- sprintf(buf, "%d of %d", GetThermocycler().GetCurrentCycleNum(), GetThermocycler().GetNumCycles());
+ sprintf_P(buf, CYCLE_FORM_STR, GetThermocycler().GetCurrentCycleNum(), GetThermocycler().GetNumCycles());
iLcd.print(buf);
}
@@ -187,6 +202,6 @@ void Display::DisplayState() {
}
iLcd.setCursor(0, 0);
- sprintf(buf, "%-13s", stateStr);
+ sprintf_P(buf, STATE_FORM_STR, stateStr);
iLcd.print(buf);
}
diff --git a/arduino/OpenPCR/pcr_includes.h b/arduino/OpenPCR/pcr_includes.h
index 8c35b4b..48e53cd 100644
--- a/arduino/OpenPCR/pcr_includes.h
+++ b/arduino/OpenPCR/pcr_includes.h
@@ -37,7 +37,6 @@ extern "C" void __cxa_pure_virtual(void);
#define STEP_NAME_LENGTH 16
#define MAX_CYCLE_ITEMS 16
#define MAX_COMMAND_SIZE 256
-#define COMMAND_SIGNATURE "s=ACGTC"
enum PcrStatus {
ESuccess = 0,
diff --git a/arduino/OpenPCR/serialcontrol.cpp b/arduino/OpenPCR/serialcontrol.cpp
index f6efa93..2019297 100644
--- a/arduino/OpenPCR/serialcontrol.cpp
+++ b/arduino/OpenPCR/serialcontrol.cpp
@@ -34,6 +34,7 @@ SerialControl::SerialControl(Display* pDisplay)
, lastPacketSeq(0xff)
, bEscapeCodeFound(false)
, iCommandId(0)
+, iReceivedStatusRequest(false)
{
Serial.begin(BAUD_RATE);
}
@@ -140,6 +141,7 @@ void SerialControl::ProcessPacket(byte* data, int datasize)
break;
case STATUS_REQ:
+ iReceivedStatusRequest = true;
SendStatus();
break;
default:
@@ -152,53 +154,20 @@ void SerialControl::ProcessPacket(byte* data, int datasize)
#define STATUS_FILE_LEN 128
-void SerialControl::SendStatus()
-{
- char* szStatus;
+void SerialControl::SendStatus() {
Thermocycler::ProgramState state = GetThermocycler().GetProgramState();
- switch (state) {
- case Thermocycler::EOff:
- case Thermocycler::EStopped:
- szStatus = "stopped";
- break;
- case Thermocycler::ELidWait:
- szStatus = "lidwait";
- break;
- case Thermocycler::ERunning:
- szStatus = "running";
- break;
- case Thermocycler::EComplete:
- szStatus = "complete";
- break;
- case Thermocycler::EError:
- default:
- szStatus = "error";
- }
-
- char* szThermState = "\0";
- switch (GetThermocycler().GetThermalState()) {
- case Thermocycler::EHeating:
- szThermState = "heating";
- break;
- case Thermocycler::ECooling:
- szThermState = "cooling";
- break;
- case Thermocycler::EHolding:
- szThermState = "holding";
- break;
- case Thermocycler::EIdle:
- szThermState = "idle";
- break;
- }
+ const char* szStatus = GetProgramStateString_P(state);
+ const char* szThermState = GetThermalStateString_P(GetThermocycler().GetThermalState());
char statusBuf[STATUS_FILE_LEN];
char* statusPtr = statusBuf;
Thermocycler& tc = GetThermocycler();
+
statusPtr = AddParam(statusPtr, 'd', (unsigned long)iCommandId, true);
- statusPtr = AddParam(statusPtr, 's', szStatus);
+ statusPtr = AddParam_P(statusPtr, 's', szStatus);
statusPtr = AddParam(statusPtr, 'l', (int)tc.GetLidTemp());
statusPtr = AddParam(statusPtr, 'b', tc.GetPlateTemp(), 1, false);
- statusPtr = AddParam(statusPtr, 't', szThermState);
+ statusPtr = AddParam_P(statusPtr, 't', szThermState);
if (state == Thermocycler::ERunning || state == Thermocycler::EComplete) {
statusPtr = AddParam(statusPtr, 'e', tc.GetElapsedTimeS());
@@ -268,3 +237,60 @@ char* SerialControl::AddParam(char* pBuffer, char key, const char* szVal, boolea
return pBuffer;
}
+
+char* SerialControl::AddParam_P(char* pBuffer, char key, const char* szVal, boolean init) {
+ if (!init)
+ *pBuffer++ = '&';
+ *pBuffer++ = key;
+ *pBuffer++ = '=';
+ strcpy_P(pBuffer, szVal);
+ while (*pBuffer != '\0')
+ pBuffer++;
+
+ return pBuffer;
+}
+
+const char STOPPED_STR[] PROGMEM = "stopped";
+const char LIDWAIT_STR[] PROGMEM = "lidwait";
+const char RUNNING_STR[] PROGMEM = "running";
+const char COMPLETE_STR[] PROGMEM = "complete";
+const char STARTUP_STR[] PROGMEM = "startup";
+const char ERROR_STR[] PROGMEM = "error";
+const char* SerialControl::GetProgramStateString_P(Thermocycler::ProgramState state) {
+ switch (state) {
+ case Thermocycler::EOff:
+ case Thermocycler::EStopped:
+ return STOPPED_STR;
+ case Thermocycler::ELidWait:
+ return LIDWAIT_STR;
+ case Thermocycler::ERunning:
+ return RUNNING_STR;
+ case Thermocycler::EComplete:
+ return COMPLETE_STR;
+ case Thermocycler::EStartup:
+ return STARTUP_STR;
+ case Thermocycler::EError:
+ default:
+ return ERROR_STR;
+ }
+}
+
+const char HEATING_STR[] PROGMEM = "heating";
+const char COOLING_STR[] PROGMEM = "cooling";
+const char HOLDING_STR[] PROGMEM = "holding";
+const char IDLE_STR[] PROGMEM = "idle";
+const char* SerialControl::GetThermalStateString_P(Thermocycler::ThermalState state) {
+ switch (state) {
+ case Thermocycler::EHeating:
+ return HEATING_STR;
+ case Thermocycler::ECooling:
+ return COOLING_STR;
+ case Thermocycler::EHolding:
+ return HOLDING_STR;
+ case Thermocycler::EIdle:
+ return IDLE_STR;
+ default:
+ return ERROR_STR;
+ }
+}
+
diff --git a/arduino/OpenPCR/serialcontrol.h b/arduino/OpenPCR/serialcontrol.h
index 055ced3..5e5b7fe 100644
--- a/arduino/OpenPCR/serialcontrol.h
+++ b/arduino/OpenPCR/serialcontrol.h
@@ -19,10 +19,11 @@
#ifndef _SERIALCONTROL_H_
#define _SERIALCONTROL_H_
+#include "thermocycler.h"
+
#define START_CODE 0xFF
#define ESCAPE_CODE 0xFE
-class Thermocycler;
class Display;
class ProgramComponent;
class Cycle;
@@ -55,6 +56,7 @@ public:
void Process();
byte* GetBuffer() { return buf; } //used for stored program parsing at start-up only if no serial command received
+ boolean CommandReceived() { return iReceivedStatusRequest; }
private:
void ReadPacket();
@@ -65,6 +67,10 @@ private:
char* AddParam(char* pBuffer, char key, unsigned long val, boolean init = false);
char* AddParam(char* pBuffer, char key, float val, int decimalDigits, boolean pad, boolean init = false);
char* AddParam(char* pBuffer, char key, const char* szVal, boolean init = false);
+ char* AddParam_P(char* pBuffer, char key, const char* szVal, boolean init = false);
+
+ const char* GetProgramStateString_P(Thermocycler::ProgramState state);
+ const char* GetThermalStateString_P(Thermocycler::ThermalState state);
private:
byte buf[MAX_COMMAND_SIZE + 1]; //read or write buffer
@@ -80,6 +86,7 @@ private:
uint8_t lastPacketSeq, checksum;
uint16_t packetLen, packetRealLen, iCommandId;
boolean bEscapeCodeFound;
+ boolean iReceivedStatusRequest;
Display* ipDisplay;
};
diff --git a/arduino/OpenPCR/thermocycler.cpp b/arduino/OpenPCR/thermocycler.cpp
index 423ed0b..66b75be 100644
--- a/arduino/OpenPCR/thermocycler.cpp
+++ b/arduino/OpenPCR/thermocycler.cpp
@@ -80,7 +80,7 @@ PROGMEM const unsigned int LID_RESISTANCE_TABLE[] = {
#define PLATE_PID_DEC_P 500
#define PLATE_PID_DEC_I 400
-#define PLATE_PID_DEC_D 200
+#define PLATE_PID_DEC_D 200 //400
#define PLATE_PID_DEC_LOW_THRESHOLD 35
#define PLATE_PID_DEC_LOW_P 2000
@@ -100,6 +100,8 @@ PROGMEM const unsigned int LID_RESISTANCE_TABLE[] = {
#define MAX_LID_PWM 255
#define MIN_LID_PWM 0
+#define STARTUP_DELAY 5000
+
//public
Thermocycler::Thermocycler(boolean restarted):
iRestarted(restarted),
@@ -233,6 +235,19 @@ void Thermocycler::Loop() {
ReadLidTemp();
switch (iProgramState) {
+ case EStartup:
+ if (millis() - iProgramStartTimeMs > STARTUP_DELAY) {
+ iProgramState = EStopped;
+
+ if (!iRestarted && !ipSerialControl->CommandReceived()) {
+ //check for stored program
+ SCommand command;
+ if (ProgramStore::RetrieveProgram(command, (char*)ipSerialControl->GetBuffer()))
+ ProcessCommand(command);
+ }
+ }
+ break;
+
case ELidWait:
if (iLidTemp >= iTargetLidTemp - LID_START_TOLERANCE) {
//advance to running state
@@ -313,14 +328,8 @@ void Thermocycler::CheckPower() {
float voltage = analogRead(0) * 5.0 / 1024 * 10 / 3; // 10/3 is for voltage divider
boolean externalPower = digitalRead(A0); //voltage > 7.0;
if (externalPower && iProgramState == EOff) {
- iProgramState = EStopped;
-
- if (!iRestarted) {
- //check for stored program
- SCommand command;
- if (ProgramStore::RetrieveProgram(command, (char*)ipSerialControl->GetBuffer()))
- ProcessCommand(command);
- }
+ iProgramState = EStartup;
+ iProgramStartTimeMs = millis();
} else if (!externalPower && iProgramState != EOff) {
Stop();
diff --git a/arduino/OpenPCR/thermocycler.h b/arduino/OpenPCR/thermocycler.h
index 9c5f76d..bad5326 100644
--- a/arduino/OpenPCR/thermocycler.h
+++ b/arduino/OpenPCR/thermocycler.h
@@ -29,6 +29,7 @@ class Thermocycler {
public:
enum ProgramState {
EOff = 0,
+ EStartup,
EStopped,
ELidWait,
ERunning,
diff --git a/arduino/OpenPCR/util.cpp b/arduino/OpenPCR/util.cpp
index 24a5987..416c781 100644
--- a/arduino/OpenPCR/util.cpp
+++ b/arduino/OpenPCR/util.cpp
@@ -97,7 +97,9 @@ double absf(double val) {
}
char* rps(const char* progString) {
- static char buf[32];
+ static char buf[21];
strcpy_P(buf, progString);
return buf;
}
+
+