Your Own Red Light Camera Scam, Powered by Arduino

Probably not far off from the real ones

Let’s say you’re a city that has no respect for its citizens, and are looking to generate extra revenue by going against safety standards and making your yellow lights shorter, to entrap more drivers with red light cameras. Essentially, all you have to do is lower the timing for a yellow light at your stop light, thereby giving drivers much less time to safely stop and increasing the chances that you can capture them on a red light camera and issue a fine.

How about we use an Arduino to create one!

The abuse of red light cameras for revenue generation is extremely well-documented, so I thought about what would be the best way to build one, to both maximize revenue and somewhat difficult to detect, for a simple Arduino project. Let’s approach the problem from it the perspective of a shady city official and traffic engineer accomplice.

After doing some research about traffic engineering standards for yellow light timing and how they’re abused, I decided that we’d assue that we’re going to place the traffic light on a 40 mph road, where the accepted yellow light timing should be 4.5 seconds (or 4500 milliseconds). I decided that the minimum time for our yellow light would be 2.5 seconds, since if we cause too many accidents, then people will start to notice.

At 40 mph, the car would be able to travel 146.75 ft during the 2.5 sec yellow light duration (our shortest stoping time, before accounting for deceleration), while according to this stopping distance calculator, the driver would need 119 ft to fully stop. This gives the driver an extra 27.75 ft to stop in that time. This means that we’re not asking drivers to stop in an impossibly short time span in our worst-case scenario, and will help our chances if we face legal challenges.

To get the proper balance for revenue generation and avoiding detection, I thought that we’d want to make the light shorter 45% of the time, with a random amount of time subtracted off our base 4.5 second timing. That way, it’s not too often so that drivers will notice since it’s just below random chance, and because we’re randomizing the yellow light time within that probability, it would be extremely difficult to detect unless someone timed themselves at that intersection a number of different times.

Here is our simple circuit for the traffic light (using the Smraza Arduino kit and guides). I prefer to use the 220 Ω resistors, since traffic lights have to be relatively bright to be seen in daylight. (Pictures courtesy of Smraza docs.)

The completed circuit will look something like this:

Once we’ve built our circuit, we can first use the example of a stoplight following traffic engineering standards. We have our red and green lights on for 30 seconds (30000 msecs) each, then a yellow light time of 4.5 seconds (4500 msecs), with 250 msecs in the middle. Basically, we turn on the pins that are connected to each light with digitalWrite (where HIGH is on, and LOW is off), with our delays (in milliseconds) in between.

int redLED = 3;
int yellowLED = 5;
int greenLED = 7;

void setup()
{
    pinMode(redLED, OUTPUT);
    pinMode(yellowLED, OUTPUT);
    pinMode(greenLED, OUTPUT);
}

void loop() {
    digitalWrite(greenLED, HIGH);
    delay(30000);
    digitalWrite(greenLED, LOW);
    delay(250);
    digitalWrite(yellowLED, HIGH);
    delay(5000);
    digitalWrite(yellowLED, LOW);
    delay(250);
    digitalWrite(redLED, HIGH);
    delay(30000);
    digitalWrite(redLED, LOW);
}

Our code for the abusive version of the light will be very similar, but we’ll first generate a random number between 1 and 100. To seed our pool of entropy, we’ll call the randomSeed function at each interation of the loop, which we point to an unused analog pin (A0) on our Arduino board.

void loop() {
  //-- Snip --
  randomSeed(analogRead(A0));

  float randomNumber  = random(1,100);
  //-- Snip --
}

If that random number is less than or equal to 45, we’ll apply the random subtraction to our yellow light timing, giving us our 45% probability. To decide the time that we’ll shorten the light, we’ll take our random number divided by 100 to get a percentage, then multiply that by our 2 second (2000 msecs) shortening range to figure out how much we’ll shorten the light. Finally, we subtract this number from the baseline 4.5 second time, and insert this delay in between calling digitalWrite for the yellow LED pin. We also add serial output for funsies (though in production you’d want to remove that to help with evading detection and creating evidence of your fraud).

float BaseYellowDelay = 4500.0;

//-- Snip --
randomDelay = (randomNumber / 100.0) * 2000.0;
Serial.println("Random number is:");
Serial.println(randomNumber);
Yellowdelay = BaseYellowDelay - randomDelay;

if (randomNumber <= 45.0 ) {
  Serial.println("Yellow light delay is:");
  Serial.println(Yellowdelay);
  Serial.println("Profit!");
  digitalWrite(yellowLED, HIGH);
  delay(Yellowdelay);
  digitalWrite(yellowLED, LOW);
} else if (randomNumber > 45.0) {
  Serial.println("Non-skewed yellow delay is:");
  Serial.println(BaseYellowDelay);
  Serial.println("Evading detection...")
  digitalWrite(yellowLED, HIGH);
  delay(BaseYellowDelay);
  digitalWrite(yellowLED, LOW);
}

Our finished code looks like this:

int redLED = 3;
int yellowLED = 5;
int greenLED = 7;

float randNumber;
float randomDelay;
float Yellowdelay;

// Need to be subtle, but we want to maximize revenue
// 45% likeliness of short yellow light - this is a good balance
// http://shortyellowlights.com/standards
// Let's use 4.5 seconds (4500 msecs) as our baseline
float BaseYellowDelay = 4500.0;

void setup()
{

    pinMode(redLED, OUTPUT);
    pinMode(yellowLED, OUTPUT);
    pinMode(greenLED, OUTPUT);

    Serial.begin(115200);
}

void loop() {
    // read from unused analog pin, to initialize randomness
    randomSeed(analogRead(A0));

    digitalWrite(greenLED, HIGH); 
    delay(30000);
    digitalWrite(greenLED, LOW);

    // This determines our chances of getting caught
    // we will delay it randomly between
    // 4500 msecs all the way down to 2500 msecs
    // (2000 msec range)
    float randomNumber  = random(1,100);
    // Take fraction of randomNumber,
    // then apply percentage to our 2000 msec range for shortening
    //
    // per arduino docs, with floating point
    // all numbers need decimal
    randomDelay = (randomNumber / 100.0) * 2000.0;
    Serial.println("Random number is:");
    Serial.println(randomNumber);
    Yellowdelay = BaseYellowDelay - randomDelay;

    if (randomNumber <= 45.0 ) {
      Serial.println("Yellow light delay is:");
      Serial.println(Yellowdelay);
      Serial.println("Profit!");
      digitalWrite(yellowLED, HIGH);
      delay(Yellowdelay);
      digitalWrite(yellowLED, LOW);
    } else if (randomNumber > 45.0) {
      Serial.println("Non-skewed yellow delay is:");
      Serial.println(BaseYellowDelay);
      Serial.println("Evading detection...")
      digitalWrite(yellowLED, HIGH);
      delay(BaseYellowDelay);
      digitalWrite(yellowLED, LOW);
    }

    delay(250);
    digitalWrite(redLED, HIGH);
    delay(30000);
    digitalWrite(redLED, LOW);
}

Output:

Profit!

Thankfully the legal challenges to red light cameras are starting to become pretty widespread, but I’m still shocked at how many places were getting away with it, even places that don’t seem to rely on rapacious fines for revenue generation. (Depressing side note, places where the police do this extensively, they forget to solve actual crimes, since they’re focused instead on profit motives, usually specifically targeting people of color!) Hopefully these legal challenges are coming to a jurisdiction near you!


 
1 Kudos
Don't
move!