The smoker needs to handle quite a bit at a time:
- Reading the temperature and updating the PID.
- Reading commands from the laptop.
- Sending periodic status updates to the laptop.
- Flipping the hotplate on and off.
- Whatever else we can think of.
So, to make handling all this a little easier, I began writing a little pseudo-threading library (called Polyester) when Josh pointed me at ProtoThreads. It’s a stackless threading library built for low memory devices, and someone was nice enough to package it in an Arduino library.
I took a crack at making a simple sketch that blinked two LEDs at different intervals to see how the library works. Here’s what I came up with:
// Blink 2 LEDs, one every second and the other every other second.
// include ProtoThreads
// Originally from: http://www.sics.se/~adam/pt/
// Arduino package: http://arduino.cc/pipermail/developers_arduino.cc/2009-January/000456.html
#include <pt.h>
// LED pins
const int led1Pin = 13;
const int led2Pin = 12;
// state for the led1 function
static int led1Millis;
static int led1State = LOW;
// state for the led2 function
static int led2Millis;
static int led2State = LOW;
// ProtoThreads structures for each function
static struct pt pt1, pt2;
// function to blink led 1 on and off every second
static int led1 (struct pt *pt) {
PT_BEGIN(pt);
while(1) {
led1Millis = millis() + 1000;
PT_WAIT_UNTIL(pt, led1Millis < millis());
if (led1State == LOW)
led1State = HIGH;
else
led1State = LOW;
digitalWrite(led1Pin, led1State);
}
PT_END(pt);
}
// function to blink led 2 on and off every other second
// basically the above method with s/1/2/g
static int led2 (struct pt *pt) {
PT_BEGIN(pt);
while(1) {
led2Millis = millis() + 2000;
PT_WAIT_UNTIL(pt, led2Millis < millis());
if (led2State == LOW)
led2State = HIGH;
else
led2State = LOW;
digitalWrite(led2Pin, led2State);
}
PT_END(pt);
}
// Arduino setup
void setup()
{
// we're using the pins for output
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
// initialize the ProtoThreads varables
PT_INIT(&pt1);
PT_INIT(&pt2);
}
// Arduino loop
void loop() {
// call each function continuously
led1(&pt1);
led2(&pt2);
}
While this code seemed to work just fine, after about 30 seconds, the LEDs stop blinking. The first version of the code printed to the serial monitor, and I noticed that closing and opening the serial monitor kicked my Arduino enough that it worked for another 30 seconds. However, removing the serial code didn’t change this behavior. Neither did running the Arduino off of the wall wart (with no USB cable attached).
After poring over the code for a bit, I rewrote it to not use ProtoThreads, to eliminate the library as the source of the problem:
// Blink 2 LEDs, one every second and the other every other second.
// LED pins
const int led1Pin = 13;
const int led2Pin = 12;
// state for the led1 function
static int led1Millis;
static int led1State = LOW;
// state for the led2 function
static int led2Millis;
static int led2State = LOW;
// function to blink led 1 on and off every second
static void led1 () {
if (led1Millis > millis()) {
return;
}
led1Millis = millis() + 1000;
if (led1State == LOW)
led1State = HIGH;
else
led1State = LOW;
digitalWrite(led1Pin, led1State);
}
// function to blink led 2 on and off every other second
// basically the above method with s/1/2/g
static void led2 () {
if (led2Millis > millis()) {
return;
}
led2Millis = millis() + 2000;
if (led2State == LOW)
led2State = HIGH;
else
led2State = LOW;
digitalWrite(led2Pin, led2State);
}
// Arduino setup
void setup()
{
// we're using the pins for output
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
}
// Arduino loop
void loop() {
// call each function continuously
led1();
led2();
}
However, the problem didn’t go away. It still freezes after about 30 seconds. At this point, I was concerned that it may be a hardware issue.
So I loaded both blink sketches from the Arduino tutorial site and let them run for a while. Thankfully, after several minutes, there were no freezes.
Time to do a little debugging.