Detecting RC Receiver removed

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:

  1. Camera OFF
  2. Camera ON
  3. 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);
      }
  }
}

Can you give more information about this part.
A datasheet of this RC (or a link).

Also post a schematic of your project so we can understand it better.

Can you add one extra connection? Wire from ground in the receiver to an input pin and set it to use the internal pull-up resistor. When the device is connected the pin will read low and when disconnected it will read high.

The receiver will be a standard Frsky receiver (could be any of half a dozen), using the normal servo PWM output (Nominally 1-2msec pulses at a 50hz frame rate). This shouldn't matter because pretty well all RC receiver PWM outputs are exactly the same*.

The signal pin of the receiver's servo (PWM) output is connected to a DIO pin (D2, as defined in the first code line), and while connected the Receiver's ground is connect to the Arduino ground. The receiver outputs positive-going 5v pulses. Pulse width is around 980usec at the low end, 1500usec at centre and around 1980usec at the high end. The pulsein() function has no difficulty reading these pulses and returns rational values when the receiver is connected.

But the receiver shouldn't matter because what I want to do is detect when the receiver is disconnected, so there are no pulses at all on the DIO pin - it is open circuit. The pulsein() function returns very unpredictable values when the there is nothing connected to the input - probably reacting to noise. Should I put a pull-down on it and then try using the pulsein() time-out value?

PDR

  • Other than the faster frame rates which some offer for "digital" servos, but I'm not using the fast rate.

That, sir, is a stroke of genius! I knew there would be a simple solution!!

Am I right in thinking there's a software command which will provide an internal pull-up, or am I thinking of something else?

PDR

This did it, and by declaring the pin type as "INPUT_PULLUP" I didn't even need a pull-up resistor.

Many thanks

PDR

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.