Arduino Beyond the Blink: How Fast is Fast?

Arduino's "blink" sketch has introduced a lot of people to the world of programmable microcontrollers, but where do you go from there? A simple 555 circuit can blink an LED, so why did we pay $35 to have an 8-bit computer do it? Let us investigate a bit about how fast our eyes, ears, and brain are compared to silicon transistors and LEDs.

In addition to the LED, let's add some input so we can vary the LED speed. Attach a potentiometer to ground, pin A1, and VCC like shown in the diagram.


Load and run the following sketch:

/*
LED attached to D13
Potentiometer attached to A1
*/


int sensorPin = A1;   // potentiometer connected analog pin 1          
int ledPin = 13;      // LED is connected to digital pin 13
long lastPrint;       // variable to track how often to print


void setup()
{// this function runs once when the sketch starts up
  Serial.begin(9600); // so we can talk back to the computer
  Serial.println("LED_and_Potentiometer.pde");
  pinMode(ledPin, OUTPUT);
  lastPrint = millis(); // time in ms since reset
}


void loop()
{ // this function runs repeatedly after setup() finishes
  int sensorValue = analogRead(sensorPin); // get 10-bit reading  
  digitalWrite(ledPin, HIGH);              // Turn the LED on
  delay(sensorValue);                      // Pause for sensorValue in ms
  digitalWrite(ledPin, LOW);               // Turn the LED off
  delay(sensorValue);                      // Pause for sensorValue in ms
                                 
  if((millis() - lastPrint) > 1000){// only print once a second
    Serial.println(sensorValue);
    lastPrint = millis();
  }
}

You should be able to open the Serial Monitor () and see how long the delay is and change it with the potentiometer.  Here are some questions:
  • What is the range of sensorValue
  • How many bits would it take to represent these values?
  • What is the shortest sensor value that you can still see the blinking?
Your eye can detect changes somewhere in the 10 - 20 ms range. That seems to be limited by how fast the rods and cone can react. I don't have a data sheet for the human eye, but there is a trick to catch much faster changes if you employ a range of receptors instead of one group. How you you do that? Just move the LED. You should be able to see blinks 10 times as fast.  Here is an RGB LED spinning on a piece of thread while cycling at 1 ms.

So how fast can the Arduino cycle the LED? It is clocked at 16 MHz, which means it executes 16 million instructions per second, but how many instructions does it take take to turn the LED on and off? Let's write a routine to figure it out:
void timerLoop(){
  long cycles = 100000;
  long startTime = millis();
  Serial.print("Timing 100,000 LED cycles: ");
  for(long x=0; x<cycles; x++){
    digitalWrite(ledPin, HIGH);
    digitalWrite(ledPin, LOW);
    }
  long elapsedTime = millis() - startTime;
  Serial.print(elapsedTime);
  Serial.println(" ms");
  Serial.print(cycles / elapsedTime);
  Serial.println(" LED cycles per millisecond!");
  Serial.print("or ");
  Serial.print(cycles / elapsedTime * 1000);
  Serial.println(" per second.");
}
I'm measuring 112 on/off cycles per milliseconds. That has us talking about 9 microseconds per on/off cycle. Notice we've gone from milliseconds to microseconds. That is a jump of 1000 times or three orders of magnitude. (We are going faster, so shouldn't it be orders of "minitude"?) So at 16 million instructions per second, in 9 microseconds 144 instructions would execute. That seems like a lot to just turn an LED on and off, but that is part of the overhead the Arduino libraries and the beautiful simplicity the digitalWrite() function provides. If you needed it faster, you could write it in assembly language, but it is already several orders of "minitude" faster than your eye so why bother! That, and it would be nearly impossible to read or debug the code.

Tune in next time and we'll add a button and test the eye/hand reaction time.

1 comment:

  1. Amazing, thanks! 9microseconds per on/off cycle. Very interesting. I've wondered about building an Arduino-driven strobe system to watch jet break-up (Rayleigh instability). One would only need on the order of 100 Hz for this, I think.

    ReplyDelete