-
Installing Servomechanisms
02/20/2016 at 12:49 • 0 commentsOf course I don't want the mechanisms to show, so I have to put most of it inside the ears themselves. The servomechanisms are simple -- I made some longer levels from servo horns connected with small screws. Then I inserted that into the ear through a small hole that was helpfully left in it:
I initially planned to secure them by sewing, but I couldn't be bothered to find my needle, so I just secured the servo horns with more of the small screws:
I might remove them later and replace with some stitches after all.
Next, programming. I found a Pololu Mini IMU 9 in a drawer, so I guess that's what I'm going to use for the accelerometer. I found some example programs in the documentation, and I'm trying them now. More in the next log.
-
Movement Test
02/20/2016 at 18:43 • 2 commentsI have the mechanical part ready, and I did a small test of the ears movement. They move so slow because that's what the test does, not because they are so slow -- in fact, they can move into a new position quite fast.
On the control side, I gave up on the Pololu IMU, and instead went with a simple GY-61 analog accelerometer. This should be more than enough, since I only need to react to movements, and this is much simpler to interface.
-
First Prototype Working
02/20/2016 at 22:03 • 0 commentsI got the first version to work. Here's the demo video:
There are several things there. I have the control board with the battery and accelerometer sitting at the top of my head -- this is obviously suboptimal, especially during rain. I suppose I can hide most of the electronics and the battery inside the ears themselves -- there is enough room for that. But the accelerometer has to stay. Or I could move the whole thing to the side, making it look like a bluetooth headset or something -- I would just need to switch the accelerometer axes then. I need to sleep on that.
Second thing, the range of movement is really limited. Those tiny servos don't really have enough strength to squash the material of the ears enough to flatten or perk them completely. I used those little guys, because I was afraid about space, but turns out that there is a lot of room inside those ears, so I might try with 9g servos next.
Third, they make noise. Since constant buzzing would be annoying and would drain the battery fast, I'm actually switching the servos off (by disabling PWM signal) when they are not changing the ears position. I only enable them for 600 milliseconds when they need to move. It would be much cooler to have them move fluently all the time, but not with those servos.
Fourth, I guess I could attach them to a hat -- then there would be no problem with hiding the electronics, and I could even have a larger battery.
Fifth, right now they only react to the head position. I need to experiment with tracking how fast I'm moving, and make them move based on that too -- make them droop when I'm not moving, and perk up when I make a sudden move with my head. Also, twitch them randomly when they are perked up.
-
Source Code
02/20/2016 at 22:44 • 0 commentsThis is the first prototype version, but still here's the source code if you are interested in how it's done:
#include <Servo.h> Servo servos[2]; void move(int position) { static int current = -1; if (position == current) { return; } current = position; servos[0].attach(9); // right servos[1].attach(10); // left switch (position) { case 0: // Perk up. servos[0].writeMicroseconds(1500 + 300); servos[1].writeMicroseconds(1500 - 300); Serial.println("perk"); break; case 1: // Droop down servos[0].writeMicroseconds(1500 - 300); servos[1].writeMicroseconds(1500 + 300); Serial.println("droop"); break; case 2: servos[0].writeMicroseconds(1500 + 300); servos[1].writeMicroseconds(1500 + 300); Serial.println("left"); break; case 3: servos[0].writeMicroseconds(1500 - 300); servos[1].writeMicroseconds(1500 - 300); Serial.println("right"); break; default: Serial.println("unknown"); } } void rest() { servos[0].detach(); servos[1].detach(); } void setup() { Serial.begin(115200); move(0); } void loop() { int z = analogRead(A0) - 490; int y = analogRead(A1) - 490; int x = analogRead(A2) - 490; Serial.print(x); Serial.print(", "); Serial.print(y); Serial.print(", "); Serial.print(z); Serial.println(); if (x > -10) { if (y > 10) { move(2); } else if (y < -10) { move(3); } else { move(0); } } else { move(1); } delay(600); rest(); }
-
Miniaturization
02/21/2016 at 09:43 • 0 commentsSo I've been thinking... If I were to do it seriously, I would probably drop the Pro Mini and use an ATtiny85 instead, with a custom, small PCB to contain the whole thing. It would be small enough to actually fit on the band holding the ears, something like this:
That's 23×6.5mm, and could be made even smaller if I populated both sides... Then of course the battery would need to go into one of the ears, and there also needs to be a power switch...
-
PWM on ATtiny85
02/23/2016 at 22:05 • 3 commentsSo I decided to go for this miniaturized version, and ordered the PCB at OSHPark. Since it was so small, it's quite cheap. But that means that now I need to port my code to ATtiny85. I can use an Arduino core, but I still need to come up with a way to control the hobby servos. The obvious way is to use Fast PWM mode.
The usual way to do it is to set a timer with two triggers -- one that switches the pin low, and one that resets the counter and switches the pin back to high. This gives you precise control over the exact frequency and duty cycle of the signal. ATtiny85 has two such timers, so I should be all set.
There is a small problem, however. I will also need 3 ADC pins, and one of those is the same as the Timer1 PWM pin. There is an ADC on the reset pin too, but I don't have a high voltage programmer to make use of that. So I can't use the second timer.
What I can do, is to use Timer0 but don't reset it on the second trigger, but let it overflow. Then use the second trigger for the second PWM pin. That however removes the precise control over the frequency -- now I can only use the frequencies that are available with the given prescalers and CPU speeds. Turns out I can do 62.5Hz with the ATtiny85 at 1Mhz. This is close enough for most servos.
With some diving into the datasheet and a bit of experimenting, I came up with this code:
void setup() { pinMode(0, OUTPUT); pinMode(1, OUTPUT); // Setup the PWM clock to ~62.5Hz for the servos. TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00; TCCR0B = 0<<WGM02 | 1<<CS00 | 1<<CS01 | 0<<CS02; OCR0A = 0; OCR0B = 0; } void loop() { for (int i=10; i<30; ++i) { OCR0A = i; OCR0B = i; delay(100); } }
Note that since I'm messing with Timer0, which is also used by the Arduino core to keep track of millis(), the delay() is no longer accurate. But I can live with that.Here's the servo in action:
-
PCBs Arrived
03/09/2016 at 09:29 • 0 commentsToday the printed circuit boards arrived from OSHPark. I'm still waiting for the accelerometer chip (it will be fun to solder it), though. Here's the size comparison between the new PCBs and the old prototype:
-
Hot Plate Soldering
03/21/2016 at 10:43 • 1 commentThe PCBs that I wrote about last time were not the real PCBs. OSHPark has made a mistake in the board thickness (a new option that they have), and sent me the boards again, this time thinner. I didn't realize that, so I was quite surprised to see the second shipment, but all is good.
The GY-61 breakout kit also arrived, so I'm ready to try and solder it on that board. This is a "LFCSP LQ" surface-mount package, so impossible to do with a hand soldering iron. At the hackaday channel someone suggested using a kitchen stove, so I have that a try. First, I tinned the board:
Then I covered it in flux, and went to the kitchen. I have an electric stove with a glass top, so I put the board directly on it, and heated it until the solder melted. Then I carefully placed the chip on the right spot, and pressed it gently down. Finally, I removed the whole thing from the stove.Next, time for a test. I didn't want to solder an attiny85 on the board just yet, because it's inconvenient to debug with it, so instead I connected a 3.3V Pro Mini with some kynar wire:Note that the VCC cable from USB2TTL is connected to the RAW pin, not to the VCC pin on the FTDI header, because I don't want 5V on the VCC pin...A quick sketch lets me verify that the thing works!
void setup() { Serial.begin(115200); } void loop() { Serial.print(analogRead(A0)); Serial.print(", "); Serial.print(analogRead(A1)); Serial.print(", "); Serial.print(analogRead(A2)); Serial.println(); delay(300); }
Now I just need to figure out what are the center values when powered with the battery I want, and write the program.
-
Assembled, Programming
04/16/2016 at 20:17 • 0 commentsSince all my "current" projects are either waiting for parts, or being punished for not going the way I wanted, I decided to finish this one. I started with connecting all the wires to an ATTiny85 I have soldered to a breakout board. Turns out that the accelerometer connected to the chip's pins doesn't prevent it from being programmed! Yay, that means I can just solder the chip in place and re-program it with a clip.
Next step, I made some connectors for the servo sockets, so that I can use SoftwareSerial on them for debugging. In particular, I needed to check what are the rangers on the accelerometer readings. Turns out that "0" is smack in the middle of the range, at 512, and 1g is about 100 units. Good enough.
Next I will need to check the servo's limits (since I'm not using exactly 50Hz for PWM, they will be different) and actually write the code for the ears-moving logic... I guess for that last part, I will still use the Pro Mini-based prototype. It's simply easier to reprogram.
-
Servos Hate Grease
04/16/2016 at 22:36 • 0 commentsSo I also made an attempt at making those servos a little bit more quiet. I opened one of them, and filled it with some servo grease that I ordered from China some time ago. Assembled it back together, and...
Turns out the servo is perfectly quiet now. Unfortunately, that's because it doesn't move.
Turns out that the smallest gear -- the one near the motor -- has to move with such ease, that even a little bit of grease makes it completely stuck. It took me about an hour to clean all the grease from those gears, and the servo works again. As loud as before, though.