|
//board:duemilanove |
|
// Arduino serial pulser. |
|
|
|
// Pulses a PWM pin supplied over Serial for the duration that was sent. |
|
#include <stdint.h> |
|
|
|
//#define DEBUG |
|
#define CHANNEL0 9 |
|
#define CHANNEL1 6 |
|
#define CHANNEL2 5 |
|
#define CHANNEL3 3 |
|
|
|
#define NO_CHANNELS 4 |
|
|
|
#define DECAY_TIME 8 // number of cycles to run before doing a decay loop |
|
|
|
#define UINT16_MAX (65535U) |
|
|
|
|
|
#define NODE 1 // used to define which node we're looking at. TODO move this to EEPROM and burn in |
|
|
|
byte channels[] = {CHANNEL0, CHANNEL1, CHANNEL2, CHANNEL3}; |
|
|
|
long channel_time_values[NO_CHANNELS]; // used to hold the time to stay lit |
|
uint8_t channel_light_val[NO_CHANNELS]; // used to hold the light value |
|
|
|
enum LIGHT_DIRECTION { |
|
FADE_DOWN = -1, |
|
HOLD = 0, |
|
FADE_UP = 1 |
|
} channel_light_dir[NO_CHANNELS]; // used to hold the direction |
|
|
|
uint8_t current_channel = 0; |
|
|
|
long current_value = 0; |
|
|
|
enum STATE { |
|
WAITING_DATA, |
|
WAITING_VALUE, |
|
DISCLOSE_NODE |
|
} state = WAITING_DATA; |
|
|
|
|
|
|
|
void setup() { |
|
|
|
// we're going to be talking to the serial line so best we open it. |
|
Serial.begin(9600); |
|
Serial.print("Lightnode:"); |
|
Serial.println(NODE); |
|
Serial.flush(); |
|
#ifdef DEBUG |
|
Serial.println("Serial pulser."); |
|
Serial.println("Send a channel number then a duration in msec"); |
|
Serial.println("Send CR to complete"); |
|
#endif |
|
|
|
// set up the PWM pins for use. |
|
for (uint8_t i=0; i< NO_CHANNELS; i++) { |
|
pinMode(channels[i], OUTPUT); |
|
digitalWrite(channels[i], LOW); |
|
channel_light_val[i] = 0; |
|
} |
|
} |
|
|
|
|
|
void loop() { |
|
|
|
// check to see if anything is coming in on the serial line and if there |
|
// is then process it. |
|
|
|
if(Serial.available()){ |
|
|
|
char ch = Serial.read(); |
|
|
|
if (ch >= '0' && ch<= '9') { |
|
if (state == WAITING_DATA) { |
|
current_channel = (current_channel * 10) + (ch - '0'); |
|
#ifdef DEBUG |
|
Serial.print("Got a char: "); |
|
Serial.println(ch); |
|
#endif |
|
} else if (state == WAITING_VALUE) { |
|
current_value = (current_value * 10) + (ch - '0'); |
|
} |
|
} else if (ch == 32) { // space so we split the channel stuff. |
|
if (state == WAITING_DATA) { |
|
state = WAITING_VALUE; |
|
#ifdef DEBUG |
|
Serial.println("Got a space"); |
|
#endif |
|
} |
|
} else if (ch == 'n') { |
|
//channel has asked to disclose our name |
|
state = DISCLOSE_NODE; |
|
} else if (ch == 10) { |
|
// newline so end of val. |
|
if (state == DISCLOSE_NODE) { |
|
Serial.print("Lightnode:"); |
|
Serial.println(NODE); |
|
Serial.flush(); |
|
state = WAITING_DATA; |
|
} else if (state == WAITING_VALUE) { |
|
state = WAITING_DATA; |
|
#ifdef DEBUG |
|
Serial.print("Got a new line "); |
|
Serial.print("Channel: "); |
|
Serial.print(current_channel); |
|
Serial.print("msecs: "); |
|
Serial.println(current_value); |
|
#endif |
|
pulse(current_channel, current_value); |
|
current_value = 0; |
|
current_channel = 0; |
|
} |
|
} |
|
} |
|
|
|
// decay the values on the channels appropriately. |
|
|
|
for (int i = 0; i < NO_CHANNELS; i++) { |
|
channel_time_values[i]--; |
|
if (channel_time_values[i] < 0) { |
|
channel_time_values[i] = 0; |
|
if (channel_light_val[i] > 0 && channel_light_dir[i] == HOLD) { |
|
channel_light_dir[i] = FADE_DOWN; |
|
#ifdef DEBUG |
|
Serial.print("Fading down channel: "); |
|
Serial.println(i); |
|
#endif |
|
} |
|
} |
|
|
|
if (channel_light_dir[i] == FADE_UP) { |
|
if (channel_light_val[i] < 255) { |
|
channel_light_val[i] += channel_light_dir[i]; |
|
} else { |
|
channel_light_dir[i] = HOLD; |
|
#ifdef DEBUG |
|
Serial.print("HOLDING HIGH channel: "); |
|
Serial.println(i); |
|
#endif |
|
} |
|
} else if (channel_light_dir[i] == FADE_DOWN) { |
|
if (channel_light_val[i] > 0) { |
|
channel_light_val[i] += channel_light_dir[i]; |
|
} else { |
|
channel_light_dir[i] = HOLD; |
|
#ifdef DEBUG |
|
Serial.print("HOLDING LOW channel: "); |
|
Serial.println(i); |
|
#endif |
|
} |
|
} |
|
// now we actually know what the value should be write it to the pin. |
|
analogWrite(channels[i], channel_light_val[i]); |
|
} |
|
|
|
delay(1); |
|
|
|
} |
|
|
|
void pulse(uint8_t channel, uint16_t msecs ) { |
|
// this function adds the value of a pulse onto the specified channel |
|
|
|
if ((channel_time_values[channel]+ msecs) > UINT16_MAX ) { |
|
channel_time_values[channel] = UINT16_MAX; |
|
} else { |
|
channel_time_values[channel] += msecs; |
|
#ifdef DEBUG |
|
Serial.print("Setting time value to: "); |
|
Serial.println(channel_time_values[channel]); |
|
#endif |
|
} |
|
channel_light_dir[channel] = FADE_UP; |
|
|
|
#ifdef DEBUG |
|
Serial.print("Fading up channel: "); |
|
Serial.println(channel); |
|
#endif |
|
} |