I'll apologize now because it is both horribly commented and way more than you need for what you want to do.
This project had an LCD display that showed ammo for both stampedes, had configurable burst fire, semi, and fully automatic fire modes, and maintained preferences when powering on and off.
here is the bit that managed the relay and stampede fire cycle switch.
void pullTrigger(int barrel) {//0 neither, 1 upper, 2 lower if(barrel == 1) { while(digitalRead(UpperSensor) == HIGH) {//check and see if the firing cycle has taken over Serial.println("firing interval"); digitalWrite(RelayUpper, LOW);//turn the relay on delay(FIRING_INTERVAL);//wait a little bit digitalWrite(RelayUpper, HIGH);//turn the relay off } } else if(barrel == 2) { while(digitalRead(LowerSensor) == HIGH) {//check and see if the firing cycle has taken over Serial.println("firing interval"); digitalWrite(RelayLower, LOW);//turn the relay on delay(FIRING_INTERVAL);//wait a little bit digitalWrite(RelayLower, HIGH);//turn the relay off } } }
Like i said, i had two stampedes, but there you can see how it handled firing via relay.
the full code is below
/* */ #include <LiquidCrystal.h> #include <DFR_Key.h> #include <stdio.h> #include <avr/pgmspace.h> #include <phi_big_font.h> #include <EEPROM.h> //storing preferences between power cycles #define EEPCOUNTUPPER 0 #define EEPCOUNTLOWER 1 #define EEPBARREL 2 #define EEPROUNDS 3 #define EEPMODE 5 #define CAPACITY 18 #define DISPLAYCOUNT 19 char* capacityDisplay[] = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "XX"}; static unsigned char CountUpper; static unsigned char CountLower; #define BARRELS 3 static boolean Shooting = true; static boolean menuBarrel = true; static int Mode; //0: Both, 3 Empty uppersecond; 4 Lower emptysecond; 5 Both empty; 6 menuRounds; 7 menuBarrel //0 > 5 > 0 // 1 > 3 > 2 > 4 > 5 // 2 > 4 > 1 > 3 > 5 static char Rounds; //0: semi-auto, 1: Full auto, 2+ bursts static unsigned char Barrel; //0 both, 1 upper, 2 lower const static int RelayUpper = 11; static const int RelayLower = 12; static const int Trigger = 13; #define UpperSensor A2 #define LowerSensor A3 #define FIRING_INTERVAL 10 //A1 unused #define UPPERMAGSENSOR A4 #define LOWERMAGSENSOR A5 #define UPPEROVERRIDE 2 #define LOWEROVERRIDE 3 #define BLINKRATE 500 #define DISPLAYRATE 3000 //Pin assignments for SainSmart LCD Keypad Shield LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //--------------------------------------------- DFR_Key keypad; int localKey = 0; String keyString = ""; unsigned long time; unsigned long lastDisplay; unsigned long lastBlink; void setup() { Serial.begin(9600); digitalWrite(RelayUpper, HIGH); digitalWrite(RelayLower, HIGH); pinMode(RelayUpper,OUTPUT); pinMode(RelayLower,OUTPUT); pinMode(Trigger,INPUT_PULLUP); pinMode(UpperSensor,INPUT_PULLUP); pinMode(LowerSensor,INPUT_PULLUP); pinMode(UPPERMAGSENSOR, INPUT_PULLUP); pinMode(LOWERMAGSENSOR, INPUT_PULLUP); pinMode(UPPEROVERRIDE, INPUT_PULLUP); pinMode(LOWEROVERRIDE, INPUT_PULLUP); init_big_font(&lcd); lcd.begin(16, 2); lcd.clear(); lcd.setCursor(0, 0); lcd.print("SPARKYBFG ONLINE"); lcd.setCursor(0,1); lcd.print("INITIALIZING NOW"); waitTrig(2000); lcd.clear(); Mode = 1; keypad.setRate(2500); char check = EEPROM.read(0); if(check == 255) {//no preferences saved CountUpper = CAPACITY; CountLower = CAPACITY; Rounds = 1; Barrel = 0; } else { CountUpper = EEPROM.read(EEPCOUNTUPPER); CountLower = EEPROM.read(EEPCOUNTLOWER); Rounds = EEPROM.read(EEPROUNDS); Barrel = EEPROM.read(EEPBARREL); } displayCount(); } void loop() { waitTrig(100); Serial.print("Barrel: "); Serial.println( Barrel); Serial.print("Rounds: "); Serial.println(Rounds, DEC); HandleKeys(); //reload detection if(digitalRead(UPPERMAGSENSOR) == HIGH) { Serial.println("Upper Reloaded"); CountUpper = CAPACITY; } if(digitalRead(LOWERMAGSENSOR) == HIGH) { Serial.println("Lower Reloaded"); CountLower = CAPACITY; } // Serial.println(analogRead(UPPEROVERRIDE)); // Serial.println(analogRead(LOWEROVERRIDE)); if(digitalRead(UPPEROVERRIDE) == LOW) { Serial.println("Upper Disabled"); Barrel = 1; CountUpper = 0; } if(digitalRead(LOWEROVERRIDE) == LOW) { Serial.println("Lower Disabled"); Barrel = 2; CountLower = 0; } //firing control -- Blocking while(digitalRead(Trigger) == LOW) { Serial.println("shooting"); Shooting = true; switch(Barrel){ case 0://fire both barrels { FireBoth(Rounds); } break; case 1://fire upper { FireUpper(Rounds); } break; case 2://fire lower { FireLower(Rounds); } break; default://not a valid firing mode { } break; } } time = millis(); if(Shooting == false) { Serial.println("Not Shooting. Display menu"); if(time > lastDisplay + DISPLAYRATE) { selectCount(); lastDisplay = millis(); } if(lastBlink + BLINKRATE < time) { if(((time/BLINKRATE)%2) == 0) { blinkMenuCursor(); } else { blankMenuCursor(); } } } else { if(time > lastDisplay + DISPLAYRATE) { displayCount(); lastDisplay = millis(); } } switch(Mode){ break; case 3: { if(CountLower == 0) { Mode = 5; } else { Mode = 2; Barrel = 2; } } break; case 4: { if(CountUpper == 0) { Mode = 5; } else { Mode = 1; Barrel = 1; } } break; case 5: { reload(); } break; default: { } //don't need to do nothin } savePrefs(); } void FireBoth(int rounds)//0 makes no sense in this mode, but is valid. { if(rounds == 0) { FireUpper(rounds); Barrel = 1; } else { short ready; while(rounds > 0) { ready = readyToFire(); if(ready) { pullTrigger(ready); rounds--; shotFired(ready); } } } } void shotFired(short barrel) { if(barrel == 1) { CountUpper--; displayCount(); } else { CountLower--; displayCount(); } } short readyToFire()//checks upper first { if(digitalRead(UpperSensor) == HIGH) { return 1; } else if(digitalRead(LowerSensor) == HIGH) { return 2; } else { return 0; } } void pullTrigger(int barrel) {//0 neither, 1 upper, 2 lower if(barrel == 1) { while(digitalRead(UpperSensor) == HIGH) {//check and see if the firing cycle has taken over Serial.println("firing interval"); digitalWrite(RelayUpper, LOW);//turn the relay on delay(FIRING_INTERVAL);//wait a little bit digitalWrite(RelayUpper, HIGH);//turn the relay off } } else if(barrel == 2) { while(digitalRead(LowerSensor) == HIGH) {//check and see if the firing cycle has taken over Serial.println("firing interval"); digitalWrite(RelayLower, LOW);//turn the relay on delay(FIRING_INTERVAL);//wait a little bit digitalWrite(RelayLower, HIGH);//turn the relay off } } } void FireUpper(int rounds) { if(CountUpper != 0) { if(rounds == 0) { while(digitalRead(UpperSensor) == HIGH) {//check and see if the firing cycle has taken over Serial.println("firing interval"); digitalWrite(RelayUpper, LOW);//turn the relay on delay(FIRING_INTERVAL);//wait a little bit digitalWrite(RelayUpper, HIGH);//turn the relay off } while(digitalRead(UpperSensor) == LOW) { //firing in progress }//and finished shotFired(Barrel); if(CountUpper == 0) { Mode = 3; } while(digitalRead(Trigger) == LOW) { //wait because semi-auto means 1 shot per pull } } for(int i = rounds; i> 0; i--) { if(CountUpper == 0) { FireLower(i); i = 0; } while(digitalRead(UpperSensor) == HIGH){//check and see if the firing cycle has taken over Serial.println("firing interval"); digitalWrite(RelayUpper, LOW);//turn the relay on delay(FIRING_INTERVAL);//wait a little bit digitalWrite(RelayUpper, HIGH);//turn the relay off } while(digitalRead(UpperSensor) == LOW) { //firing in progress }//and finished shotFired(Barrel); } } } void FireLower(int rounds) { if(CountLower != 0) { if(rounds == 0) { while(digitalRead(LowerSensor) == HIGH) {//check and see if the firing cycle has taken over Serial.println("firing interval"); digitalWrite(RelayLower, LOW);//turn the relay on delay(FIRING_INTERVAL);//wait a little bit digitalWrite(RelayLower, HIGH);//turn the relay off } while(digitalRead(LowerSensor) == LOW) { //firing in progress }//and finished shotFired(Barrel); if(CountLower == 0) { Mode = 3; } while(digitalRead(Trigger) == LOW) { //wait because semi-auto means 1 shot per pull } } for(int i = rounds; i> 0; i--) { if(CountLower == 0) { FireUpper(i); i = 0; Mode = 3; } else { while(digitalRead(LowerSensor) == HIGH){//check and see if the firing cycle has taken over Serial.println("firing interval"); digitalWrite(RelayLower, LOW);//turn the relay on delay(FIRING_INTERVAL);//wait a little bit digitalWrite(RelayLower, HIGH);//turn the relay off } while(digitalRead(LowerSensor) == LOW) { //firing in progress }//and finished shotFired(Barrel); } } } } void Select_Button() { Serial.println("Select Pressed"); Shooting = !Shooting; Serial.print("Shooting value : "); Serial.println(Shooting); if(Shooting) { displayCount(); } else { lastDisplay = 0; } } void Left_Button() { Serial.println("leftbutton pressed"); if(Shooting) { reload(); } else if(menuBarrel) { Barrel = (Barrel +(BARRELS-1))%BARRELS; lastDisplay = 0; } else { if(Rounds == 0) { Rounds = 1; } else { Rounds--; } lastDisplay = 0; } } void Right_Button() { Serial.println("Right Pressed"); if(Shooting) { reload(); } else if(menuBarrel) { Barrel = (Barrel + 1)%BARRELS; lastDisplay = 0; } else { Rounds++; lastDisplay = 0; } } void Up_Button() { Serial.println("Up Pressed"); if(Shooting) { reload(); } else { menuBarrel = !menuBarrel; lastDisplay = 0; lastBlink = 0; } } void Down_Button() { Serial.println("Down Pressed"); if(Shooting) { reload(); } else { menuBarrel = !menuBarrel; lastDisplay = 0; lastBlink = 0; } } void HandleKeys() { localKey = keypad.getKey(); if (localKey != -1)//TODO confirm that -1 is correct and not 0 { //Serial.println(localKey); //Key Codes (in left-to-right order): //None - 0 //Select - 1 //Left - 2 //Up - 3 //Down - 4 //Right - 5 switch(localKey){ case 1: { Select_Button(); } break; case 2: { Left_Button(); } break; case 3: { Up_Button(); } break; case 4: { Down_Button(); } break; case 5: { Right_Button(); } break; default: //should never happen break; } } } void blinkMenuCursor() { if(menuBarrel) { lcd.setCursor(5,1); lcd.print("::"); } else { lcd.setCursor(5,0); lcd.print("::"); } } void blankMenuCursor() { if(menuBarrel) { lcd.setCursor(5,1); lcd.print(" "); } else { lcd.setCursor(5,0); lcd.print(" "); } } void selectCount(){ // ________________ // BURST: SEMI-AUTO // BURST: FULL-AUTO // BURST: XX ROUNDS // ________________ // FIRE : UPPER // FIRE : LOWER // FIRE : DOUBLE lcd.clear(); lcd.setCursor(0, 1); lcd.print("FIRE "); switch(Barrel) { case 0: lcd.print(" DOUBLE"); break; case 1: lcd.print(" UPPER"); break; case 2: lcd.print(" LOWER"); break; default: lcd.print(" ERROR"); } lcd.setCursor(0,0); lcd.print("BURST "); switch(Rounds) { case 0: lcd.print("SEMI-AUTO"); break; case 1: lcd.print("FULL-AUTO"); break; default: lcd.print(Rounds, DEC); lcd.print(" ROUNDS"); } } void displayCount() { lcd.clear(); render_big_msg(capacityDisplay[CountLower],0,0); render_big_msg(capacityDisplay[CountUpper],8,0); } void reload() { CountUpper = CAPACITY; CountLower = CAPACITY; displayCount(); } void waitTrig( int mseconds) { unsigned long endTime = millis() + mseconds; while(endTime > time) { time = millis(); if(digitalRead(Trigger) == LOW) { endTime = 0; } } } void savePrefs() { char check; check = EEPROM.read(EEPCOUNTUPPER); if(check != CountUpper) { EEPROM.write(EEPCOUNTUPPER, CountUpper); } check = EEPROM.read(EEPCOUNTLOWER); if(check != CountLower) { EEPROM.write(EEPCOUNTLOWER, CountLower); } check = EEPROM.read(EEPBARREL); if(check != Barrel) { EEPROM.write(EEPBARREL, Barrel); } check = EEPROM.read(EEPROUNDS); if(check != Rounds) { EEPROM.write(EEPROUNDS, Rounds); } }