Measuring FPV Latency

I was testing a new camera and I was under the impression that the latency was quite high. Usually I am not susceptible to high latency, but this was driving me crazy. I was not sure if my mind was playing tricks on me, so the only way to be sure, is to actually measure the latency.

In this article I will tell you a bit more about my setup and why I chose to go the way I did. If you have a digital, 2 channel oscilloscope it is probably easier to do the measurements with that, but since I do not have one, I had to find a different solution.

The “wrong” way

A common method seems to be to film a timer on a computer monitor with the FPV cam next to a FPV screen receiving the signal from the video transmitter. Unfortunately this method has so many different factors to consider:

  • Refreshrate of the monitor
  • Refresrate of the FPV monitor
  • Framerate of the camera you are recording with

Considering that we want to measure latency somewhere in the range of 1-100ms the above setup will not provide good results: The monitor might have a refresh-rate of 60FPS - so each frame is shown for 1/60 of a second or 16ms. This means the range we are trying to observe is in the worst case (super high latency of 100ms) 6 frames long - or to word it differently, we can only count in 16ms increments. With low latency (around 4ms) it would mean, that we would not even be able to measure that.

Now we have to consider the frame-rate the camera is recording with - optimally this is the same frame-rate the monitor is refreshing with. If we, for example, only record with 30 FPS, we are halving our precision - suddenly we are only measuring in 32ms increments.

Measuring with an Arduino

I decided to take another route. My idea was to mount a LED in front of the cam, a photo resistor to the screen and utilize an Arduino to measure the time between the LED being switched on and the Photo resistor registering the change.

The Setup is super simple you will only need the following components, which you likely already have lying around anyway:

  • Arduino Uno (any Arduino should be OK)
  • 5V LED (almost anyone should be OK here - make just sure that the bright resistance is as low as possible) and a 10k pull down resistor
  • Blu-Tack (or similar) - this is optional, you can use sticky tape to mount LED and photo resistor
  • The Arduino sketch which can be found on my github

Wire the components according to the diagram:

You can also change the used pins, but then you will need to make adjustments in the code.


In order to test your components follow this steps:

  1. Blu-Tack your LED and photo resistor together (or put them into a well lit isolated box)
  2. Run the calibration: Min should show a value close to 0, optimally 0. max should show a value close to 1023 - realistically this will be in the range of 600-800. But the higher the better. It should at least be 10 higher than the min value. The value that will be shown here exactly will depend on the brightness of your LED and the photo resistor you used
  3. Run the measurements: You should get measurements around 120us here
Running Measurements...
##### START #####
00:	112us	(0ms)
01:	116us	(0ms)
24:	112us	(0ms)
Avg:	113us	(0ms)
Min:	112us	(0ms)
Max:	116us	(0ms)
#####  END  #####

If one of the above steps should fail, double check your wiring. Check that the LED is attached the correct way around. Also make sure the photo resistor is connected properly.


I attached the LED with Blu-Tack to the camera, but you can also simply put the camera in a box with the LED - just make sure that the LED is the only light source in the box. This can sometimes be hard, since the flight controller and video transmitters often have LED’s too.

Next I attached the photo resistor to my FPV monitor, I again do this with Blu-Tack, but you can also simply put FPV monitor and photo resistor in a different box. If you are using your goggles instead of a screen, I would not recommend using Blue-Tack on the screens. simply position the photo resistor as close as possible to the screens.


Now it is time to establish a baseline. Press 1 in the serial console and confirm with enter, this will start the calibration. The photo resistor is read once without the LED being on and once with the LED being on. From this a threshold is calculated:

Min: 18 Max: 667 Threshold: 28

You need to check that the threshold is above the minimum and below the maximum value. If this is the case, you are ready to take the measurements.


Press 2 in the serial console and confirm with enter, this will start the measurements. Ten measurements are taken at random intervals. After at most 50 seconds the measurements are done and the results are displayed:

Running Measurements...
##### START #####
00:	8296us	(8ms)
01:	11324us	(11ms)
02:	18600us	(18ms)
03:	11320us	(11ms)
04:	9972us	(9ms)
05:	4592us	(4ms)
23:	8744us	(8ms)
24:	10876us	(10ms)
Avg:	10866us	(10ms)
Min:	4592us	(4ms)
Max:	18600us	(18ms)
#####  END  #####

Each of the ten measurements is shown. Additionally a summary with minimal, maximal and average latency is shown.


Precision and Error

The results are very repeatable. For measuring the duration of the latency, Arduinos millis method is used. Obviously the Arduino is not a calibrated device. The clock of the Arduino drifts quite a bit (around 1S over the course of 40 minutes, but this also depends on temperature). If you need more precision, I would recommend using a real-time clock.

The way that Arduino is keeping time, is by it’s 16MHz oscillator. Depending on the exact components used when your Arduino was assembled, the tolerances of this oscillator might differ.

That being said, I think that this drift is negligible in the time domain we are measuring, which is - I would say - 1-100ms.

At least you can definitely use this method for relative measurements since the error will be the same across all of your measurements, if taken in the same environment. So you can make assumptions like this: Camera A has a lower latency than camera B.

Be aware that since this is a glass to glass test, you are measuring the total latency of all involved components: Camera, VTX, VRX and screen. In order to get comparable results, the only variable you should exchange in this chain should be the camera itself.

Chris is a Vienna based software developer. In his spare time he enjoys reviewing tech gear, ripping quads of all sizes and making stuff.

Learn more about Chris, the gear he uses and follow him on social media:

Show more comments