Hi All, I'm a newbie and had code written for a simple mechanical eye movement using two servos per eye on an Arduino Uno using a PWM (PCA965) for 4 servos (DS3235).
The movement sequence is triggered by a motion sensor . When I push the button to enable the motion sensor the servos start the sequence even though motion has not been detected. The serial monitor shows "motion detected" continuously. If there is actual motion it does not register. I've replace the motion detector but no change.
Any help would be appreciated.
Sensor Wired as follows
5V
output to pin 7 on arduino uno
ground
jumper is on L
I have an external power supply connected to my PWM.
Here is the code.
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h> //Including PWM libraries
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); //Setting up PWM
#define RlrSERVOMIN 290
#define RlrSERVOMAX 370
#define RudSERVOMIN 290
#define RudSERVOMAX 370
#define LlrSERVOMIN 290
#define LlrSERVOMAX 370
#define LudSERVOMIN 290
#define LudSERVOMAX 370
//CENTER
#define RIGHTlrSERVOHOME 330
#define RIGHTudSERVOHOME 330
#define LEFTlrSERVOHOME 330
#define LEFTudSERVOHOME 330
int SPEED = 8;
#define SERVO_FREQ 50 //Dont change this
#define SERVO_RUD 0 //change this only if you plug in servo to diffrent pins
#define SERVO_RLR 1 //change this only if you plug in servo to diffrent pins
#define SERVO_LUD 2 //change this only if you plug in servo to diffrent pins
#define SERVO_LLR 3 //change this only if you plug in servo to diffrent pins
int LED1Pin = 8; //change this only if you plug in LED to diffrent pin
int LED2Pin = 9; //change this only if you plug in LED to diffrent pin
int LED3Pin = 10; //change this only if you plug in LED to diffrent pin
int button1Pin = 4; //change this only if you plug in Button to diffrent pin
int button2Pin = 2; //change this only if you plug in Button to diffrent pin
int button3Pin = 3; //change this only if you plug in Button to diffrent pin
const int motionSensorPin = 7; //change this only if you plug in MotionSensor to diffrent pin
//Bools to flag system on, motion sensor active, and random move active
bool systemActive = false;
bool motionSensorActive = false;
bool randomMoveActive = false;
//bools to flag weather button was pressed before
static bool button1LastState = false;
static bool button2LastState = false;
static bool button3LastState = false;
//Dont change these they are for button bouncing
unsigned long LastTimeButton1StateChanged = millis();
unsigned long LastTimeButton2StateChanged = millis();
unsigned long LastTimeButton3StateChanged = millis();
unsigned long LastTimeRandomWasSet = millis();
unsigned long LastTimeRandomStarted = millis();
unsigned long debounceDuration = 50;
int currentPosRlr = RIGHTlrSERVOHOME;
int currentPosRud = RIGHTudSERVOHOME;
int currentPosLlr = LEFTlrSERVOHOME;
int currentPosLud = LEFTudSERVOHOME;
int doLeftToRightNonBlockingPlayCount = 0;
int doRandomMoveNonBlockingPlayCount = 0;
void setup() {
//set up for console
Serial.begin(9600);
Serial.println("System Initialized");
//set up for LED pins
pinMode(LED1Pin, OUTPUT);
pinMode(LED2Pin, OUTPUT);
pinMode(LED3Pin, OUTPUT);
//set up for button pins
pinMode(button1Pin, INPUT);
pinMode(button2Pin, INPUT);
pinMode(button3Pin, INPUT);
//set up for motion sensor pin
pinMode(motionSensorPin, INPUT_PULLUP);
//reads buttons
button1LastState = digitalRead(button1Pin);
button2LastState = digitalRead(button2Pin);
button3LastState = digitalRead(button3Pin);
//set up for PWM
pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(SERVO_FREQ);
}
unsigned long doRandomMovePreviousMillis = 0;
const long doRandomMoveInterval = 20;
int doRandomMoveStepCount = 0;
int doRandomMoveTargetPosRlr = 330;
int doRandomMoveTargetPosRud = 330;
int doRandomMoveTargetPosLlr = 330;
int doRandomMoveTargetPosLud = 330;
void doRandomMoveNonBlocking(){
if (doRandomMoveStepCount == 0) {
doRandomMoveTargetPosRlr = random(RlrSERVOMIN, RlrSERVOMAX);
doRandomMoveTargetPosRud = random(RudSERVOMIN, RudSERVOMAX);
doRandomMoveTargetPosLlr = random(LlrSERVOMIN, LlrSERVOMAX);
doRandomMoveTargetPosLud = random(LudSERVOMIN, LudSERVOMAX);
currentPosRlr = doRandomMoveTargetPosRlr;
currentPosRud = doRandomMoveTargetPosRud;
currentPosLlr = doRandomMoveTargetPosLlr;
currentPosLud = doRandomMoveTargetPosLud;
doRandomMoveStepCount = 1;
}
unsigned long currentMillis = millis();
if (currentMillis - doRandomMovePreviousMillis >= doRandomMoveInterval) {
doRandomMovePreviousMillis = currentMillis;
if (doRandomMoveStepCount <= 25) {
int posRlr = currentPosRlr + (doRandomMoveTargetPosRlr - currentPosRlr) * doRandomMoveStepCount / 50;
int posRud = currentPosRud + (doRandomMoveTargetPosRud - currentPosRud) * doRandomMoveStepCount / 50;
int posLlr = currentPosLlr + (doRandomMoveTargetPosLlr - currentPosLlr) * doRandomMoveStepCount / 50;
int posLud = currentPosLud + (doRandomMoveTargetPosLud - currentPosLud) * doRandomMoveStepCount / 50;
pwm.setPWM(SERVO_RUD, 0, posRud);
pwm.setPWM(SERVO_RLR, 0, posRlr);
pwm.setPWM(SERVO_LUD, 0, posLud);
pwm.setPWM(SERVO_LLR, 0, posLlr);
currentPosRlr = posRlr;
currentPosRud = posRud;
currentPosLlr = posLlr;
currentPosLud = posLud;
doRandomMoveStepCount++;
}else{
currentPosRlr = doRandomMoveTargetPosRlr;
currentPosRud = doRandomMoveTargetPosRud;
currentPosLlr = doRandomMoveTargetPosLlr;
currentPosLud = doRandomMoveTargetPosLud;
doRandomMoveStepCount = 0;
doRandomMoveNonBlockingPlayCount ++;
}
}
}
void doLeftToRightNonBlocking(){
if (doRandomMoveStepCount == 0) {
doRandomMoveStepCount = 1;
}
unsigned long currentMillis = millis();
if (currentMillis - doRandomMovePreviousMillis >= doRandomMoveInterval) {
doRandomMovePreviousMillis = currentMillis;
if (doRandomMoveStepCount <= 50) {
int posRlr = currentPosRlr + (RlrSERVOMIN - currentPosRlr) * doRandomMoveStepCount / 100;
int posLlr = currentPosLlr + (LlrSERVOMIN - currentPosLlr) * doRandomMoveStepCount / 100;
pwm.setPWM(SERVO_RLR, 0, posRlr);
pwm.setPWM(SERVO_LLR, 0, posLlr);
currentPosRlr = posRlr;
currentPosLlr = posLlr;
doRandomMoveStepCount++;
}else if(doRandomMoveStepCount <= 200 && doRandomMoveStepCount > 50){
int posRlr = currentPosRlr + (RlrSERVOMAX - currentPosRlr) * doRandomMoveStepCount / 300;
int posLlr = currentPosLlr + (LlrSERVOMAX - currentPosLlr) * doRandomMoveStepCount / 300;
pwm.setPWM(SERVO_RLR, 0, posRlr);
pwm.setPWM(SERVO_LLR, 0, posLlr);
currentPosRlr = posRlr;
currentPosLlr = posLlr;
doRandomMoveStepCount++;
}else{
currentPosRlr = doRandomMoveTargetPosRlr;
currentPosLlr = doRandomMoveTargetPosLlr;
doRandomMoveStepCount = 0;
doLeftToRightNonBlockingPlayCount++;
}
}
}
void resetServos() {
//this function moves all the servos to the home position
pwm.setPWM(0, 0, RIGHTlrSERVOHOME);
pwm.setPWM(1, 0, RIGHTudSERVOHOME);
pwm.setPWM(2, 0, LEFTlrSERVOHOME);
pwm.setPWM(3, 0, LEFTudSERVOHOME);
currentPosRlr = RIGHTlrSERVOHOME;
currentPosRud = RIGHTudSERVOHOME;
currentPosLlr = LEFTlrSERVOHOME;
currentPosLud = LEFTudSERVOHOME;
}
void eyeMovement(){
//Add side to side motion below
//Position 1
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 5);
pwm.setPWM(1, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME + 30);
pwm.setPWM(3, 0, LEFTudSERVOHOME - 40);
delay(150);
//Position 2
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME +5);
pwm.setPWM(1, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME + 15);
pwm.setPWM(3, 0, LEFTudSERVOHOME -40);
delay(200);
//Position 3
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 5);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME + 15);
pwm.setPWM(3, 0, LEFTudSERVOHOME - 40);
delay(150);
//Position 4
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 5);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME + 40);
pwm.setPWM(3, 0, LEFTudSERVOHOME + 5);
delay(150);
//Position 5
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 20);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 40);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME + 40);
pwm.setPWM(3, 0, LEFTudSERVOHOME + 5);
delay(100);
//Position 6
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 30);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 10);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME + 15);
pwm.setPWM(3, 0, LEFTudSERVOHOME + 15);
delay(150);
//Position 7
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 40);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 10);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME + 15);
pwm.setPWM(3, 0, LEFTudSERVOHOME + 15);
delay(150);
//Position 8
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 40);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 10);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME + 15);
pwm.setPWM(3, 0, LEFTudSERVOHOME -5);
delay(150);
//Position 9
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 40);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 10);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME);
pwm.setPWM(3, 0, LEFTudSERVOHOME);
delay(150);
//Position 10
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 40);
pwm.setPWM(1, 0, RIGHTudSERVOHOME + 10);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME);
pwm.setPWM(3, 0, LEFTudSERVOHOME);
delay(150);
//Position 11
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 40);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 20);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME);
pwm.setPWM(3, 0, LEFTudSERVOHOME - 40);
delay(150);
//Position 12
//Eye 1
pwm.setPWM(0, 0, RIGHTlrSERVOHOME + 35);
pwm.setPWM(1, 0, RIGHTudSERVOHOME - 40);
//Eye 2
pwm.setPWM(2, 0, LEFTlrSERVOHOME);
pwm.setPWM(3, 0, LEFTudSERVOHOME - 40);
delay(150);
//Position 13
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME + 40);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME + 40);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(150);
//Position 14
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME+ 30);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME + 30);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(150);
//Position 15
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME+ 20);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME + 20);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(150);
//Position 16
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME+ 10);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME + 10);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(150);
//Position 17
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(150);
//Position 18
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME - 10);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME - 10);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(150);
//Position 19
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME - 20);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME - 20);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(150);
//Position 20
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME - 30);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME - 30);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(150);
//Position 21
//Eye 1
pwm.setPWM(1, 0, RIGHTlrSERVOHOME - 40);
pwm.setPWM(0, 0, RIGHTudSERVOHOME);
//Eye 2
pwm.setPWM(3, 0, LEFTlrSERVOHOME - 40);
pwm.setPWM(2, 0, LEFTudSERVOHOME);
delay(300);
resetServos(); //Move the servos to the home position and turn the LEDS on
}
bool readyToDetectMotion = true;
unsigned long timeLastMotionWasDetected = 0;
void loop() {
//this is constantly looped
if (millis() - LastTimeButton1StateChanged >= debounceDuration) { //If debounceTime is up since first button was pressed (for debouncing)
bool Button1State = digitalRead(button1Pin); //Check to see what button 1 reads
if (Button1State != button1LastState) { //if button 1 is not what it was last time(on or off)
LastTimeButton1StateChanged = millis(); //for button debouncing
if (Button1State == LOW) { //if button is pressed
Serial.println("Button 1 has been pressed");
if(systemActive){ //if the system was active before and the button was pressed
Serial.println("SYSTEM IS NOW OFF");
systemActive = false; //turn the system off
randomMoveActive = false;
motionSensorActive = false;
}
else{
Serial.println("SYSTEM IS NOW ON");
systemActive = true; //turn the system on
resetServos();//moves all the servos to the home position
}
}
button1LastState = Button1State; //set last button press to what it is now
}
}
if(systemActive){ //if the system is on
digitalWrite(LED1Pin, HIGH); //turn the Green LED on
if (millis() - LastTimeButton2StateChanged >= debounceDuration) { //If debounceTime is up since first button was pressed (for debouncing)
bool Button2State = digitalRead(button2Pin); //Check to see what button 2 reads
if (Button2State != button2LastState) { //if button 2 is not what it was last time(on or off)
LastTimeButton2StateChanged = millis(); //for debouncing
if (Button2State == LOW) { //if button is pressed
Serial.println("Button 2 has been pressed");
if(motionSensorActive){ //if the motion sensor system was on before and button was pressed
Serial.println("Motion sensor SYSTEM IS NOW OFF");
motionSensorActive = false; //turn the Motion sensor system off
}
else{
Serial.println("Motion sensor SYSTEM IS NOW ON");
motionSensorActive = true; //turn the Motion sensor system on
}
}
button2LastState = Button2State; //set last button press to what it is now
}
}
if (millis() - LastTimeButton3StateChanged >= debounceDuration) { //If debounceTime is up since first button was pressed (for debouncing)
bool Button3State = digitalRead(button3Pin); //Check to see what button 3 reads
if (Button3State != button3LastState) { //if button 3 is not what it was last time(on or off)
LastTimeButton3StateChanged = millis(); //for button debouncing
if (Button3State == LOW) { //if button is pressed
Serial.println("Button 3 has been pressed");
if(randomMoveActive){
Serial.println("randomMoveActive SYSTEM IS NOW OFF");
randomMoveActive = false; //randomMoveActive sensor system off
resetServos(); //home the servos
LastTimeRandomWasSet = millis();
digitalWrite(LED2Pin, HIGH); //turn eye LEDS on
digitalWrite(LED3Pin, HIGH); //turn eye LEDS on
}
else{
Serial.println("randomMoveActive SYSTEM IS NOW ON");
randomMoveActive = true; //randomMoveActiven sensor system on
LastTimeRandomStarted = millis();
}
}
button3LastState = Button3State; //set last button press to what it is now
}
}
if(randomMoveActive){ //when random move is active (this will NOT move the servos randomly)
for(int i = 0; i < 6; i++){ //repeat the action 4 times CHANGE this to however many times you want eyes to do moving action
eyeMovement();
eyeMovement();
eyeMovement();
delay(1500);
digitalWrite(LED2Pin, HIGH);
digitalWrite(LED3Pin, HIGH);
delay(15000); //wait 10 seconds before turning LEDS off
digitalWrite(LED2Pin, LOW);
digitalWrite(LED3Pin, LOW);
}
randomMoveActive = false; //once system does moving action turns off random move active
Serial.println("randomMoveActive SYSTEM IS NOW OFF");
}
if(doLeftToRightNonBlockingPlayCount == 1 || doLeftToRightNonBlockingPlayCount == 2){
doLeftToRightNonBlocking();
}else if(doLeftToRightNonBlockingPlayCount == 3){
doLeftToRightNonBlockingPlayCount = 0;
doRandomMoveNonBlockingPlayCount = 1;
}
if(doRandomMoveNonBlockingPlayCount >= 1 && doRandomMoveNonBlockingPlayCount <= 7){
doRandomMoveNonBlocking();
}else if(doRandomMoveNonBlockingPlayCount == 8){
resetServos();
delay(2000);
digitalWrite(LED2Pin, HIGH);
digitalWrite(LED3Pin, HIGH);
delay(5000);
digitalWrite(LED2Pin, LOW);
digitalWrite(LED3Pin, LOW);
doRandomMoveNonBlockingPlayCount = 0;
}
if(motionSensorActive){ //when motion sensor is active
int motionDetectedRead = digitalRead(motionSensorPin);
if(millis() - timeLastMotionWasDetected >= 30000){
if(motionDetectedRead == HIGH) {
if (readyToDetectMotion) {
Serial.println("MotionDetected");
doLeftToRightNonBlockingPlayCount = 1;
readyToDetectMotion = false;
timeLastMotionWasDetected = millis();
}
} else {
if(millis() - timeLastMotionWasDetected >= 30000) {
readyToDetectMotion = true;
}
}
readyToDetectMotion = true;
}
}
}
else{ //when sysytem is off
//turn all LEDs off
digitalWrite(LED1Pin, LOW);
digitalWrite(LED2Pin, LOW);
digitalWrite(LED3Pin, LOW);
resetServos();
}
}