Gas station without pumps

2017 November 28

More SolidWorks

Filed under: Robotics — gasstationwithoutpumps @ 22:24
Tags: , , , , , ,

I spent most of my day today with SolidWorks, fixing the problems noted in Bugs found in first assembly of robot and adding new layers to the robot. I’m getting a bit better at using SolidWorks, but I still find it to be an overly complicated interface with way too many modes.  I’m sure that there is a way to get it to start up with reasonable document parameters (like using mm instead of inches, or using the same settings as already open documents), but I’ve not taken the time to try to track that down.

Here is the model as it stands so far:

View from the front left of the robot. The octagon floating on top is a the beacon-detector board, which will be on standoffs that I didn’t bother to include in the model.

I cut out the three layers of the robot today, making two mistakes in the process. One mistake I caught right away, and just recut the layer after fixing the problem—there was an extra alignment circle that was not supposed to be cut that I had forgotten to erase. The other error was just as serious, but I didn’t notice it until I got home—the top layer did not have the slots cut in it for the spacers from layer 2 to layer 3. It is hard to notice this problem in looking at the SolidWorks model, as the 3D model looks the same whether the slots are cut or not. I should have noticed it when I created the dxf file for cutting the third layer, but by then I was getting pretty tired and careless. I’ll have to cut another copy on Thursday.  Luckily MDF is cheap—each layer costs me about $1, and I still have half a dozen 1-foot squares of MDF left.

Incidentally, I came up with what I think will be a cheap fix for the potential problem of the bumper springs not being stiff enough.  I added another switch front and center, just for the spring in the switch to push the bumper forward.  At 60¢ a switch, this is not a particularly expensive way to add a spring, and it saved me a lot of modeling and building time.  I could even wire up the switch if I can think of a use for it.

One other thing I made today was a “drill” test, to see what size holes were really made by the laser cutter from specifications.  I created the guide in SVG using a short Python program (so that I could tweak things easily. It took me quite a while to get the SVG just right, because of weird limitations of SVG, like that the path commands can’t take units for the coordinates. Also because I was using Inkscape to translate the SVG to the DXF format that the RDWorks laser-cutter software needs, and Inkscape assumes that the “pixels” are 90/inch for that conversion.  It is kind of messed up that SVG works in terms of “pixels”, since it is supposed to be Scalable Vector Graphics.  Inkscape only converts paths to DXF (not other shapes, like circles and text), so I wrote the program to generate paths and used Inkscape’s object-to-path conversion to convert the text.

Here is the piece I cut:

The circles were cut at 14mm/s and 100% (actually clipped at 67%) and the numbers were written at 140mm/s and 20%.

The holes were exactly the right size (to the 0.1mm limitations of my calipers), and the circular pieces that were cut out were 0.35–0.4mm smaller in diameter. That is, the kerf is about 0.19±0.02mm and it is on the inside of arcs.

Here is the code I used for generating the SVG file:

#!/usr/bin/env python

from __future__ import division, print_function

# all sizes are given in units of 0.1 mm

# Inkscape coverts pixels to real-world units in DXF at 90 pixels/in

pix_per_inch = 90
mm_per_inch = 25.4
pix_per_mm = pix_per_inch / mm_per_inch
pix_per_unit = 0.1*pix_per_mm

print('<?xml version="1.0" encoding="UTF-8" standalone="no"?>')
print('<svg width="150mm" height="150mm" xmlns="">');

y=100   # y-position of first row of circles

x_space = 60    # spacing between circles
stroke = 1       # stroke-width

xmax = None     # largest value for x

text_space =35  # space from circle to label

for diams in [range(5,50,5), range(50,80,5), range(80,105,5), range(105,130,5)]:
    x=100 # left edge of first circle
    for diam in diams:
        x += diam/2
        print ('<path stroke="red" fill="none" stroke-width="1" d="M {sx},{sy} \
a {r},{r} 0,0,0 {r},{r} \
a {r},{r} 0,0,0 {r},-{r} \
a {r},{r} 0,0,0 -{r},-{r} \
a {r},{r} 0,0,0 -{r},{r} z" />'.format(sx=(x-diam/2)*pix_per_unit, sy=y*pix_per_unit,

        print('<text x="{}" y="{}" stroke="blue" fill="blue" text-anchor="middle" font-family="Verdana" font-size="10">'.format(
        x += diam/2 + x_space
        if xmax is None or x>xmax:
                xmax = x

print('<path stroke="red" fill="none" stroke-width="1" d="M 0,0 h {} v {} h {} z" />'.format(

print ('</svg>')

2017 November 16

Another day fighting SolidWorks

Filed under: Robotics — gasstationwithoutpumps @ 22:14
Tags: , ,

I spent another day working on the SolidWorks model for my robot.  I’m getting better at it, but the user interface is still a struggle to deal with.  Here is my model so far:

I’ve got the first layer mostly done, but the second layer is barely started.

On the first layer, I still have to put in small starter holes for screwing down the optical reflection sensors, which I plan to mount on pieces of perfboard. Having the sensors on perfboard will make wiring them easier (I hope), and make them easier to replace if one fails. Also, recessing them into the perfboard should improve their directionality.

I’m planning to clamp the layers of the robot together with ¼” threaded rod—the acorn nuts I’ve put on the ends are just decorative, and there isn’t room underneath for an acorn nut.  My clearance to the ground is just 8mm, which is less that the ⅜” minimum height for an acorn nut.  There is room for one 7/32″-high hex nut or two 5/32″-high thin hex nuts, but that’s it.

[Update 17 Nov 2017: I’m now going to use 8-32 threaded rod, not ¼”, so there will be room on the bottom for the acorn nuts. See Hardware obtained today.]

The view here is mostly from the back, showing the power panel (with a voltmeter/ammeter and a hole for a barrel jack) behind the LiFe battery.  I should remodel the battery to curve the wires up to the jack and to tuck the charging wires back along the battery.

I have to decide on how the AT-M6 ball launcher interacts with the rest of the components—if I use an accelerator wheel  underneath (which I was planning), then there needs to be clearance for the wheel between the first and second layers.  But the tops of the drive wheels look like they’ll interfere with such an accelerator wheel.  I could mount the accelerator wheel in front of the drive wheels, but then I’ll have the track-wire sensor further from the edge—will it be sensitive enough? I guess I’ll to make the sensor and test it. I should also prototype the accelerator-wheel design, to make sure that it will throw ping-pong balls.  I still have a few inches of uncollapsed 1-½” PVC pipe that I could use for making (or at least prototyping a launcher.

The track wires will be running a current of 180mA—the design used in the targets is a 12V power-supply with a 1.2V drop from using a darlington transistor (why not an nFET?), and two 120Ω 1W current-limiting resistors in parallel.  The typical VCE for the TIP122 darlington at 180mA is more like 0.75V, so the current is going to be more like 188mA.

To imitate that with my track-wire that has 2 47-ohm resistors in parallel, I’d need a voltage of 4.4V.  The power dissipation would be (4.4V)^2/(23.5Ω) (0.5) = 412mW, which is just below the ½W limit from using two ¼W resistors. Rather than wire up a special circuit (using an LM555, as they did), I’ll just use the Analog Discovery 2 power supply for the 4.4V and the function generator for the pulse train to the gate of an nFET.  It’ll be a little inconvenient, since the function generator, power supply, and oscilloscope leads are so short, but I can make it work with some “extension cables”.

I think that tomorrow I’ll work on sensors, both electronics and programming, and leave the mechanical design for later—I think I’ll make more progress on the more familiar tasks, and I’m so far behind most of the groups that I’m not sure I’ll ever catch up.  I don’t even have a name for my robot!


2017 November 15

Progress report on mechatronics

Filed under: Robotics — gasstationwithoutpumps @ 19:27
Tags: , ,

I’m falling behind in the mechatronics course—I still don’t have a complete design for the robot, and I’ve built nothing so far except the cat-toy ball track, which is not complete yet—I need to know how much of it to cut away for the ball launcher(s), which I’ve not designed.  I also have the digital beacon detector done, though I think I want to retweak the code for it, as I messed it up trying to get more sensitivity at the distance competition.

I spent yesterday struggling with SolidWorks.  I’m getting better at it, but it is still a terribly complicated, unintuitive interface.  Even trivial things like creating a sphere as a model ping-pong ball took a long time to figure out (I had to Google it, and even then it took me a long time to realize that “centerline” was a special tool, not just a line through the center.  My biggest accomplishment in SolidWorks so far is modeling the helical cat-toy ball track—I’ll have to get a picture of that model to put on the blog.

I did get most of the first layer of MDF designed yesterday, with the motor mounts, the wheel wells, the tape-sensor holes, the battery holder (MDF and velcro), and the M10 ball-tip set screws (to use as skids) all modeled.  I even got one support board for positioning the next layer done, though I’ll probably have to adjust it a bit, as I changed my mind last night about what bumper switches to get.  Instead of spending $3–5 a switch for gold contacts (which is the “right” way to handle low-current switching), I followed the lead of one of the students and am getting super cheap switches from Amazon, which are $7 for 10 switches.  These are standard 5A switches and probably get unreliable with currents below 100mA, though I’ll be using them with 1mA or less.  They are also tiny (specs from the Amazon page):

  • Overall Size : 20 x 6.5 x 13.5mm / 0.79″ x 0.26″ x 0.53″ (L*W*H)
  • Mounting Hole Dia. : 2mm / 0.08″;Mounting Hole Spacing : 9.5mm / 0.37″;Pin Pitch : 7.2 x 9mm / 0.28″ x 0.35″
  • Lever Arm Size : 17.5 x 4mm / 0.69″ x 0.16″ (L*W);Roller Size : 5 x 3mm / 0.2″ x 0.12″ (D*T)

The small size means that the second level will have to be slightly higher to put the bumpers at the right height.

Before I cut the first-layer board, I want to add the rest of the spacer boards between the first and second layer—one of which will have my volt/ammeter and power barrel jack (so I need to measure those and design the panel for them).

I also have to decide how I’m going to lock the boards together.  I don’t want to glue things (messy and hard to disassemble), so I’ll probably clamp everything together with threaded rods.  I’ll need to get the threaded rods and figure out where to put the holes for them so as not to interfere on any level—avoiding the cat-toy ball track will be the hardest, as it takes up most of the second level. Although most of my robot will be using metric parts, I’ll probably go with threaded rod from the hardware store, which will most likely be ¼” rods with 20 threads per inch, as that seems to be the cheapest (at 50¢–$1 a foot).  I think I’ll need 4 pieces, a little under 11″ long each (so that the top of the rod is at 11″ but the bottom doesn’t touch the floor).

I need to laser cut a small test piece with different hole sizes, to see how much increase in diameter there is from the laser cutting.  Most of my holes can be a little loose without problems, but the set screws need to screw into the MDF (unless I get some M10 nuts and put them on either side of the MDF, which might be a better solution anyway).

Today I was going to build tape sensors (soldering the TCRT5000 reflective sensors and current-limiting resistor onto protoboards that have screw holes drilled for mounting), but I’ve not done any hardware work so far today.  Last night I did order the bigger (100mH) inductors for the track-wire sensor, plus a few smaller shielded inductors, in case I decide to add another LC resonator to the sensor, to increase noise rejection, but I forgot to order an 8:1 analog mux, which I think I’ll need for extending the number of pins on the Teensy.  Oh well, another $3–4 in shipping costs and another few days delay.

I’ve spent most of today working on porting the Events and Services Framework to the Teensyduino environment.  I’ve got it all compiling and I’ve got event checkers working, but I haven’t checked the timers or other layers of services.  It turns out that the test harnesses built into the code have not been maintained, and some wouldn’t run (or even compile) even on the Uno32, because the code they supposedly test has been changed and no longer has the entry points they rely on (ES_Timers is one example).

The ES_Framework code is also not very modular, despite being broken up into many files—almost everything is intertwined to the point where you need it all before anything can compile.  Luckily, most of it has very little dependence on the specific processor, so I was able to port it without trouble.  One of the biggest problems was that the Teensyduino environment does not support printf, and the Serial.print() routine is C++, not C.  I added a few C wrappers for different flavors of Serial.print() and converted all the printf statements to a series of Serial_print_… calls.

I’ve not still figured out the best way to handle the analog-to-digital conversion.  The Pic32 processor used in the Uno32 boards for the class have a “scan” mode where the hardware handles scanning the selected analog channels, just doing an interrupt after all the channels have been scanned.  The Kinetis processors on the Teensy boards do not have that feature, so I have several options:

  • doing conversions in event detectors or services that need the values.  This will make the individual detectors slower, but no time will be wasted doing unused conversions. It would also make it easy for users to extend the number of analog pins with an external MUX, as the code for doing the analog conversions is not buried inside the system, but in the user-level code.  The disadvantage is that the code will need to busy-wait for each conversion, as the result is needed at the point in the code where it is requested.  I could just use the Teensyduino analogRead(), which already provides support for setting the resolution and averaging levels.  Then there is no need to port the AD.c file.
  • do a block of conversions just before calling all the user-defined event detectors.  This will put a largish delay before the event detectors, but several detectors or services can look at the value with needing another conversion. Currently, the event detector loop with just a trivial DummyEventChecker (that reports an event every 100,000 calls and toggles the on-board LED) takes about 3.34µs on a 72MHz Teensy 3.1, but doing 6–8 conversions would add 8–500µs, depending on how much hardware averaging I decide to do (which the user should be given access to control).  This technique is probably the closest to letting me duplicate the existing interface, which is designed around the Pic32 scan.
  • do a start-conversion and interrupt for each conversion.  If I do little hardware averaging, the overhead of the interrupt processing is large and nothing is gained, but if I opt for 32× averaging then interrupts have a big advantage over blocking code that busy waits for the conversions.

Currently, I’m leaning towards just using the analogRead() code, discarding all the Pic32-specific AD code.  I still need to decide whether to build in a battery-level check that shuts down the system on a drained battery.  Perhaps the cleanest way to do this would be to build a separate event checker that samples the battery voltage about every millisecond and low-pass filters it (rather than at 9345Hz/number of pins, the way the Uno32 code does).  (Sampling about every millisecond could be done just by watching the clock in the event checker and taking a new sample every time that millis() changed.)  Having a separate checker in a separate file, rather than intertwined with BOARD.c, AD.c , and roach.c would be much cleaner. After I’ve gotten all the basic functions working, I’ll think about dedicating a pin (perhaps A0, which has the fewest other functions) to battery-voltage monitoring.

I’m not sure how to ensure that all the external devices (servo motors, gear motors, … ) are properly turned off in BOARD_End(), before sleeping or halting the processor.  The Uno32 version of BOARD_End() doesn’t seem to do this either—in fact, it keeps the ADC and the serial port on, and just turns off most interrupts and sets pins to be digital inputs, not doing anything about the external peripherals that are the power-hungry ones.

2017 November 9

Preliminary design review in mechatronics

Filed under: Robotics — gasstationwithoutpumps @ 21:26
Tags: , , , , ,

Today in the mechatronics class, 28 groups (29 if you count me) presented their designs in about 90 minutes—3 minutes per group.  The first few groups were slower, as the professor and TAs provided more detailed feedback, and the later ones were shorter, as much of the critique had already been delivered on similar designs.

My decision not to have a scissor-jack or lead screw to raise part of the robot were confirmed by the comments on the designs that did include such features.  I was also pleased that I had not included a moving turret, as those were also critiqued as overly complicated.

I’m now thinking of really minimizing my mechanical hardware by having only one arm, hinged on the platform and aligned with fiducial sensors so that it can push a ping-pong ball through the small, high hole of the final target.  For the larger, lower holes, the arm could swing further and drop the ball through the hole.  One other group is trying that approach—most groups went for elaborate Rube-Goldberg contraptions instead.

I’ll have to look at the geometry to see whether this would work—if it pencils out mathematically, then I’ll build a crude prototype this weekend and see whether a servo motor can move the arm fast enough to keep the ping-pong ball in a cup as the arm swings past vertical.

One problem with the one-arm design is that the larger, lower  (AT-M6) targets are best hit by a side-mounted ball delivery, but the smaller, higher target (Ren ship) is probably best hit by a front-mounted ball delivery, so that the robot can drive ram the target with slightly different aims to try to align tabs with the fiducial marks.  It may be possible to use roller-ball microswitches to sense the fiducial marks for the Ren ship target, in which case driving along the wall and firing when fiducials are sensed may work for a side-mounted arm.

Note: I need to get some microswitches, both for this purpose and for the obstacle avoidance bumpers.

Assuming I can make the one-arm design work, then the biggest problem for me will be making a delivery ramp for loading the arm.  I’m thinking that 8 balls (2 for each target) should be enough ammunition to stock, and I’d like to have them be in a spiral ramp around the outside of the robot.  The ramp needs to be 4 cm long per ball, or 32 cm, which would be about 160° around the robot (assuming that the centers of the balls are on a 9″ diameter circle).  It is nice that it isn’t a full turn, as I should have room for the arm without interference from the ramp.  (I’ll also have to clear the central beacon detector, which means that the arm can’t be centered on the robot—or I’ll have to move the beacon detector to the edge of the bot.)

To make the helix, I’m thinking of getting some 1.5″ or 2″ PVC pipe, softening it in the oven, and bending it around a cylinder.  Bending PVC should be done between 170°F and 220°F (source: 10 Best Practices When Pending PVC Pipe and Conduit).  I’ll have to be careful to keep the temperature below 284°F, at which temperature PVC starts to decompose (source: Wikipedia PVC article). I’m not likely to follow the advice they give, as they are trying to sell $350 “PVC Bendit” tools.  Those might be nice for a makerspace or a place that bends a lot of PVC, but are too expensive a toy for a one-time project.

If I heat the PVC in an oven, it would be good to fill it with sand to reduce the likelihood of it collapsing when I bend it.  The technique suggested on the web is not to heat the PVC in the oven (probably because most people want to bend longer pieces than fit in an oven), but to heat the sand in the oven to much hotter than needed, then pour it into a capped length of PVC to heat the pipe.  That seems like a simpler and safer technique than others I found on the web, so I think I’ll try it tomorrow.

According to various web sites that give dimensions for PVC pipe, 1 ½” Schedule 40 PVC averages 1.61″ ID, which is just over 4cm.  That may be cutting it a bit too close for a closed tube, but if I cut the helix in half on my bandsaw to create a half-circular trough, it should be ok.  Alternatively, 2″ Schedule 40 PVC has an average ID of 2.047″, which would allow some collapse of the tubing without blocking the ping-pong balls.

If I bend a full turn of the helix (longer than I need), I’ll need about 72cm of pipe.  The interior volume of 1 ½” pipe would be about 946(cm)3 (just under a liter). Dry sand has a relative density of about 1.6, so I’d need 1.5kg of sand (3.4 lbs). Getting a 20 lb or 10kg bag of sand from a garden supply store would be good, if they sell such small quantities—I don’t want to get a cubic yard (1.2 metric tons) delivered. Even the small bags at Central Home Supply are 100 lbs. “Play sand” is sold at hardware stores like Home Depot for about $5 for 50-lb bag, which may be the cheapest route for the amount I need. (Aquarium stores sell decorative sand in smaller amounts at over $1 a pound, and craft stores charge even more.)

Now I need to find (or make) a 7″ diameter cylinder to bend the PVC around.

In other news, I spent the afternoon struggling with SolidWorks (it is a little less painful now, but still a far from intuitive interface). I managed to get a model built for the gear motor, mounting bracket, and wheel, and I put them together as an assembly.  I also started on the SolidWorks model for the base plate for the robot, getting the motors positioned and the wheel wells cut, but not getting the mounting bracket holes transferred yet.  Maybe by the end of the quarter I’ll be proficient enough with SolidWorks not to feel like cursing it continuously.


2017 October 26


Filed under: Robotics — gasstationwithoutpumps @ 22:32
Tags: , , ,

I can’t share most of what I’m doing for the Mechatronics course, because I don’t want to put up things that students will blindly copy in future years, but I feel that I can safely put up pictures of MockRobot, the prototype we build in Lab 2 for learning SolidWorks, laser cutting, and foamcore prototyping.  The MockRobot is not very different from many other pictures students have access to, and pictures of other prototypes is not going to save them much (if any) effort.

A perspective view showing the overall shape.

The foamcore tower is properly bent with smooth paper on the outside. The lap joint was too weak with the glue I had available, so I used painter’s blue tape to hold the cylinder together. The box also has smooth bends on the bottom edge and mitered lap joints at the corners. The crushed foam was too springy, and one of the lap joints tore the paper, so again I used painter’s tape to hope things together.

The front view, showing the motor mounts on the edges of the platform, the foamcore tower, and the front skeg.

The top view with the tower in place does not show much.

Without the tower, the mounting holes for the tower and for a perfboard are visible. The tops of the two skegs are visible front and back.

The slots for the tower were a little too thin—fitted perfectly for aligned foamcore, but with slight misalignment of the tower, it was impossible for me to get the tabs in without crushing or buckling the tabs. More clearance is needed for foamcore.

The side view should show the screw holes for mounting the motors, but they are hidden behind the 3″ diameter wheels.

A detail of the motor mounting, showing the problems I had with having to reglue the parts several times—the glue kept the pieces from fitting properly after a while.

The motor mount was constructed with tab-and-slot construction on the very edge of the board, so that the wheels did not have to pass through wells. This turned out to be a poor choice, as the hot glue joints were not very strong, and repeated regluing ended up with thick layers of glue that spoiled the alignment.

In future designs, any parts that need to support weight (especially cantilevered weight like the motors here) will have slots that surround their tabs on all 4 sides (a full mortise and tenon, rather than a finger joint) and have bracing on both sides, probably using a crosslap joint. I might also have the tenon go all the way through so that it can be secured by a pin on the other side. I won’t count on hot glue to withstand any tensile forces, and only small shear forces.

I might also design wheel wells, so that when the robot bumps into things, it won’t be with the wheels. I already had trouble with the roach robots rubbing off their wheels if they had too much side force (while sliding along a wall at an angle), so I should have been more more protective of the wheels in this design.

I spent way too much time on this lab fighting the steep learning curve for SolidWorks.  It has a very arcane interface, where buttons do very different things depending where on the screen you are and what mode you are in.  Undoing things is difficult, and I frequently had to scrap several hours work and start over, because I could not figure out how to  reverse some poor early choice I  had made.  I’ve used a lot of software with bad interfaces, but SolidWorks has one of the hardest-to-learn interfaces I’ve ever been stuck with.  Despite the numerous features that SolidWorks has, I would never pay money for it—it is an experts-only tool, and I don’t want to spend the years it would take for me to become expert enough for it to be of value to me.

%d bloggers like this: