Okay, I took the time to clean up/rework my latency tester.
To start, the detector circuit(I also tried a 2 opamp configuration but it didn't seem to make any difference in performance):
The photoresistor ranges from about 3k to about 200k. (this is just the resistor, not a module)
R2 is 1k
R3 is 10k
C1 is 100uf
U1 is a NTE987
To be honest, I think my old method (comparing analog values) is a bit faster(due to being able to set a very borderline threshold), but this has the advantage of setting its own threshold, and not caring about ambient light so much. Testing the photocell against a LED illuminated by the arduino is about 50us.
Next, the sketch:
Code: Select all
//runs on arduinos based on ATMEGA 32u4
#include <Mouse.h>
boolean buttonPressed = 0;
boolean sample = 0;
volatile boolean trigger1 = 0;
boolean movedRight = 0;
// Define various ADC prescalers
const unsigned char PS_16 = (1 << ADPS2);
const unsigned char PS_32 = (1 << ADPS2) | (1 << ADPS0);
const unsigned char PS_64 = (1 << ADPS2) | (1 << ADPS1);
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
int sensorValue = 0;
int sensorPrevious = 0;
long a = 0;
long b = 0;
long c = 0;
volatile long d = 0;
void setup() {
ADCSRA &= ~PS_128; // remove bits set by Arduino library
ADCSRA |= PS_16; // set prescaler to 16,
pinMode(3, INPUT_PULLUP);//Connect to switch's normally open contact
pinMode(4, INPUT_PULLUP);//Connect to switch's normally closed contact
pinMode(5, OUTPUT);//LED
pinMode(7, INPUT);//From output of opamp/comparator
pinMode(A0, INPUT);//From non-inverting input of opamp/comparator
Serial.begin(9600);
Mouse.begin();
randomSeed(analogRead(A0));
attachInterrupt(digitalPinToInterrupt(7),trigger, RISING ) ;
}
void trigger(){
trigger1 = 1;
d = micros();
}
void loop() {
if (digitalRead(4) == LOW) {
buttonPressed = 0;
}
if (digitalRead(3) == LOW && buttonPressed == 0) {
buttonPressed = 1;
sample = !(sample);
trigger1=0;
if (movedRight){
movedRight=0;
digitalWrite(5, LOW);
Mouse.move(-1, 127, 0);
}
Serial.println("-------------------------------Break in data-------------------------------");
}
if (sample) {
if ( trigger1 && movedRight) {
c=d;
sensorValue = analogRead (A0);
Mouse.move(-1, 127, 0);
digitalWrite(5, LOW);
movedRight = 0;
Serial.print (c - a); //PC under test delay (subtracts out USB poll interval)
Serial.print (",");
Serial.print (c - b); //combined end to end delay
Serial.print (",");
Serial.println (sensorValue);
trigger1=0;
} else {
if ((c - a) > 1000000 && movedRight) {
Serial.print ("No trigger, Sensor value: ");
sensorValue = analogRead (A0);
Serial.println (sensorValue);
delay(100);
}
if (movedRight == 0) {
movedRight = 1;
delay(100); // Delay to allow for phosphor decay, pipeline clearing, etc. Helps prevent false positives
delayMicroseconds(random(1, 200000)); //get rid of refresh rate correlation, this can be changed to 1,000,000/refreshrate.
delayMicroseconds(random(1, 1000)); //get rid of usb poll correlation
Mouse.move(1, -127, 0);//mouse.move takes approx 40 microseconds.
b = micros();
while (a < b) a = lastTX; // requires modification of USB ISR in USBCore.cpp
digitalWrite(5, HIGH);
}
}
}
}
And finally, the modifications I made to the arduino library files:
In USBAPI.h I added a line defining the variable we need(I added it after the "// USB" comment):
Code: Select all
extern volatile unsigned long lastTX;
In USBCore.cpp I added 2 lines, one declaring the variable:
And one to gather the data we want from the USB ISR:
Code: Select all
USB_Flush(CDC_TX); // Send a tx frame if found
lastTX = micros();