hey all,
I am totally confused on millis() and random() functions, and maybe its because i can't do what I'm try to do with them. I have 2 separate plastic crows that were bought during halloween from a store several years back that have shorted boards. the heads turned (0-180), the eyes flashed (leds), and a "cawing" sound came through the 1w speaker. I figured i can just program a nano to control both crows; have the eyes blink at different intervals for different lengths of time, have the head turn to different angles at different speeds and stay for different lengths of time, and (at some point) add sound, a PIR, and a "irritated" mode that speeds up all actions.
I KNOW WAY BEYOND WHAT I SHOULD BE TRYING TO DO MYSELF
So I have the code for eyes done out and it does somewhat do what I am looking for, but it stays locked during each loop on the random numbers that were chosen during the first run through. I want it to change everytime. can anyone tell me where I am going wrong and how to fix it?
I've read A LOT of other posts, reseached online, and watch tons of YouTube videos but now am more confused than ever. I'll also probably runs into the issue when it comes time for adding the servos.
thanks in advance - I'm new so it wouldn't let me upload the sketch
unsigned long currentTime = millis();
const int crow1eyes = 2; // pin for crow 1 eyes
unsigned long crow1on = random(1000, 5000); // OFF time for crow 1 eyes
unsigned long crow1off = random(50, 400); // ON time for crow 1 eyes
int crow1State = HIGH; // starting state of crow 1 eyes
unsigned long PrevEyeTime1; // time used by code to keep track of crow 1 time
const int crow2eyes = 3; // pin for crow 2 eyes
unsigned long crow2on = random(1000, 5000); // OFF time for crow 2 eyes
unsigned long crow2off = random(50, 400); // ON time for crow 2 eyes
int crow2State = HIGH; // starting state of crow 2 eyes
unsigned long PrevEyeTime2; //time used by code to keep track of crow 1 time
void setup() {
pinMode(crow1eyes,OUTPUT); //sets eyes pin as output
digitalWrite(crow1eyes,crow1State); //sets initial state
pinMode(crow2eyes,OUTPUT); //define eyes pin as output
digitalWrite(crow2eyes,crow2State); //sets initial state
}
void loop() {
currentTime = millis();
if (crow1State == HIGH){
if(currentTime - PrevEyeTime1 >= crow1on){
crow1State = LOW; //changes the state of eyes
PrevEyeTime1 = currentTime;} // remembers current time
}
else {
if(currentTime- PrevEyeTime1 >= crow1off){
crow1State = HIGH; //changes the state of eyes
PrevEyeTime1 = currentTime;} //remembers current time
}
digitalWrite(crow1eyes, crow1State);// turns the eyes ON or OFF
if (crow2State == HIGH ) {
if(currentTime - PrevEyeTime2 >= crow2on) {
crow2State = LOW; //changes the state of eyes
PrevEyeTime2 = currentTime;} //remembers current time
}
else {
if (currentTime - PrevEyeTime2 >= crow2off) {
crow2State = HIGH; // changes the state of eyes
PrevEyeTime2 = currentTime;} // remembers current time
}
digitalWrite(crow2eyes, crow2State); // turns the eyes ON or OFF
}
Thanks for the help A7. Which way would be better in the long run? Keep in mind I will be adding code for both servos to move the head in pretty much the same fashion, so consistency would help a lot.
Would I also have to call out the random off time as well?
Those lines making the constants woukd go at the top of your program, outside any function definition where your other global variables are now.
Later when you execute the line of code to get a new random number in the range, you could write
crow1on = random(eye1OnMminimum, eye1OnMaximum);
It's just for convenience and making numbers obvious so you don't need to go looking in the code to change "magic" numbers or accidentally change a number that looks like you want to but you really don't.
If you think you understood and followed my idea, post the code and say what it doesn't do that it should or is doing that it shouldn't. For anything that isn't what you want it to be at this stage.
I didn't mean that your idea wasn't working I just meant that I probably didn't understand or implement it correctly.
This is what I did...
unsigned long currentTime = millis();
const int crow1eyes = 2; // pin for crow 1 eyes
unsigned long crow1On; // OFF time for crow 1 eyes
unsigned long crow1Off; // ON time for crow 1 eyes
int crow1State = HIGH; // starting state of crow 1 eyes
unsigned long PrevEyesTime1; // time used by code to keep track of crow 1 time
const int eyesOnMinimum = 1000;
const int eyesOnMaximum = 5000;
const int eyesOffMinimum = 50;
const int eyesOffMaximum = 500;
const int crow2eyes = 3; // pin for crow 2 eyes
unsigned long crow2On; // OFF time for crow 2 eyes
unsigned long crow2Off; // ON time for crow 2 eyes
int crow2State = HIGH; // starting state of crow 2 eyes
unsigned long PrevEyesTime2; //time used by code to keep track of crow 1 time
void setup() {
pinMode(crow1eyes,OUTPUT); //sets eyes pin as output
digitalWrite(crow1eyes,crow1State); //sets initial state
pinMode(crow2eyes,OUTPUT); //define eyes pin as output
digitalWrite(crow2eyes,crow2State); //sets initial state
}
void loop() {
currentTime = millis();
crow1On = random(eyesOnMinimum, eyesOnMaximum);
crow1Off = random(eyesOffMinimum, eyesOffMaximum);
crow2On = random(eyesOnMinimum, eyesOnMaximum);
crow2Off = random(eyesOffMinimum, eyesOffMaximum);
if (crow1State == HIGH){
if(currentTime - PrevEyesTime1 >= crow1On){
crow1State = LOW; //changes the state of eyes
PrevEyesTime1 = currentTime;} // remembers current time
}
else {
if(currentTime- PrevEyesTime1 >= crow1Off){
crow1State = HIGH; //changes the state of eyes
PrevEyesTime1 = currentTime;} //remembers current time
}
digitalWrite(crow1eyes, crow1State);// turns the eyes ON or OFF
if (crow2State == HIGH ) {
if(currentTime - PrevEyesTime2 >= crow2On) {
crow2State = LOW; //changes the state of eyes
PrevEyesTime2 = currentTime;} //remembers current time
}
else {
if (currentTime - PrevEyesTime2 >= crow2Off) {
crow2State = HIGH; // changes the state of eyes
PrevEyesTime2 = currentTime;} // remembers current time
}
digitalWrite(crow2eyes, crow2State); // turns the eyes ON or OFF
}
I put your code with the slight change necessary (fixed onyl crow 1) into the wokwi simulator:
You will see all I did was to move the calls to get new random numbers to where I said to put them in post #4 above. Sorry, I could have made that fleshier.
I also "auto formatted" your code. It is a good habit if you haven't yet adopted a style from the several that are popular. In the IDE, the auto format tool does an OK job and makes reading the code (and spotting cetrain kinds of errors) way easier. Until you know more and can choose for yourself, the format it enforces is fine. Many ppl use it more or less as it is.
Oh, I also cranked down the time constants you manifested nicely. Life is too short even for 5 second crow eye blink testing.
Here's all your code with the tiny change. The effect of your misplaced random calls was interesting but with my beach ride coming by soon I'll leave it on the "never gonna" list.
// https://forum.arduino.cc/t/random-led-time-on-off-using-millis/979561
unsigned long currentTime = millis();
const int crow1eyes = 2; // pin for crow 1 eyes
unsigned long crow1On; // OFF time for crow 1 eyes
unsigned long crow1Off; // ON time for crow 1 eyes
int crow1State = HIGH; // starting state of crow 1 eyes
unsigned long PrevEyesTime1; // time used by code to keep track of crow 1 time
// changed these for testing, life too short!
const int eyesOnMinimum = 100;
const int eyesOnMaximum = 500;
const int eyesOffMinimum = 100;
const int eyesOffMaximum = 200;
const int crow2eyes = 3; // pin for crow 2 eyes
unsigned long crow2On; // OFF time for crow 2 eyes
unsigned long crow2Off; // ON time for crow 2 eyes
int crow2State = HIGH; // starting state of crow 2 eyes
unsigned long PrevEyesTime2; //time used by code to keep track of crow 1 time
void setup() {
Serial.begin(112500);
Serial.println("random eyes!\n");
pinMode(crow1eyes, OUTPUT); //sets eyes pin as output
digitalWrite(crow1eyes, crow1State); //sets initial state
pinMode(crow2eyes, OUTPUT); //define eyes pin as output
digitalWrite(crow2eyes, crow2State); //sets initial state
// for testing
crow1On = 1000; crow1Off = 200;
crow2On = 1333; crow2Off = 333;
}
void loop() {
currentTime = millis();
/* NOT every time you loop!
crow1On = random(eyesOnMinimum, eyesOnMaximum);
crow1Off = random(eyesOffMinimum, eyesOffMaximum);
crow2On = random(eyesOnMinimum, eyesOnMaximum);
crow2Off = random(eyesOffMinimum, eyesOffMaximum);
*/
if (crow1State == HIGH) {
if (currentTime - PrevEyesTime1 >= crow1On) {
crow1State = LOW;
// just every time you actually use a random value, get a new one for next time
crow1On = random(eyesOnMinimum, eyesOnMaximum);
PrevEyesTime1 = currentTime;
}
}
else {
if (currentTime - PrevEyesTime1 >= crow1Off) {
crow1State = HIGH;
crow1Off = random(eyesOffMinimum, eyesOffMaximum);
PrevEyesTime1 = currentTime;
}
}
digitalWrite(crow1eyes, crow1State);
if (crow2State == HIGH ) {
if (currentTime - PrevEyesTime2 >= crow2On) {
crow2State = LOW;
PrevEyesTime2 = currentTime;
}
}
else {
if (currentTime - PrevEyesTime2 >= crow2Off) {
crow2State = HIGH;
PrevEyesTime2 = currentTime;
}
}
digitalWrite(crow2eyes, crow2State);
}
That's perfect! Awesome! Exactly what I was looking for!
How would I go about adding an "irritated mode" triggered by a pir that speeds up the process times 2, 3, or 4?
I will start a new thread for the servo issues I'm having. I need it to work in the same fashion. New angle at different intervals, speeds up when triggered by the pir