Random array of different digitalWrite delays

Hello,

I am quite new to coding for Arduino. I apologise that the subject headline might be confusing, I didn't know what else to call it.

In my project there is a small motor simulating a heartbeat. And this is the code:

[sub]int motorPin = 3;

void setup() {
  pinMode(motorPin, OUTPUT);
}

void loop() {
  digitalWrite(motorPin, HIGH);
  delay(100);
  digitalWrite(motorPin, LOW);
  delay(300);
  digitalWrite(motorPin, HIGH);
  delay(100);
  digitalWrite(motorPin, LOW);
  delay(1200);
  
}[/sub]

What I would like to do is to have the 'heartbeat' change a little so it hopefully seems less mechanical. I think a possibility could be randomly choosing from an array of various 'heartbeats'.

But unfortunately I dont experience writing in C, so I would appreciate it very much if someone could help me :slight_smile:

Look at the random() function and note that you can have the return number fall within a desired range.

http://arduino.cc/en/Reference/Random

Also, you will get better responses if you follow the posting guidelines written by Nick Gammon at the top of this Forum.

Thank you econjack, this is in the direction i was looking.
Though not randomness at every beat, but more like it at times could go a bit faster or slower, like have three or four different speeds.

You could have an array with different values that can be used in the delay() function. You can make that as complicated as you like by having several layers to the array. Then you can randomly select which element of the array is to be used.

Something simple would be

int delayList[] = { 100, 200, 300};
byte delayIndx = 2;

void loop() {
   for (n = 0; n < 2; n++) {
       digitalWrite(motorPin, HIGH);
       delay(delayList[delayIndx]);
       digitalWrite(motorPin, LOW);
       delay(delayList[delayIndx * 3);
  }
  delay(1200);
  
}

You could then arrange to change delayIndx randomly

You might also want to consider how to manage the timing without using the delay() function at all - see the demo several things at a time.

...R

Hi Robin2, thanks for your suggestion.
I have tried but i keep getting an error report: error: 'n' was not declared in this scope

I should clarify - what I would like to make is three different heartbeats.
For example:

First:
void loop() {
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(300);
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(1200);
}

Second:
void loop() {
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(500);
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(1500);
}

Third:
void loop() {
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(100);
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(1000);
}

And then change between these 3 states in (randomly chosen) either 10min, 30min, 60min or 180min.

I have tried but i keep getting an error report: error: 'n' was not declared in this scope

That's very easily fixed.
Persevere

You haven't posted the code with the errant N in it so I can't offer any advice.

...R

@Robin2, it's your code, reply#3

I have tried writing this now, which does not work. i get this error: avrdude: stk500_recv(): programmer is not responding

Further, what I really want it to do is that it changes between heartbeat1, heartbeat2 and heartbeat3 with a certain time interval. Maybe even choosing randomly between a couple of different time intervals.

Your help is very appreciated!

int motorPin = 3;

void setup() {
pinMode(motorPin, OUTPUT);
}

static void heartbeat1 () { /normal beat/
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(300);
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(1200);

}

static void heartbeat2 () { /fast beat/
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(150);
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(1000);

}

static void heartbeat3 () { /slow beat/
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(500);
digitalWrite(motorPin, HIGH);
delay(100);
digitalWrite(motorPin, LOW);
delay(1500);

}

void loop() {
int randNumber = random(1,4);

if (randNumber == 1)
heartbeat1();

if (randNumber == 2)
heartbeat2();

if (randNumber == 3)
heartbeat3();

Serial.println(randNumber);
}

Is it very difficult to code?
Otherwise i could make do with it changing heartbeat speed every 15min. Any suggestions how to code that?

Add this data definition at the very top of the program:

void (*ptrFunc[])() = {heartbeat1, heartbeat2, heartbeat3};

Add this line to setup():

   Serial.begin(9600);

And use this for loop():

void loop() {
  int randNumber = random(1,4);
  
  *ptrFunc[randNumber - 1];

  Serial.println(randNumber);
}

My guess is that most readers here would code it like this, as it's about as simple as it gets. The only weird thing is the use of an array of pointers to functions, which is the first line to be added to your code. If you need help figuring it out, see my Right-Left Rule which is nicely summarized at:

http://jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html

take a look at blink without delay, and using a random number for the initial beat and also the secondary, you may also want to add a potentiometer so that you can speed up or slow down the beats.

amag:
I have tried writing this now, which does not work.

Your help is very appreciated!

It doesn't seem to be.

What's wrong with the idea I gave you in Reply #3.
You said you had a small problem with "n" but didn't bother to show us the code with the problem.

AWOL:
@Robin2, it's your code, reply#3

Only partly - all I provided was a snippet that was not sufficient to compile.

...R

Robin2:
It doesn't seem to be.

What's wrong with the idea I gave you in Reply #3.
You said you had a small problem with "n" but didn't bother to show us the code with the problem.
Only partly - all I provided was a snippet that was not sufficient to compile.

...R

It is.

But as I understood your code it changes the delay all the time. Correct if I am wrong? What I am trying to do is that there is 3 different types of heartbeats and it changes between them every 15min (+- 10min). So each heartbeat type is played for a longer time. And that the digitalWrite(motorPin, HIGH) always is delay(100);

Robin2:
You could have an array with different values that can be used in the delay() function. You can make that as complicated as you like by having several layers to the array. Then you can randomly select which element of the array is to be used.

Something simple would be

int delayList[] = { 100, 200, 300};

byte delayIndx = 2;

void loop() {
for (n = 0; n < 2; n++) {
digitalWrite(motorPin, HIGH);
delay(delayList[delayIndx]);
digitalWrite(motorPin, LOW);
delay(delayList[delayIndx * 3);
}
delay(1200);

}

I keep getting the error: 'n' was not declared in this scope.

Use int n

...
void loop() {
   for (int n = 0; n < 2; n++) {
...

econjack:
Add this data definition at the very top of the program:

void (*ptrFunc[])() = {heartbeat1, heartbeat2, heartbeat3};

Add this line to setup():

   Serial.begin(9600);

And use this for loop():

void loop() {

int randNumber = random(1,4);

*ptrFunc[randNumber - 1];

Serial.println(randNumber);
}




My guess is that most readers here would code it like this, as it's about as simple as it gets. The only weird thing is the use of an array of pointers to functions, which is the first line to be added to your code. If you need help figuring it out, see my Right-Left Rule which is nicely summarized at:

http://jdurrett.ba.ttu.edu/3345/handouts/RL-rule.html

Hi econjack,
I have tried adding your suggestions. And now i see the quickly changing numbers in the Serial Monitor.
But the motor in my circuit doesn't buzz anymore, i think it might be changing so quick that it doesn't run the heartbeat. Is there a way to add minutes, so it selects a new every 15min (+- 10min)?

int motorPin = 3;

void (*ptrFunc[])() = {heartbeat1, heartbeat2, heartbeat3};

void setup() {
  pinMode(motorPin, OUTPUT);
  Serial.begin(9600);
}



static void heartbeat1 () { /*normal beat*/
  digitalWrite(motorPin, HIGH);
  delay(100);
  digitalWrite(motorPin, LOW);
  delay(300);
  digitalWrite(motorPin, HIGH);
  delay(100);
  digitalWrite(motorPin, LOW);
  delay(1200);
  
}

static void heartbeat2 () { /*fast beat*/
  digitalWrite(motorPin, HIGH);
  delay(100);
  digitalWrite(motorPin, LOW);
  delay(150);
  digitalWrite(motorPin, HIGH);
  delay(100);
  digitalWrite(motorPin, LOW);
  delay(1000);
  
}

static void heartbeat3 () { /*slow beat*/
  digitalWrite(motorPin, HIGH);
  delay(100);
  digitalWrite(motorPin, LOW);
  delay(500);
  digitalWrite(motorPin, HIGH);
  delay(100);
  digitalWrite(motorPin, LOW);
  delay(1500);
  
}

void loop() {
  int randNumber = random(1,4);
  
  *ptrFunc[randNumber - 1];

  Serial.println(randNumber);
}

uxomm:
Use int n

...

void loop() {
  for (int n = 0; n < 2; n++) {
...

Thanks! :slight_smile:

Instead of minutes, can i tell the number of times a heartbeat loop should be played?

amag:
Instead of minutes, can i tell the number of times a heartbeat loop should be played?

The delay numbers are milliseconds. 100 is 1/10th of a second. Arduino counts microseconds to nearest 4.

The way you do heartbeat will take as long as the delays add up.

You could store delay periods for each pattern as an array and use each step to run 1 simple blink routine.

In your IDE are the Examples. Section 5 covers arrays and loops. Try some out and see if that helps.