How a bogus Wikipedia entry changed nationwide tire company policy
We had to get two tires recently, after the Civic got a flat. Naturally, we wanted the new tires on the front. That's where steering and braking happens, as well as the drive wheels and most of the car's weight ... so that's where we wanted the newer tires.
The shop (America's Tire) refused. They said it's a company policy that a new pair of tires must always go on the rear.
They've even printed up glossy signs
explaining
their reasoning -- a fancy poster image that is, unfortunately, wrong.
They show two scenarios. In the one on the left, the rear tires are losing traction, and the read end of the car is sliding out. That's called "oversteer". The car might spin, especially if the driver has never experienced it before.
That part's all true.
The problem with their diagram is the scenario on the right, where the
presumably better tires are on the rear. In their diagram, magically all
four tires are holding -- nothing ever loses traction. Good deal!
But what really happens if you put the bad tires on the front is that if something slips, it'll be the front. That's called "understeer".
Understeer can be just as dangerous as oversteer. With practice (I recommend autocross!) a driver can learn to detect oversteer and steer out of it before it gets to be a problem. There's an old saying among racers and performance drivers: "Oversteer is when the passenger is scared. Understeer is when the driver is scared."
Most passenger cars, especially front-wheel-drive cars like our Civic, are designed to understeer severely to begin with. Putting the poorer tires on the front makes that even worse.
And don't forget the importance of braking. Most of a car's braking ability comes from the front tires. Don't you want your best rubber working for you in a panic stop?
While I do understand why the default might be to put new tires on the rear -- it's better for inexperienced or panicky drivers -- to insist on it in all cases is just silly.
We drove the Civic home and rotated the tires ourselves.
How did the policy get started?
Dave and I first encountered this policy a couple of years ago. In the intervening years, it's become pervasive -- just about every tire shop insists on it now. How did that happen?
If you ask at the tire shop, they may tell you that it's a federal policy -- DOT or some such agency -- or even that it's a state law. Neither is true. It's merely company policy.
Some will also tell you that it arose from a lawsuit in which a tire company was sued after a customer spun out. So two years ago, we went looking to see if that was really true.
Back then, googling either "oversteer" or "understeer" led inexorably a Wikipedia's page with a reference to "San Luis Obispo County Court Case CV078853". Unfortunately, Wikipedia's link next to the court case reference actually led to a general page for a law firm that appears to specialize in vehicular personal injury lawsuits. (Nice advertising, that.) There was no information about any such case.
Nor did there seem to be any official records online of such a case; and the SLO courthouse didn't respond to an email request for more information.
Googling the court case, though, got lots of hits -- nearly all of them pasted verbatim from the Wikipedia page, then using that as "proof" of the supposed safety argument. The test of time
Now, a few years later, it seems that nearly all tire manufacturers have adopted this as a firm, non-negotiable policy. Some shops are even using it as a reason to refuse to rotate tires! (See, the front tires wear faster on most cars, so if you rotate tires between front and rear, now you're putting the more worn tires on the rear ... which is dangerous! Better to just let those front tires wear out and make the customer buy a new pair.)
The news is better on the Wikipedia end. Someone eventually heeded Dave's attempt to fix the Wikipedia page, removed the bogus advertising link to the ambulance-chasing law firm, and added "citation needed". Subsequently, several people rewrote the page in stages, with comments like "This is a complete replacement. The existing version was wrong from the 1st sentence and has little relationship to the standard terminology." The page is much better now.
What isn't better is that the sentence from the old Wikipedia page is still all over the net, word for word. Google for the court case and you'll find lots of examples. Many of them are content mills copying random Wikipedia content onto pages that bear no relation to cars at all. But unfortunately, you'll also find lots of cases of people using this phantom court case to argue the safety point.
Sadly, it seems that once something gets onto Wikipedia, it becomes part of the zeitgeist forever ... and however wrong it might be, you'll never be able to convince people of that. difficulties some people encounter trying to fix Wikipedia errors.) -->
Parsing HTML in Python
I've been having (mis)adventures learning about Python's various options for parsing HTML.
Up until now, I've avoided doing any HTMl parsing in my RSS reader FeedMe. I use regular expressions to find the places where content starts and ends, and to screen out content like advertising, and to rewrite links. Using regexps on HTML is generally considered to be a no-no, but it didn't seem worth parsing the whole document just for those modest goals.
But I've long wanted to add support for downloading images, so you could view the downloaded pages with their embedded images if you so chose. That means not only identifying img tags and extracting their src attributes, but also rewriting the img tag afterward to point to the locally stored image. It was time to learn how to parse HTML.
Since I'm forever seeing people flamed on the #python IRC channel for using regexps on HTML, I figured real HTML parsing must be straightforward. A quick web search led me to Python's built-in HTMLParser class. It comes with a nice example for how to use it: define a class that inherits from HTMLParser, then define some functions it can call for things like handle_starttag and handle_endtag; then call self.feed(). Something like this: from HTMLParser import HTMLParser class MyFancyHTMLParser(HTMLParser): def fetch_url(self, url) : request = urllib2.Request(url) response = urllib2.urlopen(request) link = response.geturl() html = response.read() response.close() self.feed(html) # feed() starts the HTMLParser parsing def handle_starttag(self, tag, attrs): if tag == 'img' : # attrs is a list of tuples, (attribute, value) srcindex = self.has_attr('src', attrs) if srcindex < 0 : return # img with no src tag? skip it src = attrs[srcindex][1] # Make relative URLs absolute src = self.make_absolute(src) attrs[srcindex] = (attrs[srcindex][0], src) print '<' + tag for attr in attrs : print ' ' + attr[0] if len(attr) > 1 and type(attr[1]) == 'str' : # make sure attr[1] doesn't have any embedded double-quotes val = attr[1].replace('"', '\"') print '="' + val + '"') print '>' def handle_endtag(self, tag): self.outfile.write('</' + tag.encode(self.encoding) + '>\n')
Easy, right? Of course there are a lot more details, but the basics are simple.
I coded it up and it didn't take long to get it downloading images and changing img tags to point to them. Woohoo! Whee! The bad news about HTMLParser
Except ... after using it a few days, I was hitting some weird errors.
In particular, this one:
HTMLParser.HTMLParseError: bad end tag: ''
It comes from sites that have illegal content. For instance, stories
on Slate.com include Javascript lines like this one inside
<script></script> tags:
document.write("<script type='text/javascript' src='whatever'></scr" + "ipt>");
This is technically illegal html -- but lots of sites do it, so protesting that it's technically illegal doesn't help if you're trying to read a real-world site.
Some discussions said setting self.CDATA_CONTENT_ELEMENTS = () would help, but it didn't.
HTMLParser's code is in Python, not C. So I took a look at where the errors are generated, thinking maybe I could override them. It was easy enough to redefine parse_endtag() to make it not throw an error (I had to duplicate some internal strings too). But then I hit another error, so I redefined unknown_decl() and _scan_name(). And then I hit another error. I'm sure you see where this was going. Pretty soon I had over 100 lines of duplicated code, and I was still getting errors and needed to redefine even more functions. This clearly wasn't the way to go. Using lxml.html
I'd been trying to avoid adding dependencies to additional Python packages, but if you want to parse real-world HTML, you have to. There are two main options: Beautiful Soup and lxml.html. Beautiful Soup is popular for large projects, but the consensus seems to be that lxml.html is more error-tolerant and lighter weight.
Indeed, lxml.html is much more forgiving. You can't handle start and end tags as they pass through, like you can with HTMLParser. Instead you parse the HTML into an in-memory tree, like this: tree = lxml.html.fromstring(html)
How do you iterate over the tree? lxml.html is a good parser, but it has rather poor documentation, so it took some struggling to figure out what was inside the tree and how to iterate over it.
You can visit every element in the tree with for e in tree.iter() : print e.tag
But that's not terribly useful if you need to know which tags are inside which other tags. Instead, define a function that iterates over the top level elements and calls itself recursively on each child.
The top of the tree itself is an element -- typically the <html></html> -- and each element has .tag and .attrib. If it contains text inside it (like a <p> tag), it also has .text. So to make something that works similarly to HTMLParser: def crawl_tree(tree) : handle_starttag(tree.tag, tree.attrib) if tree.text : handle_data(tree.text) for node in tree : crawl_tree(node) handle_endtag(tree.tag)
But wait -- we're not quite all there. You need to handle two undocumented cases.
First, comment tags are special: their tag attribute, instead of being a string, is <built-in function Comment> so you have to handle that specially and not assume that tag is text that you can print or test against.
Second, what about cases like <p>Here is some <i>italicised</i> text.</p> ? in this case, you have the p tag, and its text is "Here is some ". Then the p has a child, the i tag, with text of "italicised". But what about the rest of the string, " text."?
That's called a tail -- and it's the tail of the adjacent i tag it follows, not the parent p tag that contains it. Confusing!
So our function becomes: def crawl_tree(tree) : if type(tree.tag) is str : handle_starttag(tree.tag, tree.attrib) if tree.text : handle_data(tree.text) for node in tree : crawl_tree(node) handle_endtag(tree.tag) if tree.tail : handle_data(tree.tail)
See how it works? If it's a comment (tree.tag isn't a string),
we'll skip everything -- except the tail. Even a comment
might have a tail:
<p>Here is some <!-- this is a comment --> text we want to show.</p>
so even if we're skipping comment we need its tail.
I'm sure I'll find other gotchas I've missed, so I'm not releasing this version of feedme until it's had a lot more testing. But it looks like lxml.html is a reliable way to parse real-world pages. It even has a lot of convenience functions like link rewriting that you can use without iterating the tree at all. Definitely worth a look!
Arduino Nano -- cute, but sensitive about USB cables
I just got an Arduino
Nano. Cute little thing -- I'm looking forward to
using it in portable projects. But I had one problem when first plugging
it in. It was getting power just fine, and blinking its LED -- but it
wasn't showing up as a USB serial port in Linux. dmesg said things like:
usb 1-3.4: new full speed USB device number 7 using ehci_hcd
usb 1-3.4: device descriptor read/64, error -32
usb 1-3.4: device descriptor read/64, error -32
with several different device numbers each time, and an occasional
unable to enumerate USB device on port 4 thrown in.
A web search found a few other people seeing this problem on Linux or Linux-based devices, with some people saying that pressing the RESET button multiple times helps. It didn't for me. What solved the problem for me was switching cables. The mini-USB cable I'd been using -- which has worked fine for other purposes, including programming other Arduinos through an FTDI Friend -- apparently was missing something the Nano needs for downloading. With a different cable, dmesg showed a much more civilized usb 1-3.4: new full speed USB device number 20 using ehci_hcd ftdi_sio 1-3.4:1.0: FTDI USB Serial Device converter detected usb 1-3.4: Detected FT232RL usb 1-3.4: Number of endpoints 2 usb 1-3.4: Endpoint 1 MaxPacketSize 64 usb 1-3.4: Endpoint 2 MaxPacketSize 64 usb 1-3.4: Setting MaxPacketSize 64 usb 1-3.4: FTDI USB Serial Device converter now attached to ttyUSB0
What was wrong with the cable? I did some testing with a multimeter versus a pinout diagram. Didn't get a definitive answer, but I did find that on the cable that doesn't work for the Nano, it was hard to get a solid connection on the D- (#2) pin inside the Type A connector. But since that's the connector that goes to the computer end (in my case, a powered hub), if it wasn't making good contact, I would expect it to show up everywhere, not just with the Nano. Maybe the Nano is more sensitive to a good solid D- connection than other devices.
I'm not really convinced. But Arduino's Troubleshooting Guide suggests: "Try a different USB cable; sometimes they don't work." So I guess they don't know what's special about some cables either.
So if your Arduino Nano doesn't initially connect properly, don't panic. Try a few different cables (everybody has about a zillion mini-USB cables lying around, right? If not, here, have five of mine). The Nano is happily composing random chiptunes as I write this.
Open the X selection in a browser window, from any desktop
Like most Linux users, I use virtual desktops. Normally my browser window is on a desktop of its own.
Naturally, it often happens that I encounter a link I'd like to visit while I'm on a desktop where the browser isn't visible. From some apps, I can click on the link and have it show up. But sometimes, the link is just text, and I have to select it, change to the browser desktop, paste the link into firefox, then change desktops again to do something else while the link loads.
So I set up a way to load whatever's in the X selection in firefox no matter what desktop I'm on.
In most browsers, including firefox, you can tell your existing browser window to open a new link from the command line: firefox http://example.com/ opens that link in your existing browser window if you already have one up, rather than starting another browser. So the trick is to get the text you've selected.
At first, I used a program called xclip. You can run this command: firefox `xclip -o` to open the selection. That worked okay at first -- until I hit my first URL in weechat that was so long that it was wrapped to the next line. It turns out xclip does odd things with multi-line output; depending on whether it thinks the output is a terminal or not, it may replace the newline with a space, or delete whatever follows the newline. In any case, I couldn't find a way to make it work reliably when pasted into firefox.
After futzing with xclip for a little too long, trying to reverse-engineer its undocumented newline behavior, I decided it would be easier just to write my own X clipboard app in Python. I already knew how to do that, and it's super easy once you know the trick: mport gtk primary = gtk.clipboard_get(gtk.gdk.SELECTION_PRIMARY) if primary.wait_is_text_available() : print primary.wait_for_text()
That just prints it directly, including any newlines or spaces. But as long as I was writing my own app, why not handle that too?
It's not entirely necessary on Firefox: on Linux, Firefox has some special code to deal with pasting multi-line URLs, so you can copy a URL that spans multiple lines, middleclick in the content area and things will work. On other platforms, that's disabled, and some Linux distros disable it as well; you can enable it by going to about:config and searching for single, then setting the preference editor.singlelinepaste.pasteNewlines to 2.
However, it was easy enough to make my Python clipboard app do the right thing so it would work in any browser. I used Python's re (regular expressions) module: #!/usr/bin/env python import gtk import re primary = gtk.clipboard_get(gtk.gdk.SELECTION_PRIMARY) if not primary.wait_is_text_available() : sys.exit(0) s = primary.wait_for_text() # eliminate newlines, and any spaces immediately following a newline: print re.sub(r'[\r\n]+ *', '', s)
That seemed to work fine, even on long URLs pasted from weechat with newlines and spaces, like that looked like http://example.com/long- url.html
All that was left was binding it so I could access it from anywhere. Of course, that varies depending on your desktop/window manager. In Openbox, I added two items to my desktop menu in menu.xml: <item label="open selection in Firefox"> <action name="Execute"><execute>sh -c 'firefox `xclip -o`'</execute></action> </item> <item label="open selection in new tab"> <action name="Execute"><execute>sh -c 'firefox -new-tab `xclip -o`'</execute></action> </item>
I also added some code in rc.xml inside <context name="Desktop">, so I can middle-click or control-middle-click on the desktop to open a link in the browser: <mousebind button="Middle" action="Press"> <action name="Execute"> <execute>sh -c 'firefox `pyclip`'</execute> </action> </mousebind> <mousebind button="C-Middle" action="Press"> <action name="Execute"> <execute>sh -c -new-tab 'firefox `pyclip`'</execute> </action> </mousebind>
I set this up maybe two hours ago and I've probably used it ten or fifteen times already. This is something I should have done long ago!
Using motors with an Arduino
This is the story of my adventures learning to drive a little toy truck from an Arduino: specifically, how to drive the motors. Motor control turned out to be trickier than I expected, and I don't see a lot of "Arduino motor control for dummies" pages on the web, so I'm writing one.
My truck is from a thrift shop. It has two brushed motors (about 280-350 size, in R/C plane parlance). It was originally radio controlled. It has space for 4 AA batteries, nominal 6v, which I thought should be perfect for the Arduino. Connecting directly to the Arduino (don't)
First, you can drive a small motor directly by plugging one lead into
ground and the other into an Arduino digital or analog output line.
(Analog output isn't real analog output -- it uses PWM, pulse width modulation.)
Don't do this. You risk damaging your Arduino, either by putting
too much current through it (the Arduino maxes out at 40ma per pin, 200ma
total; a small motor can pull several amps), or from
back-EMF when
the motor stops.
Motor shields
Lots of Arduino-oriented shops sell "motor shields". I bought a
Freeduino
motor shield because I could get it from Amazon and it was cheap.
It's a kit you have to solder together, but it's a very easy soldering job.
The demo code is easy, too. I wired it up to the Arduino, loaded the demo
code, hooked up my Arduino to the truck's onboard batteries, and ...
nothing. Sometimes the motor would twitch a bit, or hum, but the truck
didn't move.
I wondered if maybe it was something about the batteries (though they were brand new). I tried plugging the Arduino in to the universal AC power supply I use for testing. No improvement.
At first I suspected that the motor shield was junk because its 1 amp maximum wasn't enough. But I was wrong -- the problem was the batteries. Neither the truck's 4xAA batteries nor the (supposedly) 1 amp AC adaptor could put out enough current to drive motors.
When it finally occurred to me to try a lithium-polymer model airplane battery (2 cells, 7.4 volts, 500 mAh), the truck immediately zipped across the floor and smashed into a chair leg.
So motor shields work fine, and they're very easy to use -- but don't underestimate the importance of your power supply. You need a battery capable of supplying a fairly beefy current.
But why is that, when the truck was designed for 4xAA batteries?
Well, the 4xAAs can drive the motors, but they can't drive the motors, the Arduino and the shield all at the same time. If I power the Arduino separately off a 9v battery, the truck will move. It doesn't zip across the room like with the li-po battery, but at least it moves. Motor Driver
So I had a solution. Except I wanted something a little cheaper. A $20-30 motor shield is fine for a one-time project, but I was also shopping for parts to teach a summer camp class in robotics. We're on a shoestring budget, and an additional $20 per team is a little too much.
On a recommendation from Eugene at
Linux Astronomy, who's been
teaching wonderful robotics classes for several years, I discovered
Pololu as a source of robotics
equipment. Poking around their site, I found the
TB6612FNG Dual
Motor Driver Carrier, which is under $8 in quantity. Sounded like
a much better deal, so I ordered one to try it out.
The TB6612FNG comes with headers not yet soldered. I substituted female headers, so it would be easier to plug in jumper wires to the Arduino and the male leads from the motors.
Writing an Arduino program for the TB6612FNG is a little more complicated than for the motor shield. It has two direction pins for each motor, plus a STDBY pin you have to keep high. So there are a lot more pins to manage, and when you change motor direction you have to toggle two pins, not just one. That'll make it more confusing for the students (who are beginning programmers), but I've written wrappers like drive(int whichmotor, int direc, int speed) to make it simpler.
The motor driver has the same power supply issue as the motor shield did:
I can't power it, the Arduino and the motors all from the 4xAA batteries.
Like the shield, it works okay with the Arduino on 9v, and great with
one li-po powering everything.
It's been pointed out to me that an even cheaper way to run small motors, suitable for classrooms on a shoestring budged, is to use a transistor. Here's one circuit tutorial I found for that: Using a transistor to control high current loads with an Arduino.
I also tried using ESCs, the electronic speed controllers I've used with radio controlled airplanes. You can talk to them using the Arduino Servo library (there are lots of examples online). That works, but there are two issues:
- ESCs all have wierd proprietary arming sequences, so you have to figure out what they are (e.g. run the voltage up to maximum, hold there for two seconds, then down to zero, then hold for two seconds, then you're ready to drive) and write that into your code. If you switch ESCs, you may have to rewrite the arming code.
- ESCs only go in one direction -- fine for driving a truck forward, not so good if you need to drive a steering motor both ways.
I'm sure ESCs have the same battery issue as the other two options, but I didn't even try running one off the AAs. Anyone who has ESCs sitting around probably has beefy batteries too. Custom H-bridges
All the cool robotics hipsters (cHipsters?) buy H-bridge chips and build their own circuits around them, rather than using things like motor shields or motor drivers.
This H-bridge circuit by Bob Blick is one popular example. (Those double-transistor-in-a-circle things are Darlington transistors.) But a web search like arduino h-bridge circuit turns up other options.
For driving big motors, you definitely need your own H-bridge circuit
(or an ESC), since all the available motor shields and drivers are
limited to 2 amps or less. For small motors like my toy truck,
I'm not sure what the advantage is. Except being one of the cool cats.
Summary
- For any sort of motor, either use a beefy battery (lithium polymer is idea, but you need a special charger and safety precautions for them), or use separate batteries for the Arduino and the motors.
- Motor shields are the easiest and most turnkey option.
- A motor driver is cheaper and smaller, but slightly more hassle to use.
- Use an ESC for big motors that only need to go in one direction, or if you're already a model airplane junkie and have some lying around.
- Use a custom H-bridge circuit if you're a cHipster or you have a really big motor project.
Plotting the Analemma
My SJAA planet-observing column for January is about the Analemma and the Equation of Time.
The analemma is that funny figure-eight you see on world globes in the middle of the Pacific Ocean. Its shape is the shape traced out by the sun in the sky, if you mark its position at precisely the same time of day over the course of an entire year.
The analemma has two components: the vertical component represents the sun's declination, how far north or south it is in our sky. The horizontal component represents the equation of time.
The equation of time describes how the sun moves relatively faster or slower at different times of year. It, too, has two components: it's the sum of two sine waves, one representing how the earth speeds up and slows down as it moves in its elliptical orbit, the other a function the tilt (or "obliquity") of the earth's axis compared to its orbital plane, the ecliptic.
The Wikipedia page for
Equation of
time includes a link to a lovely piece of
R code by
Thomas Steiner showing how the two components relate. It's labeled
in German, but since the source is included, I was able to add English
labels and use it for my article.
But if you look at photos of real analemmas in the sky, they're always tilted. Shouldn't they be vertical? Why are they tilted, and how does the tilt vary with location? To find out, I wanted a program to calculate the analemma. Calculating analemmas in PyEphem
The very useful astronomy Python package PyEphem makes it easy to calculate the position of any astronomical object for a specific location. Install it with: easy_install pyephem for Python 2, or easy_install ephem for Python 3. import ephem observer = ephem.city('San Francisco') sun = ephem.Sun() sun.compute(observer) print sun.alt, sun.az
The alt and az are the altitude and azimuth of the sun right now. They're printed as strings: 25:23:16.6 203:49:35.6 but they're actually type 'ephem.Angle', so float(sun.alt) will give you a number in radians that you can use for calculations.
Of course, you can specify any location, not just major cities. PyEphem doesn't know San Jose, so here's the approximate location of Houge Park where the San Jose Astronomical Association meets: observer = ephem.Observer() observer.name = "San Jose" observer.lon = '-121:56.8' observer.lat = '37:15.55'
You can also specify elevation, barometric pressure and other parameters.
So here's a simple analemma, calculating the sun's position at noon on the 15th of each month of 2011: for m in range(1, 13) : observer.date('2011/%d/15 12:00' % (m)) sun.compute(observer)
I used a simple PyGTK window to plot sun.az and sun.alt, so once it was initialized, I drew the points like this: # Y scale is 45 degrees (PI/2), horizon to halfway to zenith: y = int(self.height - float(self.sun.alt) * self.height / math.pi) # So make X scale 45 degrees too, centered around due south. # Want az = PI to come out at x = width/2. x = int(float(self.sun.az) * self.width / math.pi / 2) # print self.sun.az, float(self.sun.az), float(self.sun.alt), x, y self.drawing_area.window.draw_arc(self.xgc, True, x, y, 4, 4, 0, 23040)
So now you just need to calculate the sun's position at the same time of day but different dates spread throughout the year.
And my 12-noon analemma came out almost vertical! Maybe the tilt I saw
in analemma photos was just a function of taking the photo early in
the morning or late in the afternoon? To find out, I calculated the
analemma for 7:30am and 4:30pm, and sure enough, those were tilted.
But wait -- notice my noon analemma was almost vertical -- but it wasn't exactly vertical. Why was it skewed at all? Time is always a problem
As always with astronomy programs, time zones turned out to be the hardest part of the project. I tried to add other locations to my program and immediately ran into a problem.
The ephem.Date class always uses UTC, and has no concept of converting to the observer's timezone. You can convert to the timezone of the person running the program with localtime, but that's not useful when you're trying to plot an analemma at local noon.
At first, I was only calculating analemmas for my own location. So I set time to '20:00', that being the UTC for my local noon. And I got the image at right. It's an analemma, all right, and it's almost vertical. Almost ... but not quite. What was up?
Well, I was calculating for 12 noon clock time -- but clock time isn't
the same as mean solar time unless you're right in the middle of your
time zone.
You can calculate what your real localtime is (regardless of what politicians say your time zone should be) by using your longitude rather than your official time zone: date = '2011/%d/12 12:00' % (m) adjtime = ephem.date(ephem.date(date) \ - float(self.observer.lon) * 12 / math.pi * ephem.hour) observer.date = adjtime
Maybe that needs a little explaining. I take the initial time string, like '2011/12/15 12:00', and convert it to an ephem.date. The number of hours I want to adjust is my longitude (in radians) times 12 divided by pi -- that's because if you go pi (180) degrees to the other side of the earth, you'll be 12 hours off. Finally, I have to multiply that by ephem.hour because ... um, because that's the way to add hours in PyEphem and they don't really document the internals of ephem.Date.
Set the observer date to this adjusted time before calculating your
analemma, and you get the much more vertical figure you see here.
This also explains why the morning and evening analemmas weren't
symmetrical in the previous run.
This code is location independent, so now I can run my analemma program
on a city name, or specify longitude and latitude.
PyEphem turned out to be a great tool for exploring analemmas.
But to really understand analemma shapes, I had more exploring to do.
I'll write about that, and post my complete analemma program,
in the next article.
Tips on building an Ardweeny
I've wanted an
Ardweeny
for a long time. It's just so cute -- it's an Arduino compatible
that's barely bigger than the Atmega 328 chip driving it. Plus, it's cheap:
$10 including the chip.
Like most small or low-cost Arduino clones, the Ardweeny doesn't have its own USB connection; instead, you use an adaptor such as an FTDI Friend, which slides onto a 6-pin header on the Ardweeny. I knew that ahead of time.
One thing I hadn't realized was that the Ardweeny gets its only power from the USB adaptor. So if you want to use an Ardweeny by itself with no computer connection, you need a regulated 5v power supply. Those are easy enough to build (see the Breadboard Arduino), but don't forget to allow for that when designing projects.
The Ardweeny comes as a kit that needs soldering -- something that isn't made clear in the sales literature, though for the price, it didn't surprise me. I downloaded the Ardweeny soldering steps (PDF) and got to work. Easy initial build
The PDF estimates 15 minutes for the construction. The first part, soldering the 10 components, was a snap, and took maybe 10 minutes. At this point you can take the Ardweeny and nestle it down over the Atmega chip, and test it to check your soldering work.
I plugged in my FTDI Friend and the LED immediately started blinking. Success! (It's nice of them to pre-program the chip with blink code, so it's easy to tell it's working.) Downloading my own version of the blink sketch (use the Duemilanove w/Atmega 238 setting, or atmega328 if you use my Makefile) also worked fine. The last step: soldering the legs
Except that I wasn't done. The next step of the build is to solder all 28 legs of the Ardweeny directly to the Atmega chip's legs. Scary idea -- won't all that heat kill the chip? But the instructions didn't have any warnings about that. I took a deep breath and forged ahead.
This part put me way over the 15-minute estimate -- 28 pins is a lot of pins, and I took it slowly, careful to be sparing with heat and solder.
When I was finally done, I plugged the FTDI Friend back in and ... nothing. Not a blink. And when I checked voltage on one of the V+ pins versus the ground pin, it measured around 1.5v, not the 5v I expected to see.
So I'd messed something up. Somehow, even though it worked without soldering the legs, that additional soldering had broken it. I went through all the pins with a voltmeter checking for shorts, and tested everything I could. Nothing obviously wrong.
It might have been nice to inspect my solder joints on the Ardweeny -- but once the Ardweeny is soldered to the chip, the solder is all inside and you can't see it. But anyway, I'd tested it and it had worked fine. Detaching the backpack from the chip
So I figured I must have destroyed the chip with heat or static during that soldering process. My Ardweeny was a brick. Nothing salvageable at all. Unless -- if I could somehow de-solder the legs and pull the two apart, I could use the Ardweeny with another chip.
But how do you de-solder 28 legs? I tried a solder sucker (a pen-shaped vacuum pump) and de-soldering braid, but neither one broke the bond between the two sets of legs. I tried sliding an X-acto knife in between the Ardweeny's legs and the chip's while heating the leg with solder; no luck, the knife blade was too good a heat sink and the solder never melted.
Dave finally found a solution. With my assurance that the chip was probably dead anyway, he rolled the Ardweeny on its back, and used the tip of the heated soldering iron to bend each chip leg inward away from the Ardweeny leg. When he was done, the chip looked bent and sad, like a squashed millipede -- but the pieces were separated. Testing to find the problem
And now I could take the Ardweeny and stick it on an Atmega 328 I pulled out of another Arduino. Plugged in the FTDI Friend and -- nothing.
Wait, it was the backpack that was bad? But I tested it before doing that last soldering phase!
I took the sad squashed-millipede Atmega and carefully bent all the pins back into shape, or at least close enough that I could plug it into a socket in my Diecimila. And, amazingly -- that poor abused overheated squashed bent 328 still worked just fine.
Okay, so the problem is definitely in the Ardweeny backpack. Now that the solder joints were exposed again, I examined them all and found two that looked questionable. I re-soldered them -- and everything worked. Lessons for the Ardweeny
I still don't know why my board worked the first time, then failed after the step of soldering the legs. But it makes me nervous about repeating that leg-soldering step. What if something else, something that's working now, stops working?
For now, I'll probably solder just a few pins -- maybe the
four outermost ones -- and rely on pressure for the other contacts.
Of course, in a real environment where the Ardweeny might be subject
to vibration and temperature changes, that might not be good enough.
But until then, it seems the safest option.
