Thursday, January 31, 2013

Easy Pogo Pin Test Jigs

Tindie update: I have a few of the older Rev 0.2 eeZee Propeller breakout boards on clearance at Tindie, $16 each. Also, 10% off eeZee Tiny, 8-pin ATtiny breakout board (coupon code 52CAF8E)


All the Rev 0.3 eeZee Propellers ordered during the Tindie Fundraiser have been shipped after extensive testing.  My test jigs are primitive, but are huge time-savers. One jig programs the board. Another tests VGA. A third tests output pins.



Monday, January 28, 2013

Robot Magazine Article

I'm very excited to announce that I've been published in the March-April 2013 issue of Robot Magazine! They should be on the newsstands now.

My article about Data Bus and the 2012 Sparkfun AVC goes into some of the trials and tribulations of building a high speed autonomous rover.

Thursday, January 24, 2013

555 Schmitt Trigger Circuit for Wheel Encoders

I've been playing with Schmitt trigger circuits again, this time using a 555 Timer based on a discussion on diyrovers started by Jason.

Schmitt triggers are circuits that provide hysteresis. The concept is simply that instead of one threshold for on and off, there's an upper and lower threshold.

Signal (U), no hysteresis (A), Schmitt (B) - Wikipedia
With one threshold (red line, U above) a noisy signal can trigger an action more often than intended (A). When there's an upper threshold to trigger on and a lower threshold to trigger off (green lines on U), noisy signals won't trigger falsely (B), so long as the noise doesn't cross the thresholds.

Wheel Encoder Adapters

To measure speed and distance travelled, Data Bus uses Sparkfun QRE1113 IR reflectance sensor breakout boards and wheel encoder discs printed with WheelEncoderGenerator.

On my robot, using QRE1113 reflectance sensors running at 5V, this is the waveform I get.


It looks similar to a half-rectified AC signal, about 3V peak and around 1.5V offset. Running on 3.3V, I get a 1.8V peak with 0.9V offset. Either one should be enough to trigger logic circuits.

It's not a bad idea to add hysteresis, though. If the sensor is right between encoder stripes, add a little noise and it could trigger more than intended.

555 Timer Schmitt Trigger

While you can easily find many examples of 555 timers wired to provide hysteresis triggering, and we'll look at the two common ones, a third circuit works better for the wheel encoder system on Data Bus.

In all cases, the encoder signal is ultimately wired to the Threshold and Trigger pins of the 555.


Inside the 555 timer is a 3-way voltage divider that provides the hysteresis thresholds. When the input voltage is above 2/3 Vcc, the 555's output goes low. When the input is less than 1/3 Vcc, the 555 output goes high.

555 Internals, more or less
But the 555 won't trigger for my 1.8V encoder signal which is below the 2.2V threshold. It won't work at 5V either. What can we do...?

Series Capacitor

By passing the signal through a capacitor, low frequencies (including DC) are filtered. If this high-pass signal is fed in between a voltage divider, it adds a dc offsets to the signal.


If the offset is 1/2 Vcc then the new peak voltage will be 0.9 + 3.3/2 = 2.55V, more than enough to trigger. The lowest voltage will be 3.3/2 - 0.9V = 0.75, well below the 1.1V lower threshold.

In the LTSpice simulation below, the red trace is the low threshold, the blue trace the high threshold, and the green trace is the signal with the dc offset.


So we're done. Let's build the board and move on, right? Wrong. I prototyped the circuit on a breadboard and found out it doesn't work like I want. At low wheel speeds, the 555 doesn't trigger at all. Why?


In the picture above, the red trace is the signal coming out of the high pass capacitor. Because the wheel speed is so low, most of the signal is low frequency and thus filtered and thus too small to trigger.

So, all you have to do is slap a big capacitor in place of the small one, right? With a capacitor that's large it can trigger on low wheel speeds, yes. However, it can can also get the 555 output "stuck."

Stuck? Yeah. If the robot sits with the input low too long, the 555 won't trigger for a long time after the wheels start spinning.

The reason is that, with the input voltage low, DC offset increases (the series capacitor charges) until the low voltage is now the new DC offset. When the wheels start moving again, it takes a long time for the circuit to bleed off the DC offset. This is the simulated result with a large capacitor, 220uF. It mirrors the real life experiments I did.


A smaller capacitor reduces the effect. Here's a 47uF capacitor. This also shows the output of the 555. The simulations do a good job of approximating what I'm seeing in real life.


Bottom line: you have to find the right capacitor for your needs. A small cap would work on Data Bus. It goes fast, and is only stopped at the starting and finish line. Still, I don't really like this circuit for wheel encoders. I'd prefer to fix the problem with the first circuit.

Transistor Amplifier Inverter

Using an NPN transistor to amplify (and invert) the phototransistor signal works well. It's not revolutionary although I didn't notice any similar circuits when searching for 555 Schmitt Trigger circuits. So, here it is.


Connect the base of the NPN through a resistor to the encoder board output, tie the collector to Vcc through a resistor, and the collector becomes the output for the 555. Simple, eh?

The Q1 transistor is either nearly 5V thanks to the pullup, or nearly 0V when base current is permitted to flow by the QRE1113 breakout board.

As a result, the circuit triggers at the lowest practical wheel speeds and doesn't lock up. Seems reliable enough to use. The only downside is that the duty cycle isn't even close to 50%, although no circuit is going to get it perfect. One can address this issue in software.


Encoder Imperfections and Software

With a pulse train that isn't a 50% duty cycle, calculating speed and distance is probably best done by timing either rising edges or falling edges, but not both.

The longer the robot travels on a particular leg of its journey, the less jitter affects distance calculation.

For speed, it may be wise to adjust control loop timing, encoder resolution, or robot speed ranges to adequately filter jitter and other noise. A slow robot needs more stripes, a fast robot needs fewer. A slower processor needs fewer and/or slower.

Think about how often the MCU has to sample encoder counts to adequately filter noise and calculate speed with acceptable accuracy, given the number of stripes and the robot's typical speed range.

And maybe filtering isn't even necessary. If a speed PID controller is adjusting a robot's speed at every edge, jittery speed adjustments between edges may be effectively filtered by the momentum of a fast, heavy robot.

If the robot is slow and very light, momentum won't filter jittery speed changes very well. Software can do it instead. Change speed based on a running average, leaky integrator, or other software filter. Or, the PID controller can check speed by timing many pulses instead of few.

Wheel imperfections and encoder disc mounting imperfections cause a low frequency modulation of the encoder signal. Sent through a Schmitt trigger, the output pulse width will vary.

That sort of jitter may be a problem when precisely traveling short distances at slow speeds. More precision in the assembly may help. Or increasing the encoder resolution.

Conclusion

The 555 is quite the Swiss Army Knife of ICs. Acting as a Schmitt trigger is one of its many capabilities. With all that said, it's probably just as easy to just use a Schmitt Trigger inverter instead of the 555. I'm looking into that next.

Tuesday, January 22, 2013

LifeCam HD-6000 autofocus fix, Raspberry Pi

LifeCam HD-6000 autofocus fix

The Microsoft Lifecam HD-6000 autofocus is notoriously annoying. It refocuses unnecessarily sometimes every few seconds making the camera nearly unusable. Here's the workaround on Raspbian (Debian) for the Raspberry Pi.

Friday, January 18, 2013

Raspberry Pi Wifi Static IP

My RPi is going to be a telepresence robot so it uses wifi. It also needs a static IP address. Here's how to configure Raspbian Wheezy with a static IP for wifi. Included are two useful techniques. Follow the series of steps and options below.

You can configure Wheezy for 1. Roaming with Static IP, below, or 2. Static IP With No Roaming, WPA2, PSK, below.

1. Roaming With Static IP

By default, Wheezy is configured for wireless roaming using wpa_supplicant, a daemon that manages roaming and authentication to access points with WPA, WPA2, WEP, or no encryption. With it, you can specify multiple access points and your RPi will join them automatically. First you'll need to add a Static IP Configuration, below.

a. Static IP Configuration

First, edit your /etc/network/interfaces and add the following to specify a static IP for demo which is any arbitrary name that we can use in the wpa_supplicant.conf to associate any network with this static IP configuration. You'll also make sure you have your wlan interface configured correctly.


allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

iface demo inet static
address 192.168.0.4
netmask 255.255.255.0
gateway 192.168.0.1

Next, you'll configure wpa_supplicant. Add a specification for a network Without Encryption below, With Encryption, WPA2, PSK below, or Any Network Specification below.

b. Without Encryption

To specify a network without encryption, edit  /etc/wpa_supplicant/wpa_supplicant.conf, add your network specification to the end of the file as follows. Specifying key_mgmt=NONE says the AP does not require encryption. To use the static IP configuration that you added in your interfaces, set id_str="demo" or whatever name you chose.

network={
 ssid="BotThoughts"
 scan_ssid=0
 key_mgmt=NONE
 priority=5
 id_str="demo"
}

Now proceed to the 3. Final Steps below.

2b. With Encryption, WPA2, PSK

To specify a network with WPA2 encryption using PSK (pre-shared key), edit /etc/wpa_supplicant/wpa_supplicant.conf, add a network specification to the end of the file as follows. To use the static IP configuration that you added in your interfaces, set id_str="demo" or whatever name you chose.

network={
 ssid="your-ssid-here"
 scan_ssid=0
 psk="your-pre-shared-key-here"
 proto=RSN
 key_mgmt=WPA-PSK
 pairwise=CCMP
 auth_alg=OPEN
 priority=1
 id_str="demo"
}

Now proceed to 3. Final Steps below.

2c. Any Network Specification

The bottom line is that you can add any network specification, following various online examples, to wpa_supplicant.conf and use a static IP for that access point simply by adding  id_str="demo" or whatever name you chose in interfaces.

In fact, you can have multiple strings, like home, work, traveling, demo, etc. Once you have edited wpa_supplicant.conf and interafaces, proceed to the 3. Final Steps below.

2. Static IP With No Roaming, WPA2, PSK 

This config does not use wpa_supplicant and is for WPA2 personal with PSK (Private Shared Key). The changes to your /etc/network/interfaces file will result in something like the following.

auto lo

iface lo inet loopback
iface eth0 inet static
address 192.168.0.5
netmask 255.255.255.0
gateway 192.168.0.1

auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.0.4
netmask 255.255.255.0
gateway 192.168.0.1
wpa-passphrase yourpassphrasehere
wpa-ssid yourssidhere
wireless-channel yourchannelhere

#wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
#iface default inet dhcp

Specify using static instead of manual for interface wlan0, then specify the address, netmask, and gateway, configure the WPA passphrase and SSID, and the wireless channel. Finally, you have to disable the wpa_supplicant configuration, and you have to disable the default dhcp behavior.

Proceed to 3. Final Steps below.

3. Final Steps

After making your configuration file changes, either reboot, or issue the following commands to restart the wlan0 interface:

sudo ifdown wlan0
sudo ifup wlan0

If you get no errors on the last command, except possibly some ioctl errors, you're a-ok.

pi@raspberrypi:/etc/network$ sudo ifup wlan0
ioctl[SIOCSIWAP]: Operation not permitted
ioctl[SIOCSIWENCODEEXT]: Invalid argument
ioctl[SIOCSIWENCODEEXT]: Invalid argument
pi@raspberrypi:/etc/network$

Double-check by issuing iwconfig to make sure the RPi is joined to the access point, then use ifconfig wlan0, make sure it's configured correctly, then issue a ping to your gateway (ping 192.168.0.1) and then ping google.com or some other reliable website.

pi@raspberrypi:/etc/network$ ifconfig -a
eth0      Link encap:Ethernet  HWaddr b8:27:eb:fb:8d:50
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:36 errors:0 dropped:0 overruns:0 frame:0
          TX packets:36 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3480 (3.3 KiB)  TX bytes:3480 (3.3 KiB)

wlan0     Link encap:Ethernet  HWaddr 80:1f:02:86:ef:61
          inet addr:192.168.0.4  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:38 errors:0 dropped:1467 overruns:0 frame:0
          TX packets:14 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:841044 (821.3 KiB)  TX bytes:100717 (98.3 KiB)

pi@raspberrypi:/etc/network$ ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_req=1 ttl=64 time=3.07 ms
64 bytes from 192.168.0.1: icmp_req=2 ttl=64 time=1.90 ms
^C
--- 192.168.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 1.905/2.491/3.077/0.586 ms
^C

Et voila, you have a wifi static IP. Congratulations!

Did this help you? If so, do me a favor and share via redit, twitter, Google+, etc. Thanks!

Tuesday, January 15, 2013

Tindie, Projects, New Look

New Look

You can't miss the new look if you're visiting bot-thoughts.com right now.

After 5 years, I figured it was time for a new look and layout. Besides, every single one of my projects is completely stalled waiting for various parts and boards. What else am I to do with my spare time?

Projects

I mentioned I'm waiting on parts for two projects. Those projects are, respectively, a JeeNode sensor to tell me when the mail has arrived and a tele-presence robot based on a Raspberry Pi.

The latter project will be using Pololu tracks and motors to drive around an RPi with a Webcam and WiFi dongle attached. I'll set up a web page on the Pi to control it from anywhere in the world. We'll be travelling this year and I want to check up on the house remotely.

The main challenge? Charging the batteries...

Bot Thoughts Store on Tindie

I've started a Google Group for the Bot Thoughts Store so I can post updates there. All the parts have arrived for the eeZee Propeller and eeZee MicroSD. I'm now waiting on boards. They'll arrive possibly next week. Also, another batch of eeZee Tiny 8-pin ATtiny breakouts will be in stock by Feb 1.

Friday, January 11, 2013

Getting Started with JeeNode v6

Two JeeNode v6 kits; RFM12-B radios not installed yet
JeeNode is an Arduino-compatible wireless solution based on the RFM12-B-S2 wireless transceiver including really nice driver libraries that make multi-node wireless communication ridiculously easy.

Starting with a standard JeeNode v6 kit, let's get cracking with assembly and testing.

Tuesday, January 8, 2013

ATtiny 2313 Breakout and I2C ADC

I have a couple more #tindie fundraisers going:


eeZee Propeller and eeZee microSD boards are on order and I'll be ordering parts soon.

Friday, January 4, 2013

Generating a clock signal with dsPIC33F

dsPIC33F generates a 500kHz clock signal
Generating a 500kHz clock signal with the dsPIC33F to run a Game Boy camera entails using Timer2 or Timer3 and one of the Output Compare peripherals. Here's how...

Wednesday, January 2, 2013

2013

Happy New Year!