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

ILI9341-Based Digital Clock Project

A while ago, the clock/time display on our microwave started having problems; it’s a 7-segment vacuum-flourescent display, and a couple of the segments a no longer lighting up. Instead of “End”, we now see “Erd”, and the clock is getting harder to read. The microwave itself is still running fine, but because this particular display is our primary time display in the house (aside from our phones), not having a good clock display is annoying.

I investigated getting the appropriate repair part for the display, but that module costs more than the entire microwave did originally, so that didn’t seem like a practical idea. And while I can get a cheap stick-on clock for just a few bucks, what’s the fun in that?

So, I’m in the middle of a design project to build a digital clock to replace the one on the microwave. At first I built up a clock using a Teensy 3.2 and one of my spare Nokia 5110 LCD displays, but that turned out not to be very practical, as the display is basically unreadable from more than just a few feet away, with or without backlighting.

So, I started looking around for better displays, and ran across the ILI9341 TFT display with a touch-sensitive screen. Even better, this was available with Teensy-optimized drivers, as shown here – what a deal! I started thinking that with a touch-sensitive screen, I might be able to implement some on-screen buttons for setting the time, which would be way cool!

So, I ordered two of these displays from PJRC, and started working on the design. Here’s the initial schematic

Here’s my initial breadboard setup:

Teensy 3.2 in foreground, Adafruit DS3231 RTC in background, ILI9341 TFT touch display

I originally used the Arial proportional font provided by the library, but I discovered that it produced bad artifacts after a few hours, as shown below: The only way to avoid these artifacts is to refresh the entire screen on every pass through the 1-second timing loop, which causes a very annoying ‘blink’. Eventually I figured this out, and changed to a non-proportional font, as shown below;

Non-proportional font looks worse, but doesn’t suffer from artifacts

Once I got everything working (well, except for the touch screen stuff that I plan to add later), I fabricated a nice box using Open SCAD and TinkerCad, and made a more permanent version using a half-sized ‘perma-proto’ board, as shown below

Here’s the more-or-less final schematic

7 March 2021 Update:

After a long and somewhat agonizing journey, I finally got the touch-screen stuff working, so I can now adjust the time on my digital clock using on-screen touch-sensitive controls. Here’s the updated schematic:

The only real difference between this one and the previous schematic is the T_IRQ line is no longer connected; the Teensy-optimized XPT2046_Touchscreen.h/cpp library doesn’t use it.

Here’s a short video showing how the touch-screen enabled time/date adjustment feature works:

Although I hope to clean up this code considerably in the future, I include it here in it’s entirety in it’s current state

10 March 2021 Update:

After getting all of the above to work, I decided to re-tackle the proportional fonts issue. In my first attempt, I had used the ‘ILI9341_t3’ version of the ILI9341 Teensy library, and there is a newer ‘ILI9341_t3n‘ version out now. So, I modified one of the example programs (unfortunately still written for the old library) to be compatible and got proportional fonts (well, just the Arial one) working on the display.

After several hours of running this example with no apparent artifacts or problems, I decided to update my complete clock program to use the Arial font. After making the modifications and running it overnight, the time & date displays were still rock-solid the next day, as shown in the following photo – YAY!!

So now all that is left to do is to upload the new Arial-based code (with the time background color switched back to ‘black’) to my ‘working’ clock module, sit back and enjoy the proportional font display.

14 July 2021 Update:

I noticed that my clock had some ‘issues’ with time/date adjustments, so I ‘put it back in the shop’ for some additional TLC. While I was at it, I noticed that the system schematic didn’t include the DS3231 (hard to have a clock without a RTC!), so I updated it as well. Here’s the updated schematic.

The updates made were to make the time/date adjustments more robust. The updated code is included in its entirety below. First the main program:

And then the ‘CustomBox’ class file (no .cpp file – everything is in the .h file)

Stay tuned,

Frank

Dewalt DWS713 Miter Saw Cut Line Shadow Mod

My wife got me a brand-new Dewalt DWS713 Miter Saw for Christmas, and boy is it nice! Sure beats the heck out of my old plastic miter box, that’s for sure. After playing with it for a while and making some gorgeous cuts, I decided I wanted to try my hand at adding a cut line shadow modification.

After doing some web research, I found this post, of a guy who added a cut line shadow system to Bosch miter saw, and this Thingiverse design for a LED mounting shroud. So, I ordered an LED lamp similar to the one used in the video, and downloaded the Thingiverse shroud design so I could print one here on my 3D printer.

The LED lamp comes with a small cylindrical control module containing an ON/OFF switch and an AC/CD converter, as shown here

ON/OFF switch and AC/DC converter are housed in the magnetic base

As described in the video showing how to mount a cut line shadow LED to a Bosch miter saw, the gooseneck part of the LED lamp wasn’t long enough to allow full travel of the blade guard. So I cut the gooseneck away from the magnetic base, and fabricated a new housing for the AC/DC converter and (because I managed to screw up the original one) a new, larger ON/OFF switch.

3D printed enclosure for ON/OFF switch and AC/DC converter.

With the added length gained by replacing the original cylindrical enclosure, I was able to mount the LED at the front end of the blade housing and still allow full travel of the retractable blade guard. However, I discovered that I needed to reduce the height of the LED lamp housing slightly, to allow more clearance for the retractable blade guard travel, as shown

Here is a photo of the LED assembly temporarily attached to the miter saw, with the retractable blade guard removed

This temporary setup produced a nice cut line shadow as shown below

The photo below shows the completed assembly, with the gooseneck attached to the blade housing via a 3D-printed gooseneck retainer clip and two 3mm machine screws (the blade housing was drilled & tapped for 3mm), and the control housing mounted to the rear of the blade housing.

The final product seems to work fairly well, as demonstrated in the following photo

Here is a photo of the 3D-printed gooseneck retainer clip

I used hot glue to temporarily attach the clip to the blade housing, and then drilled through the clip and into the housing with a 3mm tap drill. Then I removed the clip, tapped the housing for a 3mm screw, and then re-drilled the clip for a 3mm clearance hole, then re-assembled using 2ea 3mm x 6mm machine screws.

Here is a screenshot showing the rounded-corner enclosure I designed to hold the ON/OFF switch and the AC/DC converter

Because I managed to screw up the original ON/OFF switch, I used this switch I had in my parts bin, from an earlier project

All the 3-D printable parts are on Thingiverse here.

27 October 2021 Update:

While changing blades the other day, I noticed that the front LED lamp holder had come loose from the top of the blade guard – the hot glue attachment of the holder had detached from the metal. So, I printed up a new lamp holder with longer sides and this time attached it with 3mm screws to 3mm tapped holes in the blade guard, as shown in the following photo:

New front LED lamp hold, this time attached with two 3mm screws

Replacing HC-SRO4 Ultrasonic Sensors with VL53L0X Arrays Part III

In the previous two posts on this subject, I described my efforts to replace the ultrasonic ‘ping’ sensors on my autonomous wall-following robot Wall-E2 with ST Microelectronics VL53L0X ‘Time-of-Flight’ LIDAR proximity sensors, with the aim of using an array of the ToF sensors to solve the problem of wall tracking at a specified offset. Part II demonstrated just such a capability, but only on the right side, and not in a way that was fully integrated with the rest of the robot operating system.

This post describes the work to fully integrate the new ‘parallel-find’ and ‘OffsetCapture/Track’ algorithms into the rest of the robot’s autonomous wall-following operating system. The robot operating system is a loop that runs every 200 mSec.  Each time through the loop the current operating mode is determined in GetOpMode(), as follows:

  • Dead Battery:  Battery died before robot could find and connect to a charging station
  • IR Homing: Robot has detected a charging station and is homing on it’s IR signal
  • Charging: Robot is currently charging on one of the available charging stations
  • Wall Follow:  nothing else is going on, so continue tracking the nearest wall

In the above list, all but the last (Wall Follow)  are ‘blocking’ in the sense that once they start, they run to completion without interruption.  The ‘Wall Follow’ mode processing path however, typically makes a small adjustment to the left/right motor speeds depending on the situation and then exits back to the main loop, where GetOpMode() runs again.  So wall following involves multiple passes through GetOpModes() so that higher-priority tasks (like dead battery recognition, IR homing, and battery charging are executed in a timely manner.

The result of GetOpMode() is passed to a CASE statement where actions appropriate to the determined mode are executed as follows:

  • MODE_CHARGING:   This mode blocks until charging is complete
  • MODE_IRHOMING:  This mode blocks while homing station to the charge station.  If the robot isn’t ‘hungry’, it attempts to go around the charging station rather than connecting to it.
  • MODE_DEADBATTERY:  This mode blocks forever
  • MODE_WALLFOLLOW: This is the default robot mode – whenever one of the above ‘special’ modes doesn’t apply. The MODE_WALLFOLLOW mode is further broken down into tracking cases as determined in GetTrackingDir(), which returns one of TRACKING_NONE, TRACKING_LEFT, TRACKING_RIGHT, or TRACKING_NEITHER.

With the replacement of the ‘ping’ sensors with the VL53L0X array) Wall-E2 can now accurately determine its orientation with respect to a nearby wall.  So I now believe I can make the offset capture operation a blocking call, significantly simplifying the MODE_WALLFOLLOW code.  Here is the code for the TRACKING_RIGHT case:

In the above code the robot first checks for obstacles, and either maneuvers to capture the desired wall offset (first time through this case) or continues to track the previously captured offset.

 

 

 

Integrating Heading-based Wall Tracking into Wall-E2

Posted 09 September 2019

After successfully demonstrating heading-based wall tracking with my little 2-motor robot, I am now trying to add this capability to Wall-E2’s repertoire.

Current Algorithm:

Every MIN_PING_INTERVAL_MSEC millisec Wall-E2 measures left/right/forward distances, and then calls ‘GetOpMode()’ to determine its current operating mode.  The currently defined modes are:

  • MODE_NONE: (0) default case
  • MODE_CHARGING (1):  connected to the charger and not finished
  • MODE_IRHOMING (2): coded IR signal from a charger has been detected
  • MODE_WALLFOLLOW (3):  trying to run parallel to a wall
  • MODE_DEADBATTERY (4): battery exhausted

The MODE_WALLFOLLOW operational mode is returned from GetOpMode() when none of the other modes are active – in other words it is the real ‘default mode’.  The MODE_WALLFOLLOW mode has three distinct sub-modes;

    • TRACKING_LEFT (1): actively tracking the left wall
    • TRACKING_RIGHT (2): actively tracking the right wall
    • TRACKING_NEITHER (3): not tracking either wall (both distances > 200cm)

TRACKING_LEFT & TRACKING_RIGHT are identical for purposes of heading-based wall tracking, and the TRACKING_NEITHER case isn’t relevant, so we just have to come up with a way of integrating heading-based tracking into either the LEFT or RIGHT case.  The TRACKING_LEFT case block is shown below:

The first thing that happens is a check for an obstacle within the MIN_OBS_DIST_CM or the ‘stuck’ condition (determined via a call to ‘IsStuck()’).  If this test passes, a check is made for an obstacle that is farther away than MIN_OBS_DIST_CM but closer than STEPTURN_DIST_CM, so a gradual ‘step-turn’ can be made to negotiate an upcoming corner.  If that check too fails, then the robot is assumed to be tracking the left wall, safely far from any oncoming obstacles.  In this case, a new set of motor speeds is computed using a PID setup to keep the left PING distance constant – no consideration is given for whether or not the PING distance is appropriate – just that it is either greater or less than the one measured in the last pass.

So, the thing we want to change is the way the robot responds to PING distances to the left wall.  We want the robot to acquire and maintain a selected standoff distance from the wall being tracked (the LEFT wall in this case).  Pretty much by definition, this requires two distinct activities – the first to acquire the selected standoff distance, and the second to maintain that distance for the duration of the wall-tracking activity.  So now we have three state variables for wall tracking, and only the last one (ACQUIRE/MAINTAIN) is new

  •  TRACKING_LEFT/RIGHT
    • NAV_WALLTRK (as opposed to NAV_STEPTURN)
      • PHASE_ACQUIREDIST/PHASE_MAINTAINDIST

In the PHASE_ACQUIREDIST phase, a heading change of up to 20 deg is made in the appropriate direction to move toward the selected offset distance.  The situation is then monitored in subsequent loop passes to determine if a larger or small heading cut is required.  When the robot gets close to the desired distance, all the added heading offset is removed and the robot enters the PHASE_MAINTAINDIST phase.  In this phase, small(er) ping distance variations cause larg(er) heading changes, resulting in a sawtooth pattern about the selected distance.

 

Alzheimer’s Light Strobe Therapy Project

Posted 24 March, 2019

A friend told me about a recent medical study at MIT where lab mice (genetically engineered to form amyloid plaques in their brains to emulate a syndrome commonly associated with Alzheimer’s) were subjected a 40Hz strobe light several hours per day.  After repeated exposures, the mice showed significantly reduced plaque density in their brains, leading the researchers to speculate that ‘light strobe therapy’ might be an effective treatment for Alzheimer’s in humans.

The friend’s spouse has been diagnosed with Alzheimer’s, so naturally he was keen to try this with his spouse, and asked me if I knew anything about strobe lights and strobe timing, etc.  I told him I could probably come up with something fairly quickly, and so I started a project to design and fabricate a light strobe therapy box.

The project involves a 3D printed housing and 9V battery clip, along with a white LED and a Sparkfun Pro Micro 5V/16MHz microcontroller, as shown in the following schematic.

Strobe Therapy schematic

I had a reflector hanging around from another project, so I used it just as much for the aesthetics as for functionality, and I designed and printed up a 2-part cylindrical housing. I also downloaded and printed a 9V battery clip to hold the battery, as shown in the following photos

Finished Strobe Therapy Unit

Internal parts arrangement

Closeup showing Sparkfun Pro Micro microcontroller

The program to generate the 40Hz strobe pulses is simplicity itself.  I used the Arduino ‘elapsedMillis’ library for more accurate frequency tuning, but ‘delay()’ would probably be close enough as well.

 

I’m not sure if this will do any good, but I was happy to help someone whose loved one is suffering from this cruel disease.

Frank

 

WallE2 Robot in Arduino #include file hell

Posted 02 February 2019

After a vacation from my WallE2 autonomous wall-following robot code to recover from rotator cuff surgery (and creating/testing my new digital tensionometer), a week or so ago I decided it was time to get back into WallE2 mode.   At the time I thought this would be a piece of cake, as I had left WallE2 in pretty good shape, code-wise back in September 2018  (at least that’s what I thought!).

Instead, For the past couple of weeks I have been enduring what can only be described as “#include file hell”.   The first time I tried to compile my main program, I saw a couple of warnings in an i2cDev related library.   The code still compiled, but I take all warnings very seriously, and these weren’t there the last time I compiled the code.

So, I started trying to figure out what, if anything, had changed, and how to go about fixing whatever problem had caused the warnings to pop up.   Unfortunately, everything I did made things worse – and worse – and worse.   Nothing made sense.   Jeff Rowberg, the creator of the fine i2cDev collection of i2c device drivers was mystified, as was Tim Leek, the main guy on the Visual Micro forum.   Arggghhhh!

So, Jeff Rowberg suggested I try compiling the project in the Arduino IDE rather than in VS2017/Visual Micro, to eliminate any issues caused by that environment.   Up until this point I had actually  never used the Arduino IDE, much preferring the more helpful and feature rich VS2017/Visual Micro IDE. But, what the heck – how hard could it be?

Well, the answer was –  DAMNED HARD!   Using the Arduino IDE after the VS/VM environment was like moving backwards in time from the 21st century to the stone age –   having to rub sticks together to make a compile happen!   Moreover, the Arduino IDE created even more (and different) problems than I had experienced so far, meaning that I not only wasn’t draining the swamp, but the alligators were getting even more numerous!   Some of the ‘features’ of the Arduino IDE:

  • When the IDE is first launched, it comes up with the last .INO file loaded.   If you want a different file, it launches a new IDE instance with file->open; soon your desktop is littered with IDE instances.
  • When it tries to find a library based on a ‘#include <libraryName.h>’ line, it can’t handle [library name]-master as is common with libraries downloaded from GitHub
  • It requires exact name matching, including capitalization.   So ‘#include <libraryName>’ will not match with the ‘Arduino\Libraries\Libraryname’ folder.
  • Editing is clunky, and there’s no such thing as Intellisense.

After running around in circles with my hair on fire for the last week or so, making my wife miserable with my griping and inundating Tim Leek and Jeff Rowberg with ever-more-desperate cries for help, I finally decided that I was simply going to have to start over from scratch with my robot program (some 3000+ lines of code in the main program and over a dozen custom libraries), and just build it up piece by piece until everything works again – groan.   It’s not like I don’t have backups and wasn’t using revision control – I do and I was; it’s just that the programs that compiled cleanly back in September are generating warnings and errors now, and everything I do makes the problem worse!

Since the original problem seemed to be related to the library that runs the DFRobots MPU6050 module, I decided to start there.   After struggling up the learning curve on the Arduino IDE, I also decided I would make sure that each program step would compile cleanly in  both the VS/VM and Arduino IDE’s before proceeding to the next step.   I reasoned that since the Arduino IDE is much pickier about library locations and names, I could use it as sort of an editorial check on VS/VM; if it works in the Arduino IDE, the VS/VM setup will have  no problem.

For the DFRobots MPU6050 6DOF IMU module, I started with Jeff Rowberg’s ‘MPU6050_DMP6.INO’ example program buried way down in the ‘i2cdevlib-master\Arduino\MPU6050\examples\MPU6050_DMP6’.   According to the i2cDev ReadMe, I could either put the entire i2cDev-master folder in Arduino\Libraries and let the linker figure it out, or just put the required files in the project (solution folder for VS/VM, ‘sketchbook folder’ for Arduino IDE) folder.   I elected for the latter (local files) option, as I was at least a little suspicious that part or all of my original problem was caused by the compiler/linker loading from the wrong library folder in the i2dDev folder tree.   In addition, I completely removed the i2cDev folder tree from my PC and re-downloaded it from GitHub, placing it in a completely unrelated folder so that neither environment could possibly find it.   Then I copied the required header/.cpp files from the hidden i2cDev folder tree into the project folder.   In VS/VM I created a project called ‘MPU6050_DMP6_Example’ and copied the Arduino versions of I2Cdev.cpp/.h, MPU6050.cpp/.h, MPU6050_6Axis_Motion.h, and helper_3dmath.h into it. Then I started working to get this project to compile both in the VS/VM & Arduino IDE’s.

I’ve now gotten it to compile and link in the Arduino IDE (albeit with the same warnings I started with just before I went down the rabbit hole into header file hell).   However, I can’t get it to compile in VS/VM – it blows a whole bunch of errors of the form – apparently one error for each MP6050 function)

These errors proved impossible to correct, and nobody on either the Arduino or Visual Micro forums seemed to be able to help.   Finally in desperation I uninstalled and re-installed the Visual Micro extension to VS2017, and  that didn’t solve the problem either – exactly the same behavior.

So, last night I uninstalled VS2017 entirely from my system, and deleted the entire contents of the temp folder being used for temporary compile files.   On my system this was  C:\Users\Frank\AppData\Local\Temp.

03 February 2019

This morning I reinstalled VS2017CE and, using the Tools & Extensions menu, reinstalled Visual Micro. I left everything pretty much at the default settings (including the IDE selection and IDE location entries).   The only thing non-standard with the setup was the inclusion of ‘https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json’ in the ‘Optional additional boards manager urls’ field.   This was apparently left over from my previous installation.   I’m not worried about this particular setting, but it does indicate that not everything about the previous incarnation of Visual Micro was actually removed from my system.

After installing VS/VM, I ran through a few of my simpler projects, and so far they have all compiled w/o problems (or had understandable and easily fixable problems).   I also compiled each program in the Arduino IDE,  taking care to follow the Arduino IDE restrictions (no “-master” in library folder names, exact capitalization, etc).

  • BlinkTest.ino – very simple, no #includes
  • ClassTest.ino – Very simple class construction project – no #includes
  • DigitalScale.ino – Several #includes, including the HX-711 load cell library
  • StepperSpeedCtrl – uses   #include <Stepper.h>
  • AdaFruit_BTLE_UART_Test.ino – uses 7 different library #includes
  • Arduino_IMU6050_Test4.ino – uses i2cDev and MPU6050 libraries, along with SBWire, elapsedMillis, and PrintEx.   this compiled OK, but with the same warnings (overrun & ‘one definition rule’) as when I first started this odyssey.   Fortunately, that’s all that happened – I didn’t get the ‘(.text.startup+0x1e4): undefined reference to MPU6050::initialize()’ error – yay!   This program also compiles in the Arduino IDE, with the same exact warnings.   So, it appears I may be back where I started on this odyssey, with a program using the MPU6050 libraries that compiles OK but with one   understandable/fixable warning (the overrun warning) and one mystery warning (the ‘one definition rule’ warning)
  • MPU6050_DMP6_Example:   spoke too soon!   This program blows the same  ‘(.text.startup+0x1e4): undefined reference to MPU6050::initialize()’ errors as before in VM, but compiles fine (albeit with the same two warnings as always)   in the Arduino IDE.
  • Arduino_IMU6050_Test4:   This is a program I created some time ago, and I found that it compiles/links fine (stil with the overrun/ODR warnings), both VS/VM and Arduino IDE

In desperation, I decide to create a completely new Arduino project in VS/VM, copy the ‘known-good’ code from  Arduino_IMU6050_Test4 into it, and then start hacking it down to the point where it fails.   Surprise surprise, when I did this, the new project (UnDefTest2) failed right away in VS/VM, blowing LOTS of linker errors!   Moreover, it compiled/linked fine in Arduino IDE – how could this be?   There MUST be something different about the VS/VM environment between  Arduino_IMU6050_Test4 and UnDefTest4 – but what?   After putting the two projects up side-by-side (this is where a dual monitor setup comes in REAL handy), I finally twigged to the difference; in the ‘working’ version, the local header/cpp files had been ‘added’ to the project’s ‘Header Files’ and ‘Source Files’ folders via the Solution Explorer (right-click on the folder icon, select ‘Add Existing…’, select the desired files, click OK). As soon as I added the relevant files to the UnDefTest4 project, it compiled/linked fine – YAY!!

I could not believe what I was seeing!   For some reason, VS/VM refused to process header/cpp files in the same folder as the .INO file, even though I had carefully checked the ‘Local Files Override Library Files’ option in the ‘Vmicro->Compiler’ menu.   At the same time, the Arduino IDE  always searches the local folder before anything else, so simply placing the relevant files in the local folder does the trick.   The fact that Visual Micro requires an additional (and non-intuitive) step for this boggles the mind.

04 February 2019

OK, when I started all this foolishness I was trying to find out (and fix) whatever was causing the ‘One Definition Rule’ (ODR) violation warning I was getting on all my programs that used the MPU6050.   I really  really hate warnings, and I was determined to get to the bottom of this, and I finally did!

The ‘one definition rule’ (ODR) warning is caused when the compiler/linker sees code that can produce two different definitions for the same object. If that can happen, EVER, then an ODR violation warning is issued. Believe it or not, that is exactly what happens when the compiler processes MPU6050.H – it sees that there are some conditions for which two different descriptions of the MPU6050 class could exist – and says “no no”. The relevant portion of the class definition is shown below:

When the compiler sees these lines, it says to itself; “Hmm, the way this is written, it is theoretically possible for there to exist  two different versions  of ‘Class MPU6050’, one with just two private member variables (devAddr & buffer) and one with four (with the addition of dmpPacketBuffer & dmpPacketSize), and this is a strict no-no; I’m going to whack that programmer across the head with an ODR violation!”

If the #ifdefined and #endif lines are commented out – the ODR warning goes away

Now, I suspect nobody has ever had a problem with this issue, as it would be very unlikely to have a project where BOTH versions of MPU6050 are in play, but of course the compiler doesn’t see it this way.

On a slightly different, but related subject, the OTHER warning was due to a potential integer overrun in the dmpGetGravity() function, as shown below:

if the last line of the above calculation is changed to (note the addition of ‘UL’)
– (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384UL);
then this warning goes away as well.

Mission accomplished!   I now have MPU6050 code that compiles without errors (or warnings!!) in both the VS/VM and Arduino IDE environments.   Along the way I learned more than I ever wanted to know about ‘One Definition Rule’ violations and the innards of both the VS/VM environment and the Arduino IDE.

to paraphrase a quote attributed to Abraham of Lincoln:

I feel like the man who was tarred and feathered and ridden out of town on a rail. To the man who asked him how he liked it, he said: “If it wasn’t for the honor of the thing, I’d rather walk.”

 

Stay tuned,

 

Frank

 

 

 

Digital Tension Scale, Part V

posted 09 January 2019,

In my previous post on this subject I described the components I planned to use for my Digital Tension Scale project, and also the design for a box that would mount directly on the S-shaped load cell assembly.

This post describes the ‘final’ (to the extent than anything I do can be considered final) assembly of the completed system into my 3D-printed housing, and the results of some initial battery-powered testing.

As shown in the following photos, the major components (Teensy 3.2 microcontroller, HC-05 Bluetooth Module, HX-711 load cell amp/A-D, and Sparkfun ‘Basic’ LiPo Charger) were mounted on perfboard, which was then in turn attached to the box lid via a set of custom-printed standoffs.   A short piece of ribbon cable connects the Teensy to the LCD display.   The general idea behind this physical layout is to allow easy access to the electronics for troubleshooting, and to allow for battery charging and/or Teensy programming without having to open the box.

3D-printed housing. Note the glow from the Sparkfun charger LED

View of housing showing the access port for supplying USB power and/or programming the Teensy

View with the lid and electronics board removed. The LCD display is face down in its cutout

Exploded view showing all system components

Showing connections from load cell to HX-711

Top view showing how load cell attaches to the housing

Closeup showing load cell lead routing and power/programming port

End view showing charging port

 

Preliminary Testing Results:

At this point I have everything running on battery power only inside the box, and I have been able to demonstrate remote data capture on my PC using the HC-05 BT link.   The following image shows the data taken from my rowing machine, and a short video demonstrating the setup.

Complete Code:

Here is the complete Teensy 3.2 program as it stands today.   As you can see if you inspect the code, I have the Teensy low-power stuff turned OFF for the moment (that’s the purpose of the ‘#define NO_SNOOZE’ statement.

 

Schematic:

Future Work:

  • Do some more work to reduce power consumption to extend the battery life.   I got the ‘Snooze’ feature to work on the Teensy, but that only reduces the Teensy’s power consumption; it does nothing directly to reduce the power consumption of the other components.   I tried using a MOSFET to turn the HC-05 BT module on & off, and found this to be impractical, as then the module loses its connection to the remote data collection device.    I have also tried removing power from the LCD module, but that also turned out to be problematic.

Stay tuned,

Frank

 

 

Digital Tension Scale, Part IV

Posted 25 December 2018

In my copious free time I have been refining the design for a low power battery operated tensionometer.   In my last post on the subject, I had described the components I had planned to use, and in the ensuing weeks I have been working on implementing this design.   There are several challenges in this project:

Bluetooth Link:

There are a huge number of Bluetooth products out there in the Maker-verse, with varying degrees of Arduino support, and widely varying performance characteristics.   To add to the confusion, there is ‘regular’ Bluetooth and the more recent  ‘BLE’ (Bluetooth Low Energy) which are completely incompatible with each other.   As I now understand it, BLE is synonymous with Bluetooth 4.0+ (the iPhone 4S was the first smartphone to implement the new standard).   However, the most common product in use in the Arduino world seems to be the venerable HC-05 ‘regular’ Bluetooth module, available from your local grocery store (well, not quite, but from almost everywhere else!) for not much more than a few pennies

I had no previous experience with BT modules, so this part of the project took some time, and was the last major part to be accomplished.   After receiving my HC-05 modules from China, I used this tutorial to get started.   The real challenge for this part of the project wasn’t getting the HC-05 hooked up to the microcontroller – it was sorting through all the layers of BT-related settings on my Win 10 laptop to pair with the HC-05 device and determine which serial port did what.

  • In Windows 10, I used the ‘Bluetooth and other devices settings’ panel (Settings -> Devices -> Bluetooth and other devices) to find and pair to the HC-05.   The device shows up as ‘HC-05’ and the default pairing password is “1234”.
  • When the HC-05 is paired it automatically sets up at least two serial ports that show up in device manager as ‘Standard Serial over Bluetooth’ ports, as shown below.   However, only one of these ports is actually usable for two-way communication, and it isn’t clear to me why, or how to tell which is which;   I had to experiment with each available ‘SSoB’ port to figure out which to use  (so far, it seems like the highest-numbered port is the proper one).
  • After the HC-05 is paired and the com ports are set up, then any serial terminal app (I used RealTerm) can be used to communicate between the PC and the microcontroller via the HC-05.
  • On the microcontroller (I used a Teensy 3.2 with multiple hardware serial ports), I wired the HC-05 to Serial1 leaving Serial (Serial0) available for normal communication between the Teensy and my Visual Studio 2017 Community Edition/Visual Micro add-on for Arduino development platform.

Physical Layout:

The original idea behind this project was to create a self-contained battery-operated digital weight scale that could display weight values on a local display, but could also stream the data live to a remote recording station like a laptop or smartphone. The ‘self-contained’ part requires that all the electronics be mounted on the S-shaped load cell assembly itself, and to that end I designed a housing that connects to the two bolts that hold the arms of the load cell.   The idea is that all the electronics save the LCD display and the battery will be mounted to the underside of the box lid so that servicing would be easier.   Also, by mounting everything to the lid, I can make cutouts for the charger and Teensy USB connectors for easy charging and reprogramming.   After several iterations in TinkerCad, I came up with the following design

Looking up at the underside of the box lid, showing all modules except the battery and the LCD display

Showing the top of the lid with the mounting bracket for the load cell

Isometric view with transparent box walls. The LCD display module is under the battery.   Note the cutouts for the charging and programming USB-C connections

Module Integration:

I had previously tested each module individually, but hadn’t had all of them working at the same time.   I had tested the HC-05 with an Arduino Mega, and I had tested the load cell with both a Sparkfun Pro Micro and with a Teensy 3.2, and I had tested the Nokia LCD display with a Teensy 3.2, but I hadn’t put everything together.   So I wired everything up on my half-size ASP plugboard and got it all working together with a simple program (included below) that exercised the LCD Display, the load cell, the BT module, and the battery charger, as shown in the following photos

RealTerm Serial Terminal Program showing load cell readouts collected wirelessly via the Bluetooth HC-05 modules

HC-05 Bluetooth, HX-711 Load Cell Amp, Sparkfun Charger, and Teensy Microcontroller modules integrated together. Note disconnected USB cable showing that the circuit is running on battery power. The scale is currently measuring 1.8 liters of water in the suspended plastic bag (note the ‘1.8 Kg’ reading on the LCD display)

 

Software:

The software used for the above integration tests is a reasonably complete sketch for day-to-day use of the digital weight scale.   It displays the measured weight on the LCD display, and also sends it to the USB serial port for display on a directly connected PC, and to the HC-05 Bluetooth module for display/capture via a BT-connected laptop or smartphone.   This program is shown below:

However, this program depends on the proper calibration of the load cell, which I have been doing with a separate sketch (also included below):

What I need to do now is to combine these two programs into a single sketch with ‘operating’ and ‘calibration’ modes.   My calibration program already does this to some degree, as it waits 5 seconds on startup for the operator to send the ‘y’ key via the direct-connect serial port. If the ‘y’ character is detected within this window, then the program starts the calibration sequence; otherwise it starts taking measurements as normal.   This behavior needs to be expanded somewhat in that it should accept a calibration command either through the direct-connect serial port (Serial) or via the BT port (Serial1).

Low Power Operation:

I have already done some experimentation on low-power operation of the Teensy 3.2, using Colin Duffy’s fine ‘Snooze’ library, and have determined that I can easily drop the Teensy’s operating current from around 20-30 mA to about 1-2 mA by putting it to sleep during periods of load cell inactivity.   Assuming I get the full 2500 mA hours out of the battery, then I can expect something like 1000 hours or about 40 days between recharges.   However, more work needs to be done to get the low power mode fully operational.

 

Stay Tuned!

Frank

 

Digital Tension Scale, Part III

Posted 25 November, 2018

Over the Thanksgiving weekend I had a chance to do some more work on my digital tension scale project.   My wife and I drove to St. Louis to visit our kids and grand-kids, and its a 6-hour drive each way.   I make sure we have an audio book going for my wife, and as a consequence I get 6 hours of (mostly) uninterrupted geek time to work on things like this project.

As I mentioned in Part II, my goal is to construct a battery-operated tensionometer that can be mounted directly on the dual-hook S-shaped tension block, as defined by the features delineated in Part II.   After doing some more web research, I came up with the following possible components for the system:

Display:

Apparently, the Nokia 5110 84×48 pixel monochrome LCD display used in prehistoric times as the display in Nokia cellphones has found a second career as a simple, low power display for battery-operated devices like the one I envision.

 

Nokia 5110 Monochrome LCD display

Battery & Battery Charger:

The LCD display will operate quite nicely from 3.3V, so as long as I can come up with a 3.3V micro-controller (like the Teensy 3.2) and a small, capable LiPo charger, I should be in business.   For this component, I plan to use the Adafruit PowerBoost 1000C and something like the 3.7V 2500 mAh battery as shown below

Adafruit PowerBoost 1000C single-cell LiPo charger

3.7V 2500 mAh LiPo battery

 

I don’t think I’ll need the 5V boosted output from the PB1000C and the entire thing may be a bit of overkill for this project, but I had them hanging around from a previous project, so…

MicroController:

For this I plan to use one of  Paul Stoffregen’s magical Teensy 3.2’s.   Again this is probably  way overkill for the project, but…

Wireless Connection:

This component is the one for which I have the least understanding and confidence.   I currently use a Pololu Wixel for wireless serial comms and programming with my autonomous robot, but I haven’t figured out how to use it with a Teensy, and I thought maybe there were better solutions out there by now anyway.   So, after some more web searching I found that many ‘makers’ are using the HC-05/6 Bluetooth modules for this purpose.   Hopefully with this module I’ll be able to use a Bluetooth connection from the tensionometer to my laptop or even my cellphone to perform calibrations and collect real-time tension data.

Combining all these with the HX-711 load cell amplifier, I came up with the following system schematic.

 

Stay tuned!

Frank