2

I'm new to programming and using Arduino products, and was wondering if someone wouldn't mind assisting me with a project I'm trying to tackle?

If you review my code below, I have 3 conditions within my "idle" case, and the program is constantly looking for any of those 3 conditions. If the first condition is met, then case 1 is called; if the second condition is met, then case 2 is called; if the third condition is met, then case 3 is called. All 3 cases return to the "idle" case once done running.

What I would like to do is find some way to insert the "warning" case if any of the conditions are met, BEFORE going to case 1, case 2 or case 3, without writing the functions of the "warning" case over each time for each of the other 3 cases. Essentially, the flow would be like this:

condition 1 --> warning --> case 1 --> case idle;

condition 2 --> warning --> case 2 --> case idle;

condition 3 --> warning --> case 3 --> case idle:

void loop() {
  static byte theState = idle;
  switch (theState)
  {
    case idle:
      if (voltageA0 > 1.0) {
        theState = case1;
      }

      if (voltageA1 < 2.0) {
        theState = case2;
      }

      if (voltageA2 > 3.5) {
        theState = case3;
      }
      break;
    case warning:
      digitalWrite(7, HIGH);
      delay(5000);
      digitalWrite(7, LOW);
      delay(0);
      break;
    case 1:
      digitalWrite(8, HIGH);
      delay(2000);
      digitalWrite(8, LOW);
      delay(0);
      theState = idle;
      break;
    case 2:
      digitalWrite(9, HIGH);
      delay(2000);
      digitalWrite(9, LOW);
      delay(0);
      theState = idle;
      break;
    case 3:
      digitalWrite(10, HIGH);
      delay(2000);
      digitalWrite(10, LOW);
      delay(0);
      theState = idle;
      break;
  }
}

Also, if there is a more efficient way to do this, code-wise, I'm all ears!

  • Simplifying the code before posting it is generally a good thing. But if you change it so much that it becomes mostly unrelated to the original one, then a proper answer to the question may not be applicable to your real problem. Judging from your comments to Look Alterno's answer, this is exactly what happened. The blocking code you posted is a very different beast from the non blocking one you are using. Please, edit the question to make it relevant to your actual problem. This would be more useful than trying to explain in comments the extent to which the codes differ. – Edgar Bonet Feb 3 '18 at 14:18
1

There is something incoherent in your code. It is structured as a finite state machine, and yet you are using delay() within it. In this kind of scenario, the whole purpose of a state machine is to avoid using delay(), so that your program never blocks. If your program happens to not have anything better to do than delaying, then you can forgo the state machine and write much simpler code. For example:

void warn_and_flash(byte pin)
{
    // Flash the "warning" LED.
    digitalWrite(7, HIGH);
    delay(5000);
    digitalWrite(7, LOW);

    // Flash the requested LED.
    digitalWrite(pin, HIGH);
    delay(2000);
    digitalWrite(pin, LOW);
}

void loop()
{
    if (voltageA0 > 1.0) warn_and_flash(8);
    if (voltageA1 < 2.0) warn_and_flash(9);
    if (voltageA2 > 3.5) warn_and_flash(10);
}
  • I agree. Imagine you are writing code for a motor car, and the driver puts on the left indicator, which is supposed to flash once every second. Do you really want to the car to ignore the other inputs (brakes, accelerator, air conditioning) for an entire second while you delay for one second? I think not. – Nick Gammon Feb 3 '18 at 10:01
0
case idle:
  if (voltageA0 > 1.0 || voltageA1 < 2.0 || voltageA2 > 3.5) {
     digitalWrite(7, HIGH);
     delay(5000);
     digitalWrite(7, LOW);
     delay(0);     

     if (voltageA0 > 1.0) {
        theState = case1;
        }

    if (voltageA1 < 2.0) {
       theState = case2;
       }

    if (voltageA2 > 3.5) {
       theState = case3;
       }
   }

EDIT: To clarify original answer, I inlined the "warning" code and deleted the "case warning", as obviously this state is not longer needed.

  • Thanks so much for your assistance guys! I suppose I should have explained why I'm using a state machine for the code. The code I gave the example of omits the millis() functions that I actually have in my real code. I re-wrote the example without the millis() functions to simply what I'm trying to do, but cases "warning", "1", "2", and "3" all use millis() functions to trigger LEDs and relays. Sorry for not explaining that. Edgar, thanks for pointing out the "delay(0);" redundancy I had... I was thinking that may have been redundant, but wasn't sure. Based on the fact that I need to... – Andrew Feb 2 '18 at 21:58
  • ...call a different set of functions after the "warning" function, specific to the condition that was met, I don't believe the example you suggested would work. I may be wrong though so please let me know if I missed something :) Look Alterno, thank you for your help as well. Something else I didn't explain is that the "warning" state/function also remedies the conditions by triggering relays to cut voltage to some devices. The successive cases (1, 2, 3) are just used as an indicator to tell me which condition was just met, after the warning state remedies the problem. – Andrew Feb 2 '18 at 22:09
  • So think of it this way... condition 1 will trigger the warning case, then go to case 1, where an LED will flash 5 times to indicate condition 1 was just met condition 2 will trigger the warning case, then go to case 2, where an LED will flash 10 times to indicate condition 2 was just met condition 3 will trigger the warning case, then go to case 3, where an LED will flash 10 times to indicate condition 3 was just met Again, my fault for not elaborating all of this initially. Does this make more sense?? Thanks again, very much, for the help! – Andrew Feb 2 '18 at 22:12
  • @Andrew. That's what the code does: if any condition is met, then warning is executed. After that, the code tests for the specific condition (case 1, 2 or 3) and executed the pertinent action(s). – user31481 Feb 2 '18 at 22:20
  • thanks! But yeah the warning state will remedy any of the 3 conditions, so checking for the condition AFTER the warning state won't do any good unfortunately. The best way to think of it is let's say voltage on pin A0 increases as a pot of water gets hotter. Once the pot of water reaches a certain temperature (voltage), the "warning" function illuminates an LED for, let's say 10 minutes, while also cutting the heat source to the pot of water. Once that 10 mins is up, the condition-related case (1, 2, or 3) will flash an LED a certain number of times to indicate which cond was met – Andrew Feb 2 '18 at 22:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.