Help changing this code to be non-blocking

I have the following code which I have hard time to make it work without delay. How can I make it using millis so the delay won't block arduino to do other stuff

int outputPin1 = 10;  // Digital output pin for pulse generation
const int outputPin2 = 11; // PWM output pin for random voltage
const int potPin = A4;     // Analog input pin for the potentiometer



void setup() {
  Serial.begin(115200);
  pinMode(outputPin1, OUTPUT);
  pinMode(outputPin2, OUTPUT);
  randomSeed(analogRead(0)); // Seed the random number generator with an analog input value
}

void loop() {
  // Generate a random duration between 50ms and 750ms
  int randomDuration = random(5, 10);

  // Output a random pulse
  digitalWrite(outputPin1, HIGH);
  delay(randomDuration);
  digitalWrite(outputPin1, LOW);

  // Generate a random voltage on another PWM pin
  analogWrite(outputPin2, random(256)); // random voltage between 0 and 255

  // Read the potentiometer value to determine the upper limit of the delay time
  int potValue = analogRead(potPin);
  // Map potValue to the upper limit of the delay range (10, 100)
  int upperLimitDelay = map(potValue, 0, 1023, 50, 2000);

  // Generate a random delay between the constant minimum (10) and the variable upper limit
  int currentDelay = random(10, upperLimitDelay);

  // Print the current delay duration
  Serial.print("Current Delay: ");
  Serial.println(currentDelay);

  // Add the delay between pulses
  delay(currentDelay);
}

Have you looked at the "blink without delay" sketch on offer in the IDE?

Also this has been tutorialed to death, google

arduino blink without delay 

and poke around.

Maybe a bit hard until it is easy. Then your life changes. :slight_smile:

a7

1 Like

Give a try to "arduino blink without delay" (search)... you will see a well-annotated sketch.

I made a sketch that I followed the "blink without delay" using many-events. The basics are:

  1. set an interval (or more)
  2. store the current time of the running timer (millis()) - this will be "time 0"
  3. compare if that the running timer (millis()) is farther from "time 0" than the interval
  4. if yes, do the thing
  5. store this time as the start of the "time 0" timer

A timing chart could look like this. Each asterisk is an LED getting lit at its interval...

// Each character on this timing graph represents 100ms.
// interval[0] RED LED every 300ms |--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*
// interval[1] ORG LED every 700ms |------*------*------*------*------*------*------*------*------*
// interval[2] YEL LED every 900ms |--------*--------*--------*--------*--------*--------*--------*
// interval[3] GRN LED every 2100ms |--------------------*--------------------*--------------------*
// interval[4] BLU LED every 3150ms |-------------------------------*------------------------------*

Here is that timing chart in a simulation...

Here's another for you:

You can use this pseudocode as a basis:

// declare a variable to hold the time (millis()) when the pulse went HIGH "lastHIGH"
// declare a variable to store the pulse duration (HIGH) "durationHIGH"
// declare a variable to store the time (millis()) when the pulse went LOW "lastLOW"
// declare a variable to store the pulse duration (LOW) "durationLOW"
// declare a variable to store the pin status (HIGH or LOW) "pinStatus


void setup(){
	 // set pinMode
	 // the following 2 lines will trigger a change to HIGH upon starting loop()
     // set pin status to LOW 
	 // set lastLOW to 0
}


void loop() {
// store millis() as current time

// if (pin status is HIGH) {
// 	if (current time - lastHIGH >= durationHIGH) {
//    ...pin has been HIGH long enough
//    set pin to LOW, store millis() in lastLOW, set pin status to LOW
//    calculate next durationHIGH (random duration)
//  } else { 
//   if (current time - lastLOW >= durationLOW) {
//    ...pin has been LOW long enough
//    set pin to HIGH, store millis() in lastHIGH, set pin status to HIGH
//    calculate next durationLOW (read the potentiometer, use your random logic)
//  }
}

Some of the above is redundant, but you can start from there and later on simplify the pseudocode at will

here is my final code that seems to work without a delay:

//int outputPin1 = 10;  // Digital output pin for pulse generation
//int outputPin2 = 11;  // Additional digital output pin for another random pulse
//int outputPin3 = 3;   // PWM output pin for random value 1
//int outputPin4 = 6;   // PWM output pin for random value 2
//const int potPin1 = A4; // Analog input pin for the first potentiometer
//const int potPin2 = A7; // Analog input pin for the second potentiometer
//
//unsigned long lastPulseTime1 = 0; // Variable to store the time of the last pulse for outputPin1
//unsigned long lastPulseTime2 = 0; // Variable to store the time of the last pulse for outputPin2
//unsigned long currentDelay1 = 0;   // Variable to store the current delay between pulses for outputPin1
//unsigned long currentDelay2 = 0;   // Variable to store the current delay between pulses for outputPin2
//bool pulseInProgress1 = false;     // Flag to track if a pulse is in progress for outputPin1
//bool pulseInProgress2 = false;     // Flag to track if a pulse is in progress for outputPin2
//
//void setup() {
//  Serial.begin(115200);
//  pinMode(outputPin1, OUTPUT);
//  pinMode(outputPin2, OUTPUT);
//  pinMode(outputPin3, OUTPUT);
//  pinMode(outputPin4, OUTPUT);
//  randomSeed(analogRead(0)); // Seed the random number generator with an analog input value
//}
//
//void loop() {
//  unsigned long currentTime = millis();
//
//  // Check if it's time for a new pulse on outputPin1
//  if (!pulseInProgress1 && currentTime - lastPulseTime1 >= currentDelay1) {
//    // Start a new pulse on outputPin1
//    digitalWrite(outputPin1, HIGH);
//    pulseInProgress1 = true;
//
//    // Update the last pulse time for outputPin1
//    lastPulseTime1 = currentTime;
//
//    // Generate a random value on outputPin3
//    analogWrite(outputPin3, random(256));
//  }
//
//  // Check if the pulse duration has passed for outputPin1
//  if (pulseInProgress1 && currentTime - lastPulseTime1 >= 10) {
//    // End the pulse on outputPin1
//    digitalWrite(outputPin1, LOW);
//    pulseInProgress1 = false;
//
//    // Generate a random delay between the constant minimum (10) and the variable upper limit for outputPin1
//    int upperLimitDelay1 = map(analogRead(potPin1), 0, 1023, 50, 2000);
//    currentDelay1 = random(10, upperLimitDelay1);
//
//    // Print the current delay duration for outputPin1
//    Serial.print("Current Delay (OutputPin1): ");
//    Serial.println(currentDelay1);
//  }
//
//  // Check if it's time for a new pulse on outputPin2
//  if (!pulseInProgress2 && currentTime - lastPulseTime2 >= currentDelay2) {
//    // Start a new pulse on outputPin2
//    digitalWrite(outputPin2, HIGH);
//    pulseInProgress2 = true;
//
//    // Update the last pulse time for outputPin2
//    lastPulseTime2 = currentTime;
//
//    // Generate a random value on outputPin4
//    analogWrite(outputPin4, random(256));
//  }
//
//  // Check if the pulse duration has passed for outputPin2
//  if (pulseInProgress2 && currentTime - lastPulseTime2 >= 10) {
//    // End the pulse on outputPin2
//    digitalWrite(outputPin2, LOW);
//    pulseInProgress2 = false;
//
//    // Generate a random delay between the constant minimum (10) and the variable upper limit for outputPin2
//    int upperLimitDelay2 = map(analogRead(potPin2), 0, 1023, 50, 2000);
//    currentDelay2 = random(10, upperLimitDelay2);
//
//    // Print the current delay duration for outputPin2
//    Serial.print("Current Delay (OutputPin2): ");
//    Serial.println(currentDelay2);
//  }
//
//  // Add other non-blocking tasks here
//}
//





int outputPin1 = 10;  // Digital output pin for pulse generation
int outputPin2 = 11;  // Additional digital output pin for another random pulse
int outputPin3 = 3;   // PWM output pin for random value 1
int outputPin4 = 6;   // PWM output pin for random value 2
const int potPin1 = A4; // Analog input pin for the first potentiometer
const int potPin2 = A7; // Analog input pin for the second potentiometer

unsigned long lastPulseTime1 = 0; // Variable to store the time of the last pulse for outputPin1
unsigned long lastPulseTime2 = 0; // Variable to store the time of the last pulse for outputPin2
unsigned long currentDelay1 = 0;   // Variable to store the current delay between pulses for outputPin1
unsigned long currentDelay2 = 0;   // Variable to store the current delay between pulses for outputPin2
bool pulseInProgress1 = false;     // Flag to track if a pulse is in progress for outputPin1
bool pulseInProgress2 = false;     // Flag to track if a pulse is in progress for outputPin2

void setup() {
  Serial.begin(115200);
  pinMode(outputPin1, OUTPUT);
  pinMode(outputPin2, OUTPUT);
  pinMode(outputPin3, OUTPUT);
  pinMode(outputPin4, OUTPUT);
  randomSeed(analogRead(0)); // Seed the random number generator with an analog input value
}

void loop() {
  unsigned long currentTime = millis();

  // Check if it's time for a new pulse on outputPin1
  if (!pulseInProgress1 && currentTime - lastPulseTime1 >= currentDelay1) {
    // Start a new pulse on outputPin1
    digitalWrite(outputPin1, HIGH);
    pulseInProgress1 = true;

    // Update the last pulse time for outputPin1
    lastPulseTime1 = currentTime;

    // Generate a random value on outputPin3
    int pwmValue1 = random(256);
    analogWrite(outputPin3, pwmValue1);
    // Convert PWM value to voltage (assuming a 5V Arduino)
    float voltage1 = map(pwmValue1, 0, 255, 0, 5000) / 1000.0;
    // Print the voltage value on Serial
    Serial.print("Voltage (OutputPin3): ");
    Serial.println(voltage1);
  }

  // Check if the pulse duration has passed for outputPin1
  if (pulseInProgress1 && currentTime - lastPulseTime1 >= 10) {
    // End the pulse on outputPin1
    digitalWrite(outputPin1, LOW);
    pulseInProgress1 = false;

    // Generate a random delay between the constant minimum (10) and the variable upper limit for outputPin1
    int upperLimitDelay1 = map(analogRead(potPin1), 0, 1023, 50, 2000);
    currentDelay1 = random(10, upperLimitDelay1);

    // Print the current delay duration for outputPin1
    Serial.print("Current Delay (OutputPin1): ");
    Serial.println(currentDelay1);
  }

  // Check if it's time for a new pulse on outputPin2
  if (!pulseInProgress2 && currentTime - lastPulseTime2 >= currentDelay2) {
    // Start a new pulse on outputPin2
    digitalWrite(outputPin2, HIGH);
    pulseInProgress2 = true;

    // Update the last pulse time for outputPin2
    lastPulseTime2 = currentTime;

    // Generate a random value on outputPin4
    int pwmValue2 = random(256);
    analogWrite(outputPin4, pwmValue2);
    // Convert PWM value to voltage (assuming a 5V Arduino)
    float voltage2 = map(pwmValue2, 0, 255, 0, 5000) / 1000.0;
    // Print the voltage value on Serial
    Serial.print("Voltage (OutputPin4): ");
    Serial.println(voltage2);
  }

  // Check if the pulse duration has passed for outputPin2
  if (pulseInProgress2 && currentTime - lastPulseTime2 >= 10) {
    // End the pulse on outputPin2
    digitalWrite(outputPin2, LOW);
    pulseInProgress2 = false;

    // Generate a random delay between the constant minimum (10) and the variable upper limit for outputPin2
    int upperLimitDelay2 = map(analogRead(potPin2), 0, 1023, 50, 2000);
    currentDelay2 = random(10, upperLimitDelay2);

    // Print the current delay duration for outputPin2
    Serial.print("Current Delay (OutputPin2): ");
    Serial.println(currentDelay2);
  }

  // Add other non-blocking tasks here
}

The thing is that I have not clean output from the pwm pins. How can I do filtering or changing the pwm frequency to br above the hearing frequency (20k)

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