Deconstructing Kitty

“Google called, and josh.com needs more cats.”

wavevoltage

So today we look inside these amazing cats that can somehow keep on wavin’ using less than 15 microwatts (!) of power. If you are into either ultra low-power or extreme design-for-manufacture, the you will want to see what is inside of these guys!

“What I can not create with an Arduino, I do not understand”, so we then proceed to recreate a lucky cat under Arduino digital control.

Perfunctory video

Most Interesting Thing I Learned

If you are designing a solar powered thing for indoor use and you do not know what kind of lighting it will be under (incandescent, LED, florescent) then your best bet is to use cheap amorphous silicon cells. I would have figured that fancy mono-crystalline cells would be more efficient, but not always. (Thanks Robb!)

Lucky Cat explained, Socrates style

What makes the happy paw keep waving?

SNAG-0007

It is a simple pendulum.

The coil at the bottom is the secret sauce. It is an electromagnet with a LOT of turns of very, very thin wire. It gives the swinging magnet (the “bob”) an occasional well-timed push at its resonant frequency.

Then there is a minimal parts count (but surprisingly functional!) analog circuit with a couple of caps and transistors, and a cheapo solar cell.

Why does it give a push rather than a pull?

The strength of the magnetic field made by the coil falls off quickly as you move away from it, so for efficiency you want to push or pull the magnet when it is very close to the coil.

It turns out that it is easier to tell when the magnet has just passed the coil than it is tell when the magnet is about to pass the coil. See why?

Pushing is also more forgiving. If you push a little too long then you just end up pushing the bob a little harder than you meant to. If you are pulling and you pull a little bit too long, then you are actively slowing down the bob and doing it at the worst possible moment when your force is strongest.

Why is the bob a magnet and not just cheap steel or iron?

Since we are pushing the bob rather than pulling it, we need to repel it. A magnet can only attract steel or iron. We need another magnet to be able to repel.

Why do we need feedback? Can’t we just blindly drive at the resonant frequency?

In real life the resonant swing frequency is dependent on manufacturing variances, temperature, age, etc. To make the most of the low power we are spending, best to always push at exactly the right moment in the swing.

How does it know when the magnet has just passed the coil?

The moving magnet creates a voltage in the coil. We can watch this voltage to sense when the magnet is swinging past.

Why does the coil use air core rather than something like iron that would concentrate the magnetic field?

Because then the magnet would want to stick to it.

Why is the coil offset from the midpoint of the pendulum swing?

I am pretty sure that this is to help with kickstarting. If the coil was directly below the bob, then when it tried to kick, the repulsion force would be acting straight up. Pushing straight up is not the best way to get a swinging motion started.

I think another solution to this could be to mount the magnet horizontally and have it travel through the center of the coil, but this is probably a more difficult geometry to manufacture.

Why is the coil the secret sauce?

My theory: the more turns and the thinner the wire, the more efficient the electromagnet will be at a fixed voltage (the voltage generated by our solar cell).

Why? Ideally, a coil with 2x turns has 2x the resistance. Since V=IR, with double the R we get 1/2 the I. So the coil with 2x the turns has 1/2 the current, so each turn makes 1/2 as much magnetic field (field goes with current) so net we have the same amount of field with 2x the turns.

…BUT since the power used is P=I2R, when we 1/2 the I and 2x the R, we use 1/2 the power in the ohmic resistance in the coil wire.

So it seams that (ideally) every time we double the number of turns, we use 1/2 as much power to get the same field at the same voltage. Make sense?

Of course double the turns also makes the coil bigger, and the bigger the coil the farther away geometrically the average wire will be from the center. This is why you also want very thin wire – especially since the increased resistance of the thin wire is less important as the current goes down.

I tried to confirm this theory with google, but couldn’t find anything that specifically backed me up. Am I right?

What kind of bearing is that?

I fully expected to find a fancy ultra low friction bearing in here, but this happy cat instead uses a super simple knife edge bearing made from the same plastic as the arm and body. It is amazingly efficient for any bearing, much less one that is essentially free!

Code Drop

You should be able to get most happy cats (or just a magnet hanging over a coil) swinging by adjusting the parameters in this sketch.

// This Arduino sketch drives a coil to make a Lucky Cat wave
// The coil should be connected directly to pins A0 and ground
// It uses the voltage generated by the magnet passing the coil to time its pulses
// More info at…
// http://wp.josh.com/2018/05/07/deconstructing-kitty
#define LED_PIN 13 // Show a flash on this pin everytime we pulse the coil
void setup() {
Serial.begin(9600); // setup serial
pinMode( A0 , INPUT );
pinMode(LED_PIN, OUTPUT);
}
// Keep track of the highest value since we last triggered
// so we can detect when the bob is moving away from the coil just
// as it switngs past bottom dead center
int peak=0;
int triggered=0;
// The values from the ADC are very noisy, so we make a crude
// averaging filter here
#define BUFFER_COUNT 25
int buffer[BUFFER_COUNT];
int nextSlot=0;
int runningTotal=0;
// Push the magnet away by energizing the coil
void push(unsigned int ms) {
pinMode( A0 , OUTPUT ); // Switch the input pin to output so we can drive it.
digitalWrite( A0 , HIGH );
digitalWrite(LED_PIN, HIGH); // Flash the LED to show the coil is on
delay(ms);
digitalWrite( A0 , LOW );
digitalWrite(LED_PIN, LOW);
pinMode( A0 , INPUT ); // Go back to input mode so we can keep sensing the back voltage
}
void nudge() { // A very short and low power nudge
push(1);
}
void kick() { // A big kick to get it swinging from rest
push(50);
}
#define KICKCOUNT_TIMEOUT_MS (5*1000) // Give a kick if we have not seen a swing in 5 seconds to get things started
unsigned long nextkick=0;
void resetKickTimeout() {
nextkick = millis() + KICKCOUNT_TIMEOUT_MS;
}
// Slow down the data feed back to the Arduino plotter so it doesn't run too
// fast to see
unsigned long nextplot=0;
// Display the trigger as the 2nd variable so we can see when we give a nudge
// on the plot.
int triggerflag=0;
#define PLOT_INTERVAL_MS 3
void plot( int val1 ) {
if (millis() >= nextplot ) {
Serial.print(val1); // debug value
Serial.print(" "); // debug value
Serial.print(triggerflag ); // debug value
Serial.println();
nextplot = millis() + PLOT_INTERVAL_MS;
triggerflag=0;
}
}
void loop() {
// If we have not seen a swing in a while then give it a kick to get it started
if ( millis() >= nextkick ) {
kick();
resetKickTimeout();
}
int val;
val = analogRead(A0); // read the input pin. We are lucky that the voltage of the coil
// falls in the range of the Arduino ADC or we would need some
// kind of scaling here
// Remove oldest value
runningTotal-=buffer[nextSlot];
// Add new value
runningTotal += val;
buffer[nextSlot] = val;
// Bump to next slot
nextSlot++;
if (nextSlot==BUFFER_COUNT) {
nextSlot=0;
}
int smoothedvalue = runningTotal/BUFFER_COUNT;
if (triggered==0) {
if (smoothedvalue> peak ) {
peak = smoothedvalue;
} else if ( smoothedvalue < (peak*8)/10 ) {
// Trigger a nudge when we are at 80% of the most recent peak
// this helps prevent false triggers from noise and also
// I think gives a better force vector away rather than just up.
nudge();
triggerflag=peak;
resetKickTimeout();
triggered=peak;
}
}
// Display the data on the Arduino Serial Plotter
plot( smoothedvalue );
if (smoothedvalue == 0 ) { // Clear a trigger if we are back down to zero
triggered=0;
peak=0;
}
}

view raw
luckycatbrian.ino
hosted with ❤ by GitHub

Why?

Robb got me interested in his cool Restroom Neutralizer Project , which has the heart of a lucky cat. It quickly became clear that these cats quite interesting from both ULP and DFM perspectives.

Why would you want to replace $0.05 worth of analog parts with a $15 Arduino?

Happy cat analog circuits are impressively simple/complicated, but I wanted to play around with all the parameters to really understand what was going on. It is much easier to type new numbers into a sketch than to replace components in a circuit.

###

Leave a Reply