One of the best parts about being involved with Dorkbot is that it has kicked me into making some new sculptures. The Winter Lights show at Vermillion Gallery opened last Thursday and our piece was in it. Bob Gallup and I collaborated again with great results I built the physical platform and Bob handled the software (with his usual skill and aplomb). The piece uses a UV LED to draw vector patterns on a phosphorescent screen. It is controlled by an Arduino, with an Adafruit motor controller board to run the motors.
I am really happy with the way it turned out. The flotsam piece we worked on last summer was a bit of a compromise for me. I had not yet gotten the garage set up, and many of my tools and materials were still packed away. This time I had most everything out and ready to use. I treated this as an exercise in patience and intention. Every step was carefully considered, and if I screwed something up (which was often) I did it over again instead of hacking it together. I wanted to try and build something that looked as if it would have been right at home in an early laboratory, so that meant it had to look handmade, but also polished and "engineered". Every decision was made based upon functionality, and I tried very hard to avoid any kind of ornament or decoration. Although I would really have appreciated the milling machine I left in Philadelphia, I was pleasantly surprised with how much I could do just using my drill press, band saw, and hand tools.
I started by building a frame from scraps of reclaimed Douglas fir from a local architectural salvage place. I have completely fallen in love with stuff. It is everywhere out here, and I really enjoy working with it.
The next step was to start laying out bit and pieces of ink jet and scanner hardware. I was looking for a good pair of stepper motors that I could use as X and Y axis drivers. I have lots of these so it was not too hard to find two that would work together, I also dug out a pile of polished steel rods (also from printers and scanners) and some linear bearings that originally held the print heads of an ink jet.
The x-axis is almost a complete steal from an old scanner with the ink jet linear slide being the only addition. I made up a brass plate to ride on the x-axis and hold the y-axis motor and rod assembly. The y-axis is all custom made with bits and pieces from aho knows how many other machines. It was fun to machine up the various fittings I needed for keeping everything in place (even though I ended making many of them at least twice).
Brass was my material of choice as it is easy to work, and it looks great with the warm color of the Fir. I was initially very concerned with how to manage the wires. I considered lacing them, but in the end I made long brass springs out of fine wire and slid the wires through them. They look amazing (if I do say so).
All of the materials, and most of the screws and fasteners are from other things I have taken apart or collected. I think that at most I spent $30 for materials, much of it on the phosphorescent paint. A few coats of shellac gives the fir a perfect "old school" finish, and adds to the antique feel. Once done I turned it over to Bob to write the code. He managed to build quite a sophisticated system in just a few days. I will let him describe it (hopefully) but I know he took his inspiration from the old logo turtle graphics and built a parser that can read simple "programs" to draw the patterns. Here is a video he took at the opening, and if you are impatient skip ahead to about 1:11 to see it start drawing one of the 6-7 patterns it draws at random. Bob refers to this one as "triangle 90", but I call it "Iron cross". Bear in mind, it is called SlowLight for a reason...
I just found out that user br3ttb created a very useful looking PID library for the Arduino.
I had considered turning my hacked together code into a library, but never got to the point where I thought I could pull it off.
This should definitely make it easier to test various physical setups as it will standardize the software to a great extent. I can't wait to try it out with a real project. I even have one!
Joe Gray has been running an open lab night at 911 media arts center for quite a while now. I have been talking up the idea of an Arduino Hackday, and it seems like a natural combination. So on May 30th we are going to have an Open LocalHackday in the "lab" at 911. Bring your projects, bring your tools, bring your toys. Meet other local hardware hackers, artists, and makers. There won't be a formal leader, and it is not a class, but you will definitely learn something!
For me, the focus is going to be on Arduino projects, but that does not preclude you from bringing whatever you are working on. Just show up!
It has been a crazy few months here and I have barely had time to breath let alone work on projects or blog.
Work kept me tied to the keyboard for most of January, and all of February, and then I buzzed off to SXSW interactive for a week of sessions, schmoozing, and beer. Now I am getting really excited about some things that are happening this spring and summer.
First off I am teaching another Arduino class at 911 Media Arts Center starting sometime in mid April (exact date TBD, watch this space).
Then at the end of April I am going to be helping out with the next iteration of IgniteSeattle.
In June will be the opening of the 4th edition of the dorkbot-sea art show "People doing strange things with electricity" at 911 Media. This year I am collaborating on a piece for the show with my friend Bob Gallup.
Finally in July we are launching a really exciting event. July 11th will be the first Frayed Wire art/tech unconference, and it should be a weekend of great fun (http://www.frayedwire.com).
I think I should have some interesting posts in store on motor control and arduino experiments as Bob and I work on the piece for PDSTWE. We are going to be using processing or vvv for video analysis and talking to the arduinos (or maybe one of my makecontrollers) via OSC or something. Details are sketchy but I know it will be fun.
arduino linear positioning with an ink jet printer carcass from Josh Kopel on Vimeo. I spent a bit more time messing with the ink jet guts, and finally had some success getting the linear print head positioning to work. The first challenge was that the motor kept hanging up and moving in big jerks. After burning my finger on the Arduino's voltage regulator, I finally realized that routing all the power through the Arduino was the problem. Now I am running the Arduino off of the USB cable, and I hooked a random 13.5 volt wall wart up directly to the power terminals on the motor control board. Once I got enough torque out of the motor it works quite well.
I am getting a measure of the upcoming challenges though. For one I need to add at least one limit switch so that I can establish a repeatable zero position. That should be fairly easy.
I think there may be a bigger problem dealing with the interrupts from the encoder circuit. When I try to get any feedback from Serial.print() inside my loop{} it hangs up and stutters out only an occasional message. The issue seems to be that the encoder is too precise! The encoder strip has 200 line per inch rulings, and I am currently triggering an interrupt with each 0 ->1 and 1->0 transition. This means it is generating interrupt hits 400 times for each inch it travels, and I think the Arduino is never able to get through a complete loop execution without being interrupted (I can sympathize).
I am going to try just using one of the edge transitions (i.e. low -> high) and see if that helps. It may mean that the code needs to handle the rapid interrupts more gracefully. I can see this being with a very tight loop while the motor is seeking, and then a detachInterrupt() and power down (or set to shorted out braking) while it does anything else.
In the mean time it is fun to zip the motor back and forth.
I found that the newer ink jet printers often use a combination of a DC motor and an optical encoder to take the place of stepper motors for print head positioning (linear motion) and paper feed (rotary positioning). The pieces often come out (after some effort) as a whole, and they seemed like a natural to experiment with.
The motors themselves are pretty nice if you just want to make something move and control its speed, and in combination with the encoder, I thought I could use them as a free alternative to a hobby servo. I knew there had to be some information out there about using a feedback loop to position a motor, and of course there was. It turns out that the classic way of doing this is through a PID servo controller (Proportional, Integral, Derivative). At its simplest this method can be thought of as a way to use the difference between where the motor should be and where it is (error), plus the speed at which the error is changing, plus the sum of past errors to manage the speed and direction that the motor is turning.
Ok, so I have to say at this point, that I am not an engineer. I did take an engineering calc. class or two, but that was more then 25 years ago, and I never much understood it even then. So all I really have to go on is my intuition about how this is working, a few good explanations, and some example code. As always , Google is your friend. If you do have a good understanding I would welcome your comments!
The first resource I found was this exchange on the Arduino forums and then followed through to an article that really explained what was going on here at embedded.com.
After reading the embedded.com article a few times I put together some simple code, and was amazed to find that the thing worked almost perfectly the first time.
The key elements of the code look like this
int val = analogRead(potPin); // read the potentiometer value (0 - 1023)
int target = map(val, 0, 1023, 0, 3600);// set the seek to target by mapping the potentiometer range to the encoder max count
int error = encoder0Pos - target; // find the error term = current position - target
// generalized PID formula
//correction = Kp * error + Kd * (error - prevError) + kI * (sum of errors)
// calculate a motor speed for the current conditions
int motorSpeed = KP * error;
motorSpeed += KD * (error - lastError);
motorSpeed += KI * (sumError);
// set the last and sumerrors for next loop iteration
lastError = error;
sumError += error;
What is going on here is:
1. read a value from the potentiometer through an analog to digital input (0-1023)
2. map that value so that it lives in the range from 0-3600 (the count from one full rotation of the motor). We need to scale like this so we can make an apples to apples comparison with the current position reported by the optical encoder. The current position is being calculated in another function (an ISR) whenever an interrupt is generated by the optical encoder (more on what this is all about here).
3. create an error term by subtracting the value we want to go to (target) from where we are (encoder0Pos)
4. multiply the error by a constant (proportional gain) to make it large enough to effect the speed. This is the Proportional term, and gives us a simple linear speed value. Basically it says that the further we are from where we want to be, the faster we need to go to get there. The converse is true, so that we will slow down as we approach our destination. Of course, if we are going to fast to begin with, we may overshoot. Then the Proportional will switch signs (from - to + or visa versa) and we will back up towards our target. If the speed is really off then we end up zooming past many times and oscillating until we (hopefully) get to the target.
5. add the difference between the error NOW and the error from the last time around. This is a way to figure out how fast the error is changing, and is the Derivative term of the equation, and you can think of it a bit like looking into the future. If the error rate is changing fast then we are getting close to where we want to be FAST and we should think about slowing down. This helps dampen the oscillation from the position term by trying to slow us down faster if we are approaching the target too quickly. Again, we multiply the value by a constant to amplify it enough to matter.
6. lastly add in the sum of all past errors multiplied by a constant gain. This is the Integral term, and is like looking at our past performance and learning from our mistakes. The further off we were before, the bigger this value will be. If we were going too fast then it will try to slow us, if to slowly, then it speeds us up.
7. set the lastError to the current error, and add the current error to our sum.
The resulting motorSpeed value will be a signed integer. Since the Adafruit controller takes an unsigned int as its speed value I do a little more manipulation to figure out the direction and get a abs() value for the speed, but that part is all pretty easy.
As I said, it seems really simple for such a complicated process. It turns out that the geared motor from the ink jets is much easier to control that some other mechanical systems. The physics of its gears, and the performance curve of the simple DC motor mean that you can be pretty far off on your tuning and it will still end up in the right place (eventually). If we were trying to do extremely precise positioning, or make it all work really fast, or handle huge inertial loads, then it would need to be a lot more robust. I am still working on "tuning " the configuration (i.e. slowly changing the 3 constant parameters one-by-one until it works best) and I will write more about that later.
In the mean time here is the code [SORRY! It looks like the code has vanished, and I cannot find a copy. DO NOT DISPAIR! Instead go here http://www.arduino.cc/playground/Code/PIDLibrary]. Bear in mind that it is designed for use with the Adafruit controller and library. You will also most likely find that it does not work well with the constants I have chosen*. In that case you will need to do some tuning yourself. Stay tuned (hah) and I will show you how I did it.
*discerning readers of code will notice that the Kd constant is 0 meaning that this is actually a PI controller. I found that while the Derivative made the motor settle into position faster, it also injected an enormous amount of noise and jitter. This is due in part to the cheap, noisy, and non-linear potentiometer I am using. I need to do some more experimenting before I can really call it a complete PID.
finally started tearing into the ink jet pile looking for useful parts and working on examples for the class. The first victim was a fancy HP all-in-one model. It consisted of a scanner and color printer and had sd and flash card sockets built in.It turned out to be extremely easy to tear apart. There was exactly one size of torx screw involved and only about 15 of them used. The rest is just intricate plastic snap together, which obviously means snap apart as well. I had to exercise some caution in not breaking the little tabs to make sure I would be able to reuse some of the connecting parts.
The main goals were to strip out the paper feed mechanism with its associated rotary encoding wheel and optical encoder, and get down to the linear print head driver with its position sensor/encoder strip. Along the way I also uncovered a small motor and encoder wheel in the ink waste tray, and the stepper motor for the scanner head. this last was especially nice as it came out with its gears, belt drive, and linear bearing axle in one unit. I took some not very useful pictures to document the teardown: http://www.flickr.com/photos/mrigneous/sets/72157608191419120/
I already have the paper feed motor running off the Adafruit motor shield and am working on how to connect the quadrature encoder to measure angle and direction of motion. The encoder device itself is dead simple to use as it is on its own little breakout board and only requires 4 wires +, GND, and two channels of signal (so only 2 i/o pins on the arduino). The challenge I am facing is figuring out which pins are used by the motor shield, and if they are the ones that support the interrupt(s) I need to manage the encoder. I will post more pics and code as I get that worked out. If I am successful (fingers crossed) then the same should be usable for the linear mechanism of the print head. In the end I hope to have a general purpose set up for reusing printer internals.
I also took apart an old lexmark printer and it had a very simple stepper controlled print head. The Motor shield really shines here as it took me all of five minutes to get the stripped down print head shuttling back and forth with microstepped accuracy and smoothness. I took a little video (not much plot, but there ya go).
I really wanted to make something cool with my new toys before the last make:philly meeting. I knew there was not much time, so I settled on a POV device. I figured that would be easy to show off, and would be a good way to interest people in the hacktory arduino/freeduino class. As it turned out, the hardware was the easy part. Here you see my attempts to get it to spell MAKE. Obviously I still had some work to do...
I found these great little smd leds on a junked keyboard pulled from the trash. Soldering them down with their individual current limiting resistors was a challenge. Unsoldering them from the keyboard was a nightmare! In the end I only ruined one. I really want to build a hot air rework unit.
Along the way I came across this post. Pure freakin' genius! I used an smd cap instead (because I had it and I am addicted to soldering tiny things), but other then that I can't add anything useful other then to say it works like a charm.
I ordered 4 bare bones arduino kits from Modern Devices. But in a moment of false economy decided not to order a USB < -- > TTL cable for them. Instead I decided that I would use some of the parts from the SMD grab bag I got ages ago and make one myself. My old laptop has a serial port, so I did not have to contend with USB, and it is "old tech" so there is lots of info out there.
Finding a suitable schematic was as easy as looking at the serial Arduino schematic and finding the rs232 input area. I rounded up all the parts, and used a peice of prototyping board designed for SMD parts from OnePas (http://www.onepasinc.com/). I also dug up a DB9 connector in a plastic box that had enough room for the tiny board I ended up with.
I have a desk mounted magnifier lamp (which had been in storage unused for 30 years!) and it turned out to be an absolute necessity. Soldering the parts down was surprisingly easy, but working without a design provided the usual set of challenges and opportunities for cursing.
In the end I got it all put together, but I simply could not get it to work. Two days of fiddling, finding mistakes, testing with the scope, trying different computers, and learning the intricacies of rs232 protocols left me no closer to a working cable. In a funk I ordered a USB cable from mouser, and almost gave up.
One final investigation finally revealed the problem. DB9 connectors are number as you look at the BACK not the FRONT! Switch one wire and suddenly the thing works like a charm. One of those things you just need to know.
It is probably the most expensive cable ever built, but I am quite happy with it.
Many years ago I was a graduate student studying metalsmithing. One day, one of my fellow students looked at my work area in dismay and pronounced "It looks like there is a big magnet under there and all that shit just sticks to it."
I accumulate things.
Sometimes I make stuff out of them.
These days I spend my almost all my time working as the CTO (and co-founder) of Squigaloo.
This blog is sort of on hiatus until life settles down a bit, but I still make things and it will be back!