/* ZX Light Sequencer ver 1.1 - 2009-04-04 - Ray Andrews - SteelToad Software, Inc.
My first program on the Arduino platform, and my first dive back into C in a long time.
The circuit is intended to drive the tail-lights and marker-lights on a car I'm rebuilding.
The led's will be replaced with mosfet's to drive the auto voltages and switch the lights.
There are three (T)ail-lights on each side of the car, and a single (m)arker light
Vehicle lights (m) (T) (T) (T) (T) (T) (T) (m)
| | | | | | | |
Arduino pins 13 12 11 10 9 8 7 6
------------------------------------------------------------
Profile bits 128 64 32 16 8 4 2 1
This program stores the sequences as profiles, each profile has four step sequence for
each of six possible values to be read from the available inputs. Each byte in the profile
drives a light with each corresponding bit as shown above. The program does one step in the
sequence each time through the loop in order to maximize responsiveness to inputs. I dont
want to be waiting to finish a turn singal sequence when I'm already standing on the brakes.
Another reason I've designed it this way rather than coding individual digitalWrite commands
is that I can add new profiles, or extend the number of steps in a sequence without having
to change the actual code. With the current four steps per sequence, each new profile only
adds an additional 24 bytes to the program.
ver 1.0 (1844 bytes / Ardunio 0015)
ver 1.1 (1780 bytes / Ardunio 0015)
- removed setup line that set all digital pins to input, controller does that automatically
- hazard lights only come on if no other signal is present
- removed unused const profile_size
/**********************************************************************************************/
const int first_light_pin = 6; // starting point for led output pins
const int speed_pin = 2; // analog pin (potentiometer speed adjustment)
const int right_turn_pin = 1; // digital input pins for control signals
const int left_turn_pin = 2; //
const int brakes_pin = 3; //
const int hazard_pin = 4; //
const int profile_selector_pin = 5; //
const int no_activity = -2; // these constants are possible values for the
const int brakes_only = 0; // signal_type variable and indicate which of
const int left_turn = 1; // the controls are active
const int right_turn = 2; //
const int left_turn_brakes = 3; //
const int right_turn_brakes = 4; //
const int hazard_lights = 5; //
const int profile_max = 2; // number of profiles
const int signal_type_max = 6; // how many types of signals can there be
const int step_max = 4; // number of steps in each sequence
/**********************************************************************************************/
// different profiles for light settings, the first group are the standard sequence,
// the second are settings that are more "inspection time" friendly. Other profiles
// could easily be added later.
byte profiles[profile_max][signal_type_max][step_max] =
// 1 = Light On 0 = Light Off
// step 1 step 2 step 3 step 4
// Basic Profile
{B11111111, B11111111, B11111111, B11111111, // 0 brakes
B11110000, B00000000, B11110000, B00000000, // 1 left turn
B00001111, B00000000, B00001111, B00000000, // 2 right turn
B00111111, B11111111, B00111111, B11111111, // 3 left turn with brakes
B11111100, B11111111, B11111100, B11111111, // 4 right turn with brakes
B11111111, B00100100, B11111111, B00100100, // 5 hazard lights
// Sequenced Lights Profile
B11111111, B11111111, B11111111, B11111111, // 0 brakes
B00010000, B10100000, B01000000, B10000000, // 1 left turn
B00001000, B00000101, B00000010, B00000001, // 2 right turn
B11101111, B01011111, B10111111, B01111111, // 3 left turn with brakes
B11110111, B11111010, B11111101, B11111110, // 4 right turn with brakes
B10100101, B01011010, B10100101, B01011010}; // 5 hazard lights
int cycle_delay; // analog reading from the speed_pin
int profile_id = 0; // the currently selected profile
int previous_signal_type = no_activity; // the previous signal reading (for later comparison)
int signal_type = no_activity; // the current input signal reading
int step_counter = 0; // where in the four step sequence: 0 - (step_max-1)
int x = 0; // counter varaible for small for loops
/**********************************************************************************************/
void setup()
{
// set led pins for output starting at first_light_pin
for (x = 0; x < 8; x++) pinMode(first_light_pin + x, OUTPUT);
}
void loop()
{
// find out what switches are pressed, the speed, which profile to use
read_controls();
// if the signal has changed, start at the beginning of the new sequence
if (signal_type != previous_signal_type) step_counter = 0;
if (signal_type == no_activity)
{
// turn all of the lights off, but only if we're changing to no_activity
// theres no need to turn them off every time through the loop if nothing has changed
// restart the loop to make looking for the next signal faster, we dont need the delay
if (previous_signal_type != no_activity)
for (x = 0; x < 8; x++) digitalWrite(first_light_pin + x, LOW);
return;
}
// look-up the byte to use according to the profile, signal_type, and step_counter
// set each let based on the corresponding bit in the profile byte
for (x = 0; x < 8; x++)
digitalWrite(first_light_pin + x, profiles[profile_id][signal_type][step_counter] & (1<<x));
// increment the step_counter and reset back to 0 to start the sequence over
if (++step_counter >= step_max) step_counter = 0;
// wait time is set by the potentiomenter on speed_pin
delay(cycle_delay);
}
void read_controls()
{
// reading the cycle_delay and profile_id could be moved to the setup function
// but for testing, it's easier to just leave them here to get called by loop
// save the previous signal_type to help detect changes
previous_signal_type = signal_type;
// assume no activity, and then adjust accordingly based on input pin values
signal_type = no_activity;
if (digitalRead(left_turn_pin)) signal_type = left_turn;
if (digitalRead(right_turn_pin)) signal_type = right_turn;
if (digitalRead(brakes_pin))
{
if (signal_type == left_turn) signal_type = left_turn_brakes;
if (signal_type == right_turn) signal_type = right_turn_brakes;
if (signal_type == no_activity) signal_type = brakes_only;
}
if (digitalRead(hazard_pin) && signal_type == no_activity)
signal_type = hazard_lights;
// read the delay to put between steps
cycle_delay = analogRead(speed_pin) + 10;
// determine which profile to use, right now it's by input pin selection, but
// it could be software derived, from a rotary switch, or other method later
if (digitalRead(profile_selector_pin) == HIGH)
profile_id = 1;
else
profile_id = 0;
// make sure whatever profile_id is selected is within the profile table range
if (profile_id >= profile_max || profile_id < 0) profile_id = 0;
}
|