The Rage Maker

A Sneaky USB Prank

Johann Wyss

Issue 17, November 2018

This article includes additional downloadable resources.
Please log in to access.

Log in

Imagine laying in bed at the end of a long day, you turn the TV and lights off, shut your eyes and get comfortable. Just as you’re starting to drift away, a soft but commanding beep begins to ring out, each time jolting you from your near slumber!

You turn the lights on and go looking for whatever it was beeping as things don’t just beep for no reason. Unable to find anything you get back into bed and switch the lights off only to have the same beeping return...

Do you consider yourself a practical joker and enjoy pranking your friends or family? This project is for you!

BUILD TIME: 2-3 Hours

If that sounds like the perfect prank to play on one of your close friends or family members who enjoy a good prank, then let us introduce you to what we have affectionately called the Rage Maker.


As avid fans of some light pranking, my son Johnathan and I decided to spend a little time over the school holidays building our own new and improved version of the popular “Annoy-A-Tron” range of prank products sold by ThinkGeek. We wanted a device which would be very simple to build allowing anyone with a basic understanding of modern electronics assembly to build it.

We wanted it to be as low cost as possible, so it can be shared, given away and perhaps even left behind for an unsuspecting victim. We also wanted it to be as small as possible, making it hard to find.

Therefore, considering the previous two criteria, we needed it to not require batteries. This allows the device to work as long as possible, making it as cheap as possible and also as small as possible as we didn’t need to include a battery in the case.


The device is extremely simple, using only a few components. It uses a light dependent resistor (LDR), which is a variable resistor that changes its resistance when exposed to a light source. In very bright light from, let’s say a torch, the resistance of the LDR is about 500Ω. Whereas, in the dark, it is closer to 75000Ω. Using the LDR in combination with a series resistor we can create a voltage divider, which if you missed it, was covered in issue 11.

The voltage divider allows us to read the changes in voltage as a result of the LDR changing its resistance dependent on the ambient light. This change in voltage can be read by the analog to digital converter (ADC) on a microcontroller.

If the device is in a very bright room for example, it would create a voltage divider of essentially a 500Ω resistor in series with the second resistor (in our case a 10,000Ω resistor). This would produce a voltage of:

Vout = Vin × (R1 / (R1 + R2))

Vout = 5 × (10,000 / (10,000 + 500))

Vout = 4.76V

Whereas, if it were in a very dark room the LDR has a resistance of 75,000Ω, thus the output voltage would be:

Vout = Vin × (R1 / (R1 + R2))

Vout = 5 × (10,000 / (10,000 + 75,000))

Vout = 0.58V

The ADC in the microcontroller reads the voltage then gives it a 10-bit value between 0 and 1023 with 1023 being 5V, and 0 being 0 volts. Then all we needed to do was create a program/sketch that would use that value to know if the device is in the dark.

If the device is indeed in the dark, we can then have the device beep at a pre-defined rate, switching a digital pin of the microcontroller high or low. This digital pin is then connected to the piezo buzzer, causing the piezo crystal to vibrate, thus creating the audible beep for our “victim/loved ones” to enjoy.

The Fundamental Build:

The Prototype

Parts Required:JaycarAltronicsCore Electronics
1 × Arduino Compatible NanoXC4414Z6372CE05101
1 × 5mm Red LED*ZD0150Z0800CE05103
1 × Light Dependent ResistorRD3485Z1621SEN-09088
1 × 10kΩ 1/4W Resistor*RR0596R0058PRT-14491
1 × 330Ω 1/4W Resistor*RR0560R0040PRT-14490
1 × 12mm Piezo BuzzerAB3459-ADA1536

Parts Required:

* Quantity shown, may be sold in packs. Breadboard and prototyping hardware is also required.

My first step to designing the Rage Maker was to build a prototype on a Breadboard. Even though I intended to use an ATtiny13 on the final build, I chose to use an Arduino Nano to make programming and debugging much easier.

I have included the parts list, schematic and fritzing here if you would like to make your own. You can skip this prototype build if you prefer.

Prototype using a Nano
Prototype using a ATtiny


I found using an Arduino Nano made it is significantly easier to program, and to test, debug and interactively tinker with the code.

Keep in mind though, the code built on the Arduino will not perfectly match the behavior when changing to the ATtiny due to the different clock speeds. The Nano has an 16MHz clock speed while the ATtiny13 is using a 9.6MHz internal oscillator.

I added an LED to the prototype as a visual cue for the beep (just in case like me, you can’t stand constant beeping). If you’re much more tolerant of beeping than I, you can omit the LED and the 330Ω resistor.

The ATtiny version is exceptionally compact.

Other than that, it is just a simple process of following the Schematic and Fritzing diagram shown here, and then programming the Arduino as you would any other project. The code is described in the main build. With the prototype working, you can now make the main build.

Making It Portable

While we've focused on USB power here, since it's so robustly available, it would be very easy to adapt this project to run from a battery.

ATtiny chips have versatile power ranges, so you don't really need a boost converter to run them from 2 × AA batteries or similar, however you're unlikely to get alot of battery life from them.

If you're planning to make it totally portable and run for a long period, it is worth investigating low power modes.

Unlike the loops where the microcontroller is idle, putting things into sleep mode while waiting can drastically reduce power consumption, providing you with exponentially greater battery life. Sometimes the gain will be from mere hours, to a number of days, all with the exact same batteries! Actual results are dependent on many factors of course.

Our article on ATtiny low power modes in Issue 15 covers this in great detail, and can easily be applied to this project.

The Main Build:

Complete Rage Maker

Parts Required:JaycarAltronicsCore Electronics
1 × ATtiny13 Microcontroller--014-9171550
1 × Light Dependent ResistorRD3485Z1621SEN-09088
1 × 10kΩ 1/4W Resistor*RR0596R0058PRT-14491
1 × 100nf Monolythic CapacitorRG5125R2736BCE05188
1 × 100µf Electrolytic CapacitorRE6130R4825CE05258
1 × USB plug--PRT-00437
1 × 12mm Piezo BuzzerAB3459-ADA1536
1 × 20mm × 43mm PerfboardHP9550-ADA2670

Parts Required:

*Quantity shown, may only be sold in packs.

For my main build, I used an ATtiny13A that I had on hand. These are available from Core Electronics, or alternatively, you could use an ATtiny85 and change the pinouts in the code.



When soldering the capacitors keep them as close as practical to the VCC pin of the microcontroller, in our case with the ATtiny13 pin 8. These form a noise suppression and stability function for the microcontroller.


The first challenge with building the device is figuring out the pinout for the USB A connector. This connector will be used only to deliver power to the device, so we will leave the D+ and D- pins floating/disconnected.

Looking front on to the connector the pinout is as follows.

From right to left. VCC, Data -, Data +, GND.

You need to drill the PCB so that the two locating / support pins can be soldered down to the board, this will ensure the connector is firmly held in place and that it can sustain the forces of repeatedly, inserting and removing it into a USB socket. I recommend making the blob of solder extend to at least one other solder pad for additional strength. For more strength you can solder to more, just make sure that the pads you’re soldering to are not needed for other components or traces.


For this project, I opted to use the ATtiny13, which is an 8-pin microcontroller with a very similar footprint to the ATtiny85 and about 60% of its cost. Likewise, it is generally about 70% cheaper than the ATmega328P. These characteristics make it ideal for this project.

Whilst cheaper and smaller microcontrollers exist, they are generally significantly harder to program, usually requiring specialised programming hardware and compilers. Whereas, using an Atmel microcontroller allows us to simply use the Arduino IDE, along with a library specifically for the controller.


In order to use the Arduino IDE to program the ATtiny13A, we need to show the Arduino IDE specific information about the microcontroller we are using, i.e. the pinout, clock speeds and number of ADCs , etc. This is usually done via the board manager/selector, however, if you open your Arduino IDE and navigate to Tools › Board, you will notice there is no option to select the ATtiny13A. Therefore, we need to add it to the IDE, by navigating to File › Preferences.

Under Additional Board Manager URL’s you want to add:

This will direct the board manager inside the Arduino IDE to this site when searching for updated board data.

Now we need to update the boards via the board manager. Go to Tools › Board › Board Manager. In the search field type in “DIY Attiny”, or simply scroll down the results field. Once you find it simply click install. Once done, you should get a lot more board options in the Arduino IDE. Go to Tools › Board and you should see something like this:


Once we have the hardware and IDE ready to go, we now need to prepare the Microcontroller by burning the Arduino bootloader to it.

First, you need to set the programmer to "Arduino as ISP". Go to Tools > Programmer and select Arduino as ISP.

Programming The ATtiny13:

I can’t recommend enough the benefit of using a dedicated programming hat/shield like the AtDev described in Issue 14. Having a shield like this gives you the ability to rapidly program the microcontroller when making multiple devices and possibly, more importantly, reduces the risks of damaging your devices.

If like me, you don’t have the AtDev shield or one like it, you can still program the ATtiny13 using an UNO, breadboard and a little hardware.

  • Arduino 5V to the ATtiny pin 8 or VCC
  • Arduino GND to the ATtiny pin 4 or GND
  • Arduino pin 10 to the ATtiny pin 1 or PB5
  • Arduino pin 11 to the ATtiny pin 5 or PB0
  • Arduino pin 12 to the ATtiny pin 6 or PB1
  • Arduino pin 13 to the ATtiny pin 7 or PB2

Now you want to select the exact board you are using. I had the ATtiny13A, so navigate to TOOLS › BOARD and select the ATtiny13. It will now show something like this:

Note that I have selected the 13a as that was the variant I had. If your micro is not the 13a leave it simply as the 13.

From here, you simply pick the correct port as you usually would.

After you have verified everything is correct, you just need to navigate to tools and click the burn bootloader button.


With all the tedious stuff out of the way, now it’s time to upload our sketch. Keep the settings as we have just described, and simply hit the 'Upload Using Programmer' button.

Bear in mind of course, that other code written for Arduino Nano’s / Uno’s etc will need to be modified to work with the smaller ATtiny’s.

Take, for example, the blink sketch which refers to “LED_BUILTIN” which is pin 13 on the development boards. Naturally, our 8 pin microcontroller does not have a pin 13, so in this case, you would need to redefine “LED_BUILTIN” as an available pin on the ATtiny.


The enclosure for this device took many iterations to get it to how I wanted. The size was the primary concern with the early designs being significantly bigger than a regular sized USB device. To get the size as small as possible I had to get some general dimensions.

  • The PCB thickness was 1.8mm
  • The tallest component was 10mm
  • The enclosure needed to be 1.2mm thick or 3 × (nozzle diameter) = (3 × 0.4mm)
  • The solder pads/wires under the board were 2.5mm

Therefore, theoretically the smallest thickness the case can possibly be is:

= (2 × Enclosure Thickness) + PCB Thickness + Tallest Component + Solder Pad

= (2 × 1.2mm) + 1.8mm + 10mm + 2.5mm

= 16.7mm approx.

I was able to get it a little smaller by having the tallest component (piezo buzzer) protrude flush with the top cover. Meaning the case would need to be approx 15.5mm thick.

This is still bigger than even the biggest USB flash drive I had, although, it is on par with the other types of dongles etc. As such, it shouldn’t look too out of place if attached to the back of a computer, television, printer, gaming console, etc.

This hopefully means the device will be as inconspicuous as possible. For my device, I opted to make the enclosure out of transparent filament so it does not require a hole for the LDR to protrude.

If you want to make yours using opaque filament you will need to have a hole for the LDR to protrude through. I have included an STL file with the hole for that purpose.



const int DELAY = 8000;    
          //Time between beeps (cycles)
const int LIGHTLIMIT = 1000;
          //Light threshold 0 - 1023 
int count = 0;
int buzzer = 3;
int LED = 4;
int sensorValue = 0;
void setup() {
  pinMode(buzzer, OUTPUT);
  pinMode(LED, OUTPUT);

Here we specify the delay which is the number of loops the program takes before beeping. If you want to adjust this read ahead to the testing phase where I will discuss the process.

We also specify the light limit/threshold, which you can adjust to suit your specific environment. I wanted it to only go off when it was quite dark, so a value of 1000 worked well for me.

You may like to experiment with these values based on where you anticipate using this device. If you want the Rage Maker to work in any light conditions, select 0 (or near zero).

However this really works best when only set to go off in the dark (depending on your viewpoint of "working best").


void loop() {
  sensorValue = analogRead(A0);
  count = (count +1);
  if((sensorValue > LIGHTLIMIT) && (count > DELAY))
    digitalWrite(buzzer, HIGH);
    delay(150);   //change this value to increase or decrease the length of the beep
    digitalWrite(buzzer, LOW);
    count = 0;
  if (count < 0)  //protects against erratic loop behavior
    count =0;

This part is painfully simple. All the program does is read the LDR value and increment a count register. It then compares the values against our preset constants and if both are higher than the preset it beeps.

A NOTE ABOUT THE CODE: This code will work for both versions of the project, the prototype using the Arduino Nano, as well as the final build using the ATtiny13A microcontroller. The two programs will behave slightly different though, as the clock speeds affect the timing of the circuit. Though as you may have realised, timing isn't terribly critical for this project overall.


To get a semi-accurate measure of time, I modified the code to include pulling a digital pin high and low on each loop of the counter. I then used my oscilloscope to measure the time this takes, as can be seen in the screenshots. This needs to be done for the Nano and the ATtiny, as both have a different clock frequency, and therefore run at different speeds.

const int DELAY = 8000;
          //Time between beeps (cycles)
const int LIGHTLIMIT = 1000;
          //Light threshold 0 - 1023 
int count = 0;
int buzzer = 3;
int sensorValue = 0;
void setup() {
  pinMode(buzzer, OUTPUT);
void loop() {
  sensorValue = analogRead(A0);
  count = (count +1);
  if((sensorValue > LIGHTLIMIT) && 
(count > DELAY))
    digitalWrite(buzzer, HIGH);
    digitalWrite(buzzer, LOW);
    count = 0;
  if (count < 0)
    count =0;


Using the timing method just described, we can see that each loop and, therefore, count of the program takes about 11.4ms or 0.0114s to complete using the Arduino Nano. Keep in mind that this digital write also takes time, and as such will not be identical to the code without it. However, it is still very useful as a guide.

If each loop takes 0.0114s to complete and we have a delay value of 8000, our delay time between beeps will be: 0.0114 × 8000 = 91.2 seconds. Therefore, if you wanted to set the timer for a specific delay, let’s say 5 mins, you can use the following equation:

Delay = (Time you want in seconds)/0.0114

Delay = (5 minutes × 60 seconds)/0.0114 = 26315.79

So, all you need to do is substitute the DELAY const value with the time value you want.

The output from the ATtiny13A was surpassingly significantly faster than the Arduino, proving my personal assumptions completely incorrect.


If we repeat the exact same procedure using the ATtiny13A microcontroller we discover that the time per loop/count is 2.715ms or 0.00271s. Amazingly this shows that despite the ATtiny13A having a significantly lower clock speed, it actually performs quicker. Whilst I can't completely explain why this is at this point, I'm assuming it has something to do with the overall hardware differences. The microcontroller in the Arduino Nano has significantly more internal hardware for the bootloader to handle, more ADCs etc. This could explain the performance differences. It's worth mentioning my Arduino Nano that I prototype with also uses the old bootloader, this too may have an impact on the performance.

There could, of course, also be an issue with my methodology. Perhaps using the serial print functions etc. are the cause. I will be sure to investigate this further.

This shows that with a delay of 8000 the ATtiny13A takes (0.00271 * 8000) = 21.68 seconds to complete a cycle. Therefore, to calculate a specific delay you use the equation:

Delay = (Time you want in seconds)/0.00271

Delay = (5 minutes × 60 seconds)/0.00271 = 110701.107

Output from my oscilloscope showing the process of measuring the time using the cursor function.


To be honest, there isn’t much more you can do with this project. All of the functionality we set out to include has been included and the device works as intended.

However, if you wanted to be even more devious I guess you could add to the devices annoyance by making it beep at different intervals. This way it would likely be more difficult to find as you wouldn’t know when to expect the next beep. This could easily be done by using the random function on Arduino.

random(min, max);

With the min and max numbers representing the range. So, you could have something along the lines of:

DELAY = random(3000, 11000);

Which would make the delay use a random number between the two provided values which in the case of the ATtiny13A would be between 1 min and 5 mins.

Of course, this isn’t really random it’s pseudo-random, as digital electronics can’t really pick a random number. The delays would be identical each time you connected the device, which isn’t an issue in this instance.

However, if you wanted to overcome this you could use the randomSeed() function, along with a free analog pin to create a more random sequence. i.e. In the setup use the line:


This will use the floating analog pin 1 value to decide a seed for the random generator. This will mean the same sequence of “randomly” generated numbers are not likely to come up each time the device operates.

As we have noted it's not really an issue if the random numbers aren't all that random, we just need some variation in the beeps.