How to program buttons to set a variable which will change how often a counter will run for activating a realy

Hi all, brand new user here.
The idea behind my project is to active a relay every time a counter increments.
Im using the sevseg.h counter example and trying to modify that to suit my needs.
I have 4 buttons which will change the amount that the program will count up to and then stop. eg 10, 50, 100 and the last will use eg 100 and run till i power off or press another button. (buttons are assigned to pins but thats all so far)

My code so far is stuck at trying to get a LED to flash ( imitation relay) with each change of the counter( seconds counting up).

My next problem is trying to get another function (void) to use the buttons .

thanks in advance.

#include <SevSeg.h>// note am using the wokwi simulator site to run the code.
SevSeg sevseg; //Instantiate a seven segment controller object

//button designations
const int Start100 = A0; //set Seconds for 100
const int Start50 = A1; //set Seconds for 50
const int Start10 = A2; //set Seconds for 10
const int Runinfinty =A3; //to run main loop with out stopping count to 100 then start again as per orgininal program before i destroyed it.

//state of change not sure if i need these to check for which button is checked
int State100 =0;
int ChngeState100 =0;
int State50 = 0;
int ChngeState50 =0;
int State10 =0;
int changeState10 =0;

//relay on pin 13 to activate for 500 milli after every second/count
const int RelayAction = 13;// using an LED to simulate the relay
int Seconds=0;
int lastSeconds=0;

void setup() {
  byte numDigits = 4;
  byte digitPins[] = {2, 3, 4, 5};
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12};
  bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
  byte hardwareConfig = COMMON_CATHODE; // See README.md for options
  bool updateWithDelays = false; // Default. Recommended
  bool leadingZeros = true; // Use 'true' if you'd like to keep the leading zeros
 
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros);
  sevseg.setBrightness(90);

pinMode(Start100, INPUT_PULLUP);
pinMode(Start50, INPUT_PULLUP);
pinMode(Start10, INPUT_PULLUP);
pinMode(RelayAction, OUTPUT);
  
}

void loop() {// unsure how to add in the button functions, or the raly activation function.

  static unsigned long timer = millis();
  static int Seconds = 0;
 
  if (millis() - timer >= 2000) {// will be changed to 10000
    timer += 2000;
    Seconds++; // 1000 milliSeconds is equal to 1 Second
   if (Seconds != lastSeconds) {//to activate the relay after every increment
  digitalWrite;(RelayAction, HIGH);
  delay(500);
  digitalWrite(RelayAction, LOW);// doesnt work not sure why

   }
    if (Seconds == 11) { // Reset to 0 after counting for required count, value will be changed by button input
      Seconds=0;
    }
    sevseg.setNumber(Seconds, 1);
  }

  sevseg.refreshDisplay(); // will need to change depending on button press
 

}

It would help a lot if you post a link to the wokwi project.

You have an extra ";" here.

Amazingly chatGpt understood that run on sentence better than I did and produced usable code

// Define pin numbers
const int buttonPin = 2;  // Pin connected to the button
const int relayPin = 13;  // Pin connected to the relay

// Define variables
int buttonState = 0;      // Variable for storing the state of the button
int interval = 1000;      // Default interval for counter (in milliseconds)
unsigned long previousMillis = 0;  // Variable to store the last time the counter was updated

void setup() {
  // Initialize the button and relay pins
  pinMode(buttonPin, INPUT);
  pinMode(relayPin, OUTPUT);
}

void loop() {
  // Read the state of the button
  buttonState = digitalRead(buttonPin);

  // If the button is pressed, change the interval
  if (buttonState == HIGH) {
    interval = 500; // Change interval if button is pressed
  } else {
    interval = 1000; // Default interval if button is not pressed
  }

  // Check if it's time to activate the relay
  unsigned long currentMillis = millis();  // Get the current time
  if (currentMillis - previousMillis >= interval) {
    // Save the last time the counter was updated
    previousMillis = currentMillis;

    // Toggle the relay
    digitalWrite(relayPin, !digitalRead(relayPin));
  }
}

Although I would have defined th button as INPUT_PULLUP. I'm still amazed that it's that good and getting better.

Is this sarcasm? That chatGPT usable code doesn't seem to resemble in the least the goals of the OP.

Which are not exactly made clear, but it did seem to want more than using a pushbutton to switch between two blink rates.

a7

It accomplishes exactly what's in the headline, which was all I typed in. And from that it produced useable code, which surprised me.

If your buttons are the 4 pin type like shown in your wokwi diagram, you should get into the habit of using 2 diagonal corners for connections. One corner to ground, the other to your arduino pin. That way, in the physical world, you can install the button rotated 90 degrees and it will still work correctly. If you do it the way you show, accidentally installing a physical button rotated will not work.

As for working with your buttons, look at the state change detection example in the IDE (File->examples->02.digital->State Change Detection) to learn how to detect when a button gets pressed. Note that using the pins as INPUT_PULLUP reverses the logic. No press will read HIGH and a button press will read LOW.

When you do detect a button press, the code needs to set a variable (maybe something like TopCount) to the value associated with that button. Then, you just need to check if Seconds is at TopCount and then stop. If it is not, continue.

Thanks all for the replies, and your patience.
the link is fcd with sevseg libry - Wokwi ESP32, STM32, Arduino Simulator
for those who want to see how badly ive done lol.

So to clarify the project.

The sevseg.h runs a counter in which you can change the value to count up to, and also the wait time between counts which will be changed to about 10 seconds.
I want the buttons to change this amount, eg Start10 = count up to 10 then wait for the next instruction, Runinfinity= count up to 100 and repeat until further instructions.

The next bit is after each increment of the count close and open a relay, this is where im up to and will look at the buttons later.

My code , because of the delay is causing the display to either go blank or show random segments when the relay is in operation.

Ive tried to add a milli wait command but get " sketch.ino:52:14: error: too many arguments to function 'long unsigned int millis()'
millis (500);"
as an error. I need to work out how to use this properly.

Reading the documentation is always advised.

Refreshing the display

sevseg.refreshDisplay();

Your program must run the refreshDisplay() function repeatedly to display the number. Warning: Any calls to delay() will interfere with the display. Any delays introduced by other functions will produce undesirable effects on the display. If you need help getting away from delay() statements, I recommend the simple Blink Without Delay arduino example sketch.

So basically the question is "how to do a non-blocking delay?" Although the underlying question is really "how do I write multi tasking code?".

There are so many responses to those questions, I don't feel like writing another.

And there's already one in post #4 courtesy of ChatGPT :slight_smile:

is this sorta, kinda what you're trying to do

flash LED every time the count is incremented, use buttons to determine the max count and increment interval.

the LED can only be turned on for less than the increment interval otherwise it never turns off

const byte PinButs [] = { A0, A1, A2 };
const byte PinRelay   = A3;

enum { Off = LOW, On = HIGH };

const int Nbut = sizeof(PinButs);

// -------------------------------------
struct Cfg {
    int             MaxCnt;
    unsigned long   MsecPeriod;
};

Cfg cfg [Nbut] = {
    { 100,  200 },
    {  50,  350 },
    {  10,  700 },
};
int cfgIdx;

int cnt;
unsigned long msec0;
unsigned long msec1;

// -----------------------------------------------------------------------------
void loop ()
{
    unsigned long msec = millis ();

    // update count
    if (msec - msec0 >= cfg [cfgIdx].MsecPeriod)  {
        msec0 = msec;

        digitalWrite (PinRelay, On);
        msec1 = msec;

        if (cfg [cfgIdx].MaxCnt <= ++cnt) {
            Serial.println (cnt);
            cnt = 0;
        }
    }

    // check if time to turn relay off
    if (On == digitalRead (PinRelay) && msec - msec1 >= 100)
        digitalWrite (PinRelay, Off);

    // check for button presses
    for (int n = 0; n < Nbut; n++)
        if (LOW == digitalRead (PinButs [n]))
            cfgIdx = n;
}

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

    for (int n = 0; n < Nbut; n++)
        pinMode (PinButs [n], INPUT_PULLUP);

    pinMode      (PinRelay, OUTPUT);
    digitalWrite (PinRelay, Off);
}

Thanks all for your replies and ideas, half my issue is not knowing the correct syntac for the coding so some more reading for me., ill chip away at it slowly and put up some more code in abit.

knowing the language doesn't teach you how to use the language, just as much as knowing how to a mechanics tools teaches you how to fix, much less design a car.

there are lots of computer science classes that teach things common to all programming languages, such as linked lists, tree, finite state machines, parsing,