Be gentle with me - I'm an aeronautical engineer, but the last time I did anything in software we still thought C was strictly for geeks, and I refused to touch C++ because I believed in a classless society...(that joke gets worse every time I tell it)
I'm developing a simple system for a friend who wants to monitor wildlife activity in her garden. Essentially it controls a camera from an RC transmitter to put it in one of three modes:
- Camera OFF
- Camera ON
- Camera triggered by any of several PIR detectors
I have an Rx connected and the board (Arduino Nano) takes a PWM output from one channel which is driven from a 3-pos switch using pulsein() to se the mode. The PIRs are connected to DIO pins and go HIGH when triggered. The camera is standard commercial 360 camera which is operated by a momentary button (press for on, press again for off) so I have a servo driven lever that does a move-pause-return cycle for each press, driven from another DIO pin.
After a few false starts I actually have this working (code for the 2-PIR concept trial version is below) although I have taken the easy route and done it as sequential code rather than structuring it more elegantly into subroutines (maybe later). In this form she can switch the Tx off, walk away and let the Rx failsafe control the mode, but I would like to set it up so she can set it going, then actually unplug the Rx and leave it in whatever state she set before removing the Rx (because she wants to have several of them in her copse and would like to have only one receiver). The device is powered from its own (big) battery, so the Rx connection only connects ground and signal.
I initially thought I could use the pulsein() timeout to trigger this, but pulsein() behaviour with an open-circuit input seems very unpredictable. So the question is this - is there a simple way for the Arduino to detect whether there is an Rx connected on not - something that I can use to drive a flag that goes false when the Rx is removed and becomes true again when it's plugged back in? I looked at possibly doing a heartbeat over the telemetry bus, but that will need a few days (years) of study to bring my C competence anywhere near close to doing serial data streams!
Any thoughts appreciated,
PDR
#include <Servo.h>
// PWM input settings
int pin = 2; //pin connected to Rx channel
int RxIN = 1200; //channel PPM value
// PIR Input Settings
int pin1 = 3; //pin connected to first PIR
bool PIR1 = false; //first PIR on/off
int pin2 = 4; //pin connected to second PIR
bool PIR2 = false; //second PIR on/off
//command state settings
unsigned int ON = 1800; //threshold for ON command (must be greater than this)
unsigned int automatic = 1100; //threshold for OFF command (must be less than this)
bool CameraState = false; //defines actual camera state (initialised to off)
bool PIR = false; //defines overall PIR state
bool CAM = false; //defines desired camera state (initialised to off)
int mode = 1; //Tx mode selection
//servo position settings
unsigned int LEFT = 1000; //defines left position for servo (in microseconds)
unsigned int RIGHT = 2000; //defines right position for servo (in microseconds)
unsigned int dwell = 500; //defines dwell before reversing back off the button
// Servo assignments
Servo myservo; //name of servo
unsigned int ServoPin = 9; //DIO pin number for servo
void setup() {
Serial.begin(57600); //this is a guess - may need to play with it.
myservo.attach(ServoPin); //defines servo output pin (must be 6,8,9,12,13 or 14)
pinMode(ServoPin, OUTPUT);
pinMode(pin, INPUT);
pinMode(pin1, INPUT);
pinMode(pin2, INPUT);
}
void loop()
{
//Serial.println("-------");
delay(50); //safe frame delay to protect servo
PIR1 = digitalRead(pin1);
PIR2 = digitalRead(pin2);
if (PIR1 == true || PIR2 == true) { //check to see if either PIR is triggered
CAM = true; //Set PIR Flag
} else {
CAM = false; //Clear PIR Flag
}
RxIN = pulseIn(pin, HIGH); //measure incoming pulse width
if (RxIN < automatic) { //Set mode number for auto
mode = 0;
} else if (RxIN > ON) { //Set mode number for overide
mode = 2;
} else { //Set mode number for OFF
mode = 1;
}
switch (mode) {
case 0:
if (!CameraState && !CAM) { //Automatic Mode
myservo.writeMicroseconds(LEFT); //set/keep servo to left end
delay(dwell);
}
else if (!CameraState && CAM) {
myservo.writeMicroseconds(RIGHT); //move servo to right end
delay(dwell); //pause over the camra button
myservo.writeMicroseconds(LEFT); //move servo to right end
CameraState = true;
}
else if (CameraState && !CAM) {
myservo.writeMicroseconds(RIGHT); //move servo to right end
delay(dwell); //pause over the camra button
myservo.writeMicroseconds(LEFT); //move servo to right end
CameraState = false;
}
else if (CameraState && CAM) {
myservo.writeMicroseconds(LEFT); //set servo to left end
delay(dwell);
}
break;
case 2:
if (CameraState == false) {
myservo.writeMicroseconds(RIGHT); //move servo to right end
delay(dwell); //pause over the camra button
myservo.writeMicroseconds(LEFT); //move servo to right end
CameraState = true;
}
if (CameraState == true) {
myservo.writeMicroseconds(LEFT); //set servo to left end
delay(dwell);
}
break;
case 1:
if (CameraState == true) {
myservo.writeMicroseconds(RIGHT); //move servo to right end
delay(dwell); //pause over the camra button
myservo.writeMicroseconds(LEFT); //move servo to right end
CameraState = false;
}
if (CameraState == false) {
myservo.writeMicroseconds(LEFT); //set servo to left end
delay(dwell);
}
}
}