How to perform a random task on power up

I have a panel with 25 servos ( 15 on one control board + 10 on the other board) and
Arduino Uno. The panel has a 220v PIR motion sensor that powers it up for 5 minutes when someone approches it.

The sketch has 10 different tasks which make the servos move in different patterns.
For example, task1 sweeps all, task2 moves servos 1-10 in one direction and 11-25 in other direction...
etc..etc.

How do I generate a random number ( or "one number out of the hat" ) by which the panel would
perform that numbered task on power up ?

Most likely, on power up, it will continue an unfinished task if the power was shut down before it was finished. Is there a way to avoid that ?

Can someone please give me some code ?
Thanks.

Use the built-in function.

task = random(min, max);

For further description, look here.

If you are starting the arduino from a power off condition, as opposed to waking from sleep, you will need to use the randomseed() command otherwise the random number sequence will always be identical.

Generating the random number is the easy part. Getting that number to point to a function is another issue.

Have a look at econjack's solution in #1 here.

Thanks david_2018 and 12 Stepper, will try your suggestions.

What about my second question ?

How do I kill an unfinished task on power up and start anew?

How do I kill an unfinished task on power up and start anew?

How controlled will the shutdown ? What will cause it ?

ba47:
How do I kill an unfinished task on power up and start anew?

Current program state is lost on power up, so it will do this with no special action. Making it remember the task and restart it where it left off would require you record the relevant aspects of program state in the EEPROM.

UKHeliBob, I have a 220v PIR detector that shuts off the whole panel (takes away current).

DrAzzy, I do not want to restart the unfinished task. In fact, starting where it left off is my problem.
What I need is to kill the unfinished task on power up then start with my function that sets all servos to 0 position. After that, I can generate a random number and jump to a random task indicated by that number.

The fact that it restarts an unfinished task, from where it left it, on power up gives me big a problem with
servo positions.

Thank you both.

ba47:
The fact that it restarts an unfinished task, from where it left it, on power up

It doesn't...

ba47:
gives me big a problem with servo positions.

... but it will of course leave the servos wherever they happened to be when the power went off.

I have a 220v PIR detector that shuts off the whole panel (takes away current).

Can you connect a PIR to the Arduino so that the current state can be saved before shutting of the power when it is triggered ?

This can give you a reasonably random function that runs at start-up.

//ref ../Arduino/RandomTask
//
#define NUM_TASKS   10

//define a type we can use to create an array of pointers to the functions
typedef void (*taskFuncs)();

//prototypes of the task functions
void Task1( void );
void Task2( void );
void Task3( void );
void Task4( void );
void Task5( void );
void Task6( void );
void Task7( void );
void Task8( void );
void Task9( void );
void Task10( void );

//an array of pointers to each of the functions
taskFuncs myTasks[] = 
{
    &Task1,
    &Task2,
    &Task3,
    &Task4,
    &Task5,
    &Task6,
    &Task7,
    &Task8,
    &Task9,
    &Task10
    
};//myTasks[]

void setup() 
{
    Serial.begin(115200);   //debug

    //seed the random number generator with a read of an unconnected analog channel
    randomSeed( analogRead(A5) );

    //get a random number from 0 to the number of tasks we can choose from
    //note value returned is 0..NUM_TASKS-1 or 0..9
    int idx = random( 0, NUM_TASKS );
    //run the task
    myTasks[idx]();

    //proceed to loop and the rest of the program
    //...
    
}//setup

void loop() 
{

}//loop

//tasks doing random things
void Task1( void )
{
    Serial.println( "Task 1" );
}//Task1

void Task2( void )
{
    Serial.println( "Task 2" );
}//Task2

void Task3( void )
{
    Serial.println( "Task 3" );
}//Task3

void Task4( void )
{
    Serial.println( "Task 4" );
}//Task4

void Task5( void )
{
    Serial.println( "Task 5" );
}//Task5

void Task6( void )
{
    Serial.println( "Task 6" );
}//Task6

void Task7( void )
{
    Serial.println( "Task 7" );
}//Task7

void Task8( void )
{
    Serial.println( "Task 8" );
}//Task8

void Task9( void )
{
    Serial.println( "Task 9" );
}//Task9

void Task10( void )
{
    Serial.println( "Task 10" );
}//Task10

If you want "true" random numbers, you will need to store the seed in EEPROM and increment it for each reset. Something like this would work:

seed = eeprom.get(seed_address);
seed += analogread(A?) + 127;
eeprom.put(seed_address, seed);
randomseed(seed);

First, thank you all for the replies.

12Stepper lit up a led :slight_smile: in my "hollow" head. He said it doesn't restart an unfinished task on power up.

So, I added code in the setup to make all servos go to 0 position, no matter where they
were when power went off. That solved the problem of having servos acting crazy
when a new task starts. But, somehow (?) they don't go to 0 position, they go to half position.
Strange, because I'm using the code I used before to set them to 0.

As soon as I get this issue straighten out, I can start with your valuable suggestions.

Thanks a million for the code Blackfin, you made my day.

ba47:
But, somehow (?) they don't go to 0 position, they go to half position.
Strange, because I'm using the code I used before to set them to 0.

By default a servo is attach()-ed at 90 (the middle), then goes where you tell it. So do your write(0) befoe the attach(), then they will attach() at 0.

I'm using the code... we can't see that though ;). Rule of thumb, whenever you talk code, include it for all to see.

ba47:
Thanks a million for the code Blackfin, you made my day.

What was wrong with econjack's code I linked 2 days ago?

What was wrong with econjack's code I linked 2 days ago?/i] Nothing. I haven't tried it yet.
As you might have guessed I'm a newbie still trying to figure out how to restart from power up.
Here's the code I'm using just to try things out but it's not working. i.e. all 25 servos sweep then the timer shuts down the power. After that, PIR senses approach, power up ... Now the trouble starts.
i.e. the 10 servos connected to control board 1 (PWM0X40) just shake.
```
*#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);  // Initiates library.
Adafruit_PWMServoDriver pwm2 = Adafruit_PWMServoDriver(0x41);  // Initiates library.

#define SERVOMIN  110  // Minimum pulse length count out of 4096.
#define SERVOMAX  588 // Maximum pulse length count out of 4096.

int servoNo = 0; // Defines a counter for servos.

void setup()
{
  Serial.begin(9600);      // Starts serial connecton at 9600 baud rate.
  pwm.begin();        // Sends PWM signals.
  pwm.setPWMFreq(60);  // Makes servos run at 60 Hz rate.
  pwm2.begin();        // Sends PWM signals.
  pwm2.setPWMFreq(60);
  delay(20);

for (int myservo = 0; myservo < 11; myservo++)
    pwm.setPWM(myservo, 0, SERVOMIN);
  delay(20);

for (int myservo = 0; myservo < 16; myservo++)
    pwm2.setPWM(myservo, 0, SERVOMIN);
  delay(20);

}

void loop()
{
  for (int pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++)
  {
    for (servoNo = 0; servoNo < 11; servoNo++)
      pwm.setPWM(servoNo, 0, pulselen);
    delay(1);

for (servoNo = 0; servoNo < 16; servoNo++)
      pwm2.setPWM(servoNo, 0, pulselen);
    delay(1);
  }

for (int pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--)
  {
    for (servoNo = 0; servoNo < 11; servoNo++)
      pwm.setPWM(servoNo, 0, pulselen);
    delay(1);
    for (servoNo = 0; servoNo < 16; servoNo++)
      pwm2.setPWM(servoNo, 0, pulselen);
    delay(1);

}

}*
```

ba47:
still trying to figure out how to restart from power up.

Not sure what that means tbh. If you mean (and so far it seems you don't) that you want to carry on where you left off, you would need (as suggested) to do some saving at regular intervals, and even maybe provide battery power so you always do an orderly shutdown to a known state. Then your restart would expect that.

That's what a "RE-start from power up" would mean to me; otherwise it's just a "start" :wink:

Or, attach() the servos at known positions, so at least once setup() is finished you know where they are. BUT if they just randomly stopped somewhere when the power goes off, they will still move to the position at which you attach them.

If you need to know where they actually are at power up, so you can handle the fact that those points could be pretty much anywhere, then you need servos with a 4th wire.

Thanks Stepper for bearing with me, I'll try to explain myself better.

  1. I DO NOT want to carry on where I left.
  2. Using two PCA9685 16 channel control boards, I've never seen " Attach Servos "(?)
  3. When power shut down occurs by the timer, the servos are indeed left somewhere unknown.
    So, on power up, before I "start " a new task I need all servos to go to 0 position. I tried that with the
    code I posted but no luck.
  4. I've already built this panel as a gift to an institute for kids. It will be displayed in a hallway.
    What I wanted was when a kid passes by, it lights up (led strips) and performs a random movement
    of the servos, not always the same routine.

I'm stuck on power up and "start" as you call it. If I can get the servos to 0 position on power up then
I think I can manage the rest.