Author Archives: Andrew England

Enginursday: 3D-Printing Your Way to a Better Printer (Part 1)

via SparkFun: Commerce Blog

I recently got a Lulzbot Taz 6 and like many first-time 3D printer owners, ran the thing for a week straight printing various and sundry items from Thingiverse.

After populating my pegboard with a few organization tools (the mason jar jumper holder and modular drawers are my favorites) and realizing while printing some pegboard compatible drawers that I'm having some serious adhesion and warping issues in my chilly basement, I decided it was time to create an enclosure to keep the heat in and prevent my ABS parts from cooling too quickly. I'd also like to avoid breathing some of the nasty fumes the printer can give off, so enclosing it is the first step to adding a ventilation fan to control both fumes as well as ambient air temperature.

This is a pretty big project, so I'm gonna split it into two parts, the first will be the construction of the enclosure, and the second will be the construction and addition of the optional vent fan and lighting. For part 1, I tried to design an enclosure that would use the smallest number of plexiglass pieces - my reference design is shown below. Note that this design can be used on many different Lulzbot printers by adjusting some of the dimensions (and probably some other ones, but I'm unsure).

Reference Design

Reference Design

Once I had all of my measurements I checked the vast and ever-expanding interwebs for sizes of plexiglass that may be able to fit all of the different size pieces. I eventually settled on a 3 mm thick, 3'x6' chunk that seemed it would be able to fit all of my pieces, except for my door (H), which I wanted to cut from thinner, lighter plexiglass to ease the strain on my hinges. The dimensions in centimeters of all of the pieces are listed below.

  • Back (B): 53*51.5
  • Left-back (D): 23*51.5
  • Left-front (E): 28*51.5
  • Right (C): 69.5*51.5
  • Top (A): 69.5*53
  • Front: 2-10*51.5 (F, Left and right sides)
    • 2-10*33 (G, Top and bottom)
    • 32.5*31 (H, Door)

I cut all of the pieces (except the door, which I cut from an extra piece of lighter 1/16" plexiglass I had lying around) using the scoring tool that I bought right next to the plexiglass. I used the below layout to fit all of the pieces into the chunk as well as minimize the number of cuts I had to make.

Layout for Cutting Pieces

Layout for Cutting Pieces

Cutting plexiglass can be tricky and tedious, so make sure to watch a Youtube video or two instead of learning the hard way from the back of the plastic-scoring knives package. The best tool you have here is patience.

Make sure you score a great deal of the way through the plastic (at least halfway) before trying to break it to ensure you get clean edges. Piece D was a little tricky as I had to cut away 2 cm only going up half of the piece to allow for the Taz 6's wiring harness. To accomplish this, I added some scores at the proper places and broke chunks off with a hammer. These are the times when I wish I had a big old tabletop CNC, but if I never had to do anything manually, I wouldn't appreciate my robotic servants so much.

While you're cutting plexiglass, it's a good idea to also start printing the brackets that will hold the whole thing together. The individual .stl files are in a .zip below, but you'll still need to slice them yourself.

I used the following numbers of pieces, but you can always add another set of edge pieces at the midpoint of any of the box edges to add structural support if you please. Also, you can use these pieces for any sort of 3 mm thick plexiglass box. I printed all Corner, Edge, Flat and Hinge pieces at 100 percent infill, but the rest of the pieces can be done at a standard 20 percent. I also used 60 4-40 1/4" screws for the brackets, nine 4-40 3/4" screws for the filament port and stand, and three 3/16" magnet rings to hold the door closed.

  • 4 - Corner
  • 9 - Edge
  • 5 - Flat
  • 2 - Male Hinge
  • 2 - Female Hinge
  • 1 - Knob Rest
  • 1 - Knob
  • 1 - Port
  • 1 - Stand
  • 1 - Hole Guide

To finish these prints (I rarely fine tune hole sizes on one-off things like this, instead opting for a drill bit to do my fine tuning), go ahead and bore out all of the holes with a 7/64" drill bit. You may also need to file the peg on the male hinge as well as drill out the hole on the female hinge to make them fit properly. Make sure the hinges fit together and slide smoothly before attaching them to any plexiglass.

Use the hole guide print to drill pilot holes in the appropriate corners of pieces A, B, C, D, E and F (anything that attaches to the top piece's corners). If you're confused, refer to the reference drawing, which has these corners circled in red. Once you've drilled your pilot holes, attach the four corner brackets to piece A, then flip piece A on its back so that the brackets stick up in the air to allow for easy attachment of pieces B, C, D, E and the two F pieces.

Next, attach the edge brackets in the proper locations (shown in green on the reference design) by first drilling one hole, attaching the bracket with a screw, then drilling and attaching the other side of the bracket. Finally, use the four flat bracket pieces (shown in blue on the reference design) to attach the G pieces to the F pieces, again drilling and attaching one side, then drilling and attaching the other.

Now, we need to attach the male hinges to piece H. Make sure they both hang off the left side of piece H the same amount so that they swing on the same axis. From here, slip the female hinges onto the male hinges and use them as guides to drill pilot holes for their screws on piece F. Now you can drill a hole pretty much anywhere on the right side (just make sure it's close enough to the edge that the center can be reached by a Flat piece) and attach the knob with a 3/4" screw from the backside. You can now glue the other magnet into the knob rest and attach it opposite your knob on piece F. Line things up so that the magnet aligns with the screw that holds the knob in place.

Knob

Knob

Now is a good time to slide the assembly over the printer so we know where to place our filament port and stand. For these, I simply tried to center them to the best of my ability over the printer head then drilled and attached them with 3/4" screws. The filament port needs a pilot hole with a 3/8" drill bit, then you can insert the port and use it to drill out the pilot holes on the sides to attach it with 3/4" screws. Once again make sure to drill and attach one hole before drilling and attaching the second hole. My one regret here was not making the filament stand and port one single piece, so if you're up for a little design, this is the piece that needs improvement.

Completed Printer

Now that your printer enclosure is assembled, time to rip off that protective plastic covering and marvel at your pretty new box. This is the end of part 1, stick around for part 2, where I'll add lighting and a ventilation system (which you can see is already in progress) to extract fumes.

comments | comment feed

Enginursday: Light Suit Update

via SparkFun: Commerce Blog

The Wonderful Mistakes I've Made to Get to this Point

Pretty much as long as I've been playing with electronics I've been working on this wacky Light Suit project to wear out to festivals to light up the night. I've learned so much along the journey. I've made so many Enginursday posts about it that at this point you may be getting sick of the project, but I feel an obligation to keep folks updated all the way through the end.

When I arrived at SparkFun, I was in the second iteration of the project and I needed to fix a few 3D parts. I wore this updated version to a few shows and quickly broke the gesture sensing that I had soldered into my hands. I came back into the office on Monday and bang! The SparkFun Qwiic Flex Glove Controller was born in order to isolate the exceedingly fragile solder points on the Flex Sensor. From here, I decided to scrap the second version as the 1-mm thick fibers I was using were brittle and hard to work with.

The Current Light Suit

The Current Light Suit

In the third version I got a lot closer to the vision in my head. I designed some custom PCBs to mount addressable LEDs to instead of individually PWM-ing each Common-Cathode LED (I still have unplaced anger at whoever let me live so long without knowing about the WS2812). I was also able to use the SparkFun Qwiic Flex Glove Controller that I had designed after the failure of the second iteration. I sourced new fiber to test some neat audio-reactive and gesture-reactive code.

However, I had one major flaw: the LED modules I had were connected via Qwiic cables as I had this strange obsession with making the system solderless for easy repair out in the wild. This worked for a little bit, but some of the cables had a little bit less friction with their receptacles, so exuberant movements would promptly unplug things. Also, the cables would occasionally break from the connector after a lot of movement.

The moral of the story here is that you'll need some pretty sturdy plugs if you want to use them with any sort of wearable. Qwiic cables, while useful and readily available, were not necessarily the right choice for this application. I was also having problems figuring out how to create multiple I2C ports to listen to all of my gesture sensing equipment. However, I solved most of these issues in the fourth iteration of the suit.

The Brain

To control the whole operation I made a custom board with an ESP32-WROOM. I started my design from SparkFun's ESP32 Thing Plus design. From here it was a matter of changing a few things to suit the board to my purposes. I substituted the CP2102 Serial Converter for a CH340G, as it's easier to hand place/rework. I also added breakouts for I2C and LED data lines in each corner of the board to control each limb of the suit. I tossed on a MEMS microphone for audio reaction. I also gave it two 18650 batteries in series and a 5V 3A LDO to give me voltage for my LEDs. I admit that this could've been done far better (at full charge, the LDO has to drop 3.4 volts, gross) but give me a break, I've got a strip of these LDOs and they're not gonna place themselves in designs.

In the future, my plan is to put the batteries in parallel with some sort of charger IC that I haven't had the time to source, as well as the beefiest Boost regulator I can find. Anyway, there's always room for improvement, but check out the board below.

Light Suit Brain Board File

The Brain for the Light Suit

This guy then sits in a small 3D-printed box that sits right where a belt buckle would go, I send my belt through part of the box to anchor it to my body.

Box for the Brain

3D Printed Brain Box

LEDs and Fiber Optic

Now that we have control figured out, we'll have to get some LEDs mated up to fiber optic. For this, we'll use an itty bitty custom PCB with two APA102 LEDs on each side.

LED Board

LED Board

This fits in between two identical 3D-printed parts, which align the PCB and LEDs with four strands of 5mm diameter fiber optic. Screwing these together clamps down on PCB, fiber and control/power lines all at once for a secure fit.

Fiber Grip

Fiber-LED Grip

This 3D part is then sewn onto some custom adjustable armbands (shout out to Mom for letting me use her sewing machine). We cut up a ton of fiber optic to the proper lengths and connected it all up.

Single Fiber Grip Module

Single Fiber Grip Module

Controls

I go through a detailed analysis of my gesture controls in this blog post about using multiple I2C ports on ESP32. However, I basically have two of the SparkFun Qwiic Flex Glove Controller sewn onto each hand. In each foot I have a custom board, based on the same ADS1015 Analog->I2C conversion chip as the gloves, that senses how my weight is balanced on each foot. I have two I2C buses broken out from my ESP32, one for the hand controls and another for the legs. As I was monkeying around last night, I realized that I'd bent a few of the sensors in travel (the demo always works, right?) and they don't really sense so well anymore. Due to this, all I really got to look good for video was the audio buffer portion. Check it out below and stay tuned for a final code update.

comments | comment feed

Enginursday: Multiple I2C Ports on ESP32

via SparkFun: Commerce Blog

For as long as I've been at SparkFun (longer actually, this project started back at school), I've been working on a fiber optic light suit. The idea originally came about because I was frustrated with the lack of controllability of EL wire. It's only monochrome and, as far as I can tell, most inverters don't have the required duty cycle for PWM. I wanted to have glowing wires all over me but didn't know where to look.

A friend who was also interested in the idea bought me a roll of some thin fiber optic from a supplier in Texas, and I was off to the races, hot gluing bundles of fiber optic and simple 5mm LEDs into Starbucks straws (my part-time college job) and putting them all over my arms.

Version 2 of the Light Suit at  Pretty Lights show in 2017

Version two of the Light Suit at a Pretty Lights show in 2017

I've come a very long way since then. Four versions later, I've moved from "dumb" LEDs in straws and bulky PWM controllers running on a relatively slow Arduino Pro Mega that I had left over from a digital electronics class, to shiny, custom PCBs with SMD APA102s, 3D-printed mounts, an ESP32 Thing Plus and even I2C based finger-bend sensors that eventually became a SparkFun product. In versions three and four, I made the move to add legs and a torso to this glowing suit, adding a whole host of new problems. After version three had issues staying plugged in, I took a step back and collected my thoughts before starting again.

I finally gathered the motivation and time to pick this project back up and figured I'd tackle my problems getting my six I2C gesture sensors to pull some readings, four of which are the ADS1015, ADC-to-I2C-based Qwiic Flex Glove Controller, and read how bent all of my fingers (excluding my thumbs) are. The other two sensors in the feet are also ADS1015-based boards that attach to force sensors; this enables me to see how my weight is balanced.

Weight Sensing Insole

Weight-sensing insole

The ADS1015 has a hardware configurable address; tie the ADR pin to GND, 3V3, SDA, or SCL to select one of four available addresses. If you're a math genius you'll realize we have more sensors than addresses. That's a problem our trusty ESP32 can solve. We'll simply need to create an I2C bus for each side - this way we can have each side be a mirror image of the other in code. To do this, we first need to include a few libraries and create our I2C buses.

#include <SparkFun_ADS1015_Arduino_Library.h>
#include <Wire.h>

TwoWire leftBus = TwoWire(0);
TwoWire rightBus = TwoWire(1);

We'll then say which addresses we want our sensors to be on as well as create the objects for our sensors themselves, since we have two buses, we'll only need to use 3 addresses.

/***Addresses for Different Parts of Limb***/
#define PINKY 0x48
#define INDEX 0x4A
#define FOOT 0x4B

/***ADS1015 Objects***/
ADS1015 leftPinky;
ADS1015 leftIndex;
ADS1015 leftFoot;
ADS1015 rightPinky;
ADS1015 rightIndex;
ADS1015 rightFoot;

In our setup loop, we initialize some Serial output to see what's going on, we then initialize our left and right buses on two different sets of pins. I also use 100 kHz as I've got some pretty long wires, which hinders I2C communication. We then add our gesture sensors to their respective buses using their respective addresses. No need for an I2C Mux today! Note that I also change the gain of my sensors; this is specific to my project and sensors, so you won't need to do this for your accelerometer or other I2C device.

void setup() {
  /***Debug Output***/
  Serial.begin(115200);
  Serial.println("Startup");

  /***Initialize I2C Devices***/
  leftBus.begin(23, 22, 100000);
  rightBus.begin(16, 17, 100000);
  leftPinky.begin(PINKY, leftBus);
  leftIndex.begin(INDEX, leftBus);
  leftFoot.begin(FOOT, leftBus);
  rightPinky.begin(PINKY, rightBus);
  rightIndex.begin(INDEX, rightBus);
  rightFoot.begin(FOOT, rightBus);

  /***Change Gain***/
  leftPinky.setGain(ADS1015_CONFIG_PGA_1);
  leftIndex.setGain(ADS1015_CONFIG_PGA_1);
  leftFoot.setGain(ADS1015_CONFIG_PGA_1);
  rightPinky.setGain(ADS1015_CONFIG_PGA_1);
  rightIndex.setGain(ADS1015_CONFIG_PGA_1);
  rightFoot.setGain(ADS1015_CONFIG_PGA_1);
}

My main loop() is as simple as printing the values out over Serial!

void loop() {
    for (int channel = 0; channel < 2; channel++)
    {
        Serial.print("LP");
        Serial.print(channel);
        Serial.print(": ");
        Serial.println(leftPinky.getSingleEnded(channel));
        Serial.print("LI");
        Serial.print(channel);
        Serial.print(": ");
        Serial.println(leftIndex.getSingleEnded(channel));
        Serial.print("RI");
        Serial.print(channel);
        Serial.print(": ");
        Serial.println(rightPinky.getSingleEnded(channel));
        Serial.print("RP");
        Serial.print(channel);
        Serial.print(": ");
        Serial.println(rightIndex.getSingleEnded(channel));
    }
    for (int channel = 0; channel < 4; channel ++)
    {
        Serial.print("LF");
        Serial.print(channel);
        Serial.print(": ");
        Serial.println(leftFoot.getSingleEnded(channel));
        Serial.print("RF");
        Serial.print(channel);
        Serial.print(": ");
        Serial.println(rightFoot.getSingleEnded(channel));
    }
    delay(50);
}

And here's the output below, notice how all of the feet values are resting close to 0, as the circuit the board they are on doesn't include the op-amp circuit.

Serial Output from 4 Limbs

Serial output from all four limbs

comments | comment feed

Enginursday: Internet of Terror

via SparkFun: Commerce Blog

In this Enginursday, I've repurposed a project I was using to light fireworks during the Fourth of July. Now I can't really tell you how I did that, but I had an airhorn lying around and figured I could hook that up and have a little fun. The concept is pretty simple: have an ESP32 host up a webpage, click a button on your phone on said webpage, and set off the airhorn! I'm pretty lazy and wanted to do things solderless, so I grabbed a Qwiic Relay and was off to the races. All I had to do was connect my airhorn-battery circuit up to the common and normally open connections on the relay, connect the relay to my ESP32 and add a LiPo to power my ESP32. The whole setup is one of the simplest things I've ever made, but oh boy is it super effective. Check the whole thing out below.

Beeper Setup

Beeper Setup

We just need to add some code for our web server to serve up our button. To do this, we configure our ESP32 as a soft access point, and have it serve up a button for our horn. We then attach our relay functions to our on and off URLs. Lines 69-78 are where our web interface is actually doing actions on the ESP32, so check in here if you want the ESP32 to do some other things on your button presses. Check out lines 17 and 18 to change your WiFi settings to something neat and super secret.

/******************************************************************************
  Horn.ino
  Example for controlling a relay using a webpage served by an ESP32
  by: Rui Santos
  Adapted for horn by: Andy England, SparkFun Electronics
******************************************************************************/

#include <WiFi.h>
#include <Wire.h>
#include "SparkFun_Qwiic_Relay.h"

#define RELAY_ADDR 0x18 // Alternate address 0x19

Qwiic_Relay relay(RELAY_ADDR);

// Replace with your network credentials
const char* ssid     = "HORN";
const char* password = "beepbeep1";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String hornState = "off";

void setup() {
  Wire.begin();
  Serial.begin(115200);
  relay.begin();

  relay.singleRelayVersion();

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.softAP(ssid, password);
  server.begin();
}

void loop() {
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the horn on and off
            if (header.indexOf("GET /horn/on") >= 0) {
              Serial.println("Horn on");
              hornState = "on";
              relay.turnRelayOn();
            } else if (header.indexOf("GET /horn/off") >= 0) {
              Serial.println("Horn off");
              hornState = "off";
              relay.turnRelayOff();
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>The Big Old Beeper</h1>");

            // Display current state, and ON/OFF buttons for our horn
            client.println("<p>Horn - State " + hornState + "</p>");
            // If the hornState is off, it displays the ON button
            if (hornState == "off") {
              client.println("<p><a href=\"/horn/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/horn/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Upload this to your ESP32 and you should see a WiFi hotspot with your chosen SSID pop up when looking for networks on a phone or other device. Go ahead and connect to it. If it's not popping up, open up a Serial connection at 115200 baud to try and see why your ESP32 is unhappy.

WiFi Hotspot

WiFi Hotspot

At this point your phone might tell you that there isn't an internet connection. This is fine, as we only need the ESP32 to serve up its own webpage. Once connected, open up a web browser and navigate to 192.168.4.1 (this is the default IP address, as occasionally the ESP32 has trouble hosting a DNS server). You should see a webpage like the one below.

Webpage

Horn Webpage

Now, hide the thing somewhere and scare some folks!

comments | comment feed

Enginursday: How to Develop a Package for Microsoft MakeCode

via SparkFun: Commerce Blog

Microsoft MakeCode is a quite powerful, block-based coding language useful for anybody trying to learn how to code. However, creating packages for this language is sometimes a little difficult. I've developed quite a few of these packages in the past and figured that the somewhat unclear process could use some documentation for posterity. The below tutorial will get you developing your own MakeCode packages in no time.

New!

How to Create a MakeCode Package for Micro:Bit

April 16, 2019

Learn how to develop code blocks for the Micro:bit in Microsoft MakeCode!

comments | comment feed

Enginursday: Spotify Album Artwork Display

via SparkFun: Commerce Blog

Over the past few weeks, I’ve been working on a few square LED matrices and thus have had glowy square projects on the brain. I had the idea to try and snag my current album artwork off Spotify and display it on some of the matrices. I never had enough prototype matrices to make a nice high resolution display, so I moved to a big old 64x64 matrix. This worked, but there were a few kinks and I got busy again, so I let the project go a little.

My coworker Wes wasn’t satisfied and wanted to see the project finished so he worked out some of the bugs (mainly pinning the task that grabs the JPEG to a separate core to prevent it from interrupting the display). I figured hey, if Wes is so excited, maybe you would be too! Check out the below project tutorial to get started sending the album artwork from what is currently playing to a display.

Live Spotify Album Art Display

Spotify Art Display

comments | comment feed