Recently I got to work on a project that was destined to serve as a table display at a major U.S. tradeshow. Complicating matters was that I would not be traveling to the tradeshow myself so the contraption had to be shipped and set up by those who would not see the hardware in person until the day it was delivered. Furthermore, while I was the hardware guy with a limited software background, the smart folks setting it up were software engineers with limited hardware background. One last background fact, the project was built to showcase the services and capabilities of three separate companies who were teaming up for this specific effort. Also, one of the major components was a given so we had to work within the constraints of the hardware and firmware of that device.

I learned quite a few lessons about building a project that was more than a prototype and less than production-ready. It was also a rather physically large contraption (relative to what I typically work on) coming in at 36” (L) x 18” (W) x 12” (H). And as I mentioned before it had to be shipped across the country and set up by others with my support only possible over the phone.

This blog is meant to serve as a quick and dirty debrief of those lessons in case you find yourself in a similar predicament.

First, let’s look over the top-level requirements for the project:

  1. Two tanks that move liquid between them while monitoring the water levels with alerts when either tank becomes full.
  2. Send tank and pump telemetry to the designated IoT cloud service.
  3. Minimize hardware complexity since the demonstration is about the Cloud and software
  4. Quiet
  5. Desktop size  (Estimated Overall Dimension: 30” (L) x 18” (W) x 12” (H)
  6. Lightweight so to be easily transportable
  7. Constraint: x4 4-20mA or 0-10V sensor inputs
  8. Constraint: x5 Open Collector Output, 200mA; selectable 3.3, 5, 15, 24 VDC

In short, it was a rather straightforward demonstration of an industrial process meeting the Internet of Things (IoT) in a small, demo-sized form factor.

Lessons Learned

  1. Do not permanently mount any component that might need to be replaced or is fragile enough that it may need to be shipped separately. Ensure that any mounting is easily swappable.  Consider magnets, velcro, or universal mounting systems such as DIN rail. Screws and adhesives should be used only if absolutely necessary.
  2. Use lever-nuts connectors to connect wires between components. Do not solder or use other permanent connectors between wires.
  3. Use quality 20 or 22 SWG solid core wires for breadboarding. 18 AWG stranded wire for routing wire long distances or with lots of bends. 
  4. Establish q wire color code (e.g black for ground, red for power, yellow for clock signals, white for data signals)
  5. Use colored heat shrink to indicate the purpose of grouped wires in a wiring harness.
  6. Use zip ties or hot glue around cables when they go external from an enclosure to provide strain relief.
  7. Always tin the ends of wires before joining two wires together.
  8. Use  ¾” standoffs to raise up project off the table.  It gives enough clearance to route wires without being too tall.  It also adds some ruggedness during shipping.
  9. When cutting a hole through plastic use a step bit, go slow, and coat with dish soap. Use a piece of tape to indicate which bit step to stop at.
  10. Ensure that you are not using oddball components in your project. Being able to source components quickly and cheaply relies on using common parts. Octoparto’s Common Parts Library is a great source to find which electronic components are easily sourced.  When it comes to screws, #6-32, #4-40, and #2-56 are among the most common with common lengths being 1”, 3/4”, 1/2”, 3/8” and 1/4”.
  11. Don’t invent the wheel if not needed. Breakout boards of components are your friend. Do not create your PCB if not necessary.
  12. When inserting switch in series with external battery pack, cut positive cable and insert a switch/button in series
  13. Measure power consumption on the low side, between load and ground.
  14. Use a “#define DEBUG” macro to easily toggle whether or not the microcontroller is printing debug messages over the serial connection.
  15. Know the difference between const int, static int, and the #define preprocessor directive.
  16. Know the difference uint_16 vs int
  17. Know the difference between delay functions, interrupts, timers, and schedulers.
  18. Follow PEP8 naming conventions for variables:
    1. variable and function names use lower_case_with_underscores
    2. class/struct names use CamelCase,
    3. constants/DEFINE use CAPITALS_WITH_UNDERSCORES
    4. byte RfidReaders[] = {RFID_READER1_CS};
    5. _VarName for private variables
    6. enum PuzzleState {Initialising, Running, Solved};