Yearly Archives: 2021

The Tao of Engineering

Posted 17 December 2021

I have a step-granddaughter of whom I am immensely proud, not least because she has “the knack” – i.e. been bitten by the engineering bug. Although we never talked much as she was growing up, we (or at least “I”) have begun to talk about engineering in general and her Materials Science studies in particular. This morning I was searching my emails for a missing link to her blog site when I ran across a forgotten email from three years ago where I described some of my approach to problem-solving. As I glanced through the material, it hit me that this could be something that others might benefit from, so I decided to post it on my blog site – maybe others will see it and benefit – maybe not. Anyhoo, here it is:

Claire,
I had a lot of fun geeking with you over the weekend with your Raman spectroscopy project, and it occurred to me that you and I look at problems like this from different ends of a long journey (end of mine and start of yours).
So, in an effort to fulfill my role as GOG, I thought I would pass some thoughts on ‘the Tao of Engineering”

  • It’s rarely obvious how to get from where you are to where you want to go, but it is usually fairly easy to see how to get from where you are to someplace that might give you some additional insight into the problem.
  • It is extremely easy to exhaust yourself going in circles.  This is probably the number one killer of prospective engineers/scientists.  If you can develop an effective technique for avoiding this one problem, you’ll be much more successful.  Everyone believes they can recognize this phenomenon and won’t fall victim to the trap, but humans aren’t evolved to handle long-term problems – their memory isn’t good enough.  There are probably an infinite number of effective ‘circle-breaking’ techniques, but the one that I chose/discovered is to write everything down, in excruciating detail, as if I were describing the situation to someone else.  This produces an intellectual ‘breadcrumb trail’ that allows you to recognize when you are covering the same ground again.  Over and over again I have experienced that the act of documenting a problem will often solve it entirely, or at least illuminate bad assumptions and/or fruitful lines of inquiry.
  • Make sure you actually understand the problem; can’t tell you how many times I solved the problem I wanted to solve (easier, more fun, whatever) rather than the one I was supposed to solve.  Any problem, no matter how large or small, can be described in a single paragraph.  If you can’t write a single paragraph that completely describes the problem, then you don’t understand it.  I would tell my young engineers they had to be able to put the entire problem description on one side of a 3×5 card, in an easily readable type  size. 
  • physics doesn’t care what you think!  The data is the data, and you have to adjust to it – as it will never adjust to you.  Too many people try to make the data tell the story they want to hear, rather than listening to the story the data wants to tell.
  • Until proven to be correct, always assume everything is wrong. Find a way to cross-check everything.  Many times this can be accomplished by ‘cheating’ – using a known-good information set as the input to a process or program, and comparing the answer from the program/process to the already-known answer.  If they agree, then it’s a good bet that the program/process can then be trusted to do the same for your data.  If they don’t, then you need to discard that program/process, or find out why it doesn’t work the way you think it should (referring back to ‘physics doesn’t care what you think’ as necessary).  Everyone wants ‘THE BIG RED BUTTON’ (like the Staples ‘That was easy’ button) that solves the problem in one fell swoop, but that almost never happens (if it were that easy, it wouldn’t be your homework/lab assignment).

I have attached a Word document showing how I used my ‘document everything’ technique on a recent problem I had with a solid-state accelerometer module I wanted to use on my autonomous robot.  As usual, I ran around in circles for a while chasing ghosts until I decided to get serious and start documenting things, and then (also as usual), I started making progress toward a real solution.
love,
Frank


G.Frank Paynter, PhD
OSU ESL Research Scientist (ret)
EM Workbench LLC614 638-6749 (cell)

Loader Loading…
EAD Logo Taking too long?

Reload Reload document
| Open Open in new tab

Wall-E3 Replacing Mega 2560 With Teensy 3.5 Part II

Posted 12 December 2021,

Just after getting to the point noted at the end of Part I of this saga, I discovered that I had managed to kill the Teensy 3.5 I was using at the time. This post (and maybe subsequent ones) describes my efforts to determine what happened, and how to keep it from happening again.

Well, there was a small detour on the way to the forum…. After installing a Teensy 3.5 on the robot chassis and wiring everything up, I did something that killed the Teensy. I was connecting the charger to the robot, and noticed that the Teensy rebooted (I was running a sketch that blinked the on-board LED 5 times/sec). That should never happen, so I disconnected and reconnected the charging plug a few more times. Sometimes (but not all the time) the Teensy would reboot – and then it stopped responding entirely; the LED was still blinking, but it was much dimmer, and the Teensy would no longer respond to programming inputs. I measured the 3.3V regulated output, and it was now down to about 1.9V – ouch!

I spent a LOT of time looking around for the cause of the problem without finding anything really credible. I finally decided that having a Teensy input connected directly to the pin on the charging jack that gets disconnected from GND when the charging plug is inserted must be problematic somehow. So I added an RC filter to the line so that when the disconnect occurred, the signal presented to the Teensy pin would be filtered through the RC filter, as shown below:

This didn’t work either – a brand-new Teensy rebooted after just a few connect/disconnect cycles – rats!

Next I abandoned the idea of using the normally closed switch portion of the charging jack entirely, and decided instead to look at a stepped down (4:1 divider) version of the +12V input line with one of the Teensy’s many analog inputs, as shown below:

This too failed to protect the Teensy, and after a few connect/disconnect cycles it too was completely unresponsive; now I’m a multiple Teensy 3.5 killer – yikes!

After killing not one, but two Teensy’s, it was time to realize I simply did not know what was happening, so as usual I went back to basics. First I connected yet another expensive Teensy 3.5 to my PC via USB, but this time I simply placed it near, but not on, my robot chassis. Then I performed 10-20 charging plug connect/disconnect cycles, and confirmed that the Teensy still lived. While this step seems pretty stupid, it at least eliminated some form of magic that killed all Teensy’s within some radius of the robot chassis. Next, I placed this Teensy on the robot chassis, but not connected electrically to anything – just the same USB connection back to my PC. Another 10-20 connect/disconnect cycles with no complaints, and now I’m convinced whatever is killing Teensy’s is a conducted signal, not radiated.

Next, I connected the Teensy’s ground pin to the ground side of the 5V LDO output, which is also the ground side of the charging connector. Another 10/20 cycles with nothing bad happened, and now I’m convinced that whatever is killing Teensy’s is a conducted signal, but not something inherently on the ground line only.

At this point I realized that since I now had Teensy ground, USB ground, and robot power ground all connected together, I could now look at the +12V side of the charger power supply with my Hanmatek DOS1102 100MHz digital O’scope, and compare/contrast it to my lab power supply output when using the latter as a substitute charger input. After a bunch more connect/disconnect cycles with both my charger power supply and my lab power supply acting as a charger input, I noticed that the charger power supply exhibited very pronounced ‘ringing’ on the +12V line when repeatedly connected and disconnected from the charging jack, as shown below:

Charging PS ‘ringing’ during connect/disconnect cycles. Note scale is 5V/div

In the above photo, the vertical scale is 5V/div, meaning that some of the excursions are upwards of 15V (plus AND minus!) – plenty enough to kill a Teensy.

So now I knew what was happening, but not why. After some more playing around I realized that the really big ringing pulses were caused by just tapping the front of the charging plug against the front of the circular jack opening — and then I realized that the front surface of the charging plug isn’t insulated – it’s actually the same surface as the +12V inner cylinder!

Plug on left from Wall-E2 charging cable. Plug on right doesn’t cause problems

So, I began to understand that the why was because I was occasionally shorting the +12V output of the power supply to ground, effectively shorting out the power supply. The power supply doesn’t die because it has short-circuit protection, but the process of shorting and then opening the circuit causes (I think) the ringing.

So, why didn’t I see this before? I’ve been using this same power supply and jack for (literally) years with my older 4WD Wall-E2 robot, with no problems. The answer (I think) is shown in the following photo:

Charger connection port on Wall-E2 robot

As can be seen in the above photo, the charger jack on Wall-E2 features a lead-in ‘registration’ cone so that slightly off-center alignments can be accommodated. An unintended (and unknown till now) side-effect of this arrangement was to prevent the front face of the old charging plug from touching the grounded inner outer circumference of the jack.

Assuming all this holds water as I move forward, I can go back to looking at the normally-closed grounding switch on the charging jack for physical charger plug insertion detection, or leave it the way it is now with the 4:1 voltage divider on the +12 line to the charger module.

13 December 2021 Update:

Well, maybe not. I removed the probe lead-in collar from my old robot and put it on the new one, then re-ran the experiment where I look at the output of the 4:1 voltage divider wrt robot system ground, and I still see very large +/- excursions when I connect and disconnect the charging power supply using the original plug. So, There may be something else going on, or it may be that these perturbations have existed all the time, but the Mega2560 wasn’t negatively affected. When I do the same experiment with my lab power supply, I see almost no excursions or ‘ringing’. The next experiment will be to swap the connectors (conductor-faced one on my lab supply, insulator-faced on on my charging supply) and see what happens.

Well, not so clear; when I swapped plugs I could still see significant, but much reduced, excursions when connecting/disconnecting the charging supply. However, the lab supply looked pretty clean, with either connector. Here are the screen grabs from my scope for all four conditions

Charging PS, Old (conductor-faced) Plug
Charging PS, New (insulator-faced) Plug
Lab PS, New (insulator-faced) Plug
Lab PS, Old (conductor-faced) Plug

From the above plots, it looks like the charging PS with the new (insulator-faced) plug should be OK. We’ll see.

16 December 2021 Update:

After thinking about the situation for a while, I realized there was simply no way to avoid potentially dangerous (to a Teensy, at least) +/- voltage excursions on anything connected to the +12V charging input line, so “hoping for the best” is probably not the best plan moving forward. I started thinking about optical coupler ideas, and after sleeping on this for a couple of nights, I realized that I already had half of an optical coupler available; the TP5100 charger typically comes with a two-color (red/green) LED for visual display of charge/end-of-charge states. This LED typically isn’t installed, but the PCB pads are there and ready to go. So, If I installed the LED and placed a photodetector of some sort nearby, I could implement a non-conductive connection between the charger +12V input and my poor defenseless Teensy 3.5 – woohoo!

I poked around in my parts bin for a while, and came up with some photo transistors and a couple of small, simple GL5537 photoresistor parts. According to the datasheet, it exhibits a dark resistance in the meg-ohms and a fully-illuminated resistance in the single-digit ohms – perfect! So I whipped up a small breadboard circuit to test this out, as shown in the following photo:

GL5537 Photoresistor nose-to-nose wth the green/red dual color LED shipped with each TP5100 charger

I used a 20K resistor pullup to 3.3V to simulate a Teensy GPIO pin set for a digital input with a pullup resistor, and this worked great; with the LED OFF, the scope showed very nearly 3.3V, and nearly zero with the LED ON (I did have to cover the photoresistor/LED combination with an opaque shade to keep my lab overhead lights from interfering though). Now the +12V supply and anything electrically connected to it can perturbate all it wants to – it won’t be able to kill any more Teensys because the only electrical connection now is through the battery itself to the +5V LDO regulator and then through the 5/3.3V regulator on the Teensy – yay!!

The next step was to integrate the photoresistor and LED onto the TP5100 charging module. I was able to replace the voltage divider resistors on the perfboard holding the TP5100 charging module with the photoresistor and I installed the 2-color LED on the PCB pads provided on the TP5100 module, with the leads arranged so that the LED boresight pointed toward the photoresistor, as shown below:

With this setup, I can connect/disconnect either style charging plug to my heart’s content without damaging anything. The only question remaining is whether or not I should install a light-shield around the LED/photoresistor pair. I could do that easily with a small section of heat-shrink tubing, but I’m not sure it’s necessary; in addition, if I do that I’d lose the ability to visually confirm that the charger is actually charging. Something to think about, anyways.

15 January 2022 Update:

While the above solution worked perfectly for decoupling any charging plug connection transients from the Teensy(s), it meant that the charge status LED on the TP5100 module wasn’t very (i.e. not at all!) visible from the outside of the chassis, so I had no way to visually confirm that plugging in the charging cable was actually doing something. I thought about this for a while, and had the idea that this might be the perfect place for a ‘light pipe’. After some Google searching, I found this part.

This light pipe worked great, and there was just enough length for me to attach the input end to the TP5100 charge status LED and the output end to the front panel of the robot, as shown below:

black 4″ light pipe attached with hot glue to charge status LED
Output end of light pipe installed on Wall-E3 front panel.
Red ‘charging’ status light visible from across the room
TP5100 charge status LED changes to green to indicate full charge

Stay tuned,

Frank

Teensy, MPU6050 and Rowberg’s I2CDev Library, Take Two

Posted 17 November 2021,

This post describes my efforts, once again, to figure out how to get a Teensy running with Jeff Rowberg’s I2CDev library for the purpose of interfacing to a MPU6050 6-axis IMU with on-board DMP.

After some initial teething problems, I have been using the MPU6050 for years on my various autonomous wall-following robots using Arduino Mega 2560 controllers with great success. However, when I tried switching over from Arduino UNO/Mega controllers to the Teensy 3.x controller, Jeff Rowberg’s library wouldn’t compile at all. At the time I got the library to compile by replacing #include Wire.h with #include i2c_t3.h in i2cdev.h/cpp. See this post from almost two years (December 2019) ago for the gory details.

Unfortunately, two years later when I tried to change out the Mega 2560 for a Teensy 3.5 in Wall-E3 my latest autonomous wall-following robot, I ran into compile problems again – rats! Looking at the code, I saw that the maintainers had accepted my pull request to add a ‘I2CDEV_TEENSY_3X_WIRE’ identifier to I2Cdev.h to switch from <Wire.h> to <i2c_t3.h> as I had done previously, but I still couldn’t get the library to compile with a Teensy 3.x target.

So, back to basics. Fortunately, I had kept all the old versions of the required i2cdevlib files, so my two-year old project (Teensy_MPU6050_DMP6_V2.ino) still compiled and ran properly – whew. So now to figure out why it doesn’t compile with the newest version of the libraries.

So I created a new VS2019 Arduino project called Tensy_MPU6050_DMP6_V3, copied my code and other files from two years ago, and trimmed the program down to just the code required to print out MPU6050 headings every 200 mSec.

And here is a sample of the output:

This program, using the i2cdevlib files from two years ago, compiles and runs fine. The things that have changed in i2cdevlib since then. Comparing i2cdev.h as used in this program with the current i2dev.h, I see

Changelog diffs
I2CDEV_TEENSY_3X_WIRE for convenience in switching from Wire.h to i2c_t3.h
I2CDEV_TEENSY_3X_WIRE used to switch to i2c_t3.h (as opposed to manually as before)
added ‘void *wireObj=0’ parameter to end of every I2Cdev method signature

And the difference in the i2Cdev.cpp files:

‘void wireObj’ added to all i2Cdev class method implementations
All instances of ‘wire.’ are replaced by ‘useWire->’ where *useWire is defined as a TwoWire object

In the i2Cdev class methods that actually talk to the MPU6050 over the i2c bus (readBytes, readWords, writeBytes, writeWords) the new version uses a pointer to a ‘TwoWire’ object called ‘useWire’ instead of Wire. The ‘useWire’ object is defined at the top of each of these methods with the lines

but the declaration (invocation?) of the ‘TwoWire’ class is guarded by an #ifdef as shown

Declaration of ‘Wire’ as a ‘TwoWire’ object

Which means it isn’t included if ‘I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE’ is used. In my old version of I2Cdev.cpp, this didn’t matter, because all the class method declarations & definitions use the ‘Wire.’ object technique for invoking a ‘i2c_t3’ class method. However, the new code uses the ‘useWire->’ pointer technique which does require the ‘TwoWire’ declaration, only it’s not available for ‘I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE’ – ouch!

Comparing the old and new MPU6050.h files, the only changes of significance are:

  • The name of the class was changed from MPU6050 in the old file to MPU6050_Base in the new one, with ‘, void * wireObj = 0’ added as the last parameter in the constructor
  • GetCurrentFIFOPacket, setFIFOTimeout, and getFIFOTimeout methods were added
  • The entire #ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20 section was removed
  • void *wireObj and uint_32t fifoTimeout objects were defined

The new GetCurrentFIFOPacket method added by Homer Creutz replaces the inline method I used in my older code, and does a nicer job to boot, and the wireObj declaration makes possible changing all the method calls from ‘Wire.’ to ‘useWire_>’ style.

Comparing the old and new MPU6050.cpp files, the only changes of significance are:

  • The names for all method implementations are changed from MPU6050:: to MPU6050_Base::, with a ‘,wireObj(wireObj)’ parameter added at the end of the constructor method and most other methods as well
  • The implementation code for GetCurrentFIFOPacket, setFIFOTimeout, and getFIFOTimeout methods were added

Comparing MPU6050_6Axis_MotionApps_V6_12.h (the old version) to MPU6050_6Axis_MotionApps612.h (the new version), there were a lot of changes:

  • The implementation code was split out from the header file into a new MPU6050_6Axis_MotionApps612.cpp file
  • A new MPU6050_6Axis_MotionApps612 : public MPU6050_Base class is declared and all the dmpxxx methods are now part of this class.
  • All the hard-coded MPU6050 DMP firmware image is gone (in the cpp file?)
  • At the very bottom is the line ‘typedef MPU6050_6Axis_MotionApps612 MPU6050;’ declaring ‘MPU6050’ to be a object of type MPU6050_6Axis_MotionApps612

The new MPU6050_6Axis_MotionApps612.cpp file now contains the DMP firmware image and the definitions for all the methods declared in the .h file.

So, it looks like the whole problem with changing over from the old setup to the new one may be just the fact that the declaration (invocation?) of the ‘TwoWire’ class is guarded by an #ifdef that disables the line for ‘I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE’. So tomorrow (neeeeeeedddddd, sleeeeepppp!) I’ll try again with the new setup, with the additional condition added to the #ifdef line.

So, I created yet another VS2019 Arduino project called ‘Teensy_MPU6050_DMP6_V3’, identical in every way to ‘Teensy_MPU6050_DMP6_V2’ except this project includes MPU6050_6Axis_MotionApps612.h instead of MPU6050_6Axis_MotionApps_V6_12.h. To make things simpler, I copied all the reference files from the i2cdevlib folder into the project’s local folder, as shown below:

After editing I2Cdev.h as shown below

to utilize the i2c_t3.h version of the Wire library, I compiled it for Teensy 3.2 and got the following output:

As shown, all the compile errors reference a missing declaration for TwoWire, which I hope means that adding the ‘I2CDEV_TEENSY_3X_WIRE’ identifier to the guard around the code that declares TwoWire in i2Cdev.cpp.

I edited i2Cdev.cpp to add the ‘I2CDEV_TEENSY_3X_WIRE’ identifier to the guard around the code that declares TwoWire in I2Cdev.cpp, and edited I2CDev.h to do the same thing for the guard around the ‘class TwoWire’ declaration, and recompiled. This time the output was:

So I commented out the ‘

line and recompiled, still getting way too many errors – time to punt.

20 November 2021 Update:

As mentioned above, I decided to punt on the idea of incorporating the newest I2CDevlib files, as I keep getting lost trying to sort out the ‘Wire/TwoWire/useWire’ mess.

However, I did discover that the new library versions work just fine with an Arduino UNO or MEGA2560 as the target. So, I created an Arduino project called ‘Arduino_MPU6050_6Axis_MotionApps612’ and used it to tune the rate-controlled turn PID for the new robot. After the requisite number of false-starts and screwups, I was able to get pretty decent 45º/sec and 90º/sec turns with:

So, at this point I have an Arduino program ( Arduino_MPU6050_6Axis_MotionApps612) targeting the Arduino UNO that works fine with the new versions of the i2cdevlib libraries, and an older Arduino program (Teensy_MPU6050_DMP6_V3) targeting the Teensy 3.x that works fine with the 2-year old versions of the i2cdevlib libraries. The next step I think is to move ahead with the Teensy-targeted program using old libraries on the assumption that eventually Jeff Rowberg and company will either fix the current libraries to work properly with Teensy, or show me the error of my ways so that I can fix the Teensy compilation problem.

Wall-E3 – Different Form-factor for Better Turn Performance

Posted 20 October 2021

I have been struggling for years now with Wall-E2’s reluctance to turn smoothly, and I have been looking for ways to improve the situation. I have even thought of going back to the 3-wheel form-factor with two driven wheels and a 3rd caster wheel, just for the ability to make smooth angle adjustments. However, the 3-wheel layout has its own problems, like a tendency to get stuck when one or both drive wheel loses traction, and a tendency for the caster wheel axle to accumulate carpet fibers to the point where it won’t turn.

Recently I ran across a blog post called ‘4-wheeled robot design basics and challenges‘ that seemed to describe Wall-E2’s turning difficulties pretty accurately. In addition, this post went on to suggest how the 4-wheel form-factor could be modified to minimize the high side-slip friction exhibited by most 4-wheel drive robots. The author suggested that by reducing the front-back dimension and increasing the side-side dimension, the side-slip friction exhibited during turns could be minimized. The author showed (literally) that the problem with a traditional 4-wheel form factor is that the front and back wheel pairs have non-intersecting turn radii, as shown in the following animated GIF from the RonRobotics site:

Traditional 4-wheel robot form-factor exhibiting high side-slip friction during turns

If the form-factor is changed from the traditional ‘long and narrow’ style to a more ‘short and wide’ style, then the turning situation is more like the following animated GIF:

4-wheel drive form factor to minimize side-slip friction during turns

The author didn’t provide any numerical guidelines for how short and how wide, but the above animated GIF provides a pretty good idea.

I decided to see if I could use TinkerCad to model a form factor that might be more like the ‘short and wide’ form-factor. From previous work I already had most of the individual elements (wheels, motors, battery compartment, charger module, etc), so I did a ‘FrankenRobot’ copy as shown below:

traditional (left) and ‘short/wide’ form-factor (right). Orange disk represents turning circle

The orange disk shown in the above image was intended to model the turning circle. I manually adjusted the form factor until the turning circle more-or-less matched the layout in the ‘design 3’ image from the RonRobitics site.

After playing with this for a while, I came up with the following ‘final’ design for my new Wall-E3 short/wide robot:

Short-Wide Robot Version. Battery pack in green, TPS5100 charger in red, charging probe in orange

With the above form factor, there is plenty of room for the battery pack (4 x 18650 Li-ion) and the TPS51000 charging module. After arriving at the above layout, I started working fabrication details. At first I thought this was a perfect opportunity to use some Adafruit 20x20mm slotted extrusions and associated hardware I have had hanging around for years looking for a project. However, as I got into the design in TinkerCad, I realized I had a problem, as shown in the following screenshot:

Short-Wide Robot chassis using Adafruit 20x20mm slotted extrusions

The motors must be mounted either above or below the extrusion. This could be effected using the Adafruit ‘T’ plate, as shown above, but then the question becomes – “what to do about a bottom plate”? I could put in a second set of extrusions, but that would severely reduce ground clearance. I could maybe bend the bottom part of the ‘T’ plate to support a bottom plate, but bending a cast aluminum piece didn’t seem like a good idea. In addition, an even bigger problem was how to mount the top plate. The obvious solution would be to drill 4 holes in the top plate, and use the slotted channel threaded insert hardware to mount the plate. But, how does that work – the threaded insert pieces are made to slide freely in the channel until tightening the mounting screw causes them to bind to the sides of the channel – all fine and good, but that won’t work for a blind mounting arrangement; the inserts could be anywhere in (or out of) the channel – oops! I thought I might be able to find a way of fixing the inserts into place, but that didn’t seem like a good idea either. I could simply drill and tap 4 holes around the periphery of the extrusions, but then I’m using expensive extrusions just like flat plate – bummer!

Eventually I realized that a standard U-channel from McMaster Carr should do the trick. The motors can be mounted through the ‘bottom’ of the U, and the top/bottom plates can be mounted to the top/bottom of the U-channel. Much simpler, and because I can mount the motors low in the U-channel, I can maximize ground clearance – yay!

27 October 2021 Update:

The first try at McMaster-Carr U-channel wasn’t too successful – it was much thicker and heavier than I realized from the drawings, so I went back to their site and re-ordered a much lighter (and nicer) U-channel style. The following photo shows the difference.

First order on the left, second on the right

I got 2ea 24″ lengths of the lighter U-channel, and as an experiment I tried cutting 45º bevels on both pieces to see how I might form right angles for the chassis. This worked out pretty nicely. In addition, I cut a 1/2″ section from the thicker U-channel, and then cut it in half to produce 2ea right-angle brackets for use in connecting two pieces of a right-angle corner. The following photos show the results:

I was very pleased with my first try at forming a right angle corner for my new chassis – it looks like using pieces of the thicker U-channel for connecting brackets will work. I don’t think I’ll need more than two screws per corner, as I will also have top & bottom plates that will add tremendously to the overall structure rigidity. Now I just have to get the dimensions correct so that my already-cut top/bottom plates will fit, and then do all the other stuff to produce a finished ‘Wall-E3’ chassis.

02 November 2021 Update

After the usual trials and tribulations, I think I have produced a decent 200 x 230 mm chassis, as shown in the following photos:

One minor ‘gotcha’ to using the thinner sidewall U-channel is that I managed to strip the threads on a couple of the threaded holes as I was installing the top plate. Fortunately I had some 3mm press-fit nuts left over from Wall-E2 and was able to convert the threaded hole to a press-fit nut installation without too much problem. Right now I have two holes converted to press-fit, but I suspect all sixteen holes will need to be treated at some point. So, back to McMaster-Carr where I ordered another 100 press-fit nuts, along with some additional 3x6mm flathead screws.

By the way, just as a plug for McMaster-Carr: I ordered and received a 90º countersink bit so I can use flat-head screws on the chassis, but when I received it I realized the tip of the bit wouldn’t fit into my 3mm holes – bummer! So, I contacted McMaster-Carr and asked if I could return it for a refund, and (well within the 30 minute reply guarantee) I got a note back that they would refund the cost of the order, but I didn’t have to return the item – wow! I have been a loyal MC customer for decades, and they continue to impress me with their responsiveness and speedy deliveries. The next time you have a need for hardware, think of McMaster-Carr.

The next step is to add the motor drivers and motors to the prototype setup to wring out any mechanical issues there. As can be seen in the following photo, the current Wall-E2 setup has the motors mounted through the side walls equidistant from top and bottom. However, I plan to mount the motors as close as possible to the lower edge of the U-channel, so as to achieve the largest possible terrain clearance.

To facilitate this I designed and created a ‘motor mounting template’ with motor axle location holes that fits inside the sidewall U-channel, as shown below:

Wall-E3 motor mounting template

The template has two holes per motor location to allow the template to be placed either way (side tabs toward the top plate, or side tabs toward bottom plate) and still have one set of holes in the proper vertical location.

06 November 2021 Update:

As described in the companion post to this one, I assembled a basic system on a blank aluminum plate as shown in the following photo:

Basic system assembled on blank aluminum plate

After fabricating the aluminum chassis, I started transferring pieces from the prototype to the new chassis, as shown below

After transferring everything except the Teensy module and the 5V LDO regulator module, this is what the new chassis looks like:

Still lots of work, but it is now clear that everything fits comfortably into the chassis, including both motor drivers which are mounted on top of the chassis on the Wall-E2 robot. This will clear up lots of space on the top plate, so things should be a lot neater with Wall-E3.

07 November 2021 Update:

After getting the basic component layout established, I decided to see if I could get the robot to actually move forwards and backwards under computer control via the HC-05 Bluetooth link. So, I transferred all four wheels from Wall-E2 to Wall-E3, and temporarily hot-glued the Teensy 3.5 and its accompanying 5V LDO regulator/HC-05 module to the battery pack, as shown in the following photo:

And, after fixing the problem of one set of motors turning in the opposite direction as the other set, I was able to move Wall-E3 forwards and backwards utilizing the wireless link from my PC to the robot, as shown in the following short video:

The next thing I tried was some manually controlled ‘spin’ turns. To do this I added an overload to the function that does normal rate-controlled turns using an MPU6050 IMU sensor to make a turn through a defined angle span. The overloaded function simply starts a CW or CCW turn and waits for any key to stop the turn. Here’s a short video showing the result

CW & CCW ‘spin’ turns

As can be seen from the above video, Wall-E3’s turn behavior is MUCH smoother than that of Wall-E3, and is quite close to the behavior exhibited in the ‘wide’ form factor GIF that prompted the Wall-E3 redesign (repeated below for comparison):

4-wheel drive form factor to minimize side-slip friction during turns

With such good results from the above turns on hard-surface flooring, I decided to try my luck with my test carpet patch. Turns on carpet with Wall-E2 have always been a jerky procedure, with PID algorithm having to ramp motor current way up to overcome wheel side friction, and then way back down again when the wheels broke free. With Wall-E3, the turning behavior on carpet was indistinguishable from its behavior on hard flooring – both cases exhibited very smooth turning behavior around an almost constant turning axis, as shown in the following short video.

For comparison, here is Wall-E2 making a 180⁰ turn on carpet:

And here is the plot of motor speed vs time for the turn.

Average turn rate = 41.8 deg/sec

As can be seen from the above, the motor speed goes from max (255) to min (50) several times per second as the wheels alternately grip and then slide. In contrast, the Wall-E3 turns on both carpet and hard flooring were done with a constant half-speed (125) motor current, resulting in an angular rate of about 70 ⁰ /sec on both carpet and hard surface.

20 November 2021 Update:

Unfortunately, when I tried to add MPU6050 capability to Wall-E3, I went down a rabbit hole due to changes in Jeff Rowberg’s I2CDevlib library for the MPU6050 that have made it incompatible with Teensy 3.x targets (see this post for the gory details). After chasing Alice for way too long, I finally figured out that I had two choices. I could use an older (as in 2 years older) version of the i2cdevlib libraries with a Teensy, or I could use the current versions with an Arduino UNO or MEGA. Because at this point I already had an Arduino UNO running with a MPU6050 and the new libraries, I decided to continue on that track and see if I could tune the PID engine for smooth(er) turns with the new form factor. Here’s the physical setup:

Wall-E3 with Arduino UNO/MPU6050 setup running the motors

Here’s the code:

After a number of iterations, I arrived at the following PID values:

Here are the Excel plots showing the turn performance:

At this point, I think I’m pretty much done with this post. The ‘rest of the story’ will continue in the companion ‘Replacing Mega 2560 With Teensy‘ post.

Stay Tuned,

Frank

Wall-E3 Replacing Mega 2560 With Teensy 3.5

Posted 23 October, 2021

For some time now, I have been contemplating a replacement for the outdated and obsolete Mega 2560 micro-controller as the main controller module of my autonomous wall-following robot. The robot actually sports three controllers – the Mega 2560 main controller runs the overall operating system, drives the motors, and manages the speaker, the front-facing LIDAR unit, and a number of LEDs. A Teensy 3.2 manages the forward-facing IR-LED charging station beacon detection/homing algorithm, and a Teensy 3.5 manages the seven VL53L0X LIDAR distance measuring modules. So, it would make a lot of sense to replace the 2560 with another Teensy, making all the software consistent, and giving the robot a significant boost in computing power. A Teensy 3.5 at 120MHz runs at almost 10 times the 16MHz rate of the 2560, has twice the Flash memory (512K vs 256) and 32 times the RAM (256K vs 8). However, until recently (see this post) it has been very difficult/impossible to perform over-the-air (OTA) firmware updates with any of the Teensy products – a deal-breaker for me as I do that quite often with Wall-E2. Now that OTA capability has been demonstrated, the only remaining hurdle was whether or not a Teensy 3.5 has sufficient I/O to replace the Mega 2560. To address this question I created an Excel spreadsheet to document the current I/O assignments of the 2560 and then tentatively assigned Teensy 3.5 pins to match, as shown below.

As can be seen from the above, the Teensy 3.5 has plenty of pins left over after all currently assigned Mega 2560 pin assignments have been covered, so that problem goes away too.

The last piece of the puzzle was just the inconvenience of changing out a currently-working Mega 2560 just to gain performance that may or may not really be necessary. However, now that I have decided to redo the entire chassis to address the turn side-slip problem (see this post), I plan to use the opportunity to start fresh with a Teensy 3.5 as the main controller and work out any problems with just the chassis, the motors and motor drivers and the Teensy before moving on to implementing the rest of Wall-E2’s capabilities.

Motor Drivers for Wall-E3:

I have a bunch of motor driver modules left over from an earlier motor driver study, so I decided to use two of the Pololu VNH5019 motor driver modules for Wall-E3 – one for the two left motors, and one for the two right motors.

01 November 2021 Update:

The first step in bringing up the Wall-E3 robot was to assemble a very basic system on a simulated chassis bottom plate, as shown in the following photo:

Prototype Wall-E3 System on simulated chassis baseplate

The basic system consists of a TP5100 charger system and a 8.4V 7200 mAH battery pack, an Adafruit 1NA169 high-side current sensor, a Teensy 3.5 and a auxiliary board containing a 5V LDO regulator and a HC-05 Bluetooth module. The Teensy’s program at this stage consists of the OTA update code developed earlier in this post and this post, plus a few lines to read the current sensor output, convert it to a current value, and send it to the BT serial port. Here’s the program:

And here is some of the output:

With this setup I noticed there were a lot of ‘dropouts’ in the sensor outputs, so I added a 1uF cap between the sensor Vout and GND. This seemed to cure the dropouts as shown in the next output snippet (after some charging time resulting in lower charging current)

04 November 2021 Update:

I installed two Pololu VNH5019 drivers onto the prototype bottom plate, and copied the associated motor support code from my latest Wall-E2 version. I modified ‘SetLeftMotorDirAndSpeed(bool bIsFwd, int speed)’ and ‘SetRightMotorDirAndSpeed(bool bIsFwd, int speed)’ for the VNH5019 pinout and truth table, and that was pretty much all I had to do. Then I copied all of ‘CheckForUserInput()’ from Wall-E2 (and added the ‘U/u’ case for OTA updates) so I could control the motor direction and speed via the OTA serial connection, and the motors and drivers behaved pretty much right away. Here’s a short video showing the action:

05 November 2021 Update

I finally got the new 200 x 230 mm aluminum chassis finished, as shown in the following photo:

10 November 2021 Update:

After getting the new aluminum chassis fabricated, it was time to start populating it with subsystems from the prototype chassis and from Wall-E2. As shown in the following photo, the next big milestone was to populate it with four Pololu D-20 motors, the battery/charger and 5V LDO regulator subsystems, and the two Pololu VNH5019 motor drivers from the proto chassis. With the addition of four 3D printed wheels/tires from Wall-E2, and Wall-E3 was officially ‘mobile’!

Basic self-contained Wall-E3 system

As can be seen above, the Teensy 3.5 controller and its companion 5V LDO regulator board/HC-05 Bluetooth module were simply hot-glued to the battery pack for initial testing; they will be moved to the top plate next.

After successful movement tests with the above arrangement (see the companion post), the next step was to install the Teensy 3.5 controller and the LDO/HC-05 module on the top plate, and permanently install the charging connector and the ON/OFF switch. I decided that a single hole punched into the center rear of the top plate would suffice for bringing necessary wiring up from the internal battery/motor bay onto the top plate, and placing the hole toward the rear would allow the top plate to be removed and placed upside down at the back of the chassis to allow access to the battery/motor bay as needed. As shown in the following photo, the top plate is secured upside-down on the main chassis by two of the normal mounting screws, thus keeping the top-plate-mounted subsystems from contacting the ground.

Top plate in the ‘open’ position

Also note that the motor/battery bay is much cleaner than the Wall-E2 layout, even though both motor drivers are in this bay rather than mounted to the top plate as they are for Wall-E2. The next photos below show the chassis closed up with the Teensy 3.5 and the 5V LDO module mounted on the top plate, with the charging connector and the ON/OFF switch permanently installed.

Front & rear aspect views of the ‘closed’ chassis

After getting everything closed up, I re-ran the ‘spin turn’ trials, as shown below:

‘Spin Turn’ trials with T3.5 and 5V LDO mounted to top plate

At this point, there are only three significant modules (the MPU6050 IMU, the ‘Run Current’ 1NA169 high-side current sensor, and the charging station beacon homing module) remaining to install on the top plate. The first step will be to install and test the MPU6050, as that will give Wall-E3 the capability to do angle-controlled turns.

20 November 2021 Update:

As described in the companion post to this one, my plan is to move forward with the Teensy program (Teensy_MPU6050_DMP6_V3.ino) and the older I2CDevlib/MPU6050 library versions while waiting for Jeff Rowberg and company to figure out why the current versions of this library are no longer compatible with the Teensy 3.x line of microcontrollers.

The first step in this process is to remove the Arduino UNO/Wixel Shield module from the robot, and get the already-installed Teensy 3.5 talking to the already-installed MPU6050 module using the above mentioned Teensy_MPU6050_DMP6_V3.ino and the older I2CDevlib/MPU6050 library versions. Here’s the hardware layout:

Teensy 3.5, MPU6050, 5V LDO Regulator/HC-05 BT module, ‘I_Run’ current sensor

And here’s some output from Teensy_MPU6050_DMP6_V3.ino showing a ‘live’ connection to the MPU6050:

At this point, we have demonstrated we can talk to the MPU6050 using Jeff Rowberg’s (old) I2CDevlib library and can pull off yaw values, so we should also be able to do the same turn-rate-controlled turns as before.

So now I have a Teensy project (Teensy_MPU6050_DMP6_V3) that demonstrates a working interface to the MPU6050, a prior project (T35_WallE3_V1) that demonstrated Teensy OTA updates using an HC-05 Bluetooth module, and a Teensy project demonstrating turn-rate controlled turns using the MPU6050 (T35_MPU6050_Demo_V2). The next step is to create yet another new project, this time cleverly called ‘T35_WallE3_V2’, to merge all these features into one project, and then hopefully proceed from there.

When I created the T35_WallE3_V2 project, the first thing I did was copy in T35_WallE3_V1.ino and supporting files, and then I tested it to make sure everything was OK. However, this project wouldn’t connect to the MPU6050 even though I was sure it was using the older I2CDevlib files. After a very careful comparison, I found there were a very few differences. When I instead used the support files from my Teensy_MPU6050_DMP6_V3 project, then T35_WallE3_V2 was able to connect to the MPU6050. The i2Cdev.h/cpp files were essentially identical. The MPU6050.h/cpp files were essentially identical. The MPU6050_6Axis_MotionApps_V6_12.h files were essentially identical, so I’m not really sure why the magic happened — but it did!

So now the T35_WallE3_V2 talks to the MPU6050. Next I enabled ‘board.txt’ and verified that I can still do OTA firmware updates.

21 November 2021 (an almost palindromic date 21_11_21) Update:

After verifying OTA update capability with T35_WallE3_V2, I started porting in turn-rate control code from the Teensy_MPU6050_DMP6_V3 project, consisting mainly of the PID values empirically found in the companion ‘form-factor’ post, and the PIDCalcs() function.

  • Replaced T35_WallE3_V2 ‘CheckForUserInput()’ with version from T35_MPU6050_Demo_V2
  • Replaced T35_WallE3_V2 ‘PIDCalcs()’ with version from T35_MPU6050_Demo_V2
  • Replaced T35_WallE3_V2 ‘SpinTurn()’ with version from T35_MPU6050_Demo_V2 and added TURN_START_SPEED constant.
  • Updated TurnRate_Kp/Ki/Kd to 1.8/1.0/0.4

22 November 2021 Update:

At this point I have T35_WallE3_V2 to the point where I can do OTA firmware updates via the HC-05 Bluetooth link, and I can remotely command CW & CCW turns, forward and backward, speed up/down. Here’s the snapshot of the code at this point.

Now that I have turn-rate-based turns working properly, it’s time to turn my attention to the other peripherals – namely the ‘I_total’ and ‘I_run’ 1A169 high-side current sensors, the battery voltage output from the 5V LDO regulator module, and the charge connection status line.

  • Ported GetTotalAmps(), GetRunningAmps(), IsStillCharging(), IsChargerConnected, and MonitorChargerUntilDone() from FourWD_WallE2_V12.ino.
  • Ported CHG_SUPP_PARAMETERS into PRE-SETUP
  • Ported charger support pin init into setup()

After these ports, I got a lot of ‘mySerial was not declared’ errors – not surprising as I needed ‘mySerial’ in the Arduino world to access ‘printf’ formatting, but the Teensy has that feature built-in. After replacing 5 instances of ‘mySerial.’ with ‘Serial1.’, I recompiled – still lots of errors – oh well.

In the Arduino code, I used a function called ‘GetAverageAnalogReading()’ to average A/D readings with a ‘CURRENT_AVERAGE_NUMBER’ parameter. However, in the Teensy world there is a function called

which causes all the ADC channels to average every reading by ‘num’ (where ‘num’ is internally forced to be 0,4,8,16, or 32). So, I can eliminate the ‘GetAverageAnalogReading()’ function entirely for the T3.5, and just use analogRead().

After some minor fumbling around to comment out or bypass non-relevant (to this phase, at least) code, I got the program to compile. Now to test for proper behavior…

Testing for the two 1NA169 current sensors went OK, but I hit a snag when testing the ‘Charger Connected’ line from the charging plug. This line is tied to GND with no jack inserted, and the GND connection is broken when the plug is fully inserted. The pin is initialized for INPUT_PULLUP, meaning the line will be pulled HIGH via the internal pullup resistor when the charging cable is plugged in, and pulled to GND when the plug is removed. My initial pin assignment for this pin was 36/A17, but I discovered this wouldn’t work as some analog inputs didn’t have pullup resistors available. So, I more or less randomly chose pin 28 on the other side for this, only to find out that for no apparent reason, the pullup on pin 28 no longer seemed to exist. The charge connect line indeed measured GND with the plug removed, but only about 0.1-0.2V with the plug engaged, instead of 3.3V as it should. After some screwing around, I finally constructed a very small test program to exercise pins 28-32, whereupon I found that 29-32 operated properly, but 28 refused to behave. I posted about this to the Teensy forum, and another forum member tried my program on one of their T3.5’s and reported that pin 28 behaved properly on their module – rats! In any case, I can move the line to pin 29 no problem, but it’s frustrating to realize that of all the pins I could have picked, I managed to hit the one that misbehaved :(.

25 November 2021 Update (Happy Thanksgiving!)

I’m writing this from the home of my stepson and his family in St. Louis, MO, where we are all gathered for the traditional Turkey Day dinner. Of course I brought my Wall-E3 robot so I could continue to work on bringing it along. While here I managed to get the CHG_CONNECT issue solved, but in the process may have killed another port on the Teensy 3.5. At the moment I have the CHG_CONNECT input assigned to pin 31, and the CHG_CONNECT_LED output assigned to pin 30. Pins 28 and 32 appear to be inactive and might have been casualties in some previous project, or casualties of this one – hard to tell. In any case that all appears to be working now.

The following photo shows the current pin assignments for the T3.5. These may well change before the whole adventure ends, but it’s a good starting point.

29 November 2021 Update:

Here’s my first cut at a system-level schematic for the new Wall-E3 robot:

Wall-E3 System Schematic

The above schematic has the same basic layout as for Wall-E2, with the following changes:

  • The Wixel RF serial extender module has been replaced by the HC-05 Bluetooth module (physically located on the small perf-board module along with the 5V LDO voltage regulator)
  • The left and right motor drivers are now VNH5019 parts instead of DRV8871
  • The MPU6050 & IR Detector modules now use their own I2C channel (SDA1/SCL1) instead of everything being serviced on the single I2C channel available on the Mega 2560
  • The VL53L0X ToF sensor array is still managed by a separate Teensy 3.5, but now is the only device on the primary (SDA0/SCL0) I2C bus

At this point I have verified proper operation for both VNH5019 motor drivers, both 1NA169 inline current sensors, the MPU6050 IMU and the HC-05 Bluetooth module.

The next big milestone is to get the second-deck mounted and verify proper operation of the forward-looking LIDAR and the VL53L0X side and rear ToF distance sensors.

Stay tuned,

Frank

Over-the-Air (OTA) Firmware Updates For Teensy 3 & 4.x, Part II

Posted 16 October 2021,

In my previous post on this subject, I described my effort to automate over-the-air (OTA) updates of a Teensy 3.5 using a C# command-line program called by a post-build script from Visual Studio 2019 with the Visual Micro Arduino IDE extension, combined with Joe Pasquariello’s find ‘FlasherX’ code. As the article described, I was successful in doing this, but the time required to transfer the .HEX file using the C# .NET serial interface appeared to be about 2-3 times slower than that required by using the Tera Term serial comms program manually.

So, I went back to the drawing board, and started searching for a way to automate Tera Term, rather than building my own serial port management applet. I found the Tera Term help index, and subsequently I found that there is indeed a quite rich macro language associated with Tera Term, so I started learning the language and trying to apply it to my problem of using Visual Micro’s post-build commands via the ‘board.txt’ feature to automate the process of OTA for the Teensy microcontroller.

After the normal amount of fumbling around with the macro language, I was able to create a reasonably functional macro file that accepts three arguments from the Visual Micro ‘board.txt’ post-build command line and then automates the process of uploading the associated .HEX file to my Teensy 3.5 and then rebooting the Teensy to run the updated program. The ‘board.txt’ contents are:

The post-build command launches the Tera Term Pro Macro interpreter (ttpmacro.exe) and passes three arguments; the first is the build path – the folder in which the compiled .HEX file will be placed. The second is the COM port number assigned to the HC-05 bluetooth link with my laptop, and the third is the project file name, i.e. ‘TeensyOTADemo.INO’.

The Tera Term macro uses the first and third argument to build a path to the compiler’s .HEX file for the project, i.e. <build_path>\<project file name minus extension>.HEX. Then it uses the COM port specified in the second argument to connect to the Teensy and send a ‘trigger character’ to force the Teensy into ‘update mode’, and upload the .HEX file. After the .HEX file has been uploaded, the macro responds to the ‘enter xxxx to update or 0 to abort’ response from the Teensy by sending back the xxxx value, which causes the Teensy to reboot and begin running the new program.

Here is the complete Tera Term macro file:

and here are two short videos showing the OTA update process. The first video shows the process from the PC’s point of view, and the second one shows the same thing, but from the Teensy’s point of view.

Teensy OTA from PC’s point of view
Teensy OTA from Teensy’s point of view

Summary:

Over-the-air (OTA) update of a Teensy microcontroller is now practical using Joe Pasquariello’s fine ‘FlasherX’ program, combined with a Tera Term macro that is launched using Visual Micro’s ‘board.txt’ post-build feature. The things you need to make this happen are:

  • Obviously any Teensy program must incorporate Joe Pasquariello’s ‘FlasherX’ functionality. See my previous post for my complete demo sketch that does this.
  • You must have a way of triggering the update functionality provided by ‘FlasherX’. In my demo I accomplished this via my ‘CheckForUserInput()’ function that runs each time ‘loop()’ executes. If this function detects the letter ‘U’ or ‘u’ on Serial1, it launches FlasherX’s ‘update_firmware’ function which does the rest.
  • You have to have a serial comms application to upload the .HEX file produced by compiling the program update. I used Tera Term for this, and it worked very well.
  • To automate the above process, you need a script file (macro) like the one I provided above to manage the upload process.

I created a new GitHub repository here containing the Tera Term macro file, the ‘board.txt’ file I used with VS/VM, and the OTA demo sketch I used to demonstrate this functionality. Enjoy!

Frank

27 October 2021 Update:

As part of my Wall-E3 project, I constructed a small perf-board module to carry the low-dropout (LD0) 5V Regulator, and added a HC-05 module for OTA updates to Wall-E3’s Teensy firmware, as shown in the following photo

5V regulator board with HC-05 BT module added for OTA updates

And here is a short video showing an OTA update:

Teensy OTA firmware update using HC-05 BT module and Tera Term script

Over-the-Air (OTA) Firmware Updates For Teensy 3.x & 4.x

Posted 23 September 2021

For some time now I have been following developments on Paul Stoffregen’s Teensy forum with respect to OTA updates for Teensy products. As it turns out, doing OTA updates is less than straightforward due to the Teensy architecture (I’m waving my hands here).

However, in recent months, thanks to Teensy forum member joepasquariello, there is a new set of programs that seem to address the Teensy OTA issue in a much more comprehensive manner. See this thread (starting with post #85) on the Teensy forum for the details. After reading through the posts, and asking some more dumb questions (which joe was fortunately willing to answer), I decided to give this a try to see if I could achieve OTA updates for a Teensy controller, and maybe make it as convenient as OTA updates are now with Arduino products using the Pololu Wixel RF serial pipe.

The FlasherX package is actually three different files; FlasherX.ino is a demo program that #includes FlashTxx.h and FlashTxx.cpp. The FlasherX.ino program is loaded into the target Teensy device in the normal manner, just like any other Teensy program. However, once it is there, it adds the capability to update the Teensy’s firmware using the .HEX file (produced by the normal compile process) transmitted over any serial port. Of course, in order to make this magic happen, the updated Teensy program must also have this capability, so that means that any Teensy program destined for OTA updates must include the basic ‘FlasherX’ components.

In order to get started, I dl’d all three files and programmed a Teensy 3.5 with the FlasherX.ino program using my normal VS2019/Visual Micro setup. Then I created a new Arduino Project in VS2019 called ‘TeensyFlasher_V1’ and copied the entire contents of FlasherX.ino. I compiled it for a T3.5 target and used my normal Teensy bootload process to transfer it to the Teensy 3.5. Here is the serial port output after the upload:

Initial output from FlasherX.ino after upload to Teensy 3.5

Next I used Tera Term’s ‘file send’ capability to send the FlasherX.hex file to the Teensy using the wired USB connection as just another serial port. When I first launched Tera Term I got an error dialog saying it “Cannot open COM11. Access denied” – reminding me that I had to close the normal connection in order for Tera Term to operate properly. Once I had done this, I used the ‘File->New Connection menu item in Tera Term to create a new connection to COM11 (the Teensy 3.5 USB port), as shown:

New connection to Teensy port

Next I used ‘File->Send File… to select the .HEX file created by the compiler, and transfer its contents over to the Teensy using the COM11 serial port

After selecting the .HEX file and clicking ‘Open’, the HEX contents were sent over the serial connection as shown below:

The reason for using the HEX file created from compiling FlasherX.ino (as opposed to a random Teensy app) is because FlasherX.ino already contains all the pieces needed to do OTA updates. Although a bit recursive, using the FlasherX app demonstrates that a Teensy device can be updated via a serial connection repeatedly, as long as the newly updated firmware contains the pieces needed to support the next OTA update.

The next step was to figure out how to get VS2019/Visual Micro to do the update automatically, so that the process emulates what happens with an Arduino controller when F5 is pressed. VS2019 supports post-build scripts, but they aren’t used in the Visual Micro environment. Instead, as I learned from VM guru Tim Leek, VM supports post-build operations via a special file called ‘board.txt’ in the project directory. If this file is present, properly formatted lines are treated as ‘build property overrides’. For instance, this is the line in ‘board.txt’ that calls a C# console app to actually communicate with the target Teensy.

This command launches the console app, and provides it with the path to the project, the path to the sketch, and the currently selected port number. See this thread on the VM forum for all the gory details.

I ran into a problem when I tried to use the above command line with my C# console app, because the arg[] string array in the console app was interpreting spaces in the strings in the calling command differently than expected, so when I sent three strings to the command, the console app thought I was only sending two – somehow concatenating the com port number into the second string (the sketch path). After playing around some more, I found that the following treatment:

when passed as an argument to this small code snippet

produced the following output:

With the correct number of arguments, and the comport number on its own line – yay. I have no idea why this works and the other formulations don’t, and why the second argument has to be have it’s quotes escaped with ‘\’, but hey – it works.

As it turns out, this exercise was a bit academic anyway, because both the {ProjectDir} and {sketch_path} expand to identical results, so I only need one of them and the comport number to proceed. So, the ‘final’ (for now) call argument list looks like:

which produces:

27 September 2021 Update

In order to do OTA updates, I need to be able to connect to one of the Teensy’s hardware serial ports. Up til now I have been just using the USB serial port for convenience, so I thought I would try using a FTDI Pro USB/Serial converter module to connect to Serial1 on the teensy, as shown in the following photo:

In the above photo, the normal USB connection provides 5V power for the Teensy, and also allows ‘direct’ programming via the normal VS2019/VM route. The FTDI module connection shows up as COM3, a ‘regular’ USB serial port. With this setup I was able to upload a .HEX file to the Teensy using Tera Term, confirming that I can indeed use a hardware serial port for this purpose.

04 October Update:

Between the last update and now, I spent a lot of time trying to get the command-line post-build console app working, mostly to no avail. I kept getting wrapped around the axle trying to deal with three different serial connections; two to the teensy itself, and one from the command-line app to VS2019’s Console service. This got to the point where at one time the ‘Console’ output was going to my computer display, which made the mouse jump around wildly, occasionally launching or closing apps! Even trying to restart the PC was a trial-and-error process, because about half the time the screen focus would jump away from the target button before I could get it clicked!

So, I decided to go back to basics and use just the FTDI serial adaptor to run the Teensy. This required using the Vcc connection from the FTDI module to power the Teensy, which worked OK once I figured out how to switch the FTDI module from 3.3V out to 5V out.

FTDI USB-serial module now powering Teensy 3.5

With this setup I am able to upload programs to the Teensy using Tera Term, as before, but now I don’t have the other USB connection to confuse things. It does mean however, that now I MUST use Tera Term to upload sketches, as I no longer have the capability to use the Teensy bootloader from VS2019.

With this simpler setup, ‘Console’ statements from the command-line app should go only to the VS2019 debug session, and serial port operations from the command-line app should go only to Teensy’s ‘serial1’ hardware serial port.

05 October 2021 Update:

I expanded the above operation to restore the USB connection to the PC, and created a small Arduino program to (at first) just echo serial data from one serial port to the other. Here’s the program:

Once I had this going to my satisfaction, I started adding pieces from my ‘TeensyFlashDemoV2’ project until I had a complete working program, as shown below:

Here’s the Arduino code:

and here is the companion C# command-line app:

And here is the command-line output from my last run:

In the above printout, most of the HEX lines were removed just to keep the line count down, but all 2977 lines were successfully sent to the Teensy. The lines

were emitted from the Teensy at the conclusion of the HEX file upload. The line

was from the command-line app comparing the number of lines sent with the number of lines received. The numbers matched, so ‘2977’ was sent to the Teensy to complete the update.

At this point I have a working automated update system except the COM port number and HEX file location was passed to the C# program as a set of fixed arguments (as shown below), to disconnect the command-line app from the Arduino sketch, instead of dynamically providing the same parameters from VM build properties

Now that I have some confidence that the command-line app does what it is supposed to do, I can go back and make that connection again, hopefully with better results this time.

A problem with the Arduino-to-C# command-line app is that the ‘build properties’ exposed by Visual Micro aren’t always the same, so what works for one sketch may or may not work for another. Here’s the ‘build properties’ output from my expanded ‘TeensySerialBridgeV1.ino’ file:

I need two things from the build properties – the COM port number, and the path to the .HEX file. From the above list, it appears that I could use either of the following properties,

but neither is very convenient, as the COM port number has to be extracted from a ‘known’ string. On other projects, I have seen a build property like ‘serial.port.number = 11’ which would be much more convenient, but it seems to have disappeared. For the path to the .HEX file, I should be able to use

or

but it appears the ‘final_output_path’ is a bit more directly related to the .HEX file location. So, to make this work using the VM post-build facility, the required ‘board.txt’ file should look like:

When the above is placed in ‘board.txt’ and the Arduino sketch is run, I got the following output:

Which appears to be correct, and the Teensy was obviously updated (got the USB disconnect/connect tones, and the LED tell-tale stopped and then resumed blinking). It looks like I might actually have a working program now – woo hoo!

06 October 2021 Update:

One minor snag occurred with the build property used to pass the COM port number to the command-line program; I had been using {serial.port.caption} and it turns out that this parameter (along with many other serial.port parameters) isn’t always available – things change depending on the COM port chosen in the Arduino program and the actual device connected (or not connected) to the PC. After another round of posts in the Visual Micro forum, Tim Leek pointed out that the ‘serial.port’ parameter should always be available. I had missed this on this because it isn’t grouped in with the rest of the ‘serial.xxx.xxx’ parameters. With the benefit of hindsight, I can see why this is so; the ‘serial.port’ parameter is probably pulled from the VS2019 IDE, while the other ‘serial.port.xxx’ parameters are hardware-specific. Once I switched my ‘board.txt’ to use the ‘serial.port’ parameter vs ‘serial.port.caption’, I started getting much more consistent results. Here’s the ‘final’ (I hope) board.txt configuration:

One other small snag; my ‘TeensySerialBridgeV1’ program was originally intended to just pass serial data back and forth between two terminal programs (Tera Term on one side, the Teensy sketch on the other). As a result, there was a built-in assumption that both serial connections would always be available, as shown in the following code snippet:

The first ‘while()’ statement causes the program to hang if the physical Teensy USB connection is missing. This gave me some grief when I removed the Teensy USB cable to prove I could do the entire update cycle with only the Serial1 hardware serial device connected – oops!

The final Teensy program is shown below:

09 October 2021 Update: The final product

After encountering and solving a few more ‘gotchas’, I think I now have a reliable Teensy OTA mechanism using the VS2019/Visual Micro IDE and Joe Pasquariello’s wonderful ‘FlasherX’ code . The ‘trick’ is using Visual Micro’s ‘board.txt’ feature to add a post-build command that runs each time the Teensy sketch is compiled, and a small C# command-line program to trigger the FlasherX update code and feed it the correct Hex file.

I created a very simple Teensy project called ‘TeensyOTADemo’ that does only two things; it flashes the built-in LED, and launches the FlasherX update code when triggered by a ‘U’ (for Update) ascii code on Serial1 (pins 0 & 1 on a T3.5). Then I created a small C# command-line program to actually send the trigger character and then transmit the .HEX file created as part of the normal compile process.

Then I created a ‘board.txt’ file containing a post-build command that launches the C# command-line program and feeds it two arguments – one containing the build path, and the other containing the COM port number to be used to connect to the Teensy’s Serial1 port.

Here’s the Teensy sketch:

And the C# command-line program:

And last, the ‘board.txt’ file contents that launches the C# command-line program:


Here’s a short video showing the update process. The clip starts with the ascii ‘U’ trigger code arriving at the Teensy Serial1 port, and ends with the update finished and the Teensy rebooted back into the ‘blink’ code.

09 October 2021 Update: HC-05 Bluetooth link:

The next step is to replace the FTDI module with an HC-05 Bluetooth link. I had some HC-05 modules from previous work, and I had done a similar project with an Arduino some time back – so how hard could it be?

I hooked up a HC-05 to the Teensy as shown in the following photo, using a bench power supply to power both the HC-05 and the Teensy 3.5

HC-05 and Teensy both powered by lap power supply

Then I paired the HC-05 with my laptop; this took a bit of fumbling around, as the laptop thought it was still paired with an HC-05 even though it’s been over two years since I last used it, and I had since forgotten that the default password was ‘1234’. In any case, I eventually got it paired, as shown, with an automatically generated COM port on COM4.

Next I fired up Tera Term and created a connection to COM4, as shown:

And then tried sending some ascii text through to the Teensy. This appeared to work fine, but when I tried a program update via the HC-05 link I got an error that indicated the FlasherX code didn’t like something I was sending it.

The ‘abort – bad hex line’ output happens before I try to send it the .HEX file contents, so it clearly isn’t choking on that; maybe some extra characters getting sent instead of just the “U” character?

Looking at the ‘FlasherX’ code, it appears that the offending characters/line is supposed to be printed out with the lines

which implies whatever caused the problem is non-printable – maybe an extra CR/LF? So, I added some debug code to update_firmware() to print out each line as it is read into the ‘line’ character array, so maybe I can see the problem.

Hmm, more mysteries. I reconnected the regular USB connection, and uploaded the new version of the sketch. Then I disconnected the USB connector, and used Tera Term to send the update command (“U”). However, this time the OTA Update code didn’t choke, and AFAICT performed a completely successful update via BT and the HC-05 – yay! Of course, I now have no idea what caused the problem to start with, and whether or not my addition of a few lines of debugging code made the difference.

So, I undid the changes to the update code and tried again. And, as shown below, the OTA update worked perfectly – double Yay!!

The printed out lines from the .hex file are from the previous run.

So now to try an OTA update using my command-line program instead of Tera Term. I disconnected TT from COM4, and then, after selecting COM4 in the VS2019 IDE, pressed F7 to start the process. This worked as well, but it appeared the transfer rate was considerably slower – no idea why.

Here’s a short video showing the OTA update using the command-line program and BT OTA.

Teensy OTA update using command-line program and HC-05 BT link

Just comparing the overall times from the two videos above the one using the command-line program runs approximately twice as long. It’s hard to believe it is only the use of the command-line program vs Tera Term that is causing the delay – but it is possible that TT was simply running at a higher baud rate – more study required.

In summary, however, slow rate or no, it is clear that we now can implement completely automated, seamless OTA update processes using VS2019 and Visual Micro. Now that the groundwork has been laid, I would assume that this same strategy could be implemented for other IDE’s as well.

I have started GitHub repositories for the Teensy demo sketch TeensyOTADemo and my TeensyFlash C# command-line program on my GitHub site, and I would welcome suggestions/improvements.

10 October 2021 Update:

I’m trying to determine what caused the slow update when using my command-line program and the HC-05 when doing an OTA update relative to the situation when using Tera Term to manually transfer the .HEX file to the Teensy. In both cases, the OTA link is through the HC-05, so that module shouldn’t be the cause. However, just to check I went back and checked the HC-05 settings using the ‘AT Command Mode’ trick discussed in this post. AFAICT, the HC-05 was set to 115200 baud rate. I also checked to see if I had somehow misconfigured the serial port created in my command-line program, but it is set to create a port at 115,200 BPS as well. So, I’m officially baffled.

To investigate the problem, did an OTA update via the HC-05 BT link, but using Tera Term to trigger the update process and send the .HEX file. Using this method, it took approximately 14 sec to transfer the entire 3142-line .HEX file. Then I did an OTA update using my command-line program, using the same HC-05 BT link. With this setup, the transfer took approximately 35 seconds – over twice the time. Watching with my scope, it is clear that the transfer takes place at a much slower rate when using the command-line program, even though (at least AFAICT) the programmed baud rates are identical in both cases. The two photos below show the transfer rate for both cases, using the same time scale for both.

File Transfer using Command-line Program and HC-05 BT Link
File Transfer using Tera Term and HC-05 BT Link

After a bit of web research on C# .NET serial port programming, I came across this post, which indicates that using .NET for this task was not a very wise move – bummer!

Stay tuned,

Frank

FlashForge Creator Pro 2 IDEX Profile for Prusa Slicer 2.3

Posted 12 September 2021

I recently sold my MakerGear M3-ID and replaced it with a FlashForge Creator Pro 2 IDEX (FFCP2) model. The M3-ID was a great printer, but I could never get it to reliably print with dissolvable filaments. Since that was the entire reason I got the printer, I was more than a little bummed out. After viewing some very positive YT reviews of the FFCP2, I decided to sell the M3-ID and used the proceeds to buy my new FFCP2.

The new printer allowed me to successfully print water soluble PVA with PLA pretty much right away using the FlashPrint5 slicer that comes with the printer. However, after a few prints I started looking for ways to use the printer with either Simplify3D or with the Prusa Slicer, as the FlashPrint5 software is pretty buggy and suffers from really poor GUI design (for instance, the only way to specify the support extruder is via a right-click option in the plater view). This post is a description of my efforts so far to make this happen.

Some web research revealed that there was a FFCP2 profile for the Simplify3D (S3D) slicer floating around. This sounded like a good start, as I had S3D from well before from my PowerSpec 3D Pro (FlashForge dual extruder knockoff marketed by MicroCenter) days, and later with the M3-ID. In response to my emailed request, S3D sent me their FlashForge Creator Pro 2 17MR21.zip file containing just one file – FlashForge Creator Pro 2 17MR21.fff. After loading this into S3D, I was able to print a storage rack for a metric nut driver set fairly easily using a PVA dissolvable support structure.

So, now I could get away from the stupid FlashPrint5 slicer, but what I really wanted was a workable profile for Prusa Slicer 2.3. I use this slicer with my Prusa MK3S single-extruder printer, and I love it. Also, it is open-source, and quite actively developed by Prusa Research. Unfortunately, nobody seems to have developed a profile for PS2, and the process of doing so is not straightforward, at least to me.

After a LOT of reading through the Prusa FAQs and other support documents, I discovered there is already a profile available for a dual-extruder printer – the BIBO printer, so I thought I would try adapting it to use with the PS2. Here’s the BIBO profile, edited to change ‘BIBO’ to FFCP2 and other minor stuff.

By placing this file (FlashForge.ini) in

C:\Users\Frank\AppData\Roaming\PrusaSlicer\vendor 

I was able to get Prusa Slicer to recognize the new profile and load it. However, when I tried to print a small 20mm cube (one that I had printed successfully using S3D), it appeared that the right extruder and the bed heated up properly and the movement codes were reasonable, but I wasn’t getting any filament extruded onto the bed.

Comparing the gcode from S3D with the gcode for the same model but sliced in PS, I found the following:

  • The beginning of the start g-code sections were identical (no surprise, as I had copied the start/end gcode from S3D to PS), but the PS2 file had the following lines added

After that, both files contained LOTS of G1 commands, so I got lost pretty quickly. However, I could see that the PS code definitely contained code that should have pushed filament out of the extruder, as shown below:

But this code doesn’t actually extrude enough filament to make the model, as shown in the following photo:

Very faint filament extrustion – should be a skirt with a solid 20mm x 20mm square.

I posted this problem to the Prusa Slicer section on the Prusa forum, and got a reply that triggered off yet another search through all the various slicer settings to see if there was something that might affect this issue. This time, however, I found a setting in the ‘Advanced’ section of the ‘General’ page on the ‘Printer Settings’ tab, as shown below:

The ‘Use relative E distances’ box was checked. UNchecking it fixed the problem

After UNchecking the ‘Use relative E distances’ box, the demo cube started printing correctly – yay!

After UNchecking the ‘Use relative E distances’ checkbox (deliberately stopped after several layers)

The Prusa-supplied informational flyover associated with this setting said ‘most firmwares use absolute E distances’ and ‘the default is absolute’ , so now I had to figure out where this unusual setting was coming from – the .INI file?

So, it turns out that the FlashForge.ini file, which I ported from the BIBO.ini file, did indeed have ‘use_relative_e_distances = 1’ in the [printer:*common*] section (and in a couple of other places as well). So, I edited the .INI file to change these settings from ‘1’ to ‘0’ and then closed and re-launched PS2 to confirm that the proper value changes were being picked up from the INI file.

There is still (at least) one mystery remaining, in that the little ‘padlock’ icon at the top of the ‘Printer Settings’ page still shows an ‘unlocked’ condition, even immediately after the initial load from the INI file. Don’t know why this is, but at least I’m one more step toward my goal of having a working FFCP2 profile for the PS2 slicer. Here’s the current .INI file contents:

15 September 2021 Update:

When I tried printing a simple 2-color 20x20x10mm cube using S3D, the actual print came out all in one color, even though I could see what I thought was a tool change gcode command in the gcode file. However, when I did this same thing in FlashPrint (FP5), it came out OK. So, I looked at the gcode commands in the .gx file emitted by FP5 and saw the following (after the binary thumbnail image code)

This shows that the FP5 slicer is using considerably different g-codes than S3D or Prusa Slicer. In particular I was dumbfounded by the first line – M118 X30.00 Y30.00 Z10.10 T0 T1 When I looked up the M118 command, it shows as a ‘serial print’ command, basically like “echo” in BASIC or other script languages. This clearly not right, as the M118 command used here is describing the overall dimensions of the model to be printed, including the skirt. Even after extensive web searches, I was unable to find much that described the syntax for the FlashForge usage of this command, except for one post in the Simplify 3D forum, talking about the FlashForge Adventurer 3, which had the following:

So, it appears that if this line is placed in the startup g-code section of S3D, then it will be placed in the start section of the gcode file, with the {} parameters replaced by the maximum X, Y, & Z values. I’m not sure that is actually what I want, as the FP5 output seems to be the entire size of the model, not just the half-dimensions.

16/17 September 2021

In my continuing quest to get my FFCP2 functioning with Prusa Slicer, I have been going back and forth between FlashPrint5 (FP5) – FlashForge’s proprietary slicer, Simplify3D which purports to have a FFCP2 profile, and Prusa Slicer, which purports to have a way of adding ‘vendor bundles’ to its configuration. Yesterday I managed somehow to screw up the S3D configuration so that it no longer prints with the right extruder at all, and in fact appears to be extruding from the left extruder while moving the right one – weird!

So, this morning I went back to basics and reprinted the 20x20x10 two-color cube .gx file from FP5, and verified that it worked properly – yay!

Next I reloaded the original unmodified S3D profile (FlashForge Creator Pro 2 17MR21) back onto S3D and printed the cube again using only the left extruder. This also appeared to work fine.

Next I tried the same cube using the original unmodified S3D profile and just the right extruder. This also worked fine.

Next I tried a two-color print in S3D using two processes – ‘LeftTop’ and ‘RightBottom’. I set ‘RightBottom’ to ‘Right Extruder Only’ and ‘stop printing at 3mm’. I set ‘LeftTop’ to ‘Left Extruder Only’ and ‘start printing at 3mm’. Then I selected ‘Prepare to Print’ and ‘Select All’ for process selection, but this time I said ‘Yes’ to ‘The selected process is not configured for the number of extruders you have chosen to use’, instead of the ‘No’ response I had selected before this test. When I did this, the print preview looked proper, with the right extruder shown for the bottom 3mm, and the left extruder shown for the top portion. However, the actual print failed – the bottom 3mm printed normally, but the right extruder continued ‘air printing’ after 3mm, and the left extruder first clashed with the right one, and then ‘air printed’ off to the left, like it was doing a duplicate print

I sent an email off to S3D support regarding this issue, and got a reply back saying that the problem was related to me changing the gcode flavor from ‘FlashForge Dreamer Firmware’ to ‘Makerbot’. So, I changed it back by reloading the original Flashforge profile, and tried this trick again. Got exactly the same result – the two heads crashed on the tool change.

Then I had an inspiration and tried using S3D’s ‘dual extrusion wizard’. First I created a 20x20x3mm solid in TinkerCad, loaded the model into S3D, and then duplicated it to get two separate cubes. Then I used the ‘dual extrusion wizard’ to stack the two pieces and assign them to different extruders. This worked great – yay!

So next I tried looking at the difference between the print file that worked (210917_20x3mm_S3D_DualExtWizV1.g) and the one that didn’t (20mm_2col_S3DorigFFProfile.g) and it basically boiled down to the startup gcode, and the tool changeover code. Here’s the startup code section:

The 4 commented-out lines are from the non-working print file, and the uncommented lines are from the file that worked. As can be seen, the working file set both extruders to operating temperature at the start, even though the left (T1) extruder isn’t used until the changeover point. Here’s the changeover code:

The commented-out M-commands were my attempt to get the left extruder up to temp but for some unknown reason I couldn’t get that to work. The line

was added to manually park the right extruder, as this was not done automatically by S3D (in fact, AFAICT the 2-process setup doesn’t even consider that each process could use a different extruder). The ‘M108T1’ command is the same as the one found in the ‘Dual Extruder Wizard’ print file. With the above changes, I was able to successfully print the 20x20x20mm cube with the first 3mm printed by the right extruder and the remainder printed by the left extruder, as shown in the following photo:

Successful print using the ‘2-process’ method, with manual edits as described above.

So, to summarize progress to date, I believe I have figured out that the ‘dual extruder wizard’ in S3D does a good job of handling the extruder switch, but the ‘manual multiple process’ method does not. I also figured out that – contrary to a number of web postings about the FFCP2, at least the S3D profile with it’s ‘FlashForge Dreamer Firmware’ setting for gcode flavor is correct.

22 March 2022 Update:

Early this month ‘jacotheron’ posted a comment to this article, asking if I would share my Prusa Slicer work so far. I said ‘sure’ and sent him off the FlashForge.ini file I had created by copying the BIBO printer configuration and editing it. This exchange started a long conversation between me and Jaco Theron of South Africa. Jaco was also interested in using the Prusa Slicer software to run a FlashForge Creator Pro 2 IDEX machine, and being a heck of lot smarter than me, he was actually making significant progress! In just a few days he had a working version of a Python script to convert PS gcode output to the required *.gx format required by FFCP2. Of course I volunteered to test it, and once again embarked on a new voyage of discovery.

Jaco had already put together a very complete GitHub repo for this purpose, and the Readme documented the required support software installation (Python and a couple of extensions). First and foremost, I didn’t know Python and didn’t have it on my Windows 10 system. After some inet research I felt like I knew enough to take a stab at doing the installation. Of course, even with Jaco’s very detailed instructions, I managed to run into several potholes on my way to Python nirvana.

The first step is to download and install Python (3.10.3 is the latest version) from https://www.python.org/downloads/. However, since I almost always accept all the default selections when installing a new program, I didn’t check the ‘Add Python to your PATH statement’ checkbox and boy did that leave a mark! Because I hadn’t checked this box, The ‘post-processor’ command in the FlashForge.ini file couldn’t find Python, and I couldn’t even run it from a normal command-line console. I tried modifying the PATH statement myself (you’d think that would be easy – what could possibly go wrong?) and again failed – Rats! Somewhere along the line I picked up on the fact that Python was also available from the Microsoft store – so I though “Aha – that’s the ticket! So, I uninstalled Python, and re-installed it from the store. That installed fine, and I wasn’t asked about the PATH statement, so I think Microsoft did that by default. Nope – it didn’t, and now I could not only not run Python from the command line, but apparently the Microsoft version was well out-of-date – bummer! Alright, so next I uninstalled Python (anyone keeping score?) and re-installed again from Python.org, being VERY CAREFUL to check the ‘add Python to PATH’ option, and this time it all seemed to work – yay!

One good thing did result from all my thrashing around – I learned about using the Python ‘pip’ command to install and update other packages like Pillow (also required for the Python script). Here’s a screenshot showing this process:

Python Command Window: Installing Pillow and upgrading pip

The next part of the process involved placing the FlashForge.ini and the Python post processor script ‘ff-creator-post-processor.py’ in their respective locations, and then modifying the the FlashForge.ini file’s ‘post-processor’ line to point to the Python script. I used the ReadMe recommendations from Jaco’s Github repo directly for the location of these two files, as shown below:

FlashForge.ini location
Python post-processing script location

And the modification to the ‘post-process’ line (line 80) in FlashForge.ini:

If you use the folder locations as I have above, you should be able to use this post-process line, changing only ‘Frank’ above to your user name, (and possibly ‘Python310’ to ‘Python311’ or ‘Python32’ or whatever is current at that time).

After getting all this to work, there was one more hurdle (or maybe two if you count the Prusa Slicer ideosyncracy described below); The FlashForge Creator Pro 2 firmware does not like long filenames, and Prusa Slicer loves them. Once Jaco figured out what was happening, he modified the post-processing script to shorten them to something the printer could handle. What this means to the typical PS user is – Don’t freak out when the filename you thought you were getting is not what is on the SD card! There was one last hiccup in this regard when I used the default filename for a 3D Benchy print, which came out as

after the post-processing step. This produced the dreaded “file opened failed” error when I tried to print it. When I shortened the filename to ‘_3DBenchyDualPrint.gx’ it printed fine. I passed this along to Jaco, and he has undoubtedly fixed this problem by now.

So, after all this, I was able to print my first ‘Benchy’ in dual-color splendor. Actually it was a pretty crappy print, but it certainly showed me why Jaco recommends enabling the ‘draft shield’ option as shown below:

My first real 2-color print using Prusa Slicer – unfortunately with ‘Draft Shield’ disabled
How to enable the ‘Draft Shield’ option

For the life of me I couldn’t figure out why this option was called ‘draft shield’ when its purpose seemed to be a lot more like an ‘ooze shield’. I finally twigged to the idea that the ‘draft’ in ‘draft shield’ related to wind drafts causing the print to cool off too quickly. However, this puts an image in my head of someone trying to do 3D prints on their front porch in a high wind, but what do I know 😛

One last thing. Prusa Slicer has a couple of idiosyncrasies that you normally don’t see until you start working with multiple extruders. The first (and most frustrating) one is that Prusa Slicer refuses to allow objects on the build plate to be moved in the Z-direction, which means you can’t stack parts to do a simple 2-color cube, for instance. There is a trick, however. First you add the first part to the print bed, then right-click on that part and select ‘Add Part’ from the context menu. Then add the second part from the resulting dialog. The part added this way can be moved in the Z-direction. It’s a kludge, but it works.

The second idiosyncrasy is even crazier. When multiple extruders are defined, a ‘phantom’ part appears on the print bed, as shown below:

Where did that come from?

As you can see, this part isn’t on the object list on the right, and it cannot be deleted! As it turns out, however, this catastrophe is caused by Prusa Slicer having ‘Wipe Tower’ enabled by default for multiple extruder prints, and not also placing it in the object list to give us poor users a chance to figure out where it came from. To rid yourself of this plague, disable ‘Wipe Tower’ as shown:

Disable ‘Wipe Tower’ to rid yourself of the ‘phantom part’

So, thanks to Jaco Theron’s hard work, those of us with FlashForge Creator Pro 2 IDEX printers now have a pretty reasonable (and getting better by the minute) free alternative to the truly dreadful FlashPrint5 that comes with this printer. Thanks Jaco!

Just as an aside, I’m an old broke-down retired engineer from the 70’s, so much of my professional life was spent without benefit of the internet.  Every so often now I realize how much more productive the inet makes us. How cool is it that an old fart from Ohio and a young engineer from South Africa can so easily collaborate to improve a software package written by a company in Czechoslovakia to support a completely different 3D printer.  An improvement that will be immediately available to everyone in the world!

12 August 2024 Update:

I recently acquired a new Windows 11 laptop and discovered that I no longer had the ability to use Prusa Slicer to do prints on my Flashforge Creator2 Pro IDEX printer- yikes! My choices seemed to be a) dive down the ‘rabbit hole’ to solve the problem, b) return my brand-new Dell XPS15 9530 laptop for a refund and forget the whole thing, c) commit suicide, or d) all of the above :). Because I’m a old broken down engineer with too much time on my hands I chose “a) dive down the ‘rabbit hole’ to solve the problem” (‘b’ was out because my 30-day grace period had elapsed, but I kept ‘c’ in mind too!)

Thank goodness the three-year younger version of me had the forethought to document this, as it was immensely helpful in ‘loading up the buffers’ with previous knowledge’. In particular, I had forgotten about Jaco’s Github repo, so getting that hint saved a lot of time.

Looking around on Jaco’s site, I found this ‘issue’ post – “worked in super slicer but not in prusa 2.6.1 #11′. In the comments, I found this:

I was running into a similar problem with Prusa Slicer 2.8.0.
I would put the FlashForge.ini and .idx files in …/Roaming/PrusaSlicer/cache/ and …/Roaming/PrusaSlicer/cache/vendor, but as soon as I started Prusa Slicer the files would be deleted.

Below is a workaround that finally ended up working for me:
-Close PrusaSlicer
-Remove all FlashForge files from

any folders in …/Roaming/PrusaSlicer
-Install PrusaSlicer 2.6.1
-Follow above steps detailed by @Kingston-C
:

From Kingston-C:

I believe that Prusa changed the way it reads vendors in 2.6+.

A workaround I found is to place “FlashForge.ini” inside of the PrusaSlicer’s AppData folder (typically on Windows at “C:/Users//AppData/Roaming/PrusaSlicer/cache/vendor/”). Then, in this same location, make a copy of any .idx file and rename this file to “FlashForge.idx”

I hope this helps!

-Start Prusa Slicer and add the printer
-Make sure slicing and exporting work
-Upgrade Prusa to newest version

Whatever Prusa 2.8.0 didn’t like about the .ini files seems to be fixed during the upgrade process.

The comment about PS2.8.0 not liking the older .INI file/folder arrangement rang true to me, as my old laptop was still able to process STL files for my CreatorPro2 IDEX with PS2.8.0 installed (hence my complete disbelief that the same setup didn’t work on my new laptop!).

The very first thing I did was verify (again!) that my old laptop did indeed play well with my CP2 by printing out a small calibration model – check!

The next thing was to UNinstall PS2.8.0 from my new laptop and install PS2.6.1 per the above notes. As an aside, the Prusa repo has installers for their latest (PS2.8.0), but not for earlier versions – they just offer a ZIP file. So, I didn’t so much ‘install’ PS2.6.1 as expand the ZIP file to a folder and then just run PS2.6.1 by double-clicking ‘prusa-slicer.exe’.

In my previous (unsuccessful) efforts I had installed Python 3.12.5 using the default install options (plus the ‘admin’ and PATH options), and this put python.exe way down in ‘c:\users\Frank\AppData\Local\Programs\Python\Python312\’, which made for a real long line in the post_process line in Flashforge.ini (to be fair, that’s what happened on my old laptop and the long path didn’t cause any problems, but….). In any case, per the above notes I chose the ‘custom install’ option this time and (with the ‘admin’ and ‘PATH’ options still checked), installed Python at ‘C:\Python312’ leading to a much more readable ‘post_process’ line in Flashforge.ini.

Next I had to install Python’s Pillow library. The ‘Readme’ does say ‘Using Command Prompt’ run the following two commands:

but I missed the ‘Command Prompt’ part and tried to run these commands from inside python – didn’t work :(. Once I figured that out and used Windows command prompt, it still didn’t work. Some more research revealed that the ‘python’ in these commands should be replaced by ‘py’, making the commands

The ‘upgrade pip’ command was a bit redundant in my case, as I had just installed the latest version of python, but the ‘upgrade Pillow’ command was absolutely necessary.

After this, I downloaded and unpacked the latest ZIP file from Jaco’s github repo. Then I placed ‘ff-creator-post-processor.py’ in ‘C:\Users\Frank\AppData\Roaming\PrusaSlicer\post-processor’, and ‘Flashforge.ini/.idx’ in ‘C:\Users\Frank\AppData\Roaming\PrusaSlicer\vendor’.

Then I edited the post_process line in FlashForge.ini to read:

Then I fired up PS2.6.2 again, and now the ‘FlashForge FFF’ option is available in the config wizard, as shown in the screenshot below:

And the CreatorPro2 options show up in Prusa – yay

And, even more fantastic, I was able to successfully process an .STL file for printing on my CP2, and even more amazing, the print came out perfectly (I would have accepted even a lousy print, so the print quality was a bonus!).

So, the last step in this drama is to upgrade PS from 2.6.1 to 2.8.0 and find out whether or not all my work will stay in place – fingers crossed!

Fail! PS2.8.0 popped the following error:

And now the config wizard doesn’t show the FlashForge FFF item, and when I clicked on the still-visible ‘CreatorPro2 Left Extruder Only’, PS2.8.0 crashed :(.

Interestingly though, although the ‘FlashForge FFF’ entry no longer shows up in the config wizard display in PS 2.6.0, I can still see (and select!) all the CP2 configuration choices, and I can still process gcode files properly – yay!

So, screwing around a bit, I saved a copy of ‘BIBO.idx’ as ‘FlashForge.idx’ in the ‘C:\Users\Frank\AppData\Roaming\PrusaSlicer\cache\vendor’ folder, and then re-launched PS2.6.1. This time the config wizard showed the ‘FlashForge FFF’ printer, and I can still see (and use) the CP2 options. Not quite sure why, but even though there is a ‘BIBO FFF’ printer item shown in config wizard, the various configurations don’t show up in the ‘printer’ drop-down box.

Well, I can live with PS 2.6.1, but I’d really like to get back to the newer features with 2.8.0, so I’m going to try again to run 2.8.0. Fingers crossed (again)!

Well, good news and bad news; 2.8.0 came up OK, and I could see the CP2 configuration choices, and I could process a file for the CP2. However, when I saved the processed file to disk, I got another Prusa Slicer error as shown

When I dismissed the error message, PS2.8.0 didn’t crash immediately, and I could still see (and select) the CP2 entries in the ‘printer’ drop-down box. However, when I tried to run the config wizard, PS2.8.0 hung up for a long time, and then produced the same error as above. After dismissing the error window the config wizard came up, but without the ‘FlashForge FFF’ entry. Cancelling the wizard still let me use the CP2 config entries, so that’s a plus. I ran the config wizard again, with the same long hangup and the same error message, thinking this time I would click on ‘Finish’ rather than ‘Cancel’. However, I couldn’t even get that far, as the config wizard (and Prusa Slicer) were hung, and I had to kill the whole thing. Brought 2.8.0 back up, and didn’t run the Config wizard, but still got the same ‘preset bundle version not found’ error after 10-30 seconds. Dismissing the error window allowed me to see and use the various CP2 options. I think for the moment I’m going to leave everything where it is. I don’t really need the config wizard, and dismissing one error message is a small price to pay for having the advantages of 2.8.0.

Summary:

I now have PS 2.8.0 working on my new PC, albeit with a one-time error message popping up each time I launch the program, and no ability to use the config wizard. For the moment at least, that’s good enough.

16 July 2024 Update:

Well, that didn’t last long; shortly after I typed the above summary, PS2.6.1 started crashing it was game over for the current iteration. And, it was about this same time that I noticed that I have actually been running PS2.8.0 on my older laptop – with the Creator Pro II (alias “FlashForge”) profile and without any problems – wtf?

So, I decided to start over (again). This time I uninstalled or deleted all PS installs just to be sure (PS2.6.1 wasn’t ‘installed’ – I was running it from the expanded release folder from Github). Then I uninstalled Python312 (it didn’t like some deprecated syntax in Jacothery’s Python profile) and downloaded/installed Python310. Then I copied over my Flashforge profile from my old box to my new one, downloaded PS2.61 (again) and fired it up. Right away I was able to see the CreatorPro2 selections (yay!), but when I sliced a test file and tried to save it, PS popped an error as shown below:

Yuk, down the rabbit hole again! However, by this time I had figured out how to run the post_processing script in Visual Studio in debug mode – not perfectly, but enough to get a clue, and the clue led me to understand that I had pulled a major boner and not installed Pillow, the Python Imaging Library – oops (and this clue hit me on the forehead right after I posted an issue at the Prusa Slicer Settings repo, so I had to follow up the post with a mea culpa). Anyway, I installed Pillow, and suddenly all was well – at least in PS2.6.1. I was able to load an STL model into PS, slice it, save it in proper .GX format to an SD card, and then print the model on my CP2 – yay yay yay!

Then I crossed my fingers and allowed the upgrade from PS2.6.1 to PS2.8.0, and – amazingly – it worked! So now I have both my old and new laptops running PS2.8.0 and both are fully capable of supporting my CP2 printer – whew!

Stay tuned,

Frank

Frank

Another try at Wall Offset Tracking

Posted 11 September 2021

I’m making another try at getting wall offset capture and tracking right, after several failed attempts. This time I’m starting with a small ‘FourWD_WallTrackTest_V3’ project in VS2019. I think I actually got this working before, but an unfortunate laptop backup catastrophe cost me a couple of months of work, and it has taken me this long to recover. Here’s the current program:

With this code, I ran a test using PID values of 300,0,0 and an offset target of 40cm. The following short video and Excel plot show the results

Now all I have to do is make this same trick work for both the ‘inside offset’ and ‘outside offset’ starting conditions, and then for both the left-side and right-side tracking conditions, then I can integrate the code back into the main robot operating system.

18 September 2021 Update:

After getting the left-side tracking working reasonably well, I started working on right-side tracking, and discovered that what worked for the left side with no problems did not work particularly well for right-side tracking. After the usual number of programming mistakes I did get right-side tracking working, albeit with a significantly different PID parameter set. For left-side tracking, PID = (300,0,0) seemed to work OK, but for right-side tracking I wound up with PID = (300,0,300). Moreover, when I tried even very small (like 10) values for the I parameter, the robot lost track after just two or three oscillations. So, for the moment it looks like (300,0,0) for the left side, and (300,0,300) for the right side. Here’s a short video showing successful right-side tracking.

And here is the ‘finished’ FourWD_WallTrackTest_V3 code:

Stay tuned

Frank