Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:06f27dbfa599, committed 2011-09-04
- Comitter:
- marcbax
- Date:
- Sun Sep 04 18:35:09 2011 +0000
- Commit message:
- Version 0.70
Changed in this revision
| main.cpp | Show annotated file Show diff for this revision Revisions of this file |
| mbed.bld | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 06f27dbfa599 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Sun Sep 04 18:35:09 2011 +0000
@@ -0,0 +1,372 @@
+//Firmware for P173_PoopCooker sample preparation heater block
+
+#include "mbed.h"
+char* fwversion="0.70"; //this version published 5/9/2011
+
+//Pin and object assignments
+DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
+DigitalOut buzzer(p30);
+AnalogIn ntc(p19);
+DigitalOut heater(p18);
+Serial display(p13, p14);
+InterruptIn keyup(p7), keyright(p5), keydown(p6);
+InterruptIn keyleft(p9), keyOK(p8);
+DigitalOut fan(p24);
+PwmOut rled(p21), gled(p22), bled(p23);
+Timer kitchentimer;
+Timeout kitchenalarm;
+Timeout heateroff;
+Ticker showtime;
+Ticker heatercontrol;
+
+// Global constants definitions
+
+float heaterperiod = 5; //cycle time for heater control
+float propterm = 0.1; //proportional term in PID algorithm
+float intterm = 0.001; //integral term in PID algorithm
+float difterm = 0; //differential term in PID algorithm
+
+float ntcB = 3988; //beta value for exponential NTC calculation
+float ntcR25 = 10000; //resistance value of NTC at 25 degC
+float rdivntc = 3300; //resistance value of upper ladder resistor for NTC
+
+float maxblocktemp = 115; //block temperature cutout
+float minblocktemp = 25; //25 degC minimal setpoint temp
+float defaultblocktemp = 60; //this needs to be changed to the standard extraction temperature
+int maxcountdown = 6540; //99 minutes max countdown
+int defaultcountdown = 600; //10 minutes default countdown
+
+// Global variable definitions
+
+float btemp; //current hot block temperature in degC
+float blocksettemp; //hot block setpoint temperature
+float acterror, interror, diferror; //error terms for the PID algorithm
+float ntcA; //calculated from ntcB and ntcR25
+int countdownset; //kitchen timer setting in seconds
+int remainingtime; //kitchen timer current remaining time
+char ntcerror; //0 = no error, 1 = open circuit, 2 = short circuit
+float LedRGB[3] = {0, 0, 0}; // PWM dutycycle red, green, blue
+bool kitchentimerset; // true if kitchen countdown timer is set
+char lastkeypressed; // 1=up, 2=right, 3=down, 4=left, 5=OK
+bool beepsdone;
+
+
+// Function definitions
+
+// Clears and homes the display
+void cleardisplay() {
+ display.printf("\e[2J\e[H");
+}
+
+// Short beep
+void beeponce() {
+ buzzer = 1;
+ wait(0.1);
+ buzzer = 0;
+}
+
+// beep beep beep
+void multibeeps(int number, float interval) {
+ for(int i=0;i<number;i++){
+ beeponce();
+ wait(interval);
+ }
+}
+
+// Device power up routine
+void initdevice() {
+
+ //set all outputs to "off"
+ led1=led2=led3=led4=0;
+ buzzer=0;
+ heater=0;
+ fan=0;
+ bled=0;
+ rled=0;
+ gled=0;
+ rled.period_us(100); //PWM frequency set to 10kHz
+ ntcerror=0;
+ beepsdone=1;
+
+ //key pull-up modes
+ keyup.mode(PullUp);
+ keyright.mode(PullUp);
+ keydown.mode(PullUp);
+ keyleft.mode(PullUp);
+ keyOK.mode(PullUp);
+
+ //calculate ntcA
+ ntcA = ntcR25/exp(ntcB/298); //298K = 25degC
+
+ //reset error terms
+ acterror = interror = diferror = 0;
+
+ //default block temp setting
+ blocksettemp = defaultblocktemp;
+
+ //initialise kitchentimer
+ countdownset = defaultcountdown;
+ kitchentimerset=0;
+
+ //initialise the display and show splash screen
+ display.baud(19200); //set display baud rate to 19200
+ wait(0.2); //display power-on delay
+ display.putc(0x0d); //send CR to display - this needs to be first character sent after power-up
+ wait(0.2); //wait for display to adjust to serial baud rate
+ display.printf("\e[4L\e[20C\e[2m"); //set display to 4 lines of 20 characters, cursor off
+ cleardisplay(); //clear screen and home cursor
+ display.printf("\e[2;2HLumora Sample Prep"); //display splash screen
+ display.printf("\e[3;4HFirmware: %s", fwversion); //display firmware version
+ wait(3); //time that splash screen is shown
+ cleardisplay();
+ beeponce();
+
+}
+
+// Functions called by key interrupts
+void nothing() { //this is a no-operation function, used to detach an InterruptIn
+}
+
+void int_keyup() {
+ lastkeypressed = 1;
+ beeponce();
+}
+
+void int_keyright() {
+ lastkeypressed = 2;
+ beeponce();
+}
+
+void int_keydown() {
+ lastkeypressed = 3;
+ beeponce();
+}
+
+void int_keyleft() {
+ lastkeypressed = 4;
+ beeponce();
+}
+
+void int_keyOK() {
+ lastkeypressed = 5;
+ beeponce();
+}
+
+void incrementsettemp() {
+ if (blocksettemp < maxblocktemp) blocksettemp = blocksettemp + 1;
+ beeponce();
+}
+
+void decrementsettemp() {
+ if (blocksettemp > minblocktemp) blocksettemp = blocksettemp - 1;
+ beeponce();
+}
+
+void incrementtimer() {
+ if (countdownset < maxcountdown) countdownset = countdownset + 60;
+ beeponce();
+}
+
+void decrementtimer() {
+ if (countdownset > 60) countdownset = countdownset - 60;
+ beeponce();
+}
+
+// Display update routine (also handles alarm)
+void updatedisplay() {
+ display.printf("\e[2;3HBlock Temp %3.0f%cC", btemp, 223);
+ remainingtime = countdownset - kitchentimer.read();
+ if (kitchentimerset) {
+ display.printf("\e[3;3HCountdown %02u:%02u", remainingtime/60, remainingtime%60);
+ }
+ else {
+ display.printf("\e[3;3HSet Timer %02u:%02u", remainingtime/60, remainingtime%60);
+ }
+ if (remainingtime <= 0) { //alarm condition
+ kitchentimer.stop(); //stop timer
+ kitchentimerset=0; //clear flag
+ if (!beepsdone) multibeeps(3,0.25); //duration of multibeeps needs to be less then 0.9 seconds
+ beepsdone = 1; //set beepsdone to only sound alarm once
+ }
+}
+
+// Stops the countdown timer
+void stopkitchentimer() {
+ beeponce();
+ if (kitchentimerset) {
+ kitchentimer.stop();
+ }
+ else {
+ kitchentimer.reset();
+ }
+ kitchentimerset=0;
+}
+
+// Starts the countdown timer
+void startkitchentimer() {
+ kitchentimer.start();
+ beeponce();
+ beepsdone=0;
+ kitchentimerset = 1;
+}
+
+// Returns the current hot block temperature in degrees centigrade as measured by the NTC
+float blocktemp() {
+ float vntc, rntc;
+ wait(0.03);
+ vntc = ntc.read()*3.3;
+ if (vntc > 3) { //check for NTC open circuit
+ ntcerror=1;
+ return 120; //on error return high temperature
+ }
+ else {
+ if (vntc < 0.3) { //check for NTC open circuit
+ ntcerror = 2;
+ return 120; //on error return high temperature
+ }
+ else {
+ rntc = (vntc * rdivntc)/(3.3 - vntc); //calculate Rntc from Vntc
+ return ntcB/(log(rntc)-log(ntcA))-273; //calculate temperature using exponential approximation curve (beta curve)
+ }
+ }
+}
+
+// Returns the next duty-cycle for the heater using a PID algorithm
+float getheaterPWM() {
+ float prevtemp, outpt;
+ prevtemp = btemp; //store previous temperature to calculate differential
+ btemp = blocktemp(); //measure current block temperature
+ if (btemp < (blocksettemp - 10)) { //heater constantly on when temperature way too low, no error build-up
+ return 1;
+ }
+ else { //only build up integral error when temperature is within range
+ acterror = blocksettemp - btemp; //calculate current error term
+ interror = interror + acterror; //update integral error term
+ diferror = btemp - prevtemp; //calculate differential error term
+ outpt = (propterm * acterror); //calculate and set proportional contribution
+ outpt = outpt + (intterm * interror); //calculate and add integral contribution
+ outpt = outpt + (difterm * diferror); //calculate and add differential contribution
+ if (outpt <0) outpt=0; //minimum output is "off"
+ if (outpt >1) outpt=1; //maximum output is "on"
+ }
+ if (btemp > maxblocktemp) outpt=0; //software overtemperature cutout
+ return outpt;
+}
+
+//Translates block temperature to RGB value of indication LEDs
+void temp2RGB (float temp) {
+ if (temp < 40) { //LEDs show pure blue for low temperature
+ LedRGB[0] = 0;
+ LedRGB[1] = 0;
+ LedRGB[2] = 0.5;
+ }
+ else {
+ if (temp > 60) { //LEDs show pure red for high temperatures
+ LedRGB[0] = 1;
+ LedRGB[1] = 0;
+ LedRGB[2] = 0;
+ }
+ else { //LEDs mix red and blue
+ LedRGB[0] = (temp-40)/20;
+ LedRGB[1] = 0;
+ LedRGB[2] = (60-temp)/20;
+ }
+ }
+}
+
+// Drives the temperature indication LEDs in the top plate
+void driveRGBled() { //uses global array, as functions cannot pass array variables
+ rled = LedRGB[0];
+ gled = LedRGB[1];
+ bled = LedRGB[2];
+}
+
+// Set or adjust the block setpoint temperature
+void adjustblocktemp () {
+ keyup.fall(&incrementsettemp); //define "up" key function
+ keydown.fall(&decrementsettemp); //define "down" key function
+ keyOK.fall(&int_keyOK); //define "OK" key function
+ display.printf("\e[2;6HSettings");
+ while (lastkeypressed != 5) { //loop until OK is pressed
+ display.printf("\e[3;3HSet temp= %3.0f%cC", blocksettemp, 223);
+ wait(0.2);
+ }
+ keyup.fall(¬hing); //detach InteruptIn functions
+ keydown.fall(¬hing);
+ keyOK.fall(¬hing);
+ lastkeypressed = 0; //clear flag
+}
+
+// Warm-up to operating temperature
+void warmupblock (float settemp) {
+ btemp = blocktemp();
+ float heaterdutycycle;
+ cleardisplay();
+ if (settemp < maxblocktemp) { //this test avoids overtemperature due to incorrect function call
+ while (btemp < (settemp -0.5)) { //setpoint reached if temperature within 0.5 degrees
+ btemp = blocktemp();
+ display.printf("\e[2;2HWarming up: %3.0f%cC", btemp, 223);
+ temp2RGB(btemp);
+ driveRGBled();
+ heaterdutycycle = getheaterPWM(); //PWM heater with longish period
+ heater = 1;
+ wait (5 * heaterdutycycle);
+ heater = 0;
+ wait (5 * (1 - heaterdutycycle));
+ }
+ }
+ heater = 0;
+}
+
+// Cooling down
+void coolblockdown() {
+ showtime.detach(); //avoid showing timer on display
+ cleardisplay();
+ while (1) {
+ btemp = blocktemp();
+ fan = (btemp > 40); //fan is on when block temperature above 40 degrees
+ display.printf("\e[2;3HCool down: %3.0f%cC", btemp, 223);
+ temp2RGB(btemp);
+ driveRGBled();
+ if (!fan) display.printf("\e[3;3HSafe to touch");
+ wait(5); //one update per 5 seconds is more then enough
+ }
+}
+
+// Regulating to a constant temperature
+void stayhot() {
+ float heaterdutycycle;
+ cleardisplay();
+ showtime.attach(&updatedisplay, 1.0); //set ticker for routine that updates display every second
+ keyOK.fall(&int_keyOK); //define key interrupt routines
+ keyright.fall(&startkitchentimer);
+ keyup.fall(&incrementtimer);
+ keydown.fall(&decrementtimer);
+ keyleft.fall(&stopkitchentimer);
+ while (lastkeypressed != 5) { //main program loop until OK key pressed
+ btemp = blocktemp();
+ temp2RGB(btemp);
+ driveRGBled();
+ heaterdutycycle = getheaterPWM(); //PWM heater with longish period
+ heater = 1;
+ wait (5 * heaterdutycycle);
+ heater = 0;
+ wait (5 * (1 - heaterdutycycle));
+ }
+ stopkitchentimer(); //stop timer
+ keyOK.fall(¬hing); //detach key interrupt routines
+ keyright.fall(¬hing);
+ keyup.fall(¬hing);
+ keydown.fall(¬hing);
+}
+
+// Main program
+int main() {
+ initdevice(); //power-on initialisation
+ btemp = blocktemp();
+ adjustblocktemp();
+ beeponce();
+ warmupblock(blocksettemp); //warming up
+ stayhot(); //this is where to program spends most of its time
+ coolblockdown(); //fan-assisted cool down
+}
diff -r 000000000000 -r 06f27dbfa599 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Sep 04 18:35:09 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912