On/Off with Soft-start

Hi, i am new and begginer in programming arduino or etc....
I need program for arduino and early I use this program (arduino) for programming Attiny24.
The program is:
1. Turn the main switch (240V or connect to the voltage) ON, and LED - Red is light !
2. Push the button ON, LED_R is still light, Led_G (green) - light + relay1 is ON for 3 seconds. (R/G LED, when R and G light = orange light) This is a start mode !
3. After 3 sec. relay1 is OFF, LED_R - OFF and LED_G - light (ON) + relay2 is ON. This is a ON mode. Relay2 and LED_G is in ON!
4. Push the same button again and all is OFF, but LED_R is light (ON). This is a stand-by mode.
5. Important!! When I push the button anytime, it must be able to be turned off (when is in start mode or when is in ON mode) !

Of course debounce for button is important !

I am working on the program but it is not working properly. if possible please help me.

Thank you!

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

Please include the entire error message. It is easy to do. There is a button (lower right of the IDE window) called "copy error message". Copy the error and paste into a post in code tags. Paraphrasing the error message leaves out important information.

Post a schematic.
Post an image of your project.

Please describe the problem better then you just did.

Then start at the beginning.

Without the use of the delay() function…

Can you write a program to denounce a pushbutton and count the number of times you press it?

Can you make the count repeat 0, 1, 2, 3 and back to 0?

Can you make an LED display a different colour (R, G, Orange, OFF) based on the value of a variable?

So now the pushbutton can be used to change the LED?

Worry about your real project when the above is something you can do.

Start with the examples in the IDE. When something doesn't;t work, or do what you thought, and you are stuck stuck, post your code here and we can help.

a7

Thank you very much for your answer! Here is my CODE. But is not good because, when I push the button and keep push, is OK. But I need only ON/OFF. When I push the button (TL2) (not keep pressed) only push, the program go in to Start mode (R+G led light and relay1) for 3 sec. And again when I push the same button, the program is going to OFF mode (Red LED and Relay1 and Relay2 + Green LED is OFF).

const int button = 0;    //button on my shield TL2
const int relay1 = 8;    //relay1 this relay on for 3 sec when LED_R + LED_G is light (in shield is YELLOW LED)
const int relay2 = 7;    //relay2 this relay is on when the LED_G is light (in shield is BLUE LED)
const int led_R = 5;     //this LED light when is START mode or OFF mode
const int led_G = 6;     //this LED ligh when is START mode or ON mode

        //record the current button state

enum { Off = LOW, On = HIGH };  // relay on when HIGH
int buttonState;
#define RelayPeriod     3000    // how long to relay1 is ON
unsigned long  msecRelay;
int  relayState = Off;

void setup () {    
  pinMode (button, INPUT_PULLUP);
  pinMode (relay1, OUTPUT);
  pinMode (relay1, OUTPUT);
  pinMode (led_R, OUTPUT);
  pinMode (led_G, OUTPUT);
  digitalWrite (relay1, Off);
  digitalWrite (relay2, Off);
  digitalWrite (led_R, On);
  digitalWrite (led_G, Off);
  buttonState = digitalRead (button);

}


void loop () {
unsigned long msec = millis ();
    // check for button press
    byte but = digitalRead (button);
    if (buttonState != but) {
        buttonState = but;
        delay (25);                         // debounce

        if (LOW == but)  {

            if (On == digitalRead (relay1))  {
                digitalWrite (relay1, Off);
                digitalWrite (relay2, Off);
                relayState = 0;
                digitalWrite (led_G, Off);
                digitalWrite (led_R, On);
            }
            else  {
                digitalWrite (relay1, On);
                digitalWrite (relay2, Off);
                digitalWrite (led_R, On);
                digitalWrite (led_G, On);
                relayState = 1;
                msecRelay = msec;
            }
        }
    }
    if (relayState && (msec - msecRelay) >= RelayPeriod)  {
        // turn off
        digitalWrite (relay1, Off);
        digitalWrite (relay2, On);
        digitalWrite (led_G, On);
        digitalWrite (led_R, Off);
        relayState = 0;
    }
}

PS: i found this code and I editting for me, but is not good. Origina this CODE : Switch a fan on for 5 seconds and then turn off - #4 by gcjr

corrected the code so that relay2 is configured as an OUTPUT

on startup i see

  • red LED ON
    and then after 3 secs
  • red LED off
  • green LED on
  • relay2 on

after pressing the button is see -- Case 1

  • green and red LEDs ON
  • relay1 is ON
    after 3 secs is see
  • red LED off
  • relay1 off
  • relay2 on

if the button is pressed again before 3 sec, i see

  • only the red LED ON

pressing the button again while the red LED is ON, i see the Case 1 above

Thank you for relay2. Now is function like ON/OFF but it not so good.

  1. LED_R is light! and lights up until I press it the button - it is OK.
  2. Press the button - now is start mode (LED_R + LED_G light ON and relay1 is ON) - it is OK !
  3. After 3sec. is ON mode (LED_G light on + relay2 is ON) - it is OK!
  4. Press the button again - restarting the code? - it is not OK, because when i press the button the program must go in to OFF mode ! (LED_R is light ON and other is OFF) - thats all i need.

did you try pressing the button again before the 3sec timeout?

Yeah, it doesn't do that. To turn off the system you must cancel during a soft start.

You need to think about three states. ON, the thing is on, OFF, the the thing is off and STARTING, the thing is in the three second soft start phase.

Then in each state, a button will mean different things.

ON - button turns it off
OFF - button moves it to STARTING
STARTING - button turns it off, elapse of 3 seconds moves us to ON

No code is "your" code until you figure out how it does what it is doing, and why it doesn't do exactly what you want. Mostly this comes from having written the code. Code given to you or stolen borrowed must be studied and understood at the level you can. Before you can confidently tinker with it.

Once you have an understanding of the code, modifying it to turn OFF rather than just do another soft start should be simple.

Or @gcjr will understand the shortcoming and just fix it.

Play with it here in the wokwi simulator.

a7

Thank you, i understood what you want tell me, but i am not good programmer. And a think, this is my maximum from me heh...
I try press the button before 3 sec timout and this is good, the Code go in to OFF mode. But after 3 sec is not good, the code is still restarting. And A7, thank you very much for the simulation but fix in simulation code (relay2 to a OUTPUT).

This is my last CODE update. It's almost good as you can see. But when I first time press the button, nothing happens - because first is "turn off". And when i press the button second time, the program run OK. And last bug, when I press he button twice and hold the button pressed, he program jump from OFF mode to ON mode in 3 seconds - and this is not OK.

const int button = 0;    //button on my shield TL2
const int relay1 = 8;    //relay1 this relay on for 3 sec when LED_R + LED_G is light (in shield is YELLOW LED)
const int relay2 = 7;    //relay2 this relay is on when the LED_G is light (in shield is BLUE LED)
const int led_R = 5;     //this LED light when is START mode or OFF mode
const int led_G = 6;     //this LED ligh when is START mode or ON mode

        //record the current button state

enum { Off = LOW, On = HIGH };  // relay on when HIGH
int buttonState;
#define RelayPeriod     3000    // how long to relay1 is ON
unsigned long  msecRelay;
int  relayState = Off;

void setup () {    
  pinMode (button, INPUT_PULLUP);
  pinMode (relay1, OUTPUT);
  pinMode (relay2, OUTPUT);
  pinMode (led_R, OUTPUT);
  pinMode (led_G, OUTPUT);
  digitalWrite (relay1, Off);
  digitalWrite (relay2, Off);
  digitalWrite (led_R, On);
  digitalWrite (led_G, Off);
  buttonState = digitalRead (button);
  Serial.begin(9600);

}

bool buton = false;

void loop () {
unsigned long msec = millis ();
    // check for button press
    delay (50);
    byte but = digitalRead (button);
    if (buttonState != but) {
        buttonState = but;
        delay (25);                         // debounce

        if (LOW == but)  {

           if(buton){
              buton = false;

            if (On == digitalRead (relay1))  {
                digitalWrite (relay1, Off);
                digitalWrite (relay2, Off);
                relayState = 0;
                digitalWrite (led_G, Off);
                digitalWrite (led_R, On);
            }
            else  {
                digitalWrite (relay1, On);
                digitalWrite (relay2, Off);
                digitalWrite (led_R, On);
                digitalWrite (led_G, On);
                relayState = 1;
                msecRelay = msec;
            }
        } else{
              buton = true;
              Serial.println("turn off");
              digitalWrite (relay1, Off);
              digitalWrite (relay2, Off);
              digitalWrite (led_G, Off);
              digitalWrite (led_R, On);
            }
    }  }
    if (relayState && (msec - msecRelay) >= RelayPeriod)  {
        // turn off
        digitalWrite (relay1, Off);
        digitalWrite (relay2, On);
        digitalWrite (led_G, On);
        digitalWrite (led_R, Off);
        relayState = 0;
    }
}

try to change starting state of the buton variable to true

since you initialize "buton" to false, implying that it indicates on/off, shouldn't you reverse the logic for "buton" being true and false?

the code only recognizes button presses, not the button being pressed. the timer can expire and be processed while the button is being pressed.

what do you want it to do?

Yeah, that typo was in the original, never noticed as I didn't really know what the thing was supposed to do in the first place.

This IPO model of

soft start sequencing

was hastily scribbled on top of a proposed solution already running in the wokwi and ultimately overwrote most of it. It demonstrates in a verbose verging on prolix manner a solution based on the IPO model. There are opportunities for making it smaller, there are probably ways it could be clearer, but it uses no tricks beyond "blink without delay".


const int button = 8;    //button on my shield TL2
const int relay1 = 7;    //relay1 this relay on for 3 sec when LED_R + LED_G is light (in shield is YELLOW LED)
const int relay2 = 6;    //relay2 this relay is on when the LED_G is light (in shield is BLUE LED)
const int led_R = 5;     //this LED light when is START mode or OFF mode
const int led_G = 4;     //this LED ligh when is START mode or ON mode

enum { Off = LOW, On = HIGH };  // relay on when HIGH
int buttonState;
# define RelayPeriod     3000    // how long to relay1 is ON

unsigned char state;
# define OFF        0
# define STARTING   1
# define RUNING     2

void setup () {
    Serial.begin(115200);
    Serial.println("soft  start  world!\n");

  pinMode (button, INPUT_PULLUP);

  pinMode (relay1, OUTPUT);
  pinMode (relay2, OUTPUT);
  pinMode (led_R, OUTPUT);
  pinMode (led_G, OUTPUT);

  digitalWrite (relay1, Off);
  digitalWrite (relay2, Off);
  digitalWrite (led_R, On);
  digitalWrite (led_G, Off);
  buttonState = digitalRead (button);

  state = OFF;      // the machine is off.
}

void loop () {
    unsigned char timesUp;
    unsigned char buttonEvent;
    unsigned long now = millis();
    unsigned char buttonIs = digitalRead (button);  //  LOW = pressed here

// INPUT (and timer(s))

    buttonEvent = 0;    // innocent until proven guilty
    timesUp = 0;        // auch - und es verwenden oder verlieren

    static unsigned long lastButtonTime;
    if (now - lastButtonTime > 20) {
        if (buttonState != buttonIs) {
            buttonState = buttonIs;

            if (buttonIs == LOW) buttonEvent = 1;
            lastButtonTime = now;
        }
    }

    static unsigned long startStartTime;
    if (now - startStartTime > RelayPeriod) timesUp = 1;

// PROCESS

    switch (state) {
    case OFF :
        if (buttonEvent) {
            startStartTime = now;
            state = STARTING;
        }
        break;
    
    case STARTING :
        if (timesUp) state = RUNING;
        if (buttonEvent)
            state = OFF;

        break;
    
    case RUNING :
        if (buttonEvent)
            state = OFF;
 
        break;
    }

// OUTPUT

    switch (state) {
    case OFF :
        digitalWrite (relay1, Off);
        digitalWrite (relay2, Off);
        digitalWrite (led_G, Off);
        digitalWrite (led_R, On);
//        digitalWrite (led_G, Off); make it wink:

        digitalWrite(led_G, (millis() & 0x3ff) > 960 ? On : Off);

        break;
    
    case STARTING :
        digitalWrite (relay1, On);
        digitalWrite (relay2, Off);
        digitalWrite (led_R, millis() & 0x100 ? On : Off);
        digitalWrite (led_G, On);

        break;
    
    case RUNING :
        digitalWrite (relay1, Off);
        digitalWrite (relay2, On);
//        digitalWrite (led_R, On);
        digitalWrite (led_G, On);

        break;
    }
}

The structure makes it easy to see where things happen and where you would go to fix, modify or enhance the functions.

HTH

a7

This is perfect ! I Love you alto777 you are Master ! Thank you very much !!!
I edit little bit a your CODE for AtTiny45. I try the CODE on the breadboard and it works perfectly !
This is my edit:

const int button = 2;    //button  atTiny45 - PIN 7
const int relay1 = 4;    //relay1 this relay on for 3 sec when LED_R + LED_G is light!  atTiny45 - PIN 2
const int relay2 = 3;    //relay2 this relay is on when the LED_G is light!   atTiny45 - PIN 3
const int led_R = 0;     //this LED light when is START mode or OFF mode!  atTiny45 - PWM PIN 5
const int led_G = 1;     //this LED ligh when is START mode or ON mode!  atTiny45 - PIN 6

enum { Off = LOW, On = HIGH };  // relay on when HIGH
int buttonState;
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

# define RelayPeriod     3000    // how long to relay1 is ON

unsigned char state;
# define OFF        0
# define STARTING   1
# define RUNING     2

void setup () {
  pinMode (button, INPUT_PULLUP);

  pinMode (relay1, OUTPUT);
  pinMode (relay2, OUTPUT);
  pinMode (led_R, OUTPUT);
  pinMode (led_G, OUTPUT);

  digitalWrite (relay1, Off);
  digitalWrite (relay2, Off);
  digitalWrite (led_R, On);
  digitalWrite (led_G, Off);
  buttonState = digitalRead (button);

  state = OFF;      // the machine is off.
}

void loop () {
    unsigned char timesUp;
    unsigned char buttonEvent;
    unsigned long now = millis();
    unsigned char buttonIs = digitalRead (button);  //  LOW = pressed here

// INPUT (and timer(s))

    buttonEvent = 0;    // innocent until proven guilty
    timesUp = 0;        // auch - und es verwenden oder verlieren

    static unsigned long lastButtonTime;
    if (now - lastButtonTime > 30) {
        if (buttonState != buttonIs) {
            buttonState = buttonIs;

            if (buttonIs == LOW) buttonEvent = 1;
            lastButtonTime = now;
        }
    }

    static unsigned long startStartTime;
    if (now - startStartTime > RelayPeriod) timesUp = 1;

// PROCESS

    switch (state) {
    case OFF :
        if (buttonEvent) {
            startStartTime = now;
            state = STARTING;
        }
        break;
    
    case STARTING :
        if (timesUp) state = RUNING;
        if (buttonEvent)
            state = OFF;

        break;
    
    case RUNING :
        if (buttonEvent)
            state = OFF;
 
        break;
    }

// OUTPUT

    switch (state) {
    case OFF :
        digitalWrite (relay1, Off);
        digitalWrite (relay2, Off);
        digitalWrite (led_G, Off);
         //digitalWrite (led_R, On);                  // - when is only light ON !
         analogWrite (led_R, brightness);             //fade the LED if is MODE OFF
         brightness = brightness + fadeAmount;        //fade Red LED
        if (brightness <= 0 || brightness >= 255) {   //fade Red LED
    fadeAmount = -fadeAmount;           
 }     delay(50);
        //digitalWrite (led_G, Off);
        // digitalWrite(led_G, (millis() & 0x3ff) > 960 ? On : Off);      // make it blink

        break;
    
    case STARTING :
        digitalWrite (relay1, On);
        digitalWrite (relay2, Off);
        digitalWrite (led_R, millis() & 0x100 ? Off : On);
        digitalWrite (led_G, millis() & 0x100 ? On : Off);

        break;
    
    case RUNING :
        digitalWrite (relay1, Off);
        digitalWrite (relay2, On);
        digitalWrite (led_R, Off);
        digitalWrite (led_G, On);

        break;
    }
}

Thank you !

Not quite yet!

I don't argue with success, but I do obsess over use of delay(). It is entirely plausible where you used it, and unlikely to do anything but offend (me).

And it is unnecessary. Don't derail yourself, but when you have time, take a look at doing the fading in a non-blocking manner.

Try this code, this is just the OFF case

    case OFF :
        digitalWrite (relay1, Off);
        digitalWrite (relay2, Off);
        digitalWrite (led_G, Off);

/* delay style
         analogWrite (led_R, brightness);             //fade the LED if is MODE OFF
         brightness = brightness + fadeAmount;        //fade Red LED
        if (brightness <= 0 || brightness >= 255) {   //fade Red LED
    fadeAmount = -fadeAmount;           
 }     delay(50);
*/

// millis non-blocking pattern:
# define FADE_RATE  50
        static unsigned long lastFadeStep;

        if (now - lastFadeStep > FADE_RATE) {
          lastFadeStep = now;
          analogWrite (led_R, brightness);             //fade the LED if is MODE OFF
          brightness = brightness + fadeAmount;        //fade Red LED
          if (brightness <= 0 || brightness >= 255) {   //fade Red LED
            fadeAmount = -fadeAmount;               
          }
        }

        break;

The main difference is to allow your loop to run free, probably 1000s of times a second, instead of inadvertently crippling it with delay(), meaning it will only run at 20 times per second.

The non-blocking pattern just does a fade strep every time it sees that FADE_RATE milliseconds has elapsed without a step.

As I said, unimportant in this case, but you have a future in which there may come a good reason to not block - you don't want to ever use delay() as you have plenty of stuff to do all the time.

Enjoy coding and using the IPO model. Keep an eye out for blocking code! Never a need to block, always fun (!) to code around easy solutions that do. Block. @paulpaulson, a final tip of the hat!

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.