I made this owl prop using an Arduino Nano and a PIR to trigger the owl's LED eyes to come on and the owl head (connected to a servo) turn its head back and forth a few times. After about 20 seconds or so, the eyes go dim and the owl head returns to its neutral position (90). You can see it in action here:
My code:
**/
# include <ESP32Servo.h> // this library needed specifically for the Arduino Nano
// for Uno use #include <Servo.h>
int pirPin = 2;//digital pin connected to the PIR's output
int pirPos = 12;//connects to the PIR's 5V pin
int ledPin = 12;
int calibrationTime = 30;
Servo myservo; //creates a servo object
int pos = 0; //variable to store servo position
//amount of time we give the sensor to calibrate (10-60 secs according to the datasheet)
int target = 0;
//the time when the sensor outputs a low impulse
long unsigned int lowIn;
//the amount of milliseconds the sensor has to be low
//before we assume all motion has stopped
long unsigned int mypause = 5000;
boolean lockLow = true;
boolean takeLowTime;
// -----------------------------------------------------------------------------
void setup (){
myservo.attach (9);//attaches servo to pin 9
Serial.begin (9600);//begins serial communication
pinMode (pirPin, INPUT);
pinMode (pirPos, OUTPUT);
pinMode (ledPin, OUTPUT); // LED light
// digitalWrite (pirPos, HIGH);
//give the sensor time to calibrate
Serial.println ("calibrating sensor ");
for (int i = 0; i < calibrationTime; i++){
Serial.print (calibrationTime - i);
Serial.print ("-");
delay (800); // gives time for PIR to settle down before reading
}
digitalWrite (ledPin, LOW);
Serial.println ();
Serial.println ("done");
while (digitalRead(pirPin) == HIGH) {
delay (500);
Serial.print (".");
}
Serial.print ("SENSOR ACTIVE");
}
// -----------------------------------------------------------------------------
void move (
int target,
unsigned long dly )
{
static int pos;
if ((target - pos) > 0)
myservo.write (++pos);
else if ((target - pos) < 0)
myservo.write (--pos);
delay (15);
}
// -----------------------------------------------------------------------------
byte pirState;
unsigned long dly;
void loop ()
{
move (pos, dly);
// if the PIR HIGH, select new random value
byte pir = digitalRead(pirPin);
if (pirState != pir) {
pirState = pir; // state change (recognize once)
if (HIGH == pir) {
pos = random (180);
// dly = random (800, 2800);
digitalWrite (ledPin, HIGH); // on
}
else {
pos = 90;
dly = 0;
digitalWrite (ledPin, LOW); // off
}
}
}
I would like to trigger this owl from a timer (presumably using millis function) instead of the PIR. So, say, once a minute the owl would go into its routine and then after another minute go back to "sleep" mode.
I've played around with the code, adding a Millis variable set for 10000 (which is 50 seconds. The LED eyes turn on, stay on for 50 seconds, then go back off. And this on-off cycle repeats every 50 seconds. So far so good.
When I try to put the servo code into the void loop, either nothing happens or the LED eyes still come on—but no movement of the servo. I need some help on which bits of the servo code to move into the void loop, assuming this is what I need to do.
Also, it's important to point out that the PIR's HIGH duration is controlled by the PIR itself. It's currently set for about 20 seconds, but can be adjusted by rotating a little knob on the PIR to be of longer or shorter duration. Ideally, if I'm simulating the PIR using Millis, I could have two separate time parameters—one for the simulated HIGH mode and one for the simulated LOW mode. For example the owl would be asleep for 1 minute and then go into its "routine" which would last for about 20 seconds.
Or since the PIR is still connected to this prop, is it possible to trigger the PIR into HIGH mode using a millis function? That way the PIR is still controlling the duration of HIGH mode, but triggering it is controlled by a millis time event.
Hope this makes sense. Here is my code that successfully makes the eyes come on. The part of the code that controls the servo is still commented out.
# include <ESP32Servo.h> // ESP32 Servo library
//# include <Servo.h>
int pirPin = 2;//digital pin connected to the PIR's output
int pirPos = 10; //connects to the PIR's 5V pin
int ledPin = 12;
int calibrationTime = 30;
unsigned long previousMillis = 0; // Time of the previous LED toggle
const unsigned long interval = 10000; // Time in milliseconds (50 seconds)
Servo myservo; //creates a servo object
int pos = 0; //variable to store servo position
// -----------------------------------------------------------------------------
//void setup (){
// myservo.attach (9);//attaches servo to pin 9
// Serial.begin (9600);//begins serial communication
// pinMode (pirPin, INPUT);
// pinMode (pirPos, OUTPUT);
// pinMode (ledPin, OUTPUT); // LED light
// digitalWrite (pirPos, HIGH);
// digitalWrite (ledPin, HIGH); //
//
// //give the sensor time to calibrate
// Serial.println ("calibrating sensor ");
// for (int i = 0; i < calibrationTime; i++){
// Serial.print (calibrationTime - i);
// Serial.print ("-");
// delay (800); // gives time for PIR to settle down before reading
// }
// digitalWrite (ledPin, LOW); // keeps initial state low DOESn't WORK?
// Serial.println ();
// Serial.println ("done");
//
// while (digitalRead(pirPin) == HIGH) {
// delay (500);
// Serial.print (".");
// }
// Serial.print ("SENSOR ACTIVE");
//}
// -----------------------------------------------------------------------------
bool
move (
int target,
unsigned long dly )
{
static int newpos;
if ((target - newpos) > 0)
myservo.write (++newpos);
else if ((target - newpos) < 0)
myservo.write (--newpos);
delay (dly);
return target == newpos;
}
// -----------------------------------------------------------------------------
unsigned long dly;
//void loop ()
//{
// if (HIGH == digitalRead(pirPin)) { // active
// digitalWrite (ledPin, HIGH); // on
// if (move (pos, dly)) { // new pos/dly once reached
// delay(1000); // waits for a second //***
// pos = random (180); //random position from 0-180
// Serial.println (pos);
// dly = 17; //was //random (12, 40); // more realistic to have one speed // lower is faster
// }
// }
// else {
// digitalWrite (ledPin, LOW); // low
// delay(40);
// move (90, 0); // return to center position
// }
//}
void setup() {
//myservo.attach (9);//attaches servo to pin 9 ABRACADABRA
pinMode(ledPin, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis(); // Get current time
if (currentMillis - previousMillis >= interval) { // Check if the interval has passed
previousMillis = currentMillis; // Update the previous time
toggleLED(); // Toggle the LED
}
}
void toggleLED() {
// Toggle the LED state
digitalWrite(ledPin, !digitalRead(ledPin));
}
