Sunday, March 31, 2013

MATLAB Madness, Part I: A Brief Introduction

In this class we began to investigate the fun and exciting world of MATLAB!  We worked through a series of exercises from the first four chapters of Alan Downey's Physical Modeling in MATLAB.  I greatly enjoyed Downey's many humorous asides, and I was thrilled to design and run programs that actually worked!  I was excited to program in a text language, though it was a bit less transparent than the highly-visual PicoBlocks; however, I greatly appreciated the informative textbook walkthrough of the basics.
My version of the first exercise, creating a program to print the nth number in a geometric series by calculating it with the recursive formula:
I noticed that the textbook had a rather different approach.  Mine worked well enough, but Downey's version was a bit simpler and ultimately made more sense, given the matrix foundation of MATLAB:
The second exercise was to calculate the nth Fibonacci number by using the recursive formula.  I noticed that MATLAB is unable to deal with F(0), an advance hint about all the matrix notation.
My program:
After doing a little happy dance when the program printed out 55, I moved on to the next exercise, a word problem:
I later found out that I wasn't supposed to use a "for" loop yet, but Professor Banzaert had demonstrated this technique at the beginning of class, and I was eager to apply my new knowledge.
Next I looped the car program to discover that, after a year, the numbers of cars at A and B would be in equilibrium:
Next I plotted everything; I was thrilled that my (albeit very simple) program worked perfectly the first time it ran!


By the end of the class I was still struggling with the Fibonacci series and the baseball problem, but I hoped to finish them quickly and move on to more exciting programming.

Wednesday, March 27, 2013

Driving Straight: Part II: Unforeseen Difficulties

In our last class before Spring Break, we tried to apply proportional control to the drive-straight program while running a proportional-control version of the distance-sensing program.  This proved more difficult than we expected; while the previous class had ended with our seeming success in a drive-straight program, Professor Turbak began this day with a lecture which explained about five different incorrect assumptions we had made while writing the program (order of operations, negative power, etc.).  We lamented a bit about how neither my partner nor I had ever programmed before, and then set about to fixing our many errors.
We had initially attempted to fix the negative signs on the error by using an if-then-else statement to make sure that the final value for the engine power was positive; however, this method hinged on our error being either very small or very large.  This caused an unwanted result when we held one wheel and let the other spin: ideally, the unheld wheel would stop quickly of its own accord, but our program caused the wheel to continue spinning indefinitely.
To fix this error, Professor Turbak used the text language to define a new expression, "valid".  This was initially meant to define a value as 0 if it were negative (and leave the value alone if positive).  However, since my partner and I had built the rest of our program around the assumption that a negative error would simply switch the direction of the wheels, we made this an absolute value expression (outputting -n if n<0, n if n>0).  After a bit more experimentation, Professor Turbak patiently explained how this method could never possibly work, and we went back to the absolute value program.
The absolute value program, "valid" (lower text):

This made our program much neater by cutting out two large if-then-else loops, but we needed to change large portions of the rest of it since a negative value now made the wheel's power go to zero.  After much (almost two hours) fussing, we eventually made our way to a program that stopped Snow White's other wheel when one was held.  Hooray!

(I had hoped to include images of my programs in this blog post, but after the OS switch, the engineering room computers refused to open my old PicoBlocks programs.  Hopefully we'll find away around this problem soon.)

Then we began to play around with the light sensors for our next project--the final project, whose theme is "Follow the Light", will center around...following light.  Some suggestions for projects are a sun tracker for photovoltaic panels, a fire extinguisher (sensing candle light), or moving mirrors to more naturally and efficiently light an indoor space (or the greenhouse).  I'm most enthusiastic about solar panels at the moment (though there are various other types under development that do not need a perfect angle of sunlight), but I have not yet decided on my project.  In the meantime, it seems like we'll be learning Matlab soon, which is truly exciting--I look forward to finally learning the baby steps of a text programming language!


Thursday, March 14, 2013

Driving Straight: A Conga Challenge

After another unsuccessful attempt at a robot conga line last week, we decided to work on correcting motor imperfections to drive straight.
First, we tried to program one wheel's motor to reset the shaft to a specified angle.
The bang-bang control version for getting Wheel B to reset to a value of 42 after some arbitrary displacement:
The final proportional control program:
 We soon realized that the "coutb=42" if-then-else statement was completely unnecessary and removed it from our subsequent programs.
Next, we tried to get Wheel B to follow Wheel A--i.e., when Wheel A was turned, Wheel B rotated exactly the same way, as if the wheels were on the same shaft.
The proportional-control program to get Wheel B to follow Wheel A:
We then tried to apply this new program by turning on both motors and seeing if the car drove straight.
We initially had some success, but we realized that pressing the button to start the car introduced a bit of wiggle, which made the final path imperfect, so we decided to use the ultrasonic sensor to start the car remotely after removing a hand in front of the car.
The final Drive Straight program, including the remote start:
This seemed to work a bit better, but then we were concerned about driving surface imperfections skewing our car's path, so we replaced the original wheel with a ball bearing caster, which was less likely to randomly rotate.
The original front wheel:
The ball bearing caster attached as the front wheel:


This modification seemed to slightly improve the car's straightness, though we did have a few problems with the very heavy caster falling off the car when picked up improperly.  Our final iteration of programming and hardware was a success:

Snow White climbs the ramp with the ball bearing caster!
We're excited for the robot conga line next class--Snow White will do well!

Tuesday, March 12, 2013

Proportional Control: A Rocky Road to Smooth

Last Friday we introduced the idea of proportional control--control proportionate to the magnitude of error (error defined as the actual value subtracted from the target value), as opposed to bang-bang control (all the way on or off).  We began by modifying the distance-sensing program to power the motors proportionately to the amount of error from the ideal distance (a reading of 15, about a foot away from the sensor).

"Snow White" the Cyborg:
The grey and white sensor at the front is the light sensor; the small, black cylinder is the ultrasonic sensor; the large clear/white box next to the ultrasonic sensor is the display.

The modified distance-sensing program:

The most difficult part of this exercise was figuring out how to deal with the intermittent negative sign from the sensor, which changed based on whether an object were closer or farther than a foot away from the sensor. After much thinking, we eventually realized that we should use another if-then-else statement to be sure that the error was always positive.  We found that a gain of 20 made our robot smoothly change directions and stop at the exact "15" distance.

We learned how to define new variables in PicoBlocks for this assignment, since we needed to customize "error" and "gain" values.  We used the "My Blocks" part of PicoBlocks, and a bit of the text interface to define the new variables:

































After enjoying some exciting success with this project, we next attempted to apply proportional control to our line-following program.  At first things seemed to be working, but the robot soon began to turn around in helpless circles, unable to find the line accurately.  We weren't sure if the problem were actually in the program, since we realized that the robot was no longer able to move in a straight line--the motor seemed to be listing.
Our original light-following program (left "forever" loop):

Top "forever" loop, 80% and 40% blocks, and right green columns: our attempts at applying proportional control to the line-following program:
We tried to change the power of the motors in this program according to the error and gain (being sure to keep error positive, so the power level would be positive), while keeping the ratios of power of one wheel to the next approximately the same as in the bang-bang control for the two types of motion (bearing right or spinning slowly).  To do this, we introduced the blocks "80%" and "40%", which were meant to keep the wheels spinning with independent power and direction appropriately so the robot would bear right or spin to the left (without this step, we thought the robot would simply move in a straight line with different power based on the light sensor's reading).  We also changed the gain depending on whether the sensor was fully off or fully on the line, to keep the motor values for each motion approximately constant regardless of where the sensor was (a strategy that worked well in bang-bang control).

After realizing there were some problems with the motor (the robot was having trouble bearing right, even when we returned to our previously-functional program in bang-bang control), we began a class exercise to reset one wheel to a particular degree of rotation.  The idea was that we would set some angle (say, 42 degrees), then displace the wheel, then run the program and have the wheel move back to its initial angle.  My partner and I managed to get a bang-bang control version of this to work, but the proportional control has not yet been realized.
Bang-bang wheel reset:

By the end of this class, everyone was a little annoyed with proportional control, as it seems to vastly complicate a previously-functional program.  Its obvious necessity in higher levels of design (i.e., anything with a real motor) makes me excited to actually learn how to write these sorts of programs--I look forward to continuing my experiments to tackle this challenge!

Thursday, March 7, 2013

Bang-Bang Control!

After finishing the simple battery-powered car, we moved on to more sophisticated machines: small, programmable Lego robot cars (named, for inexplicable reasons, after Disney princesses).  We're beginning to explore the exciting world of programming, using PicoBlocks, a simple visual language developed for elementary schoolers by our very own Engineering Evangelist Professor Berg.  It's an exciting program filled with color and interlocking parts, helpfully oriented so that you can input only the appropriate data into certain commands (for example, it is impossible to put a non-Boolean into a command that requires a Boolean input).  The first day, after a brief introduction to the feedback-and-control ideas (and awe-inspiring videos of the Google Car), we played with various different kinds of sensors (light and touch), and also two kinds of emitters (sound and light).  We learned the basic commands to change light colors and intensities (and play simple tunes), and quickly discovered that PicoBlocks commands were pleasingly intuitive.
One of the light sensors:
The top dot in the orange face is a photosensor that quantifies the amount of light which hits it; the bottom dot is an LED, which emits a small amount of red light which the top sensor absorbs.
At the end of the class, we tried to program the robot to change its motion based on input from the touch sensor.  This proved more difficult than expected, because of certain electromagnetic properties of the switch: the robot often mistook one press of the switch for multiple presses, so various "wait until" commands were necessary to ensure the correct motion.
Our various programming attempts:













We had most success with the stack in the bottom left corner, which would cause the robot to stop when the touch sensor was pressed.
Last class, we began programming our robot to move based on variable inputs from other sensors.  We now used an ultrasonic sensor to give the robot information about distance (which works similarly to echolocation--the ultrasonic pulses are reflected back from the nearest object to give a certain number, which may then be put into a less-than Boolean command to trigger an action).  Our assignment: program the robot to follow a piece of Delrin when the plastic was moved away, or back up when the plastic was brought toward the sensor.
We quickly tackled this challenge by discovering the less-than Boolean input, and set the robot to move backwards if the ultrasonic value were less than 20 (i.e., an object was about a foot away), but move forwards otherwise.  After this success, we tried to make various robots follow each other in a sort of conga line; the robots with smaller following distances (smaller less-than values in the Boolean input), like ours, enjoyed greater success, though the robots still moved with imperfect straightness and the train quickly fell apart.
Next, we were challenged to use the light sensor to program the robot to follow a twisting white line on a brown floor.  My partner and I initially thought to change the robot's direction quickly if it started to miss the line (i.e., if the photosensor read less than 630, which meant the robot was partially off the white and onto the brown, the robot would rapidly bear to the left and right in an alternating, wiggly fashion).  Although this was effective on a straight line, we soon realized that this design would impede our robot's ability to turn.  We eventually decided to throw the robot into a spin until it found the line again, then move straight forward.  We enjoyed some limited success with this method, but the robot would usually turn 180 degrees and then start to move backwards along the line until it moved off again, which proved rather ineffective.  After some more brainstorming, we decided the ideal movement would be a 90 degree spin left, alternating with a 180 degree spin right, until the robot again found the line.  After many annoyances and wishing we had a count-down clock input, we decided to try something a little different: bearing right while on the line, and spinning left the instant the robot no longer sensed the line.  This was particularly effective on straight-away parts of the track and on the turns--and at the end of the track, the robot turned around and trundled back along the line again!
Our code:
The top left collection of blocks is the program, with "slowspin" and "bearR" defined with the corresponding yellow-rhombus-green-block strings.
Excited with our success, we look forward to the next class working with robots!

Friday, March 1, 2013

Windlass Part IV: Success!

Thank you Olin for allowing us to use your laser cutter!
All the parts printed out nicely, and we sawed the Delrin rod to the appropriate length and heat-staked the twenty pegs.  Something went wrong in the heat-staking process--we weren't sure whether something was wrong with the heat stake machine or with our measurements, but we suspected the heat-staker since we based our dimensions off of careful caliper measurements the T part we originally used to learn how to heat stake.  I filed off the worst of the stringy plastic bits, but the model was still less aesthetically appealing than we would have liked.  Also, the laser cutter somehow burned our Delrin, so our windlass has an interestingly mottled design.
The first bit of assembly done--one A-frame heat-staked, another on its way!
Holding on to the angled Delrin frame for heat-staking everything proved more difficult than we expected.
 We used a hand saw to cut the Delrin rods:
 The windlass frame assembled!
 After much pushing and finger-jamming and hammering, we got all of the tight-fit bushings in their proper places (two bearings in the axle holes, two bushings on either side of each hole, two bushings in the middle for support, and two bushing handles on the very ends).  We tied on the string and held our breath for a test run...
 Success!

The heat-staking was less than perfect, so I filed off some of the worst stringy bits:
 
 The final windlass:
 

In retrospect: our design worked remarkably well.  While the heat-staking did not turn out as prettily as planned (perhaps because of a different Delrin thickness?), the final product was sturdy and easily lifted a 1-L bottle 10 cm above a 12-cm gap.  Our only laser cutter issue was the Delrin burning, which added a unique character to our windlass.  It was interesting to see the designs of other students--a few looked remarkably similar to some of our discarded brainstorm ideas.  Our only design flaw was the aesthetics of heat-staking, which could possibly have been fixed with more precise assembly and perhaps using a few more clamps to hold things together more tightly for assembly; regardless, our windlass was wonderfully functional and pleasingly simplistic.

Gears of Greatness: A Lego Car (Part I)

The task: create a car out of Lego bricks, gears, and axles that will carry a 1 kg weight over 1 m as fast as possible.
My partner and I initially worked through the gears handout to learn the relationship between gear ratios, speed, and torque. Then we disassembled our gearbox to start testing out what would work in an actual car.

For our first design, we hoped to move the 1 kg weight by simply pushing it along with a two-wheeled car. We struggled to find a working gear ratio for this model, but were soon informed that our car must actually carry the weight.

We then thought about driving both axles with the motor; however, this design proved less efficient than a single-axle drive, because of gear-train complications that greatly increased friction.  Around this time our professor showed us the rubber band pulley wheel to attach to the motor, which greatly simplified our gear train.

We didn't get much farther than this design the first day--we tried to build a single-axle-drive gear train with the rubber band pulley wheel, but found it was difficult to align the motor and pulley wheel to prevent the motor from falling into the car and breaking everything.  The class ended with my partner and me the proud designers of nothing but a pile of disassembling Legos. (To be fair, this was an excellent demonstration of torque.)

Gears of Greatness: A Lego Car (Part II)

We returned to the car during our next class period.  After much frustration last class, we were ready to make something work.  We knew that we should have the weight positioned as close to an axle as possible, and have short axles to increase structural integrity.  To maximize speed and sturdiness, we wanted a skinny, compact car made with the bare minimum of components.  We decided to not worry about the aesthetics or the particulars of the design so much, and just try to test out the gear train with the 1 kg weight on board.
Our first gear train (gear ratios 1:3 (pulley wheel) and 1:5 (tiny to large gear), so total gear ratio of 1:15):


We were very surprised when we first started the car without the 1 kg weight--the car reared up on its back wheels and shot forward.  Before completely scrapping this design, we decided to test once with the weight.
The first test:
Well, wow.  We didn't expect that to work.  Our car trundled along quite happily with the weight on board.
With the car finally moving (and moving very well, actually), we secured the gear train with a few more bushings and experimented with the chassis a bit. We kept the compact design, but slightly modified the weight platform to increase structural integrity (the first platform bent a bit) and minimize weight.
After we were happy with the chassis, we decided to test our car on the racetrack.  After about 4 trials, the mean time was 4.7 seconds for the meter race!  We felt pretty confident as the car whizzed along.

We weren't sure how to further optimize the design; after some brainstorming, we decided against changing the wheels (since they act similarly to a gear, and thus changing their diameter would change the gear train), but we tested various positions of the weight and changing the direction in which the car moved.
With the motor in the back, we first placed the weight at the very front of the car--this resulted in a mean time of 5.1 s/m (4 trials).  We then tried the weight in the middle--the mean time was 4.6 m/s.  Placing the weight in the back of the car proved much more difficult than expected--in 4/6 trials, the weight fell down and the car exploded when we tried to start the motor.  The car was even slower with the weight in the back.
Changing the direction of the car proved unhelpful; comparing the means of multiple trials, the car went slightly faster with the motor in the back than with the motor in the front (which makes sense, according to my knowledge of quadrupedal biology and how real cars work).
Our final design:

We finished our car early in the class period, so we were encouraged to experiment with other designs to find out what made ours work so well.  We tried a car with larger wheels and larger axles, which was very unstable and constantly exploded, causing much distress:
In the end, we raced our compact car to victory over a second faster than the next-fastest team.  Despite the initial struggles, eventually Project Lego Car was a resounding success!