Swapping out delay for millis() problems

Hi Forum members
I have code I have been writing for a project which has been working OK but due to a delay of 2000 I have problems with a lag in activations that need to be almost instant.
The problem i am having is writing the correct code to swap the delay for millis() I just cant get it to work.
The current simplified code which works using delay(2000) is as below works but delay (2000) is what I need to swap with millis()

Rather than me muddying the water with what I have already tried any support would be a great help.

/*
AnalogReadSerial
Reads an analog input on pin 0, prints the result to the serial monitor.
Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.

*/
int ledPinl = 10; // The LED is connected to digital pin 10 actually multimeter
const int PIEZO_PINL= A3; // Piezo output

int valL=0;
int valR=0;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// initialize digital pin 10 and 11 as an output.
pinMode(10, OUTPUT);
analogWrite (ledPinl, 127);
}

// the loop routine runs over and over again forever:
void loop() {

// read the input on analog pin 3:
int sensorValue00 = analogRead(A3);
Serial.print(", Sensor Value 00: ");
Serial.println(sensorValue00);
delay(100); // delay in between reads for stability
// read the input on analog pin 4:
int sensorValue01 = analogRead(A4);
// if the analog value is high enough, turn on the LED:
// print out the value you read:
Serial.print(", Sensor Value 01: ");
Serial.println(sensorValue01);
delay(100); // delay in between reads for stability

int valL = analogRead(A3);
if (valL < 10){
if (sensorValue01 > valL) // if the current state is below 01 turns on Right LED
analogWrite(ledPinl, 255);
delay(2000);
analogWrite(ledPinl, 127);
}

Can you explain in words why you do those things for stability ? I don't understand why a dummy read makes it more stable. I also don't understand why a delay makes it more stable. Can you explain in words when to turn on the led for 2 seconds ? Should the led be turned off directly if the condition is no longer true ? Should the 2 seconds be lengthen if the conditions keeps on being true ?

Please read the instructions on how to use the forum and how to post code. If you ask for assistance, at least try to make easy for those who would help.

It's not exactly clear (to me) what you mean by 'swap with millis'.

Delay(2000) gives you a two second delay. Getting rid of delay (which you should NEVER use anyhow) and replacing it with:

uint32_t _now = millis();
while ((millis() - now) <= 2000)
{
// you can do something here;
}

has the same effect. Is this what you mean by swap with millis?

Have a look at how millis() is used to manage timing without blocking in Several things at a time. Note how each function runs very briefly and returns to loop() so the next one can be called. Long running processes are achieved a tiny piece at a time. And there may be dozens of calls to some functions before it is actually time for anything to happen.

...R

Rather than me muddying the water with what I have already tried any support would be a great help.

We like muddy water, show us your attempt at incorporating millis()

Koepel:
Can you explain in words why you do those things for stability ? I don't understand why a dummy read makes it more stable. I also don't understand why a delay makes it more stable. Can you explain in words when to turn on the led for 2 seconds ? Should the led be turned off directly if the condition is no longer true ? Should the 2 seconds be lengthen if the conditions keeps on being true ?

Koepel:
Hi Koepel
Thank you for looking into my issue.
Please see below for a description of the scenario.
Currently a Potentiometer is connected to the arduino;
& an LED is connected to the arduino;
The LED should not come on when the Potentiometer is turned from 0 upwards.
The LED should come on when the Potentiometer is turned from a current reading (above 0) to a reading below its current read and stay on until it is turned to 0.
The LED should come on when the Potentiometer is turned fully to 0 (from a higher reading) the LED should then stay on for 2 seconds then turn off.

But whilst the input is at zero the Arduino must still be active ie. taking readings ever 10milli seconds.
With delay (as currently programmed) this does not happen every 10milli seconds but every 2 second, unless the Potentiometer is moved from 0.
This is not desirable.

I hope this helps
Thanks in advance
Richard

DKWatson:
Please read the instructions on how to use the forum and how to post code. If you ask for assistance, at least try to make easy for those who would help.

It's not exactly clear (to me) what you mean by 'swap with millis'.

Delay(2000) gives you a two second delay. Getting rid of delay (which you should NEVER use anyhow) and replacing it with:

uint32_t _now = millis();
while ((millis() - now) <= 2000)
{
// you can do something here;
}

has the same effect. Is this what you mean by swap with millis?

Hi DK Watson
Apologies for not being clear, I am new to the Forum and, new to Arduino probably not the best combination.
I have now realised by research and my small amount of experience that delay is not the best to use.

Your suggestion above seems to be in various instructions I have seen but what i struggling with is using it after an action has taken place
So in my piece of programming as below how would your suggestion fit in to replace the "delay(2000);" line of code.

int valL = analogRead(A3);
if (valL < 10){
if (sensorValue01 > valL) // if the current state is below 01 turns on Right LED
analogWrite(ledPinl, 255);
delay(2000);
analogWrite(ledPinl, 127);
}

Is this line
delay(2000);
only to delay this line
analogWrite(ledPinl, 127);

Or is it meant to delay everything afterwards?

.

Create two global variables. Turn the software delay on by enabling the boolean variable and remember the millis(). At the end of the loop() check if the software delay is active. Turn the software delay off if millis() is two seconds further in time.

// two global variables
unsigned long previousMillis;
boolean active = false;

void setup()
{
  ...
}

void loop()
{
  if( ...
  {
    // Turn the software delay on
    active = true;    // make software delay active
    previousMillis = millis();   // remember this moment
    digitalWrite( pinLed, HIGH);   // turn on led
  }
  ...

  if( active)
  {
    if( millis() - previousMills > 2000)   // time has elapsed ?
    {
      active = false;                 // turn software delay off, it is no longer needed.
      digitalWrite( pinLed, LOW);   // turn off led.
    }
  }
}

larryd:
Is this line
delay(2000);
only to delay this line
analogWrite(ledPinl, 127);

Or is it meant to delay everything afterwards?

.

Hi larryd
I will add the previous lines of code in and add my understanding to the right of the code

int valL = analogRead(A3);
if (valL < 10){
if (sensorValue01 > valL) // if the current state is below 01 turns on Right LED
analogWrite(ledPinl, 255); //this turns on the Right LED (full power, 5 volts) (ON)
delay(2000); //this makes the LED stay on at full power for 2 seconds (ON)
analogWrite(ledPinl, 127); //after 2 seconds has passed the LED goes back to half power (OFF)
}

Do you understand Koepel's example?

Koepel:
Create two global variables. Turn the software delay on by enabling the boolean variable and remember the millis(). At the end of the loop() check if the software delay is active. Turn the software delay off if millis() is two seconds further in time.

// two global variables

unsigned long previousMillis;
boolean active;

void setup()
{
  ...
}

void loop()
{
  if( ...
  {
    // Turn the software delay on
    active = true;    // make software delay active
    previousMillis = millis();  // remember this moment
    digitalWrite( pinLed, HIGH);  // turn on led
  }
  ...

if( active)
  {
    if( millis() - previousMills > 2000)  // time has elapsed ?
    {
      active = false;                // turn software delay off, it is no longer needed.
      digitalWrite( pinLed, LOW);  // turn off led.
    }
  }
}

Maybe add:
active == false &&

if( active == false && ...

@larryd, I have changed my example. The global variable 'active' is now default set to false.
I prefer two seperate if-statements. That makes it clear what is going on in my opinion. That just my personal preference, I don't even understand why everyone uses the opening bracket '{' at the end of a line :confused: Since the curley brackets provide a beautiful way to show the structure of a sketch.

I don't know the conditions when to start the software delay. I suppose that the software delay can be lengthened when it is already running. That means that the part to turn on the software delay can be executed over and over again regardless if it was turned off or not.

Basic:
Hi larryd
I will add the previous lines of code in and add my understanding to the right of the code

int valL = analogRead(A3);
if (valL < 10){
if (sensorValue01 > valL) // if the current state is below 01 turns on Right LED
analogWrite(ledPinl, 255); //this turns on the Right LED (full power, 5 volts) (ON)
delay(2000); //this makes the LED stay on at full power for 2 seconds (ON)
analogWrite(ledPinl, 127); //after 2 seconds has passed the LED goes back to half power (OFF)
}

I am new too, so probably REALLY going to muddy the waters.

The delay(2000) is just to keep the LED on for two seconds, yes?

If so, consider setting a variable as follows at the point of your current delay statement.

Poweroff=millis();

Let the code continue on and at whatever critical program points it is necessary to check the LED, add the following

if (millis()-Poweroff>=2000){
 analogWrite(ledPinl, 127);
}

I used "Poweroff" not "LEDOn" because it seemed the important thing you were checking was the power dropping below one - the LED coming on is just the visualisation of that.

Sorry if I didn't help...and apologies to Mods for what are probably half-formed, badly written code snippets...

Hi Guys
Tried the previous suggestions but to no avail.
Did a little bit more digging and have written the code below, now I think i am very close to cracking this part of the programme, the LED comes on full power but stays on, there must be a slight error in turning it back down, please see below.

/*
AnalogReadSerial
Reads an analog input on pin 0, prints the result to the serial monitor.
Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.

*/
int ledPinl = 10; // The LED is connected to digital pin 10 actually multimeter
int ledPinr= 11; // The LED is connected to digital pin 11 actually multimeter
const int PIEZO_PINR = A2; // Piezo output
const int PIEZO_PINL= A3; // Piezo output

const int FLEX_PIN = A0; // Pin connected to voltage divider output
int buttonState = 0;
int lastButtonState = 1;
int valL=0;
int valR=0;

unsigned long elapsedTime;
unsigned long onTime;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// initialize digital pin 10 and 11 as an output.
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
analogWrite (ledPinl, 127);
analogWrite (ledPinr, 127);

onTime = millis();
onTime = elapsedTime;
pinMode(12, OUTPUT); //Initialize pin 12 as status LED
pinMode(8, INPUT); // Our button pin
}

// the loop routine runs over and over again forever:
void loop() {

// read the input on analog pin 3:
int sensorValue00 = analogRead(A3);
Serial.print(", Sensor Value 00: ");
Serial.println(sensorValue00);
delay(10); // delay in between reads for stability
// read the input on analog pin 4:
int sensorValue01 = analogRead(A4);
// if the analog value is high enough, turn on the LED:
// print out the value you read:
Serial.print(", Sensor Value 01: ");
Serial.println(sensorValue01);
delay(10); // delay in between reads for stability

int valL = analogRead(A3);
if (valL < 10){

if (sensorValue01 > valL) // if the current state is below 01 turns on Left LED
analogWrite(ledPinl, 255);
onTime = millis();
}
if(onTime > 0 && millis() - onTime > 2000)
{
analogWrite(ledPinl, 127); // LED goes off
onTime=0;
}
}

I disagree with that code, since you don't use two variables.
Beside that, the next part of your code is not okay. I have added '{' and '}' to show what you have.

if ( valL < 10 )
{
  if ( sensorValue01 > valL )    // if the current state is below 01 turns on Left LED
  {
    analogWrite ( ledPinl , 255 );
  }
  onTime = millis();
}

Yes I think the "next" part is wrong also as the power does not does from 255 to 127

You don't see it ? Starting the software timer should be done at the same moment as turning on the led. However, one is inside a if-statement and the other is outside that if-statement.

I'm afraid that I can't help you anymore. If you have questions about my previous answer, I'm glad to answer them.

So this is what I should have

if (sensorValue01 > valL) // if the current state is below 01 turns on Right LED
analogWrite(ledPinl, 255);
onTime = millis();
if(onTime > millis() - onTime > 2000)

No. The line "analogWrite(ledPinl, 255);" is inside the if-statement and the line "onTime = millis();" is outside that if-statement. You can easily avoid the confusion by always using '{' and '}'. You still don't accept my answer about the two global variables. What is the hardest part ? Clicking this link or reading what I wrote ? I really think that you need someone else to help you. It is against my nature to help you write bad code.