Input Lag Test Analysis with Arduino Due and a 60Hz monitor

Everything about latency. Tips, testing methods, mouse lag, display lag, game engine lag, network lag, whole input lag chain, VSYNC OFF vs VSYNC ON, and more! Input Lag Articles on Blur Busters.
Post Reply
os4321
Posts: 5
Joined: 20 Jun 2018, 18:24

Input Lag Test Analysis with Arduino Due and a 60Hz monitor

Post by os4321 » 07 Nov 2018, 23:18

Hi,

I was curious how input lag can be affected on a 60hz monitor with various settings e.g. vsync on/off, RTSS scanline sync, in-game video settings low vs ultra, screen resolution scale increased, etc.

I have an Arduino Due with a photodiode pointed at a 60hz monitor (Dell U2414H). The photodiode is polled every 1ms, the Arduino Due sends a single Mouse.move(127,127,0) command via USB to the PC. The input lag is determined based on number of readings since the Mouse.move command until the photodiode readings change e.g. low to high (dark to light).

Here are some graphs I put together in case anyone is interested. Each type of test is run 100 times with random 1000-2000ms delay between each test of the Mouse.move command. Each line is 1 test run.

https://imgur.com/a/4qTnm85

This is somewhat working as far as I can tell but I dont have any way to be sure.

There is around a 16ms transition between its initial climb until it reaches it's peak which I think makes sense as it's a 60hz monitor and I think this is when the monitor has finished drawing of the frame and this is when the end user will see it.

However I notice there is quite a lot of variance for each run of the test (each line) initial climb start time when using random delays between each test. If i set the delay between each test to the same e.g. 1000ms, then the graphs line up almost perfectly (initial climb start the same time each run). I dont know if this is expected behavior or maybe something not quite right in my set-up. From what I tested the Arduino could poll the photodiode around 200 times per 1 ms, which is why I capped it to poll once per 1 ms to make the data more manageable to work with, as far as I could tell the uncapped polling had similar results.

I guess I was curious whether I can cap my fps to 60 frames, turn up video settings in game and still experience the same input lag as before. To me it felt like input lag got slightly worse when increasing video settings in game even though the GPU can easily render frames within the 16.67ms window, e.g. 60fps low video quality settings vs 60fps ultra. But I cant say for sure even with the graphs as there is so much variance between the first (min lag) and slowest (max lag) runs.

According to TFTcentral the Dell U2414H has a 4ms input lag which is similar to some of the quickest 144/240hz panels they also tested. I was curious whether the input lag is noticeable even though it's a 60hz panel.

Edit: I should also mention capping the fps to 60fps with vsync off also produced the worst screen tearing experience in my case so in practical terms it was not really a viable option as the screen tearing made spotting enemies much harder compared with frames uncapped or capped at 70 fps. The closer it was capped to 60 fps the worse the screen tearing became with vsync off. I dont know if that is expected behavior as I dont have another PC to test with. The RTSS scanline sync method was a pretty good middle ground experience which helped to eliminate screen tearing while adding slight (noticeable but manageable) input delay as long as the GPU usage was below 70%.

User avatar
RealNC
Site Admin
Posts: 3756
Joined: 24 Dec 2013, 18:32
Contact:

Re: Input Lag Test Analysis with Arduino Due and a 60Hz moni

Post by RealNC » 08 Nov 2018, 13:42

Wow! That is a neat and cheap way to test input lag. No mouse modification nor 1000FPS camera required, and seems much faster to take the samples too!

I'd suggest uploading the code for that on github or similar. Surely such a setup would be interesting to many display experts?
os4321 wrote:The RTSS scanline sync method was a pretty good middle ground experience which helped to eliminate screen tearing while adding slight (noticeable but manageable) input delay as long as the GPU usage was below 70%.
Isn't the slight latency increase simply due to the lower FPS compared to running the game completely uncapped? I don't think RTSS (scanline sync or just normal cap) adds any input lag whatsoever.
SteamGitHubStack Overflow
The views and opinions expressed in my posts are my own and do not necessarily reflect the official policy or position of Blur Busters.

os4321
Posts: 5
Joined: 20 Jun 2018, 18:24

Re: Input Lag Test Analysis with Arduino Due and a 60Hz moni

Post by os4321 » 08 Nov 2018, 18:07

The code is very simple, it just sends a mouse move command, takes readings of the photodiode every 1ms for total 200 times in my case, then moves the mouse back to its original position.

code for Arduino:

Code: Select all

#include <Mouse.h>

// define pins used on Arduino Due
int button1pin = 38;
int analogueInPin0 = 0; // photodiode

void setup() {

  // configure input button with internal pullup resistor enabled
  pinMode(button1pin, INPUT_PULLUP);

  //initiate the Mouse library
  Mouse.begin();

  // Initialize Native USB port
  SerialUSB.begin(9600);    

}

void loop() {

  // button press to start the test
  if (digitalRead(button1pin) == LOW){
    // delay to allow time for button to be depressed e.g. simple debounce mechanism
    delay(500);

	// run 100 tests
    for (int i = 0; i < 100; i++) {
      // delay between tests to allow time for light sensor reading to stablize
      //delay(1000);
      delay(random(1000,2000));
      runInputLagTestMouseMoveReadSensorOnly();
    }
    
  }

}

void runInputLagTestMouseMoveReadSensorOnly(){

    int photodiodeReading = 0;
	unsigned long totalTime = 0;

    // start timer
    unsigned long startTime = millis();
    //SerialUSB.println (startTime);
    
    // send mouse move command
    Mouse.move(127,-127,0);
    
	// take 200 readings at 1ms intervals, output readings in CSV format to serial monitor
    for (int i = 0; i < 200; i++) {
      photodiodeReading = analogRead(analogueInPin0);
      SerialUSB.print(photodiodeReading);
      SerialUSB.print(",");
      delay(1);
    }
    
    unsigned long endTime = millis();
    //SerialUSB.println(endTime);
	
	// newliine at end of CSV format so list of readings for each test on a seperate line
	SerialUSB.println();

    totalTime = endTime - startTime;
	//SerialUSB.println(totalTime);
    
    
    // move mouse back to original position
    Mouse.move(-127,127,0);
  
}
Then copy the data output from the Arduino Serial monitor console and paste it into a spreadsheet in CSV format. In my case I use Libreoffice Calc then transpose the data (swap columns to rows) to make it easier to draw the graphs: select the data in Libreoffice Calc -> Cut (ctrl + x) -> Paste Special -> choose Transpose. This makes each column separate test where the photodiode readings displayed per row, so row 1 is the first 1ms reading, etc.

From what I could tell the 200 readings take 200ms, but after around 2000 readings it starts to drift by 1ms so 2000 readings take 2001ms.

I just dont know how accurate this method is as I dont have any way to be sure. There are also some unknowns such as I dont have a datasheet for the photodiode so I dont know the response time of it.

Sparky
Posts: 682
Joined: 15 Jan 2014, 02:29

Re: Input Lag Test Analysis with Arduino Due and a 60Hz moni

Post by Sparky » 08 Nov 2018, 18:33

However I notice there is quite a lot of variance for each run of the test (each line) initial climb start time when using random delays between each test. If i set the delay between each test to the same e.g. 1000ms, then the graphs line up almost perfectly (initial climb start the same time each run). I dont know if this is expected behavior or maybe something not quite right in my set-up. From what I tested the Arduino could poll the photodiode around 200 times per 1 ms, which is why I capped it to poll once per 1 ms to make the data more manageable to work with, as far as I could tell the uncapped polling had similar results.
A random delay is required to de-correlate the test from the framerate. If the framerate is 60hz, there's a 17ms window in which an input will result in an output at the same time. Ideally that random delay is a common multiple of polling interval and frame interval. Without the random delay, you're just measuring the variance in frame time, and only know average latency to +- 1 frame.

To make the data easier to process you can set a threshold, then measure the delay until the input crosses that threshold.

With vsync off the variance in latency should correlate to frame times. With vsync on(uncapped), the variance should correlate to 1/refresh rate). With vsync on (capped), the variance should correlate to 1/(refresh rate + framerate). With freesync(capped) the variance should correlate to 1/(framerate).

I did pick up some phototransistors, to replace the photoresistor in my old setup. Maybe I'll get around to reworking it.

Here are a couple relevant posts. Though the due is built on a different microcontroller, so if you use my code you'll need to change the parts relating the the prescaler and the USB ISR.

viewtopic.php?f=10&t=3005&start=50#p22634
viewtopic.php?f=10&t=1381&start=310#p23272

One thing you can do with the Due that hasn't been done yet AFAIK is use the USBHost capability to measure the absolute latency of mice and keyboards.

os4321
Posts: 5
Joined: 20 Jun 2018, 18:24

Re: Input Lag Test Analysis with Arduino Due and a 60Hz moni

Post by os4321 » 09 Nov 2018, 12:45

Thanks for the explanation :)

Sparky
Posts: 682
Joined: 15 Jan 2014, 02:29

Re: Input Lag Test Analysis with Arduino Due and a 60Hz moni

Post by Sparky » 10 Nov 2018, 16:15

I dug up this chart from some testing a few years ago: https://docs.google.com/spreadsheets/d/ ... nteractive

Post Reply