reliable wireless solution for analog input with ms timing?

I have a timing circuit that uses a photo transistor to monitor when a racer traverses a light beam. The photo transistor is read out on an analog input of an arduino uno. The analog signal depends on the light strength but is generally 900-1000 (4.5- 5V) and I trigger it when it falls to 500. I would like to monitor the photo transistor wirelessly but am not sure what the best route to go is. I would like to be able to maintain 1 ms accuracy as well. I need a range of about 100 ft or better. Reliability and resolution are the things I'm looking for and would be willing to spend extra to get them. Any advice is appreciated.

thanks

Brad

The simple answer is a pair of 433 MHz. transceivers. My favorite is the RFM22B, with 100 mw. max transmit power. For 100 ft. line of sight, that should be easy. These units can be had for about $5.60 on Ebay, have an excellent library from Radiohead, and seem to work right all the time. They require pins 2 (or 3), 10, 11, 12, 13 on an arduino, leaving you plenty of pins to work with.

I like these little fellas so much that I designed a circuit board combing the two with all other pins brought out to one end, so I can plug it into another board with whatever else I'm trying to control.

The difficult requirement is the 1 ms accuracy.
Do you really need this?

I think it highly depends on how often the racer passes the beam. If that's e.g. every minute, I don't think there will be an issue with 1ms accuracy if it can be maintained in the current code.

I had my first venture in RF transmission last weekend using this 433MHz combo. The RadioHead library takes some significant time to transmit a message. I used it at 2kBit per second (default) and it takes 78ms for the first two bytes; each additional byte takes 6 to 7 ms.

Test code used

#include <RH_ASK.h>
//#include <SPI.h> // Not actually used but needed to compile
RH_ASK driver;
// RH_ASK driver(2000, 2, 4, 5); // ESP8266: do not use pin 11


void setup()
{
  Serial.begin(9600);   // Debugging only
  if (!driver.init())
    Serial.println("init failed");

  pinMode(13, OUTPUT);
}

void loop()
{
  static unsigned long prevMillis = 0;
  unsigned long currMillis = millis();

  char msg[24];

  static int count;

  if (currMillis - prevMillis > 500)
  {
    prevMillis = currMillis;
    sprintf(msg, "%d", count++);

    driver.send((uint8_t *)msg, strlen(msg) + 1);
    driver.waitPacketSent();

    digitalWrite(13, !digitalRead(13));

    Serial.print("TX duration (ms): "); Serial.println(millis() - currMillis);
  }
}

Get yourself some Pocket Wizards.

Thanks for the responses.

I have looked a little into the 433 Mhz systems. My concerns there are how they are set up and what the timing delay is. It seems that i would need two arduinos and they would communicate on the TX,RX pins. I'm not sure how the data is transmitted and if I can still have my main loop continuously look at the RX pin for the fall below trigger or do i need the second arduino to look for the trigger and then send a single high signal? I'm not clear for example when people show a push button that is on the transmitting arduino and a LED on the receiver that lights when the button is pushed how the signal is being sent. For instance do I have the transmitting arduino reading the photo transistor on the analog pin converting the voltage to a integer (0-1024) then that integer is sent as binary to the receiver with the bit rate that is given by the wireless connection? It seems that the 433 Mhz is noisy so the libraries use clean up routines and I'm not sure if that slows down the data transfer? I guess I'm asking what is the effective sampling rate of the 433 MHz systems once the clean up procedures are implemented?
sterretje you say your getting one byte every 6 ms, I'm wondering how many bytes to send the voltage reliably and how much faster can you go than the default 2 kbit/s?

As far as the timing goes the racers go one at a time so the events are recorded separately and would be minutes apart. I would like to keep the highest time resolution possible as winners get cash prizes. I don't mind having ties at ms timescales.

I will try to talk to pocket wizard tech support and see what they have to say as well.

Thanks
Brad

If you have an Arduino at each end why not let the remote Arduino do the timing as well and just send the data of what it was. That frees you from a lot of the timing constraints you have.

For instance do I have the transmitting arduino reading the photo transistor on the analog pin converting the voltage to a integer (0-1024) then that integer is sent as binary to the receiver with the bit rate that is given by the wireless connection?

Your current Arduino keeps on doing what it is doing. It's currently measuring time; it's not relevant how. As I visualize it, it's something like

a button is pushed to turn on the start light; this will also start a timing
2)
when the beam is interrupted, the difference between the start time and the end time is measured

The added step would be to send the measured time (and not the voltage) to the other Arduino at the moment that the beam is interrupted.

If a lap time is significantly greater than the required transmission time, you should be OK from a timing perspective to continuously send data when the beam is interrupted; e.g. your transmission time is 200ms and your lap time is 2 seconds (no idea)

If you only want to measure one lap and stop, the transmission time is irrelevant as long as the next start is after the transmission has finished (you mention minutes in between).

they would communicate on the TX,RX pins.

You should not use the serial port for simple transmitters (like the ones I linked); the transmission basically relies on a balance between ones and zeroes. Sending a bit pattern 0000001 via the serial port will more than likely not work. That is why the RadioHead library does some tricks to achieve this; I have not completely analysed it. This is the reason why the transmission with RadioHead is relatively slow relatively slow.

If you have intelligent transmitters (no idea what exists), they will handle this for you and you don't need the RadioHead library and probably you can use the serial port with them.

how much faster can you go than the default 2 kbit/s

I don't know how much faster you can go. Might very well depend on the environment (how many other 433 transmitters are there that can interfere with your one) and the distance that you want to cover. RF has never been my strong point (still getting my feet wet on this).

The below code can act as a guide if you go with the cheap transmitter / receiver and the RadioHead library.

// number of transmit repeats for one packet
// note: you need to find a balance between transmit time and lap time
#define NUMTXREPEATS 5

// number of laps to measure
#define NUMLAPS 5

// pin for start button
const byte startButton = 4;
// pin for beam; this uses a digital pin for this demo
const byte beamPin = 5;
// pin for transmit in progress LED
const byte TXinProgressLed = 13;

void setup()
{
  // button connencted between pin and ground; active LOW
  pinMode(startButton, INPUT_PULLUP);
  // sensor connencted between pin and ground; active LOW
  pinMode(beamPin, INPUT_PULLUP);
  // transmit in progress LED
  digitalWrite(TXinProgressLed, LOW);
  pinMode(TXinProgressLed, OUTPUT);
}

void loop()
{
  // flag to indicate if measuring has started
  static bool fStarted = false;
  // timing start time
  static unsigned long startTime = 0;
  // lap timing start time
  static unsigned long lapStarttime = 0;

  // current 'time'
  unsigned long currentTime = millis();

  // lap counter
  static byte lapCounter = 0;

  // if start button was not pressed yet
  if (!fStarted)
  {
    // if start button pressed
    if (digitalRead(startButton) == LOW)
    {
      // indicate 'started'
      fStarted = true;
      // set start time
      startTime = currentTime;
      // set lap start time
      lapStarttime = startTime;
    }
  }
  // if not started yet
  if (!fStarted)
  {
    // nothing to do
    return;
  }
  // if beam not interrupted
  if (digitalRead(beamPin == HIGH))
  {
    // nothing to do
    return;
  }

  // increment lap counter
  lapCounter++;
  // calculate lap time
  unsigned long lapTime = currentTime - startTime;
  // reset lap start time time for next lap
  lapStarttime = currentTime;
  // transmit N times to improve chances of reception at the other side
  // note that this transmit (with RadioHead) is blocking (as far as I know)
  for (int cnt = 0; cnt < NUMTXREPEATS; cnt++)
  {
    transmit(lapCounter, lapTime);
  }

  // if all laps completed
  if (lapCounter == NUMLAPS)
  {
    // total time
    unsigned long totalTime = currentTime - startTime;
    // transmit total time; you can repeat this
    transmit(0, totalTime);

    // reset
    fStarted = false;
    lapCounter = 0;
  }
}

void transmit(byte counter, unsigned long duration)
{
  // combine data into one packet
  ...
  ...
  // indicate transmit in progress
  digitalWrite(TXinProgressLed, HIGH);
  // transmit packet
  ...
  ...
  // indicate transmit in progress finished
  digitalWrite(TXinProgressLed, LOW);
}

Note
To improve reliability, it sends data a number of times; you need to find a balance between lap time and and transmit time. The receiver only has to receive one packet correctly; if it receives more, it can compare and ignore if they are the same. You can also add a sequence number to a packet so you can detect dropped packets. As noted in the code, the RadioHead.transmission is blocking as far as I know.

As I said, if your lap times are much larger than the transmit time, you should not have an issue because the timing for a lap is restarted before the data is transmitted.

You can change the approach and not use a for loop; the effect of the blocking will be less noticeable; but it will depend on your needs if that is required.

The remainder of the code is non-blocking. If there is nothing to do, leave loop(); it's basically a very basic state machine. The code measures lap times and total time.

From my short experience with the cheap 433MHz transmitter/receiver, it's not the most reliable communication. The one moment one in three packets can be dropped (hence the NUMREPATS of 5), the next moment one in hundred or thousand.