Few questions with blink without delay for an application

HI everyone, so i have this code and it works if i just use delays. The application is for a drinks machine controlled via bluetooth on the phone fyi. But the issue is when I tried to use blink without delay instead the pump doesnt come on, and the code seems to just bypass the interval period for the blink without dekay if statement, as I serial printed "test" and it appears at the exact time that the other values are sent when it should have appeared 5 seconds later.
Code shown below.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
int Shots = 0;
int Glass_Size = 0;
int pump_num = 0;

//int Shot_time = Shots*1000;
//int Glass_Size_time = Glass_Size

long previousMillis = 0;
const long interval = 5000;

boolean newData = false;

//============
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2); // Change to (0x27,20,4) for 20x4 LCD
void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
}

//============

void loop() {

  lcd.setCursor(1, 0); // Set the cursor on the third column and first row.
  lcd.print("Please Pick A");
  lcd.setCursor(1, 1); //Set the cursor on the third column and the second row (counting starts at 0!).
  lcd.print("Drink from App");

  recvWithStartEndMarkers();
  if (newData == true) {
    strcpy(tempChars, receivedChars);

    parseData();
    showParsedData();
    newData = false;
  }

  if (pump_num == 2)
  {

    lcd.clear();

    lcd.setCursor(1, 0);
    lcd.print("Your Drink is");
    lcd.setCursor(3, 1);
    lcd.print("Being Made");
    
    digitalWrite(2, HIGH);
    unsigned long currentMillis = millis();
     
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      Serial.write("test");
      digitalWrite(2, LOW);
    }

    //digitalWrite(2, HIGH);
    // delay(Shots * 1000);
    //digitalWrite(2, LOW);

    //digitalWrite(3, HIGH);
    //delay(Shot_time);
    //digitalWrite(3,LOW);

    pump_num = 0;



  }

}

//============

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

//============

void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index



  strtokIndx = strtok(tempChars, ","); // this continues where the previous call left off
  pump_num = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ",");
  Shots = atoi(strtokIndx);

  strtokIndx = strtok(NULL, ",");
  Glass_Size = atoi(strtokIndx);



}

//============

void showParsedData() {
  Serial.print("Pump Number ");
  Serial.println(pump_num);

  Serial.print("Shots ");
  Serial.println(Shots);

  Serial.print("Glass Size ");
  Serial.println(Glass_Size);
}

Thanks in advance.
Dean.

A millis-timer is used this way:

  1. Start the millis-timer and then continue with the sketch.
  2. The millis-timer runs on its own in the main level of the loop().

That means you need two pieces of code. One piece of code that starts the millis-timer and then the code for the millis-timer itself. They belong to each other, but they are at different places in the sketch.

If you have just one millis-timer to turn something off, then it is a straightforward millis-timer, such as my millis_single_delay.ino. Do you see the two different pieces of code ?

Question: Will there be many steps in your sketch. Such as "do this" then "do that" then wait, then "do another thing", and so on ?
In that situation you might make a Finite State Machine. That is a fancy word for something simple: https://majenko.co.uk/blog/our-blog-1/the-finite-state-machine-26.
A millis-timer can be included in a Finite State Machine in a nice way.

YEs a "state mechine" may make the process easier to code.

Have a look at my tutorial here

Right thank you both for your replies, it will have a few steps so I will look into the state machines.

This may help too:

A drink machine is a typical Finite State Machine sketch. It will be worth your time to learn to use it.
The tutorial by @johnerrington is good. My style of coding is slightly different, you can find a few examples on my Fun With Millis page (look for the word 'finite') and test them directly in Wokwi.

2 Likes

Ive just haf a quick look at the tutorial by johnerrington, but with this do all the values need to be stored in an array, because I am sending them over bluetooth?

@Koepel I love the idea of this sketch, I'll have to try it.

Worth pointing out if you are using millis() timing you can not also use delay();

yes I started with machine code on the 6802 - I guess it shows! You have a more modern approach - and maybe clearer.

Always worth reminding, though we presume the OP here understands, that "starting the timer" does not mean interfering with the timer system in any way, but recording the immediate value of millis() for later comparison.

Values are stored in an array to facilitate working with a number of instances of the same type of object where that object may be a piece of code or a corresponding physical thing such as each of your number of pumps.

The array can be multidimensional so that it stores several parameters for each instance. This can be defined using a "struct" (structure definition).

Is that sufficiently confusing? :grin:

Yes thank you :grin: