NRF 24 Netwok is this feasible?

I am trying to figure out the best way to build a wireless tally light system using an arduino uno as the base and up to eight camera mountable nanos attached to the cameras to let the cameramen (students) know when their camera is switched for the live production. All will be equipped with long range NRF 24s. I think it will be relatively easy to transmit a message (1-8) to all receivers, and have each identify if the code matches their unit which will light a LED. This should also be relatively quick as the individual cameras will receive all updates immediately.

But I would really like a system that will let me know if the camera receivers are in range and working. Since the NRF24 has only 6 pipes, eight satellite nodes cannot work directly. I think I have a creative idea, and want to consult the experts to see if it will work. I have no real experience either with networking, or as of yet, the arduinos.

My Idea:

One base station with eight satellites. Base station transmits camera #message to all odd numbered satellites.

Odd numbered satellites relay current camera number message, and add a second message with its personal station number transmitted to all even number receivers. For instance 1 might send 00000001 and three send 00000100.

Even numbered satellites then check camera number and append second message with their ID. For instance camera 4 receives information from both cameras 1 and 3, so appends second message to read 00001101 to include received and personal information, then transmits it back to the base.

Base then compiles all messages received, and shows if any digit is missing (that camera was not communicated with).

As I see it, this would require only two of the available six pipes, and hopefully will work as a pseudo mesh type environment. Is this possible?

If your system has a master Arduino/nRF24 that polls the other slaves you only need to use one pipe and you can have lots of slaves.

The pair of programs in this link were derived from a model train control system and could easily be adapted to poll a large number of slaves. Just give each slave a separate address,

I got my nRF24s working with this Tutorial

I suggest you use the TMRh20 version of the RF24 library - it solves some problems from the ManiacBug version

...R

Thanks Robin2.

I do not wish to poll the slaves, only send out a number from 0-8 that the slaves record. Then the slaves can light an led if the number sent equals the their person number. I am getting close, but am lost in the syntax I think. Fortran IV was my coding introduction, and you can probably figure out how long ago that was. Thanks for your reply

Hi,

But I would really like a system that will let me know if the camera receivers are in range and working.

You will need to poll the slaves to find out if they are in range, but I think the nRF does that when it sends packets of data.
Sorry been a long time since I played with nRF.

Tom.... :slight_smile:

MrBrooks:
I do not wish to poll the slaves, only send out a number from 0-8 that the slaves record.

You can do that with the sort of system in my link. It won't matter if the slaves have no data to send back.

"polling" generally just means communicating with each one in turn rather than simultaneously.

Another option might be to send a string like "01001010" where 0 = off and 1 = on and the example would mean slave1 OFF, slave2 ON, slave3 OFF etc. In this case all the slaves would have the same address.

That message could then be received by all the slaves at the same time. You would need to turn off the acknlowledgments so as not to confuse the master.

And (as I think more about it) maybe your original idea was to send a number (1-8) that is received by all the slaves and each one knows which to react to. That can also be done if all the slaves have the same address.

Finally it is unfortunate that some examples use the name "pipe" for the variable that holds the address. The actual 6 pipes are a quite different concept - they allow one nRF24 to listen simultaneously for messages from 6 slaves.

Sorry this is a bit confused. Hope it helps

...R

Robin 2, can I send some code your way and have you try to tell me what I am doing wrong. I keep getting a invalid conversion from int to void when I try to compile

Post your code here and I will look at it. I don't give advice privately. Please ask your question in the public Forum. That way other experienced people can also give advice and other beginners can learn along with you.

...R

Here is the code so far. I am getting errors with the radio.write line. Suggestions are appreciated. I think that part of the problem is that I have cobbled together code from various places.

For the base unit:

/*Tricaster Transmit

  • This sketch utilizes nrf24 transceivers to send a signal
  • from the base station based on which camera is currently
  • selected by the switcher.
    */
    #include <SPI.h>
    #include "RF24.h"
    RF24 radio(9,10);

// Declare global variables
const uint64_t pipe = 0xE8E8F0F0E1LL;
int CAM1 = 2;
int CAM2 = 3;
int CAM3 = 4;
int CAM4 = 5;
int CAM5 = 6;
int CAM6 = 7;
int CAM7 = 14;
int CAM8 = 15;
int LEDR = 16;
int LEDG = 17;
int LEDY = 18;
int TRCSTR = 8;

int Number;
// Pin 9 ==> CE
// Pin 10 ==> CS(N)
// Pin 11 ==> MOSI
// Pin 12 ==> MISO
// Pin 13 ==> SCK

void setup(void){
//establish pin input and output
pinMode(CAM1, INPUT);
pinMode(CAM2, INPUT);
pinMode(CAM3, INPUT);
pinMode(CAM4, INPUT);
pinMode(CAM5, INPUT);
pinMode(CAM6, INPUT);
pinMode(CAM7, INPUT);
pinMode(CAM8, INPUT);
pinMode(TRCSTR, INPUT);
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDY, OUTPUT);

}

void loop(void){
// Begin serial communication
Serial.begin(9600);
radio.begin();
// the following statements improve transmission range
radio.setPayloadSize(1); // setting the payload size to the needed value
radio.setDataRate(RF24_250KBPS); // reducing bandwidth

radio.openWritingPipe(pipe);
// Show green LED if tricaster is plugged in and operating
// or show yellow LED if not

if(digitalRead(TRCSTR==HIGH)){
digitalWrite(LEDG, HIGH);
digitalWrite(LEDY, LOW);
}
else{
digitalWrite(LEDG,LOW);
digitalWrite(LEDY,HIGH);
}
// Determine which camera is selected and set variable cameraSelected to that selection
unsigned int cameraSelected = 0;
if (digitalRead(CAM1) == HIGH){
cameraSelected = 1;}
else if (digitalRead(CAM2) == HIGH){
cameraSelected = 2;}
else if (digitalRead(CAM3) == HIGH){
cameraSelected = 3;}
else if (digitalRead(CAM4) == HIGH){
cameraSelected = 4;}
else if (digitalRead(CAM5) == HIGH){
cameraSelected = 5;}
else if (digitalRead(CAM6) == HIGH){
cameraSelected = 6;}
else if (digitalRead(CAM7) == HIGH){
cameraSelected = 7;}
else if (digitalRead(CAM8) == HIGH){
cameraSelected = 8;}
else {cameraSelected = 0;
}

// Broadcast camera number to all receivers
radio.write (cameraSelected,1);
Serial.print (cameraSelected,1);
}

For the receiver:

/*Tricaster Receive

  • This sketch utilizes nrf24 transceivers to recieve a signal
  • from the base station and determine if this camera is currently
  • selected by the switcher.
    */
    #include <SPI.h>
    #include "RF24.h"
    RF24 radio(9,10);

// Assign Global Variables
int cameraSelected;
int Number;
const uint64_t pipe = 0xE8E8F0F0E1LL;
int DIP1 = 2;
int DIP2 = 3;
int DIP3 = 4;
int DIP4 = 5;
int DIP5 = 6;
int DIP6 = 7;
int DIP7 = 14;
int DIP8 = 15;
int LEDR = 16;
int LEDG = 17;
int LEDY = 18;
// Pin 9 ==> CE
// Pin 10 ==> CS(N)
// Pin 11 ==> MOSI
// Pin 12 ==> MISO
// Pin 13 ==> SCK

void setup(void){
// Determine which Receiver number from dip switch (1-8)
pinMode(DIP1, INPUT);
pinMode(DIP2, INPUT);
pinMode(DIP3, INPUT);
pinMode(DIP4, INPUT);
pinMode(DIP5, INPUT);
pinMode(DIP6, INPUT);
pinMode(DIP7, INPUT);
pinMode(DIP8, INPUT);
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDY, OUTPUT);

//This section Identifies receiver # that is
//attached to the cameras.
if (digitalRead(DIP1 == HIGH)){
Number=1;
}
else if (digitalRead(DIP2==HIGH)){
Number=2;
}
else if (digitalRead(DIP3==HIGH)){
Number=3;
}
else if (digitalRead(DIP4==HIGH)){
Number=4;
}
else if (digitalRead(DIP5==HIGH)){
Number=5;
}
else if (digitalRead(DIP6==HIGH)){
Number=6;
}
else if (digitalRead(DIP7==HIGH)){
Number=7;
}
else if (digitalRead(DIP8==HIGH)){
Number=8;
}
else {
Number = 0; // This ensures no error if no dip is selected
}
// Start Communications
Serial.begin(9600);
radio.begin();
// the following statements improve transmission range
radio.setPayloadSize(1); // setting the payload size to the needed value
radio.setDataRate(RF24_250KBPS); // reducing bandwidth
radio.openReadingPipe(1,pipe);
radio.startListening();
}

void loop(void){
// Turns on green receive LED if the radio is available and
// yellow LED (radio off) if available
if (radio.available()){
digitalWrite(LEDG, HIGH);
digitalWrite(LEDY, LOW);
bool done = false;

// The following routine will read cameraSelected number from base
while (!done){
done = radio.read(cameraSelected,1);
Serial.println(cameraSelected);
}
// If the cameraSelected number matches number from base the red LED will light
// Otherwise the red LED will be turned off
if (cameraSelected == Number){
digitalWrite(LEDR, HIGH);
delay(10);
}
else {digitalWrite(LEDR, LOW);
}
delay(10);
}

// If radio is not available yellow LED on and Green LED off
else{Serial.println("No radio available");{
digitalWrite(LEDY,HIGH); //turns on yellow “no receive” light
digitalWrite(LEDG,LOW);}} //turns off green light
}

Again, thanks for suggestions

The first thing they will tell you is to use code tags for your code. If you go to preview you will see the icon to add code tags. This make it much easier to copy and troubleshoot.

Good luck on your project. When I was technical directing, I used a hot mic and talked to my camera men to call the shots and tell them when they were going live. Today it is a lot different with all that you can do in post production but if you don't get the shots to begin with post production isn't much help.

I did a music video shoot of a live performance and went crazy with calling for focus and zooms while doing cross fades with a 4 camera crew and an assistant doing the audio mix. When finished I then thought about edits and realized that all the crossfades make it almost impossible. When the producer saw the playback he started crying. I thought he was upset. He hugged me and kissed me and said, "I couldn't have been more perfect."

As far as the programming, just take it a step at a time. There are a lot of sample code to play with and study and this is a great place to learn and share.

Thanks Nasa. We do the same thing, director calling out cameras via wireless intercom. Of course, sometimes that fails. At those times, the director would call out the camera to one of the kids who would then raise her or his fingers to indicate the online camera. Spotters at each camera then let the operators know which camera is live. This can get pretty tough over the size of a stadium or auditorium. and we still have breaks (even though they do professional work, they are still kids). I want an easy visual reminder that would still work if comms go down (hopefully). Watching the kids is pretty impressive. We do seven camera live telecasts of sports (including two channel replay) or special school events. Kids spend hundreds of hours each year after school, sometimes until midnight, to do this. I just help out on the technical side, the real kudos go to the program instructor. We have been the National Champions in Broadcast news through Skills USA for 5 of the past 6 years, and hope to repeat this year. Our YouTube channel is

I only had a look at the transmitter part yet
int CAM1 = 2;should beconst byte CAM1 = 2;(saves two bytes RAM)

  pinMode(CAM1, INPUT);is superfluous, but I would prefer (and wire for)  pinMode(CAM1, INPUT_PULLUP);

All this

void loop(void) {
  // Begin serial communication
  Serial.begin(9600);
  radio.begin();
  // the following statements improve transmission range
  radio.setPayloadSize(1); // setting the payload size to the needed value
  radio.setDataRate(RF24_250KBPS); // reducing bandwidth

  radio.openWritingPipe(pipe);

belongs into setup.

  else {
    cameraSelected = 0;
  }

is superfluous.

  Serial.print (cameraSelected, 1);The illegal base of 1 is luckily ignored.

Transmitting one byte of an int variable (two bytes) is strange.

You should limit the packet rate by other means than blocking on 9600 baud.

I think you should debounce the buttons/keys and respond to button/key changes.
I would use a library like Bounce2 to handle the buttons/switches to make the edge detection easy.

I would get rid of the dip-switches in the receiver and store the ID in EEPROM, it could be setup via serial.

 else {
    Serial.println("No radio available"); {
      digitalWrite(LEDY, HIGH);  //turns on yellow "no receive" light
      digitalWrite(LEDG, LOW);
    }
  }   //turns off green light

Not using the F() macro wastes another 19 bytes of RAM.

So you really want to print 20 bytes (taking 2 mS) if there is no packet available?

It would be better to remember the time of the last good reception and react on that.

Get rid of all the delay() calls.

BTW 3 DIP switches are enough for 8 cameras.

Thanks for the suggestions Whandall. Many have been incorporated. The Serial prints are only for debugging, and I will comment those out when it is working well. I am interested in why you chose pullup for the inputs. I was actually planning on putting in a pulldown resistor on the inputs to take care of stray voltage. The switcher we use has a dedicated tally output that gives 5V to the channel selected. I could program the arduino to read the pin low for incoming signals...what would be the advantage of using this method?

You are probably right about the dip switch. My idea was to make every receiver the same and have the kids then manually put in the camera number. That way if I have a problem with one being dropped or otherwise not working, I could easily have a spare. It may however, offer additional fail points.

INPUT_PULLUP does not need an external resistor (on shorter connections at least).

As I look more, doesn't pullup require a path to ground through the switch? In the case I am using, I have an external 5V (it varies up to about 7.5) powered feed when selected that I need to read. No switch, except internally through the video switcher that provides the output current supposedly to a LED. Output is through a HD DB15 which I can break out for individual camera identification. My thought was using a voltage divider (1K and 2.2K resistors) to keep voltage between 3.3 and 5, then a pulldown resister on the input to avoid stray voltage. Am I going the wrong direction?

I think I have my coding figured out, but suggestions for streamlining are always appreciated!

I think you will need a GND connection anyway (unless you want to use opto-isolators).

I thought you were talking about standard switches, if you have a voltage to read that's different.
In that case just drop the pinModes(), as INPUT is the default.

Hi,

Whandall:
I thought you were talking about standard switches, if you have a voltage to read that's different.
In that case just drop the pinModes(), as INPUT is the default.

No don't drop the pinModes(), in my opinion that is lazy, change them to INPUT.
Leaving them out completely will not give you a quick and efficient list of I/O, which is important if you are looking at a sketch written by someone else.
Thanks.. Tom.. :slight_smile: