A few years ago I had seen a comic by Oatmeal claiming that cats purr at the same frequency as idling diesel engines. Thinking that it was a highly amusing fact I went on to record the sound of my friend’s bus (a MB 100), the purr of my feline overlord and that of another young kitten.

At the time we’ve been organising local geek nights in our city. I ran all the recordings through some graphical Fourier-analysis software I no longer use, included a few more cat purr recordings from the Internet for the sake of consistency and gave a short talk one night.

Alpha FFT

The frequency of Alpha’s purr, it appeared, was 28 Hz.


The other cat, which had a really loud and distinctive purr, had a frequency of 27 Hz.

Ufoliner FFT

The diesel engine was idling at 22 Hz.

Since both cats were female and I was not happy with the recording of the engine, I downloaded and recordings of 7 more cats purring, as well as the sound of a big diesel truck. This engine had a dominant frequency at 24 Hz, whereas the mean of all cat frequency peaks was at 26.1 Hz. Having decided that these sounds are reasonably similar I happily forgot about it all, until a few hours ago when I thought that cat purr would be a great sound for our upcoming anti-alarm clock that miceuz and ioch were building.

miceuz used a random motor from a scanner to emit the artificial purr. He attached a displaced weight to the motor’s shaft. An ATMega 328P microcontroller drives the motor through a MOSFET transistor by feeding a 24 Hz square wave while varying pulse width for “inhalations” and “exhalations”. Added a pinch of random to inhalation and exhalation duration.

All the parts seen on the video except the motor have nothing to do with the circuit.

The code that is presented below is just an AVR code that can be run on arduino:

byte purrCounter=0;
byte threshold = 15;

void setup() {
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1B |= _BV(CS12) | _BV(CS10) | _BV(WGM12);
  OCR1A = 651;
  OCR1B = 10;
  TIMSK1 |= _BV(OCIE1A);
  TIMSK1 |= _BV(OCIE1B);
  pinMode(9, OUTPUT);

  digitalWrite(9, HIGH);

  digitalWrite(9, LOW);
  if(purrCounter > threshold) {
    if(OCR1B == 10) {
      OCR1B = 4;
      threshold = 13 + random(6);
    } else {
      threshold = 26 + random(18);
    purrCounter = 0;

Published August 31 2013 by opit and miceuz