Monday, January 20, 2020

Rob Dobson's Scara Robot

After reading a Hackaday article about a sandbot, I got interested in building the Scara robot designed by Rob Dobson for it. I ended up making a number of changes to the design, controller and software. Mr. Dobson has not replied to comments on his blog or YouTube channel, so here are a few notes on the changes I made. But first, a picture.

Changes to the design

The design and construction are described in the blog post A New Sandbot and the STLs and code can be downloaded from Github from the links in that article. The article and the STLs are not quite the same, though it's still easy enough to work out how to assemble it. I used the laser cutter at work to make the acrylic pieces (the first time I'd used it). The changes I made were:

  • different spacers for the motors. I had two motors of different heights and neither was quite right with the original spacer.
  • made the "forearm" thicker. This is the grey piece with the magnet at the end, and it was very flimsy and wobbled whenever it moved.
  • changed the magnet holder to take a round 12mm magnet instead of the original square one. I had some of these magnets from a previous project and they are also much easier to find.
  • redesigned the lower arm locking piece to accept a 6mmx1mm magnet. This is used to trigger the endstop. The original design again used a hard-to-find square magnet.
The endstops in the original design used a board that can't now be purchased and required modification. I replaced it with some easy to obtain Hall effect sensors. They are not ideal as they trigger over a range if positions, though this can largely be fixed by adjusting the homing command, as described below. I designed new mounts for each of them.

Electronics and Software

Dobson uses a control board of his own design. There are two versions, one described in outline in the original blog post and a more recent one. I started by trying to use an off-the-shelf set up consisting of an Adafruit Huzzah32 and an Adafruit motor shield. The combination worked, though not very well, and I later replaced it with Dobson's Stepper Hat Trio board. (Another first: I haven't ever had custom PCBs made. At least, not since I was a hardware designer back in 1984). The Trio board is quite a good design, and there is an assembly video on YouTube. If you follow this video, note that one thing he forgets to say is that you have to put a jumper on J16 or the pullup resistors for the endstops will be floating rather than actually being pulled up, and won't work properly.

My experiments with the Adafruit parts worked OK, but were not great. The motor shield is not a modern stepper driver, and the motors run very noisily. I had to change Dobson's code to work with the Adafruit library (Github repo here). While I think his software is broadly good, doing this revealed a few things which were not ideal. Specifically:
  • there is a Stepper class to abstract the details of the motor, but the code writes directly to the digital pins outside this class, making it tricky to figure out where the changes need to go.
  • most of the motor control is done within an interrupt handler. As well as going against the general principle of doing as little work as possible in interrupt handlers, it's also not possible to call the Adafruit library from within the handler. ESP32 code requires all such code to have a special annotation, and so I would have had to change the Adafruit library and the libraries it depends on in the same way.

With the Stepper Hat Trio, things went more smoothly. I encountered a few issues. I suspect the published version of the code is not up to date with the board design.

The direction pins on the board are driven by a 74HC138 3-to-8 decoder. Different outputs are used for each stepper, but the effectively share the 3 pins that are the inputs. However, the code sets up the direction on a single pin, and does this some time before sending the step pulses. I fixed this by removing the 74HC138 and replacing it with a header that directly connected one of the 3 inputs to each of the direction pins for steppers 1 and 2. I am not using any of the other outputs of the decoder, so this worked fine.

The stepper drivers I used are TMC2208s. These can be controlled with SPI, and the board is designed to do this, but the code does not seem to support it yet. Instead, I added a couple of lines of code to pull the SDI/CFG1 and SCK/CFG2 pins high, so setting them for 1/16 microstepping. These pins are shared with the SPI interface, which in turn is used with the SD card on the Stepper Hat board; not a problem as I hadn't added the parts for the SD card. One final issue I found is that stepper 2 kept suddenly halting and turning the wrong way. This turned out to be because the configuration I had adapted was pulsing pin 14 to provide a WiFi status light, and I was using the same pin for the direction control of stepper 2.

As I mentioned, the Hall effect sensors trigger over quite a wide range, and so for homing, I changed the homing commands in the configuration so that they execute the following sequence: drive the motor one way until the endstop is not triggering; drive it the other way until the endstop triggers; then slowly drive it a fixed distance further, determined by experimentation. It's not super accurate but ends up with both arms centered fairly well at the home position.

For the record, here are my changes to the code to hold the extra two pins high (possibly unnecessary), and my configuration (with apologies for the horrible formatting).

  • In MotionHelper.cpp, after the loop which calls configureAxis.

    pinMode(33, OUTPUT);
    pinMode(16, OUTPUT);
    digitalWrite(331);
    digitalWrite(161);
    // Also set up auto standstill current reduction. Again, this conflicts with a SPI pin.
    pinMode(5, OUTPUT);
    digitalWrite(50);
  • Configuration
// ========================== DAHE config ===============================
"{"
\"robotType\"\"SandTableMooseScara\","
\"cmdsAtStart\"\"\","
\"webui\":\"SandUI\","
\"evaluators\":"
" {"
"   \"thrContinue\": 0"
" }"
" ,"
\"robotGeom\":"
" {"
"   \"model\"\"SingleArmScara\","
"   \"homing\":"
"   {"
// Search one way until the endstop is off, search the other way until it is on; then advance for centering, determined empirically.
"     \"homingSeq\"\"FR50;B10000n;#;B-10000N;#;FR1;B-120n;#;B=h;FR50;A10000n;#;A-10000N;#;FR1;A-450n;#;A=h;$\","
"     \"maxHomingSecs\": 120"
"   }"
"   ,"
"   \"blockDistanceMM\": 1,"
"   \"allowOutOfBounds\": 0,"
"   \"stepEnablePin\"\"21\","
"   \"stepEnLev\": 0,"
"   \"stepDisableSecs\": 10,"
"   \"axis0\":"
"   {"
"     \"maxSpeed\": 50,"
"     \"maxAcc\": 50,"
"     \"maxRPM\": 30,"
"     \"stepsPerRot\": 9600,"
// UnitsPerRot and things derived from it are only used in GeistBot, HockeyBot, MugBot and XYBot.
//"     \"unitsPerRot\": 628.318,"
// maxVal is the arm length in mm.
"     \"maxVal\": 100,"
"     \"stepPin\"\"27\","
"     \"dirnPin\"\"13\","
"     \"endStop0\":"
"     {"
"       \"sensePin\"\"39\","
"       \"actLvl\": 0,"
"       \"inputType\"\"INPUT_PULLUP\""
"     }"
"   }"
"   ,"
"   \"axis1\":"
"   {"
"     \"maxSpeed\": 50,"
"     \"maxAcc\": 50,"
"     \"maxRPM\": 30,"
"     \"stepsPerRot\": 9600,"
//"     \"unitsPerRot\": 628.318,"
"     \"maxVal\": 100,"
"     \"stepPin\"\"12\","
"     \"dirnPin\"\"14\","
"     \"endStop0\":"
"     {"
"       \"sensePin\"\"36\","
"       \"actLvl\": 0,"
"       \"inputType\"\"INPUT_PULLUP\""
"     }"
"   }"
" }"
" ,"
\"fileManager\":"
" {"
"   \"spiffsEnabled\": 1,"
"   \"spiffsFormatIfCorrupt\": 1,"
// Disable SD as we are holding the MOSI and SCK pins high for the microstepping config
"   \"sdEnabled\": 0,"
// The next 4 lines are unused with sdEnabled = 0
"   \"sdMOSI\"\"23\","
"   \"sdMISO\"\"19\","
"   \"sdCLK\"\"18\","
"   \"sdCS\"\"4\""
" }"
" ,"
/* Disable wifiLed as we are using pin 14 for dir 1.
" \"wifiLed\":"
" {"
"   \"hwPin\": \"14\","
"   \"onLevel\": 1,"
"   \"onMs\": 200,"
"   \"shortOffMs\": 200,"
"   \"longOffMs\": 750"
" }"
" ,"
*/
\"ledStrip\":"
" {"
"   \"ledPin\"\"25\","
"   \"sensorPin\"\"-1\""
" }"
"}"
,

Wednesday, July 11, 2018

Desktop thermometer

My office at work gets quite cold some days, and I wanted to know how cold. Also, I was at a loose end over the long July 4th break and looking for something to do. So I knocked together this project:


Inside the box there is an Arduino Nano, and a DHT11 temperature sensor, plus a 10k variable resistor to set the display brightness. The display is a 16x2 LCD. It displays the temperature and humidity and the range of temperatures it has seen. The readings can take a little while to stabilize, so until they do the C and F are displayed in lower case, and the % for the humidity is shown as H. The Arduino sketch is here, and the comments in this file also say how to connect it up. You might need to install the DHT library from Adafruit (info linked from this page). It uses a USB connector for power.

I designed the case with Fusion 360. It holds together with friction. I undersized the hole for the DHT11, meaning it's not quite large enough for the sensor to stick out. Rather that spend another 90 minutes printing a replacements, I just attached the DHT11 inside the case with hot glue, which works fine except that it came out a bit skew-whiff. But that's how you know it's home made.




Sunday, April 29, 2018

High altitude printing

Recently, I was printing a frame with a tall arch shaped part to it. The designer of the object  provides a version with built in support and one without. If I allow Cura to generate the support for the one without, the printing time is a lot less, so that's what I went with.

It was all going well until the support detached from the build plate. The printer then merrily continued, dumping the support material into thin air, where it gradually turned into a big pile of print snot. It is complete coincidence that I was using a green filament.


I trimmed away some of the slot and let it keep going. Amazingly, after a while, the printer managed to re-establish a bridge across the arch with a few layers of support to go, and get to the end of the print.
Here's the print with the snot that I trimmed away and the support that came loose.
After removing the support and the rest of the snot, the results are a bit ugly, but not too bad.

Sunday, April 22, 2018

Forcing variable layer heights in Cura

Recent versions of Cura have an experimental feature where it selects different layer heights according the slope of the model. As the slope changes from vertical to horizontal, it uses a lower layer height to get better shaped prints. Imagine a dome, where the later height gets smaller as it reaches the top, and you'll get the idea.

I have a piece that I wanted to print where I wanted most of it to print at 0.2mm or 0.3mm to keep the print time down, but wanted a small vertical extrusion to print at 0.1mm for strength and precision. As the extrusion is vertical, this won't trigger the adaptive layer heights.

A simple solution is to add a second object which has a dome at the same height a the extrusion. As the same layer height is used across all the objects, the low layer height needed for the dome also applies to the extrusion, while the remainder of the model prints quickly. Here is a screenshot from Cura to illustrate what I mean. I know it's a bit tiny; for a bigger version, look here. In short, the dark blue is 0.1mm layers and the yellow is 0.3mm.


Saturday, March 31, 2018

CoreXY frame

Continuing my noodling around from last week, I started to put together a frame for a CoreXY system. I could have done the right thing and designed this in a CAD package, got all the measurements right, blah-di-blah, but instead I'm just winging it and knocking together what I need in Blender. Here's the frame with motors and runners but no belts yet:
The motors are mounted on plates bolted to the bottom of the frame with spacers to raise them to the right height. These corners of the frame have internal L-shaped brackets.
The gantry is mounted on brackets with runner wheels:
They move quite smoothly, though I think the brackets will bend over time.

For the pulleys, I'm going to use flanged bearings. I really wanted ones with a 5mm inner diameter, but I would have had to wait a couple of weeks to get them, so I bought some with an 8mm inner diameter and added a insert.
I ran out of 5mm washers, but there is an easy solution to that:
The next stage will be to get all the pulleys set up. The motor height is designed to work with pulleys mounted on top of the gantry with a 30mm bolt as you can just see in the video clip. For the pulley fixed to the frame, I'll need a mount to raise them high enough. More to follow.

Sunday, March 25, 2018

Motion systems

I'm starting to play around with motion systems. I have no specific goal in mind: it's just noodling.

Here is a small testbed using a MGN12 linear guide that I bought for a printer upgrade and then never used, together with some parts salvaged from my now-defunct Folgertech printer and a few printed parts. There are printed T-nuts under there, though you can't see them.


Sunday, July 16, 2017

3D Printed Tourbillons, a coda

In my previous post, I wrote about making 3D printed tourbillon mechanisms. There are a few parts in these designs which are not printed, specifically two small bearings, and a few 2mm and 3mm shafts made of steel. There is not much I can do about the bearings, but I was curious to see if I could replace the shafts with plastic and used them in the version III design. I printed 1.8mm, 2mm and 2.8 mm diameter cylinders at 0.1mm layer resolution. They had to be printed with brim, so I then trimmed the brim off with a sharp knife and lightly sanded them. The 1.8mm shafts work quite smoothly for the spring/balance wheel, the escapement gear and the anchor. The 2mm shafts replace the two shafts which hold the frame together. The 2.8mm is a replacement for the the main 3mm shaft. It's a tight fit in the bearings, and is also too loose for the sprocket to engage with it well. I tried to shim it with a little blue tape the way I had done with the steel shaft, but this didn't work. However, putting a small blob of blu-tak (or similar) in the axis hole of the sprocket did. Here is the tourbillon working with plastic shafts (which I wave at the camera at the start).


One though which follows is that you could made the drive shaft better by printing it and the sprocket with a non-round cross section, like the flattened shafts you get on some stepper motors. They probably would not last as well as the steel ones, but it's an interesting idea, as you can cut the plastic to the exact length very easily.