Need help on a "sequence" code

Hi,
I asked a similar question a few days back, but now i could finally start code a few lines.

I want to create the electronics for a ghostbusters proton pack. I want that if a specific switch is turned on a specific i call it boot sequence gets startet.

in my code i create an enum which constist of different bootphases.

if the switch is turned on the first phase starts, after the first phase has finished the enum gets increased. then the next phase starts and so on.

the first question is, how can i reset these functions, so that if i turn the switch off and turn it back on the whole sequence starts again?

the second question is why does my code behave in this way:

  • enum is set to bootPhase0,
  • after exiting the first function it is set to bootPhase1
  • after exiting the second function it is set to bootPhase2
  • and the reset to bootPhase1 and stays at bootPhase1?? it should stay at bootPhase2 so that i can go on with the third function.

these are the functions i am using:


enum BootSequence {
  bootPhase0,
  bootPhase1,
  bootPhase2,
  bootPhase3,
};

BootSequence WandStartSequence = bootPhase0;
bool bootBlinkK = false;


void PROGRAM_BOOT_BLINK_L() {
  static bool n_on = true;
  static int timer1 = 3;

  if (bootBlink.isCycleElapsed()) {
    if (timer1 > 0) {
      if (n_on) {
        playerSoftware0.playSpecified(1);
        DM13ALeds.setSegmentDefined(l_Segment);
      } else {
        DM13ALeds.clearSegment(l_Segment);
        timer1--;
      }
      DM13ALeds.outputRefresh_direct();
      n_on = !n_on;
    }

    if (timer1 == 0) {
      bootBlinkK = true;
      WandStartSequence = bootPhase1;
    }
  }
}

void PROGRAMM_BOOT_KL() {
  static int timer = 2;
  if (bootBlinkKL.isCycleElapsed()) {


    switch (timer) {
      case 2:
        DM13ALeds.setSegmentDefined(k_Segment);
        DM13ALeds.outputRefresh_direct();
        break;

      case 1:
        DM13ALeds.setSegmentDefined(n_Segment);
        DM13ALeds.outputRefresh_direct();
        WandStartSequence = bootPhase2;
        break;

      default:
        return;  // Do nothing if timer is not 1 or 2
    }

    if (timer > 0) {
      timer--;
    }
  }
}






void bootsequence() {
  if (Switch.toggled() && Switch.read()) {
    if (WandStartSequence == bootPhase0) PROGRAM_BOOT_BLINK_L();
    if (WandStartSequence == bootPhase1) PROGRAMM_BOOT_KL();
    [...]
  }
}

this is how the loop should look like:

loop() {
  bootsequence();
}

if you want i could also provide the complete code which is work in progress and has a lot of stuff that needs to be deleted.

Please post your full sketch so that the code snippet that you posted can be seen in context

first, an enum is not a variable, it's a way of defining constants with specific or sequential values and of a specific type that can be type checked when assigning their values to variables

turning the "switch" on can enable a sequencer that can run a sequence of sub-functions such that as each completes, the next in the sequence is executed. The sequence can be track by incrementing a sequence variable that has the values of the enum which identifies the sub-function to execute.

the sequence can be reset when the "switch" is turned off by reseting the sequence variables to the first enum. When the switch is turned on again, the sequence will be restarted


const byte PinSw = A2;

int seq1 () { Serial.println (" seq1"); delay (1000); return 1; }
int seq2 () { Serial.println (" seq2"); delay (1000); return 2; }
int seq3 () { Serial.println (" seq3"); delay (1000); return 3; }
int seq4 () { Serial.println (" seq4"); delay (1000); return 4; }


enum { Seq1, Seq2, Seq3, Seq4 };
int sequence = Seq1;

void
loop (void)
{
    if (LOW == digitalRead (PinSw)) {
        switch (sequence) {
        case Seq1:
            if (seq1 ())
                sequence++;
            break;

        case Seq2:
            if (seq2 ())
                sequence++;
            break;

        case Seq3:
            if (seq3 ())
                sequence++;
            break;

        case Seq4:
            if (seq4 ())
                sequence++;
            break;

        default:
            break;
        }
    }
    else
        sequence = Seq1;
}

void
setup (void)
{
    Serial.begin (9600);

    pinMode (PinSw, INPUT_PULLUP);
}

this is my complete code:

#include "Button.h"

//Function Execution Timer
#include "NextExcecutionTime.h"

//DM13A classes
#include "DM13A_LedSegment.h"
#include "DM13A.h"

//Speaker
#include <Arduino.h>
#include <SoftwareSerial.h>
#include "DYPlayerArduino.h"


//FastLED
#include <FastLED.h>


//Poti test
#define Poti_Pin A6
#define NUM_LEDS_VENT 28
#define LED_PIN A0
int Poti_val = 0;
int Poti_adjusted = 0;


//Buttons
Button SW_WandTip(10);
Button SW_StartUp1(8);
Button SW_StartUp2(7);
Button SW_Intensify(4);
Button SW_BarGraph(3);
Button SW_Vent(2);



//DM13A
constexpr byte LATCH_PIN = 12;  // ST_CP    // LAT   -> for LED-Shiftregisters
constexpr byte CLOCK_PIN = 11;  // SH_CP    // SCLK  -> for LED-Shiftregisters
constexpr byte DATA_PIN = 6;    // DS       // SIN   -> for LED-Shiftregisters
constexpr byte CHAINED_CHIPS = 2;
DM13A DM13ALeds(LATCH_PIN, CLOCK_PIN, DATA_PIN, (2 * CHAINED_CHIPS));

//NextExcecutionTime
NextExcecutionTime barGraphIdel(90);


//Speaker 0
#define rxPin0 A4
#define txPin0 A5

SoftwareSerial mySerial0 = SoftwareSerial(rxPin0, txPin0);
DY::Player playerSoftware0(&mySerial0);




//Cyclotron LEDs
#define NUM_LEDS_CYCLOTRON 28
#define CYCLOTRON_LED_PIN A1
CRGB cyclotron_leds[NUM_LEDS_CYCLOTRON];



constexpr byte BarG_LED[][2] = { { 2, 6 }, { 2, 5 }, { 2, 4 }, { 2, 3 }, { 2, 2 }, { 2, 1 }, { 3, 7 }, { 3, 6 }, { 3, 5 }, { 3, 4 }, { 3, 3 }, { 3, 2 } };
const DM13A_LedSegment BarGraph_Segment(BarG_LED);

constexpr byte n_Led[][2] = { 2, 7 };
const DM13A_LedSegment n_Segment(n_Led);

constexpr byte k_Led[][2] = { 3, 1 };
const DM13A_LedSegment k_Segment(k_Led);

constexpr byte l_Led[][2] = { 3, 0 };
const DM13A_LedSegment l_Segment(l_Led);


const byte SlowBlow_Led[][2] = { 2, 0 };



const int L_SlowBlow = 5;


const int brightnessMax = 180;  // % brightness = x%+254/100
const int interval = 3500;      // 5 seconds

void SlowBlowLed_Boot() {
  for (int i = 0; i <= brightnessMax; i++) {
    int pwmValue = pow(2, i / 32.0) - 1;  // Logarithmic scale
    analogWrite(L_SlowBlow, pwmValue);
    delay(interval / brightnessMax);
  }
}





void setup() {

  //Slow Blow PMW
  pinMode(L_SlowBlow, OUTPUT);


  // Buttons
  SW_WandTip.begin();
  SW_StartUp1.begin();
  SW_StartUp2.begin();
  SW_Intensify.begin();
  SW_BarGraph.begin();
  SW_Vent.begin();

  //DM13A
  DM13ALeds.begin();
  DM13ALeds.clearSegment(n_Segment);
  DM13ALeds.clearSegment(k_Segment);
  DM13ALeds.clearSegment(l_Segment);
  DM13ALeds.clearSegment(BarGraph_Segment);



  //Software|Hardware Serial Stuff
  playerSoftware0.begin();
  //playerSoftware0.playSpecified(6);

  //Print stuff
  Serial.begin(9600);
}


void PROGRAM_LED_IDEL(DM13A_LedSegment LedSegment, bool reset = false) {
  static int currentPosition = 0;
  if (reset) currentPosition = 0;

  else {
    if (barGraphIdel.isCycleElapsed()) {
      DM13ALeds.setOneBit(LedSegment, currentPosition);
      DM13ALeds.outputRefresh_direct();
      currentPosition++;

      if (currentPosition > LedSegment.ledCount) {
        DM13ALeds.clearSegment(LedSegment);
        DM13ALeds.outputRefresh_direct();
        currentPosition = 0;
      }
    }
  }
}

void PROGRAM_LED_OFF(DM13A_LedSegment turnSegmentOff) {
  DM13ALeds.clearSegment(turnSegmentOff);
  DM13ALeds.outputRefresh_direct();
}



enum BootSequence {
  bootPhase0,
  bootPhase1,
  bootPhase2,
  bootPhase3,
};

BootSequence WandStartSequence = bootPhase0;

bool bootBlinkK = false;



void loop() {
  /*
  Poti_val = analogRead(Poti_Pin);
  Poti_adjusted = constrain(Poti_val, 15, 1005);
  Poti_adjusted = map(Poti_adjusted, 14, 1005, 0, 254);
*/
  Serial.println(WandStartSequence);


  if (SW_BarGraph.read()) PROGRAM_LED_IDEL(BarGraph_Segment);
  if (!SW_BarGraph.read() && SW_BarGraph.toggled()) {
    PROGRAM_LED_IDEL(BarGraph_Segment, true);
    PROGRAM_LED_OFF(BarGraph_Segment);
  }


  if (SW_Vent.read()) {
    if (WandStartSequence == bootPhase0) PROGRAM_BOOT_BLINK_L();
    if (WandStartSequence == bootPhase1) PROGRAMM_BOOT_KL();
  }

  if (!SW_Vent.read()) {
    PROGRAM_BOOT_BLINK_L();
    WandStartSequence = bootPhase0;
  }


  /*
  PROGRAM_BOOT_BLINK_L();
  if (bootBlinkK) PROGRAMM_BOOT_KL();
*/
}

and here are the functions in a separate file:


//need to find a way to reset this function


NextExcecutionTime bootBlink(1500);



void PROGRAM_BOOT_BLINK_L() {
  static bool n_on = true;
  static int timer1 = 3;



  if (bootBlink.isCycleElapsed()) {
    if (timer1 > 0) {
      if (n_on) {
        playerSoftware0.playSpecified(1);
        DM13ALeds.setSegmentDefined(l_Segment);
      } else {
        DM13ALeds.clearSegment(l_Segment);
        timer1--;
      }
      DM13ALeds.outputRefresh_direct();
      n_on = !n_on;
    }

    if (timer1 == 0) {
      bootBlinkK = true;
      WandStartSequence = bootPhase1;
    }
  }
}

NextExcecutionTime bootBlinkKL(2000);
void PROGRAMM_BOOT_KL() {
  static int timer = 2;
  if (bootBlinkKL.isCycleElapsed()) {


    switch (timer) {
      case 2:
        DM13ALeds.setSegmentDefined(k_Segment);
        DM13ALeds.outputRefresh_direct();
        break;

      case 1:
        DM13ALeds.setSegmentDefined(n_Segment);
        DM13ALeds.outputRefresh_direct();
        WandStartSequence = bootPhase2;
        break;

      default:
        return;  // Do nothing if timer is not 1 or 2
    }

    if (timer > 0) {
      timer--;
    }
  }
}