Hi. I have written a program that controls 4 100W light bulbs via relays attached to my Arduino (pins 2-5). I have a debounced button, finite stage machines, some timing, and sequences of lights on/off which are read from sequentially named (01.txt, 02.txt, etc.) text files on an SD card. This allows visual programming of sequences win Notepad outside of the Arduino environment.
I am having the curious and undesired result of only getting 5V output from pins #4 and #5 - so my relays are not firing on pins #2 and #3. When I substitute LEDs for relays, the LEDs on pins #2 AND #3 only light up dimly, and are reading ~1 and less V, while #4 and #5 are bright. My relays are 5V/0.30A so current is not the problem. My Arduino is powered by 12V DC, 1.25A. The relays are getting 5V in parallel from the Arduino VCC / GND out.
To test that electronic connections, I wrote a simple "blink 2, blink 3, blink 4, blink 5" sketch just using delays, and that manages to fire the relays and light up the light bulbs just fine. There is something in this program that is the culprit, can anyone help?
By the way, If this looks familiar to anyone I had posted asking for help in the Communication forum a few weeks ago; since then I have managed to get the program to do what it should, save for this latest issue. Thanks for having a look.
Here is my program (in two parts):
#include <Bounce.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <FiniteStateMachine.h>
int REDled = 8;
int GREENled = 9;
//Sequence
int SEQUENCEbutton = 6;
unsigned long SequenceLastFired;
//Variables for Timing
unsigned long StartupEnteredTime;
unsigned long ArmedEnteredTime;
unsigned long FiringEnteredTime;
unsigned long PausingEnteredTime;
unsigned long StartFiring;
//random intermission parameters
long randomIntermissionLengthMin = 2000;
long randomIntermissionLengthMax = 8000;
int randomValveMin = 100;
int randomValveMax = 200;
int timeBetweenBlastsMin = 50;
int timeBetweenBlastsMax = 5000;
//state machine declarations
State Idle = State (DSIdle); //idle state
State Startup = State (DSStartupStart,DSStartupUpd,DSStartupExit); //startup state
State Armed = State (DSArmedStart,DSArmedUpd,DSArmedExit); //Armed state
State Firing = State (DSFiringStart,DSFiringUpd,DSFiringExit); //cannons firing state
State Pausing = State (DSPausingStart,DSPausingUpd,DSPausingExit);//pause state
FSM DSStateMachine = FSM(Idle); //initialize DS State Machine, start in state: Idle
//sequence reset time, during which sequence button will not work after pressed (should be eventually set to 15 minutes)
int SequenceResetTime = 5000;
//button debouncing
Bounce SEQUENCEbouncer = Bounce (SEQUENCEbutton,3);
//SD card setup
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
//Text files on card names and quantity
//int offset = 2;
int fileCount = 7; // count + 1
//struct for variables in text file
struct Event {
long eventTimestamp;
byte address;
} ;
//LED or Cannon Pins
int outputPins[4] = {2,3,4,5};
int sequenceSize;
long millisSinceStart = 0;
int currentEventPtr = 0;
char name[] = "00.txt";
uint8_t fileCounter = 0;
Event sequence[150];
// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
PgmPrint("mystery error: ");
if (card.errorCode())
{
PgmPrint("SD error: ");
}
while(1);
}
//====================SETUP CODE TO RUN ONCE=====================
void setup () {
pinMode (SEQUENCEbutton, INPUT);
for (int i = 2; i < 6; i++)
{
pinMode(outputPins[i], OUTPUT);
}
if (!card.init(SPI_HALF_SPEED)) error("card.init failed");
if (!volume.init(&card)) error("volume.init failed");
if (!root.openRoot(&volume)) error("openRoot failed");
for (int i = 2; i < 6; i++) {
digitalWrite(i, LOW);
delay(10);
}
Serial.begin(9600);
//REMOVED loadSequence();
randomSeed(analogRead(0));
}
//===================MAIN PROGRAM LOOP CODE=====================
void loop (){
if (millis() > 3000 && DSStateMachine.isInState(Idle)){
{
DSStateMachine.transitionTo(Startup);
}
}
DSStateMachine.update();
}
dir_t dir;
//==================STATE MACHINES==============================
//Idle------------------------------/
void DSIdle (){
Serial.println("In State = Idle");
for (int i = 2; i < 6; i++)
{
digitalWrite(i, LOW);
}
digitalWrite(GREENled, LOW);
digitalWrite(REDled, HIGH);
}
//Startup----------------------------/
void DSStartupStart (){
Serial.println("In State = Startup");
for (int i = 2; i < 6; i++)
{
digitalWrite(i, LOW);
}
digitalWrite(GREENled, LOW);
digitalWrite(REDled, HIGH);
StartupEnteredTime = millis();
Serial.println(StartupEnteredTime);
}
void DSStartupUpd (){
if (millis() - StartupEnteredTime > 2000)
{
DSStateMachine.transitionTo(Armed);
}
}
void DSStartupExit ()
{
}
//Armed------------------------------/
void DSArmedStart (){
for (int i = 2; i < 6; i++)
{
digitalWrite(i, LOW);
}
Serial.println("In State = Armed");
digitalWrite(GREENled, HIGH);
digitalWrite(REDled, LOW);
ArmedEnteredTime = millis();
}
void DSArmedUpd (){
SEQUENCEbouncer.update();
int SEQUENCEbuttonState = SEQUENCEbouncer.read();
if (SEQUENCEbuttonState == HIGH)
{
DSStateMachine.transitionTo(Firing);
}
}
void DSArmedExit ()
{
}
//FIRING---------------------------/
void DSFiringStart()
{
Serial.println("In State = Firing");
loadSequence();
}
void DSFiringUpd()
{
StartFiring = millis();
//Serial.println(StartFiring);
//delay(1000);
//Serial.println("timestamp");
// Serial.println(sequence[currentEventPtr].eventTimestamp);
if(StartFiring > (sequence[currentEventPtr].eventTimestamp))
{
loadBinaryCannonSequences(sequence[currentEventPtr].address);
currentEventPtr++;
if(currentEventPtr >= sequenceSize)
{
currentEventPtr = 0;
file.close();
for (int i = 2; i < 6; i++) {
digitalWrite(i, LOW);
delay(10);
SequenceLastFired = millis();
DSStateMachine.transitionTo(Pausing);
}
}
// loadSequence();
}
}
void DSFiringExit()
{
}
//PAUSING------------------------------/
void DSPausingStart(){
Serial.println("In State = Pausing");
digitalWrite(REDled, HIGH);
digitalWrite(GREENled,LOW);
PausingEnteredTime = millis();
}
void DSPausingUpd(){
///*
//--------Random intermission code for TOP MAST only (PIN 2)-----------
//--can be removed if not desired, decomment exclusion characters above and below.
unsigned long randomIntermissionLength = random(randomIntermissionLengthMin, randomIntermissionLengthMax);
do
{
delay(random(timeBetweenBlastsMin, timeBetweenBlastsMax));
digitalWrite(2, HIGH);
delay(random(randomValveMin, randomValveMax));
digitalWrite(2, LOW);
delay(random(timeBetweenBlastsMin, timeBetweenBlastsMax));
}while (millis() - PausingEnteredTime < SequenceResetTime);
//--------------------------------------
//*/
if (millis() - PausingEnteredTime > SequenceResetTime){
DSStateMachine.immediateTransitionTo(Armed);
}
}
void DSPausingExit()
{
}
//PART ONE OF CODE