Lantern with SOS LED

Lost in a loop...
The project is a lantern with 9 bright LED's. It is possible to change the power in 3 steps and also choose an SOS-signal alternative. But, when changing to strobe_sos the programme works but it is stuck in a loop and I cannot go back and choose lantern ligt. What is wrong in the code?

int buttonPin = 2;
int lightPin = 3;
static int value = 0;			//Create a changing number
void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(lightPin, OUTPUT);		//Create the pinModes
}
void full_light() {
  digitalWrite(lightPin, HIGH);
  delay(50);
}
void half_light() {
  analogWrite(lightPin, 127);		//Use PWM for brightness level
  delay(50);
}
void fourth_light() {
  analogWrite(lightPin, 64);
  delay(50);
}
void strobe_sos() {
  //  loop() {
  digitalWrite(lightPin, HIGH);
  delay(100);
  digitalWrite(lightPin, LOW);
  delay(200);
  digitalWrite(lightPin, HIGH);
  delay(100);
  digitalWrite(lightPin, LOW);
  delay(200);
  digitalWrite(lightPin, HIGH);
  delay(100);
  digitalWrite(lightPin, LOW);
  delay(400);
  digitalWrite(lightPin, HIGH);
  delay(500);
  digitalWrite(lightPin, LOW);
  delay(200);
  digitalWrite(lightPin, HIGH);
  delay(500);
  digitalWrite(lightPin, LOW);
  delay(200);
  digitalWrite(lightPin, HIGH);
  delay(500);
  digitalWrite(lightPin, LOW);
  delay(400);
  digitalWrite(lightPin, HIGH);
  delay(100);
  digitalWrite(lightPin, LOW);
  delay(200);
  digitalWrite(lightPin, HIGH);
  delay(100);
  digitalWrite(lightPin, LOW);
  delay(200);
  digitalWrite(lightPin, HIGH);
  delay(100);
  digitalWrite(lightPin, LOW);
  delay(2000);
}
void loop() {
  int button_check = digitalRead(buttonPin);
  if (button_check == 1) {			//Check if the button was pressed
    value = value + 1;
    delay(220);
    if (value > 4) {
      value = 0;
      delay(70);
    }
  }
  else {					//Keep the LEDs off if the button was not pressed
    digitalWrite(lightPin, LOW);
  }
  if (value == 1) {			//Output the mode according to the button
    full_light();
  }
  if (value == 2) {
    half_light();
  }
  if (value == 3) {
    fourth_light();
  }
  if (value == 4) {
    strobe_sos();
  }
}

Please edit your post and put the code inside code tags.

Actually, the indentation makes it so unreadable that I suggest autoformatting it in the IDE with ctrl-T and re-posting it in code tags... like this:

void loop() {
  int button_check = digitalRead(buttonPin);
  if (button_check == 1) { //Check if the button was pressed
    value = value + 1;
    delay(220);
    if (value > 4) {
      value = 0;
      delay(70);
    }
  }
  else { //Keep the LEDs off if the button was not pressed
    digitalWrite(lightPin, LOW);
  }
  if (value == 1) { //Output the mode according to the button
    full_light();
  }
  if (value == 2) {
    half_light();
  }
  if (value == 3) {
    fourth_light();
  }
  if (value == 4) {
    strobe_sos();
  }
}

Did it cross your mind that while the sketch is performing a series of delays, it can't respond to any button?

@OP: code tags are accessed using the "</>" button. Block quotes are not useful for code.

Over 4 seconds of delay(), but barely a microsecond spent reading the button. See this tutorial on how to overcome that obstacle: Blink without delay() explained line-by-line

Thanks. I will read "Blink without..." but as you understand I am a newbie and trying to learn. Would really appreciate if anyone has som practical changes in the code so I can learn and get it working.

But that is the point. It is not possible to make a small change to the sketch and make it do what you want.

When using "Blink Without Delay" you have to rewrite the sketch. If we give a sketch, then you would not learn from it. If you understand the "Blink Without Delay" then we can help you to make it work.

A fantastic and highly recommended place to start is with the tutorials! There are many examples of common tasks and simple applications built right into the Arduino IDE, too.

Take charge of your own education.

See this post, browse the thread:

It’s a clever hack, some woukd call it cheating. But it works well. Take a look and see if it makes sense to you.

a7

Off the topic a bit, but fyi in Morse code, SOS is what's known as a prosign, which is not actually the letters S, O, S but one symbol ...---... in one stream with no gaps between the letters. So you don't need the longer delay(400)s that you have.

(In fact it's just as valid to say the the prosign SOS is VZE for example, which is made of ...-, --.. and . which when you stick them together with no spaces is ...---... same as SOS with no spaces.)

Hello
As already mentioned it is deeply recommended to start with the BWOD example as mother of all timers inside the Arduino Biotop.
The morse code has specified to signs DIT = . and DAH = - . If you want to make a special timing for the dimming it is recommended to use an array with two dimensions. One dimension for morse sign and the second to the timming.
All in all will result into a sketch you are looking to. Thus is a good point to start with OOP.
Have a nice day and enjoy coding in C++.

I wrote #7 above away from the big rig and also in a food coma.

This is a modification to the code in the post I linked, which should be obvious if you are employing it, to @johnwasser's idea:

bool myDelay(unsigned long milliseconds)
{
  unsigned long startTime = millis();

  while (millis() - startTime <= milliseconds) {
    if (digitalRead(buttonPin))
      return true;
  }

  return false;
}

and as he goes on to say

 Then, in place of 'delay(x)' use:
 
    if (myDelay(x)) return;

This will give the strobe_sos() the ability to return almost immediately the button is
detected.

I note that @sionaggutraidh #8 comments about the timing. It doesn't look, at a glance, to be standard Morse code durations for dots, dashes &c.

Is SOS timed out differently to regular text besides being one symbol (no inter-character gap)?

a7

Prosigns are timed as normal as far as the dots and dashes are concerned and the time between them, but as one long "character". The OP's timing is not Morse code "compliant", no, but I didn't think that was an issue as long as a long and a short are discernable.

THX. Call me, well call me anything you want, I like to see good dashes and dots.

It is, however, implausible that a distress call would be ignored because of ham-fisted improper timing. See what I did there?

a7

Thanks a lot a7!

Ken

Thank you!

Will change!

Ken

Thank you for your comments!

Ken

Thanks again!

I am as you understand, a newbie in Arduino coding so I am not really clear of exactly where in my code the changes are to be done, sorry for that.

Ken

The new function myDelay

bool myDelay(unsigned long milliseconds)
{
  unsigned long startTime = millis();

  while (millis() - startTime <= milliseconds) {
    if (digitalRead(buttonPin))
      return true;
  }

  return false;
}

should be put in your sketch the same way your other functions are placed.

All functions in C/C++, like fourth_light and strobe_sos are placed at the highest syntax level - not inside or part of any other structure.

That gives you a myDelay to use.

You can use myDelay anywhere good old delay would work.

Make every delay in strobe_sos, like this one

delay(400);

instead a call to your new function and adding a check to see if whilst performing the delay, someone hit the button:

    if (myDelay(400)) return;

Just use the same delay constant - the delay will be the same, but can be cut short and effect an immediate return to the loop function, where the button will be seen (again) and acted upon as you code it to.

TBH I don't now how to advise you - on the one hand, learning the real way to officially handle this kind of thing will unlock a new world of possibilities. On the other hand, if the above still makes too little sense for you to proceed fearlessly, it may be that you are not yet well-enough versed in the very basics. Doesn't mean you can't succeed, it just may be way less fun and you end up with less hair. :expressionless:

HTH

a7