Monthly Archive for July, 2012

ubbcom gets an upgrade

So a while back, I made a usb-to-serial converter board using FTDI’s most beloved chip: the FT232RL. This is the same chip that Sparkfun uses in their breakout boards. I just didn’t want to pay Sparkfun prices for something I could etch myself.

Well, I’ve given ubbcom a little upgrade.

First, I added the REN and RTS pins. The former is good for hooking the board up to a RS-485 level convert chip, since it can control the tri-state direction. The second I use along with the other handshake signals to bitbang program the ATtinys for bcard.

Additionally, I decided to actually bite the bullet and buy USB connectors. PCB approximations of USB connectors just don’t work. Really. They’re useless. So, I bought some connectors off of Digi-Key and made a footprint. I managed to actually orient the footprint the wrong way around the first time I tried this. That’s like the second time I’ve done this to USB connectors now. Nothing like epoxy to save the day there:

I chose to go with USB A connectors because I don’t trust mini connectors, they’re cheaper than micro connectors, and because I have USB extension cables, which work great. But yeah, now that I have a couple of these guys, it’s easy to communicate with chips, bitbang program them, etc.

How I learned to stop worrying and love crazy, stupid kludges

So, I’m in some of the final development phases of bcard. I’m working on developing an optimal touch sensor. As you can see, I’ve tried a few:

Total attempts so far: 912. That’s right, I’m on the 12th revision.

One of the things I’ve been struggling with involves power consumption. I don’t have much power to work with so I want the micro to use as little power as possible when not running the LEDs.

So I came up with a semi-batshit-insane idea. If I could somehow trigger a level change on thee INT0 pin, I could design the firmware such that I can shut basically the entire micro off until the pin level change fires an external interrupt sensor on the micro. This would basically reduce the power usage of the micro to like nothing.

So my approach would be a kind of hybrid between resistive and capacitive sensing:

  1. Enable pin interrupt, set INT0 pin to be floating. Then power down most of the micro’s functionality.
  2. When the interrupt fires, the micro will wake up and start running the capacitive sense system.
  3. If the capacitive sense system doesn’t see a swipe, then go back to sleep.

This plan at first seems kind of stupid because in general you should never just try to detect something useful from a floating pin. They’re extremely volatile. But I figure that by combining resistive and capacitive touch sensing, I will get the power savings of the former and the reliability of the latter.

So I tried implementing this idea in a few ways. First of all, I built a new board like this:

So now there are three pads and a “ground guard” around the whole thing (this isn’t really necessary). I’ll call the big pads “left” and “right” and the center strip pad “middle.” I’ve built an even newer board since then, but it’s easier to explain what I’m doing with this older one, so I’m going to stick with that (they’re functionally identical; the newer one just looks nicer).

There are basically two options. When I’m in this resistive sensing mode I can either drive left and right high, shut the micro off, and tie center to INT0 so that it detects a float. Or I could do the reverse; I can assume that the user should always start his finger on left and therefore tie that to INT0 as an input and then tie center high.

I chose the former so that I can do a bit of analog magic with the floating pin. I want to be able to add a pull-down resistor of some value such that it prevents spurious interrupts, but still is very sensitive to the press of a finger. The pull-down resistor kind of makes the floating pin more likely to detect “0”, which means that you need a bit more of a “push” to make it detect a “1”. Tuning this is a matter of adjusting that resistor. So, the layout went something like this:

So, I wired it all up like the above diagram (I started out with no resistor on the floating pin) and then had a small test program that basically went as follows:

[cc lang=”c”]
int main(void) {
// initialize UART
uart_init();

// LED output
DDRB |= _BV(PD3);

// start resistive component
// enable INT0 pin
EIMSK = _BV(INT0);
EICRA = _BV(ISC01);
sei();

while (1);

return 0;
}

ISR(INT0_vect) {
uart_tx(‘*’);
PIND |= _BV(PD3); // toggle LED
}
[/cc]

All it does is enable the INT0 pin interrupt vector and then spin in circles. When the interrupt fires, it sends a character over serial.

Results of testing? Pretty dismal actually. The interrupt barely fired… It was more likely to when I pressed a large surface area, but my goal was to make the resistive pads as small as possible and solder mask the rest.

But I had one more trick up my sleeve. If I couldn’t get a reliable level change with just a single press, what if I could simulate a whole bunch of presses and hope like hell that one hit? Enter my next idea.

The left and right pads are just being driven high right now. But what if we could instead make them oscillate between Vcc and ground. Then, since it’s slamming between the two voltage rails, it’s more likely that when we’re pressing it, it is going trouble make enough chatter on the INT0 input pin to kick the interrupt awake.

But this uses more power. After all, I now have to get the micro to continually toggle the pin, right?

Welllllll yes and no. There is going to be more power usage because the pin has to switch. But I can still keep most of the micro off by using the timer to generate a waveform.

At this point, I had to look at the capabilities of the chip I’m using. I’ve been testing with an ATmega168 because it’s easy to debug when you have stuff like serial communication. However as I’ve mentioned before the final target will be the ATtiny10, which is basically the cheapest class of processors that Atmel makes. This chip has a single 16-bit timer that can drive two output ports. Perfect. One can be used to PWM the LEDs and the other can be used to drive the floating pin input. Moreover, given that the timer is 16-bit, even if the system clock speed is kind of fast, I can make the pin oscillate slowly to prevent too much switching loss.

So, I used the 16-bit timer on the ATmega to emulate what I would do on the ATtiny. I wrote a test program that looked like this:
[cc lang=”c”]
#define FLTPORT PORTD
#define FLTDDR DDRD
#define FLT PD2

#define FLTDRVPORT PORTB
#define FLTDRVPIN PINB
#define FLTDRVDDR DDRB
#define FLTDRV PB1

void enable_float_driver(void) {
// Set up floating pins
FLTDDR &= ~_BV(FLT); // float sense input
FLTPORT &= ~_BV(FLT); // don’t you dare pull that shit up
FLTDRVDDR |= _BV(FLTDRV);

OCR1A = 0x0800;
TCCR1A = _BV(COM1A0) | _BV(WGM11) | _BV(WGM10);
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS12) | _BV(CS10);

// interrupt mask
// enable INT0 pin
EIMSK = _BV(INT0);
EICRA = _BV(ISC01);

return;
}

void disable_float_driver(void) {
// interrupt mask
EIMSK = 0;
EICRA = 0;

// shut off float driver
TCCR1A = 0;
TCCR1B = 0;
FLTDRVDDR &= ~_BV(FLTDRV);

return;
}

int main(void) {
// initialize UART
uart_init();

// LED output
DDRB |= _BV(PD3);

enable_float_driver();

while (1);

return 0;
}

ISR(INT0_vect) {
disable_float_driver();

uart_tx(‘*’);
PIND |= _BV(PD3); // toggle LED

enable_float_driver();
}
[/cc]

The results were almost too good to be true. The interrupt fired unbelievably reliably and there were relatively few spurious interrupts, too. I managed to get it even more stable by adding a 1Mohm pull-down resistor to the floating sensor pin.

So now the final step was to integrate the resistive phase with the capacitive phase, which I was developing earlier. The capacitive phase basically is a state machine. When the interrupt fires and kicks the capacitive phase into gear, the algorithm checks to see if the user is actually pressing the pad by measuring the time constant. If it is then it enters the state machine, which expects the following sequence of events to occur:

  1. User presses left pad
  2. User presses both left and right pads
  3. User presses right pad

In order for there to be a swipe, the user has to be pressing both pads at some point. I’ve designed the sensor with enough overlap between the two that this is guaranteed to happen (unless I just have super fat fingers, which is not unlikely given how shitty the emails I send from my phone are).

If any point the events in this sequence are violated, the micro drops out of the capacitive sensing phase, fires the floating pin driver, and enables the interrupt pin.

And that’s all there is to it. The ATmega implementation works quite nicely. So it’s time to start developing for the ATtiny, which should be more fun. I (unfortunately) have a lot of experience with microcontroller assembly, so I’m hoping it will go somewhat smoothly.

After I finish the implementation, I’m going to do as much power optimization and tweaking as I can. I’m basically pushing this processor to the limit of its capabilities, which is cool because I’ve never had to do something like that before. I’ve definitely learned a lot.

Here’s a preview of the current sensor design:

It’s double sided this time! The islands in the middle are the floating pin inputs. A little more tweaking to this new design and I think I can finally be happy. But I’ll get to how the double-sided business card is going to work out in another blog post.

Fixing a Seiko watch not reseting to 12

I was using my chronograph on my Seiko watch that I’ve had for a few years (7T92-0FX0) and noticed that when I reset it, the seconds hand was returning to the 57 second mark and not to 0. I Googled for a while and found this guide for another watch. This method didn’t work, so I tried a few other things.

Turns out the correct thing to do was to pull the stem out to the second click (for setting time) and then holding the top button for about 5 seconds. This will cause one of the dials to turn around fully. But, I was confused because it just put the dial back to the 57 second mark. Then, I tried hitting the bottom button, and it advanced. So, after two more presses, it was back at 0 and when I pushed the stem back in, the chronograph was reseting correctly again.

By pressing and holding the top button, you’re selecting which dial you want to reset. So if you press and hold the top button two times, it will make a different dial spin around, and then you can adjust that dial by hitting the bottom.

Magical.

Capacitive Touch Testing with bcard

While I think a little bit more about why I can’t seem to get V-USB to work with hdctrlr, I’ve gone back to working on my PCB business card, bcard.

The ATTiny10 is basically impossible to do meaningful development on, so I decided to make a breakout version of my business cards that use an Atmega168 instead. That way, I can get data over serial, etc. to develop a decent sketch of a program that I will then implement in assembly on the Attiny. Of course, when I get to that point, I could always disassemble the Atmega program and use that as a template for the Attiny program, but I’m far too much of a masochist to do something like that; I’ll be rewriting it from scratch in order to get as much power savings as physically possible.

Anyways, here’s a quick photo of the capacitive breakout board that I made:

The basic idea of this style of capacitive touch sensing is that there is a parallel RC circuit like this:

First, I set the CTRL pin to be an output so that it can charge up the capacitor (which is the interlocking bars in the image above). Then, I change CTRL to be an input pin, so that it has infinite impedance. This means that the circuit just looks like a resistor and capacitor in parallel, connected to ground. So, the capacitor will discharge through the resistor while the input pin monitors the voltage. We don’t even need CTRL to be an ADC; all it has to do is look for when the input goes from 1 to 0.

So what happens when we put our finger on the pad? Well, this is where it gets fun. When this happens, you’re changing the dielectric constant of the capacitor on the board, increasing the time constant (i.e. increasing the time it takes to discharge). This looks somewhat similar to a design by Michael Ciuffo, a friend of mine, but his sensor is being actuated on the change in resistance when you put your finger on a sensor whereas I’m looking at the change in capacitance. So, with his design, when you put your finger on the pad, the time constant decreases, whereas with mine, the time constant increases.

Screw it, let’s do it in pictures. I like pictures.  (In this example, I model the change in the dielectric constant as an added capacitor).

And how does it look in real life? Well here’s two photos of my scope measuring the CTRL pin for a sensor. The first shows the normal waveform (I charge up the cap with the CTRL pin and wait a while, then let it fall) and the second shows what happens when you put your finger on the sensor.

I based this design on inspiration from this site.

So, how do you get useful information with a microcontroller? It’s really just a few lines of code. Let’s say that you’re using PB0 as your CTRL pin.

[cc lang=”c”]
uint8_t counter = 0; // we’ll count how long it takes the pin to drop back to 0 here

DDRB |= (1<<PB0); // set CTRL to drive a voltage
PORTB |= (1<<PB0); // apply logic 1 to charge the cap
_delay_ms(PIN_ON_DELAY); // charge for a little while (this can be really small)
DDRB &= ~(1<<PB0); // set CTRL to input mode
PORTB &= ~(1<<PB0); // get rid of driving voltage

while ( PINB&(1<<PB0) && counter <= 255 ) {
// each time, we check to see if PB0 has gone back down to logic 0. If it hasn’t, then we increment counter (up until the point where it could overflow)
counter++;
}
[/cc]

That’s it! Drive the pins, stop driving them, and see how long it takes for them to change back.

So here’s a video of some live plotting of data I took (see video description for the moment on details).

In this example, I let counter be a 16-bit value instead of just an 8-bit one so that I would have more resolution, but in practice, just using an 8-bit counter is sufficient.

To measure a press versus a not-press, I start by establishing a baseline — basically when the micro first starts up, it takes a bunch of samples (I assume that the user doesn’t start by pressing the pads). It then starts performing readings. If the reading is significantly off baseline, then it registers it as a press. If it’s not significantly off, then it updates the baseline by averaging in the new value. This allows the sensor to react to minor changes in the environment around it.

With respect to bcard, I actually have two sensors (you can see that there are two sensing pins). So, I wrote a short algorithm that looks for a press on the first one and then a press on the second one to indicate that someone swiped their finger over the pads. I should have a full code implementation done fairly soon.

I really have stopped liking my current bcard design so I’m probably going to do a complete redesign and rerouting of it soon. I really want it to look aesthetically pleasing and I’m definitely not there yet. I think I’m going to make the swipey thing vertical instead of horizontal. I may also adjust the placement of the LEDs.

Testing the scroll wheel through serial

In this experiment, I send a command (either “< " or ">“) to indicate which way to scroll using the initial signal processing algorithm I designed. It guesses at which phase leg the motor is currently closest to and compares it against the previous phase leg and then decides whether that means it should scroll left or right. All this code is available on my git repo.

I then wrote a simple python program that uses PyGame to send either a left or right scroll command based on the input it receives over serial.

I currently am missing some parts to complete the V-USB setup, but when my Digikey order comes in, I should be able to finish it.

Hard Drive Scroll Wheel

With all of the failures I’ve had with bcard lately (I’ll write about them at some point), and with the design of my plasma speakers progressing rather slowly because I’m trying to develop a Class D power supply that can be audio modulated and accept a varying load (each speaker will be powered by a chain of Class D and Class E amplifiers), and because I’m moving soon, I’m not implementing any kind of room automation system until I’m somewhere more permanent.

So I grabbed a dead hard drive, opened it up, took out the controller board, and turned it into a little turntable.

Hard drive disks are typically spun by a standard brushless DC motor with 3 or 4 terminals. This one happened to have 4, so it was a motor in the wye configuration. I measured the resistance between each terminal and found the common one. Then I tacked on a few wires so that I could plug the device into my breadboard.

The black pin was common and each of the colored pins was an end of the motor, so the motor can be drawn like this:

When spinning a BLDC a wye-configured BLDC motor, you will see a back EMF voltage between the common terminal and each of the end terminals in turn. So, for example, with this motor, if I spin it clockwise (against the direction of the spindle), I can see a voltage on the yellow, blue, and green pins in that order. If I spin it counter-clockwise, then the order is yellow, then green, then blue.

This means that by measuring the voltage of each pin and watching the relative phase of the changes, we can actually get the rotational speed of the motor! Then, we can turn that into a scroll wheel or something useful. My friend Scott had done this a while back by hooking the hard drive motor up to an op-amp and then to an Arduino, which spat out serial data. He then wrote a program that emulated mouse events based on the data it received from the Arduino.

I wanted to produce a much more direct version: using V-USB to actually make a mouse device that the computer would recognize without any special software. However, first, I wanted to get an idea of what the data actually looks like when I spin the motor.

So I wired up a wonderfully messy breadboard.

The actual design is very simple: the common terminal of the drive is connected to ground and each of the motor terminals is connected to an opamp in the non-inverting configuration with a 10K/220ohm amplification ratio. The outputs of each of those 3 amplifiers go into 3 ADC ports on an Atmega168. So the schematic looks like this:

The Atmega simply reads each ADC value, and then sends a packet of data over serial that starts with “:” and has the 3 ADC samples (I’m going to call them yellow, blue, and green). Then, it waits 50ms and does it again.

Next, I borrowed the code from the second example on this page. It performs live plotting with Python! I modified the code to grab data from the serial port and interpret the packet. Eli’s code only works for a single line plot, so I also modified it to support an arbitrary number of data inputs. Finally, I boosted the refresh time to 50ms so that it would about match the speed that the Atmega was sending packets.

Here’s a slow scroll:

And here’s a fast one:

Now comes the fun part: signal processing. For the first design, it’s obviously easiest to have a state machine that looks at the progression of phases and watches for the signal crossing a certain threshold. Scott’s design amped the hell out of the signal so that it would appear as a digital input. By using a threshold crossing, I’d be creating a similar design. With a little low-pass filtering, I can also guard against false scrolling. I plan to get that working in serial first, and then I’ll implement the V-USB library to create a mouse device. In the future, I can work on nicer signal conditioning algorithms that provide more sensitivity at lower speeds (by looking at the derivative of the signals perhaps) and faster scrolling at higher speeds.

This weekend, if my design works reliably well, I’ll create a small PCB and hopefully enclose it nicely.

My work so far is located here.