Author Archives: Pete Lewis

Enginursday: Aerofest 2019

via SparkFun: Commerce Blog

On June 1st, the Longmont Innovation Center (IC) hosted their first Aerofest event. The day was filled with airshows, battles, races, vendor tents and food trucks. Many R/C pilots are makers at heart, and it felt much like SparkFun’s AVC. Best of all, it was great to see lots of youngsters getting interested in aeronautics. My four-year-old son and I had a blast watching the airplanes, and he even had a chance to build his own laser-cut glider.

Aerofest banner add showing a bunch of pilots launching their DIY aircrafts at the runway together

The IC has a focus on STEM education though many awesome programs including robotics, aeronautics, computer science and much more. Check out their website to learn more. Some of SparkFun's employees have participated in their mentoring opportunities, and it's a wonderful way to share experiences and help some young engineers with their projects, including atmospheric research, shark wands and Aquatic Robotics.

Aerofest was hosted by the IC's aeronautics program. Check out their YouTube channel to see some of their DIY aircraft in flight. They have many opportunities for high school students to learn to design, build and fly their own aircraft. Through a variety of courses, they learn about the iterative design process and many aeronautic engineering principles.

two high school students are pluggin in wires and attaching a wing to a scratch build DIY design of their own during the event.

Two high school students building an airplane of their own design from scratch design during the event.

The two students above are mounting the wing to fuselage of an aircraft they designed and built themselves. It was, by far, the largest aircraft at the event. They designed it this way not only to test their engineering skills for larger airframes and motor systems, but to also compete in a battle event. Most of the airframe was cut from foam board using the IC's in-house laser cutter, and pieced together with a healthy amount of hot glue. It was quite ambitious to build an aircraft from scratch the morning of the event, but they pulled it off!

a few airplanes lined up on the taxiway for the audience to look at

Lots of planes on display to get a closer look.

In addition to the many DIY laser cut airframes flying at the event, there were also plenty of traditional remote control airplanes out on display - most of these also flew at some point during the day. There were a couple scheduled aerobatic airshows and flying challenges, but at any given moment, you could look up and see someone flying around with the occasional loop or roll.

Some pilots getting ready to fly the DIY dragon plane

Preflight check for a DIY Dragon airplane.

Some teams of students had fun with the look of their DIY airplanes. This dragon sure looked awesome!

picture of an airplane that looks like a black dragon and the tail is broken only held on by a control string

The cracked tail on display for the afternoon

Unfortunately they had a bit of trouble on takeoff and after a couple moments of flight it came down hard on the runway. This broke the tail off, and they decided to fix it another day. All part of the design process!

close up shot of the tables where the glider kits were geting built up some kids hands and grown up hand helping with hot glue

Glider kits getting built up

The STEM zone was a great opportunity for anyone to build a glider and to have some fun with flight. The tables were crowded and glue guns were hot. Kids were popping all the parts out of the foamboard and building them up as fast as possible.

a child holding up his complete glider with a big smile on his face

Ready to launch!

The glider kit was very well thought out, and was actually designed by one of their students. One of the nicest features: there was no necessary order of assembly. You simply popped out the parts and then started putting them together with hot glue. Everything lined up nicely and made sense. Well done!

hand launch glider flying up in the perfect blue sky

Negative Ghostrider, the pattern is full.

Word quickly spread that the tail pieces could be bent to affect the flight path and in no time, gliders were turning, rolling and flipping.

Two pilots stand holding the jet in place one pilot holds the transmitter getting ready to rev up the jet engine

The jet engine demonstration

Next up was a jet engine demonstration. As you can see in the pic above, the pit crew had their ears covered – that thing was loud. The plane can fly over 150 mph and requires a bit more airspace and runway, so this demo would only include a rev up of the engine to full throttle. They turned the smoke on too, which was pretty fun to see, although there was a small, accidental fire near the tail from an error in the smoke timing. The jet pilots made it seem as though this sort of thing happens sometimes, and I'm glad they had a working kill-switch and fire extinguisher nearby.

tail end of jet model with black burn marks

The tail fins got a little extra crispy from a small fire during this demo.

alt text

Preflight check before the aerobatic show

The fixed-wing aerobatic show was another highlight of the day. This plane was mostly made of lightweight balsa wood, with a thick wing for plenty of lift and a tall, thin fuselage for good knife edge performance. When he fired up the motor, I recognized the low pitched rumble and knew it was a four-stroke. I especially enjoyed the smell of the nitro airplane fuel exhaust. He revved up the motor to full throttle and leaned out the mixture - yet another ritual I used to love (in my gas-powered days).

Balsa lightwweight powered aerobatic show plane in straight vertical climb above perfectly blue sky

Then he nodded to the MC, Jake Marshall, and they turned on the music. Of course, it had to be the Top Gun classic, “Highway to the Danger Zone”. It took off in about two feet of runway, and he went into a spinning vertical climb. He did all the classic maneuvers too: rolls, loops, flat spins, hammerheads, snaps, knife edges and even some pretty low hovering. He ended with another classic move: a dead stick landing.

hand launching the biggest plane of the day

Launching "The big one" for its first ever flight: a battle!

After lunch, we watched the fixed-wing “battle.” It started with hand launching the big DIY plane (designed and built by the IC aeronautics team). The idea behind this competition was simply to have everybody launch their airplanes and then try to crash them into each other. The last plane flying wins. Let the mayhem begin!

smaller plane chasing down the big one

The mighty mini coming in for a hit!

An ideal “hit” is when one pilot will surprise another from above and quickly come down to hit the lower plane with its propeller. Usually, this cuts a piece of the airframe away, and it will come crashing down out of control. After a few minutes of the battle, it became quite apparent just how difficult it was to have an intentional hit.

Then the game became “try to take the big one down.” About halfway through the battle I saw one younger pilot launch his smallish World War II-era bomber. I don’t think he actually had a successful hit, but it was such fun seeing him try – fearless and not worried about damaging his plane. After all, there's always more foam to cut and plenty of hot glue!

The big DIY airplane coming in on final approach looking good

The big one on final approach looking good.

Then the time was up, and a handful of planes were down in the fields. It was time to land the big one. The young pilot flew a nice pattern and then gently touched down.

The big one after touchdown shoing a close up of the landing gear ripped off

Landing gear never likes to stay on airplanes!

Unfortunately, the landing gear still ripped right off. I don’t think any pilot could have avoided that. The attachment method (hot glue, I presume) was just not quite strong enough. Back to the drawing board, but that’s what it’s all about!

Jake Marshall hand launches a DIY foam board plane its just about to break free from his hand

Jake Marshall, head of the aeronautics team, launches one of his favorite DIY airplanes.

The event was well attended, and much fun was had by all. The Longmont Innovation Center is planning on hosting the event again next year, so follow them on Twitter, YouTube, or their website to stay informed. Also, they do offer tours and have a retail store with glider kits available, so don't hesitate to reach out and arrange a visit. Next year, I am for sure bringing a couple airplanes to fly. Hope to see you all there!

comments | comment feed

Enginursday: The Qwiic Jukebox

via SparkFun: Commerce Blog

Over the past couple months, I have been working with my three-year-old son to create his own jukebox.

alt text

He wanted it to play some recordings we made of us reading books together.

alt text

It uses RFID tags as the selection process, and is totally Qwiic-based.

alt text

We have worked out most of the bugs. It is truly amazing how good a three-year-old is at beta testing. We ended up making a detailed hookup guide and video, so if you'd like to make one yourself, please check those out and share in the comments. Enjoy!

comments | comment feed

Thirty Years of Test Controller Design Progression

via SparkFun: Commerce Blog

Pete Lewis here! This blog was written by a guest author, Kelly Small. We really appreciate his contributions to our community, and are very excited to help spread his extensive knowledge here on our homepage. The conversation about testbed design has been a great one, and if you'd like to read more about SparkFun's own testbed design history, please check out our previous posts here:

And now, onto the amazing story that covers more than thirty years of testbed progression in Kelly's career. Enjoy!


Working as a test engineer for many decades, I have seen remarkable changes and advancements in the field of electronics. My job is to develop test systems that our factories use to verify our products are built correctly and function as expected. These products include everything from a simple cable to a complex module composed of multiple PCB’s with as many as 16 layers. The circuitry can consist of multiple processors, FPGAs and complex analog systems.

Test Architecture

To test our products, which we refer to as UUT’s (Unit Under Test), our test flow consists of several steps. The first test step is in-circuit testing (ICT), where all the UUT’s are tested with a fixture that presses pogo pins into test points on the board, and makes test measurements of all the components on the board. This type of testing can weed out a lot of possible problems with the UUT, such as solder bridges and open runs, as well as wrong parts, missing parts or bad parts.

The next step is programming stations that program unique information into each UUT, such as serial numbers and MAC addresses. Next are the functional testers, which vary somewhat with the product, from a simple bench test to environmental tests, which use a chamber to rapidly heat and chill the UUTs while electrically testing its functions.

While the ICT testers are commercial systems that are purchased and installed at the factories, most of our other test systems are designed, programmed and built within our test engineering group. The heart of these various testers is what we refer to as a test controller. The test controller is a standalone embedded platform that controls power, input stimulus, output measurements and communication with the UUTs being tested.

The Test Controller

Around 1985, we developed the first test controller to support functional testing of a new product line, which included I/O modules of various types. These included Digital Inputs, Digital Outputs, Analog In, Analog Out and others. Modern test systems would most likely be comprised of a PC with a host of data collection modules, but in 1985 very few PCs existed. Those that were in use were 8-bit XT systems with very little in the way of hardware and software for test purposes. We selected the Intel 8051 microcontroller for the brains of our test controller, which has very few peripherals on board. The rest of the kernel consisted of a 32KB SRAM and a 32KB EEPROM. This EEPROM is where the code was stored, typically a 27C256. This chip was programmed one time and then you had to use a UV eraser to erase the chip before you could program it again. This erase process took 20-30 minutes, so you wanted a tube of chips on hand to make constant code changes during a debug session. The rest of the electronics were a group of I/Os used for connection to the UUTs being tested.

  • 21 digital outputs
  • 8 digital inputs
  • 16 analog inputs with 12-bit resolution
  • 8 analog outputs
  • On-board power sources +5, +15, -15, +24
  • 24-volt power supply, adjustable from 10-24 volts
  • 2-channel RS-485 ports running 375KBaud
  • 1 RS-232 port that communicates with a PC

This group of I/Os is referred to as the common electronics; the intent was to use it as a starting point for each test design and add additional circuitry (point logic) as needed.

The test controller is connected to a PC via the serial port, but while the test controller runs the test sequences, the PC is only used to monitor test operation and report test results to the human operators. As mentioned earlier, PCs were uncommon and very expensive, so one PC was connected to 10 test controllers, and each test controller was capable of testing eight UUTs. This allowed one PC to monitor testing of up to 80 UUTs at the same time.

The test controller was built on a 9”x11” PCB, with a pair of 96-pin DIN connectors at one end.

alt text

From 1986, the first test controller (top side view)

This first test controller, shown above, had an 8051 kernel and no programmable logic!

alt text

From 1986, the first test controller (bottom side view)

As you can see in the picture above, all of the connections were made with 100 percent wire-wrap.

Around 1987, we created a new PCB that had all the common electronics in a copper artwork section, while the rest of the board was laid out to support wire-wrapping of .3” DIP sockets for the point logic. This reduced the amount of wire-wrapping by a considerable amount.

alt text

From 1988, the test controller with "copper artwork section" (top side view)

alt text

From 1988, the test controller with "copper artwork section" (bottom side view)

This 1988 design served us well, and we still have fixtures today using these test controllers. One of the benefits of this setup is that we’re immune to all the changes in PCs over the years, including the introduction of Windows. We continued to use our DOS software until around 2012, when a Windows version was finally introduced.

In 1996, a new product was introduced, so we took the opportunity to make a new test controller design. We switched to an 80C251 processor (16-bit), and other features included an analog section that was self-calibrating, and the introduction of a pair of CPLDs. These CPLDs were used for some of the common logic, but were mainly intended for use in building the point logic with software, rather than a mass of wire-wrapping.

alt text

From 1996, the test controller with CPLDs to further reduce wire wrapping (top side view)

Technology marched on, and in 2004 we were once again looking at a new product to test, and so went after a new test controller as well. The 82C251 never caught on, and there were better 8051 variants available. We went with a P89C51RD2, which had SRAM, FLASH and EEPROM on board. Running at 24MHZ and six clock cycle instructions instead of the original 12, we also saw some decent speed improvements. The RS-485 links were bumped to 750K to support faster speeds that the newer product was using. It was getting difficult to find through-hole logic, so some of the common area were now surface mount. We continued to use socketed parts for the buffered signals going to and from the product being tested, which allowed for easy repair at the factory. If damage occurred to the SMT common electronics, field repair was difficult to do, and the test controller was typically sent back to our facility for repair.

alt text

From 2004, the test controller with many advancement including more SMD parts (top side view)

alt text

From 2004 the test controller with even fewer wire wrap connections (bottom side view)

In 2012 I started using PCB-based daughter boards for the point logic. This reduced the wire-wrapping to very little, if any.

alt text

From 2012, the test controller with daughter boards (top side view)

My most recent design was driven by parts obsolescence. The 8051 variants were disappearing, as well as supported development tools. The CPLDs were end of life (EOL), so it was time for a new design. I selected the Atmel ATMega1281 and the Xilinx XC95144XL, one of the few remaining CPLDs that was 5-volt tolerant. Except for buffered outputs, all of the common electronics are surface mount. A second processor (ATTiny1634) is used for communication, either the 375/750K RS-485 or other protocols. The layout is designed to support daughter board add-ons, but you can still use the wire-wrap area, with selectable 3.3V or 5V power.

alt text

From 2016, the test controller with nearly 100 percent SMD parts and no wire wrap connections (top side view)

The Future

What do I see for the future? Our electronics world is governed by supply and demand – these days that means smartphones. Most of our IC vendors are dropping 5-volt and 3.3-volt parts in favor of 1.8 or lower voltages. Large capacitors and other parts are becoming less common as well. Our next generation test controller will probably move to an ARM-based processor, and the CPLDs will be replaced with FPGAs.


Kelly Small is a principle test engineer with a Honeywell division in Phoenix, AZ. He’s been employed there for over 40 years, with 38 years in test engineering. Kelly has also been a participant in SparkFun's Autonomous Vehicle Competition, and his high-tech treasure chest was featured on our blog.

We greatly value not only Kelly's participation in our events, but also his involvement in the open source community. Please feel free to ask any questions below in the comments section, and thanks for reading!

comments | comment feed

Enginursday: Innovative Testbed Design (Part 2 of 2)

via SparkFun: Commerce Blog

This is part two of our series about the history of quality control and testbed design at SparkFun (click here to read part one). There was actually much discussion in the comments about hardware design - thank you so much to all that chimed in! You had very valuable feedback, and I look forward to hearing more after we dive a little deeper into the hardware on this design.

You are welcome to download the Eagle design files from the project GitHub repository here:

Flying Jalapeno GitHub Repository

For more info on getting started with Eagle, please check out this tutorial: How to Install and Setup Eagle.

For anyone that might prefer to follow along with a PDF, you may also click on the following image:

alt text

Flying Jalapeno Schematic (PDF LINK)

Power control switching

One of the earliest advancements in testbed design was the ability to control when power is applied to the product. Before this feature, we usually left the pogopin to the product’s VCC “HOT” - meaning that it was permanently wired to a power source. This should work fine, in theory, for most of the time, but what we found was that if you didn’t place the product down perfectly, sometimes you would momentarily short VCC to GND. Note, this would only happen on products where the two header pins VCC and GND were located next to each other, but that was actually pretty common. So during this burst of current on VCC, our testbed power supplied didn’t really like this, and they would drop voltage causing the entire testbed to reset. Ugh!

Some of the first testbeds to incorporate power control actually just routed an IO pin directly from the testbed ATMega328 to the VCC on the product. In this case, we could supply power to the product, but were limited to the 40mA (or so) that the IO could provide. Definitely not the best solution, and we saw a few testbeds die, and so the progress continued.

Power switch schematic close up Power Switch highlight on board

The next approach was to try a high-side switch using a mosfet. Looking back, we could have just as easily done it with a relay, but didn’t have an ideal relay in our inventory. Now that we have some nice mini relays like the SparkX Qwiic Relay, that may be the preferred way. But at the time (2009-ish), we only had the Beefcake Relay Control Kit, which seemed like overkill for 99 percent of our products. You’ll notice we also added a transistor on the front end to ensure the mosfet opens fully and takes the load off of the IO pin on the micro, and it’s really quite nice that writing the control pin HIGH actually engages power. We are always trying to think about usability, even with in-house tools.

Testing for shorts to ground

Using a simple voltage divider style circuit, a digital control pin and an analog read pin, we can safely and easily test a product’s power line (aka VCC) for a short to GND. It is particularly nice to know this before powering up a product - especially when it is a high-current product. We actually test for shorts to GND on all products now, regardless of power consumption. Odds are the testbed and product would survive a few hundred surges, but after a few too many, you are on the quick path to destruction. When designing for production, we need to think about testbeds living on (and working well) for many years to come.

I should also note that we commonly refer to this test for shorts to GND as the “pre-test.” This is because the “main” test is usually referred to as just the “test.”

The pre-test circuit is actually a pretty good exercise in learning about voltage dividers. If you’d like to learn more check out this tutorial here.

Pre-test for shorts to ground schematic close up Pre-test highlight on board

We use the circuit shown above to see whether or not there is a GND connection (or something that pulls as much current as GND would) on the product’s VCC. When there is a short, then the two 10K resistors basically split the VCC and the ADC reads the magic dreaded “486.” When there is no short, it will essentially form another voltage divider between a 100K and a 10K, and the ADC reading will be much higher. For a more info on this circuit, please check out a previous blog about quality control here.

Capacitive Touch “Buttons”

We moved away from mechanical momentary switches to engage testing years ago. A capsense pad (most importantly, non-mechanical) is much more reliable over thousands and thousands of “presses.”

Capacitive Sense schematic close up Capacitive Sense Resistors highlight on board

We use the Arduino capacitive touch library and two IO pins with a large resistor. Because we often need two buttons on a test fixture, we opted to dedicate four IO pins and include the resistors into the Flying Jalapeno design. With this setup, we simply need to route a trace to a pad on the daughter testbed. Note: we do usually take extra care on these traces and route them with 20-millimeter width. By avoiding vias and other data lines, we have seen great results with this form of capsense. Mad-house-routed thin traces or bad ground pour flow can make for some really wonky readings.

Dedicated LED IO with Built-in Resistors

We pretty much always need four LEDs on the testbeds these days – PASS/FAIL for the pre-test for shorts to GND, and PASS/FAIL for the main test. Because we have plenty of extra IOs on the ATMega2560, we decided to include the current limiting resistors on the FJ. These pins are now fairly committed for LED use, but we’ve got plenty of IOs to spare. This way, the daughter boards simply need a trace to an LED on each of these lines. The less complex the daughter boards can be, the better!

I2C Isolation “Switch”

A lot of early testbeds that involved I2C were troublesome for us. It was pretty common for I2C testbeds to “lock up” during testing. This was usually due to the testbed trying to talk to a product that was broken, had cold solder joints or had jumpers on SDA or SCL. I seem to remember a glorious day when wire.end() actually started working… Until then, we used to (and still do) disconnect the lines with a mux built into the test fixture.

I2C "isolation" switch schematic close up I2C "isolation" switch highlight on board

Again, at the time, we didn’t really have an ideal switch, and the Beefcake seemed like overkill for data lines, so we opted to use the PCA3906 I2C converter IC we had on hand. It had an enable pin that proved to be useful in disconnecting. We found that if we disconnected the I2C lines with something like this (in between testing boards), then it was much less likely to lock up. And best of all, the techs were much less likely to wear out the old fashioned momentary reset button the test fixture.

ATMega2560

ATMega2560 schematic close up ATMega2560 highlight on board

We simply went with this because it was very similar to our RedBoard, but with many more IOs. Sometimes a testbed will require a few more IO than the ATMega328 has to offer, so we found ourselves either using a mux or shift registers – better safe than sorry when it comes to having enough IOs. Also, having an Arduino-compatible testbed brain meant that we could more often than not utilize some of the product example codes for the test fixture.

The test developer also serves as a good beta tester for the products they work on. Usually the engineer on the product design has some sort of working code ready before we launch (which is super handy for test development). But sometimes even more importantly, getting it to work on the test fixture can help discover some bugs or documentation confusion before we officially go live with it on SparkFun.com.

Logic Level Select Jumper

Taking a tip from our breadboard power supply, we opted to add in a logic level select jumper.

Logic Level Select schematic close up Logic Level Select highlight on board

There was some discussion as to whether we wanted a slide switch or jumper. We ultimately wanted to keep it a jumper, so that it couldn’t be accidentally switched during handling and cause issues for testing. Plus, there is always gonna be some soldering assembly work for the daughter boards, so what’s the trouble in setting a quick jumper as well? Also, you may note that we are doing a “no-no” here by running the ATMega2560 at 3.3V - it is slightly out of spec for a 16MHz crystal, but we have seen minimal issues (if any at all) caused by this, so we’re gonna keep running with it.

Software-Definable VReg Control on Two Power Sources

Taking the selectable VReg idea one step further, we decided to make the two power sources have adjustable outputs that were software defined. By connecting various resistors to IO on the micro, we can choose which resistor we’d like to “send to GND” by writing that corresponding IO LOW. This effectively sets the output of our VRegs.

Software Definable Voltage schematic close up Software Definable Voltage highlight on board

You’ll notice that V1 can do 3.3V or 5V, and V2 can do 3.3, 3.7, 4.2 or 5V. This is nice when emulating a charged or empty single cell LiPo battery. By bouncing V2 between 3.7 and 4.2, we can get charge circuits to engage or disengage. This has proven very handy when it comes to getting a charge LED to blink.

2x30 RA Header

There was much discussion about what type of connector would do the job. It was tough to find the balance between strength, current capabilities, size and design-ability. We opted to go with a PCB-to-PCB right-angled style connector, and the 2mm pitched RA 2x30 header we found had a 2A rating, so it fit the bill. We also opted to have some connections with redundant pins (GND, V1, V2). Not only was this a good thing for reliability, it gave us way more current capability than we’d ever need (famous last words). More connection means less resistance too, so I was glad to know we’d see very minimal voltage drop from source to pogopin.

Mounting Brackets

With our choice of connector, this required a little creativity on how to mechanically connect the FJ to the daughter boards. We did not want to rely solely on the headers themselves, and so came up with some mounting brackets on either side.

alt text

They go on either side of the connector, on the top and the bottom, and are held into place with a 4-40 screw with a nylon thread locking nut. The spacing of the drill bits also ensures that the FJ and the daughter board will be assembled at the exact spacing for every future testbed. This is nice, because we want to make sure that the 2x30 is inserted fully. Yet another benefit that I didn’t anticipate (and was pleasantly surprised while building up the first prototype), is that these brackets worked as a nice “jig” to hold them together while soldering in the 2x30 male connector on the daughter board.

Custom Eagle Part

Eagle Symbol Eagle Package

To make daughter board design faster, we opted to create a custom part in Eagle. This way, we could quickly drop in an FJ into any daughter board design, and have all of the connections easily accessible. Note: we created the female and male versions of the connector in the same device. This makes it easier when referencing the FJ design during any troubleshooting. Also, we opted to include quite a bit of “used pins” in the symbol, which help highlight what they are doing upstream and can help with developing code for this hardware. Although, using the code library in conjunction with this hardware makes life even easier.

Logic Level Conversion for Serial Debug

Serial Logic Level Conversion schematic close up Serial Logic Level Conversion highlight on board

Do you suffer from serial bridge logic level conversion problems? We do too. Around production and at most engineers' desks here at SparkFun, it is always impossible to find the right logic level version of the serial bridge. Also, it is probably one of the most common mistakes made around here - “whoops, I plugged in a 3.3V logic thing into a 5V thing,” or vice versa. Well, with the FJ, we had a chance to avoid this problem, so we did. A tech can plug in any variety of serial bridge tools into the FJ, and it has the logic level conversion to handle it. Whew!

A Future Hardware Revision

As with all projects, this will never truly be done. The Flying Jalapeno has some quirks that could be improved (thank you for all your feedback on our previous post). But after two rounds of prototypes, we are fortunate that nothing supercritical is a road blocker right now, and for the most part the Flying Jalapeno is doing its job quite well. Nevertheless, here are some of the things we are considering on the next revision:

  • Upgrade mux switch for I2C isolation. The original IC choice for the I2C isolation was not really the best IC for the job. When we need to switch a connection on most newer testbed designs, we opt to use the 74LVC4066 MUX 1:1 (x4). This has worked great for switching all of our RX/TX, USB D+/D-, and programming lines. We also used this on a recent programming tool for production: the Pi AVR Programmer HAT (https://www.sparkfun.com/products/14747), and it has been holding up well for all our 2MHz + programming speeds.

  • Additional GND connections on the right side of the header package. Sometimes it can be a challenge to get a good ground flow all the way around the daughter board, so if I were to do this again, I’d sacrifice a couple IOs to be GND connection points on the right side of the connecter.

  • Additional dedicated LED IO with resistors built in. We are finding that with most daughter boards, we usually need one or two more LEDs. In addition to the standard pass or fail LEDs, it’s nice to indicate the tech other statuses or instruct them that it is time to do a certain action. You can’t have too many LEDs!

  • A strange issue with power control. Maybe someone reading can help us with this, but strangely enough, the power control circuits seem to be interacting. When V1 is powered up, and V2 is powered down, there still is some voltage present on V2. We even tried removing the source of power on V2, and it shows the same condition. I’m guessing it has something to do with the two long traces perfectly parallel to each other. Most of the time, this is not a problem (because we have them both powered up during testing), so we’ve been able to get by with the current version of the hardware. But it sure would be great to get to the root of what’s causing this, so any thoughts would be very welcome. Thanks!

comments | comment feed

Enginursday: Innovative Testbed Design (Part 1 of 2)

via SparkFun: Commerce Blog

It’s fun to be on the quality control side of things. Not only do we get to play with all the new widgets ahead of release, we are constantly faced with new challenges and pushed to innovate testbed design. Sometimes new products require new features on a testbed, and that pushes us to innovate. Sometimes we discover a reliability issue in production, and that pushes us to revise hardware to make something more robust. We’ve progressed a lot over the years. Let’s look back and highlight some of the innovations that allow us to design, build and code new testbeds really quickly.

Back in the day

We used to have some fairly finicky test fixtures back in the day. As a production tech in 2007, I remember very careful handling the fixtures to make sure I didn’t break any of the many, many green wires (and I was lucky if it worked 50 percent of the time).

A very old testbed from 2008 showing a product being tested using male headers held at an angle as a connection

Test fixture from 2008 using bare male headers to connect to the product…eeek!

As you can see above, this early testbed uses male headers facing up to make a temporary connection to the product. The technician would have to slide the headers into the products PTH headers on the side of the product, and then apply pressure to either side to attempt to make a connection during testing. It took a very steady hand to get this sucker to work every time. If you’d like to check out more info about our older test fixtures and general quality control progress, check out these tutorials:

Custom layouts

Testbed design with all of the components designed into one single PCB layout

Testbed made with custom PCB layout using mostly SMD commponents

In 2009 (ish), we started laying out custom PCBs for every new testbed. This was nice because it kept the designs small and self contained. Another advancement here was using pogopins to make a nice temporary connection to the product. This style of testbed design actually proved to be the “norm” for quite a while. At the time, and still to this day, we build all of our test fixtures by hand with an iron (even all the SMD parts). We just couldn’t justify ordering a stencil when we could get by with an iron and a steady hand. Even if it did have some more difficult parts that require hot air to place, we wanted to keep our rework chops up to snuff!

Modular Designs

Testbed with pro mini as controller and more modular design approach

Testbed designed around an Arduino Pro Mini and a custom base layer PCB

Here we have a stepper motor driver testbed. This is a good example of how we were able to use an Arduino Pro Mini as the main “brain” of the testbed, and then add the additional components needed to a custom PCB layout. This approach to testbed design became known as the “modular” approach, and cut down on the SMD work needed to assemble a testbed. It was also nice to know that production had tested the Pro Mini on your testbed, cutting down on any troubleshooting when you first power up.

Very large testbed using a arduino mega pro as the brain

Testbed using a Arduino Mega Pro and a custom base layer PCB

Here is a second example of a “modular” designed testbed, except this time we needed more GPIOs. This required using a Arduino Mega Pro instead of the Pro Mini. This again helps cut down on assembly time, although soldering up all of the PTH headers on the Mega Pro Board, and its mating female headers on the testbed, still does take some time. You may notice that this has quite a mix of color in the PCBs. I seem to remember having to rush order this from OSH Park in order to keep up with the Free SoC2 product launch schedule. Thanks OSH Park!!

Stand-alone programming

It had always been a dream of ours to move testing and programming away from using the production techs' Windows computers. This is because each time Windows would auto-update, we would be bombarded with driver issues. We ended up going with a Raspberry Pi-based solution and designing our own custom HAT, the SparkFun Pi AVR Programmer HAT. Read all about it in the following tutorial:

Pi AVR Programmer HAT Hookup Guide

July 26, 2018

In this tutorial, we will use a Raspberry Pi 3 and the Pi AVR Programmer HAT to program an ATMega328P target. We are going to first program the Arduino bootloader over SPI, and then upload an Arduino sketch over a USB serial COM port.

Custom Generic Hardware

As we designed more and more testbeds, we found that they needed similar things. This is why it made sense to make a single design that included most of the features we needed, and then make custom “daughter” boards that are specific to each product.

Custom designed production testing tool also showing bare headers and mounting brackets

The Flying Jalapeno testing tool in all its glory!

Above, is our in-house designed Flying Jalapeno. We use this on most new test fixtures, and it dramatically decreases testbed design and assembly time. Stay tuned for a more in-depth look at the hardware design of this tool, and the accompanying Arduino code library.

Testbed based off of the flying jalapeno the bottom portion daughter board is quite small

Testbed for an IR Array sensor using the Flying Jalapeno

As you can see above, this testbed is made up of two parts. The top section (the red PCB) is the Flying Jalapeno, and the bottom section (the green PCB) is the custom daughter board for the product. This particular testbed is designed to test the SparkFun IR Array Breakout. Because we receive the Flying Jalapeno assembled (and tested) from production, the assembly time for this test fixture is reduced to simply building up the smaller bottom section. That’s just a 2x30 header, five LEDs and four pogopins. Piece of cake!

Laser-cut Acrylic parts

Lumenati Testbed based off of the flying jalapeno design with lots of lazer cut acrylic

Testbed using the Flying Jalapeno and lazer-cut acrylic parts

Here is a fairly recent testbed design for testing the Lumenati 3x3. Occasionally, we will cut certain layers on our laser cutter using clear acrylic. Not only does this look slick, but it saves us money, because previously we would have been ordering those layers from a PCB fab house and that can get pretty costly for large testbeds. Also, this allows us to fine tune the laser-cut layers in house. We can tweak the design as necessary and have a new part cut in just minutes!

A few more beauties

example testbed using flying jalapeno and acrylic waffle top design

GatorBit testbed

testbed for openlog with unique waffle top that includes precise pusher higher to mate with product and light sensor

OpenLog testbed with unique “waffle top”

very large testbed with mostly acrylic and smallish amount of PCB layout for redboard edge product

RedBoard Edge testbed

Stay tuned for Part 2

Join us next week as we give a more in-depth look at all of the hardware choices inside the Flying Jalapeno, and dive into the accompanying Arduino code library. For a sneak peak, take a close look at the following picture, and see if you can spot any design flaws. There are actually a few things that we plan to change on a future revision to this design, but I challenge you to find as many as you can. The first commenter to spot the flaw I am thinking of will get extreme street cred and I will personally mail you a Flying Jalapeno!

top down image of the flying jalapeno design with no daughter board attached

Detailed pic of the Flying Jalapeno

Also, if you have any testbed design stories to share (I’m looking at you, #773), or any questions about SparkFun testbeds, please feel free to post a comment below. Thanks for reading and we’ll see ya next week!

comments | comment feed

Enginursday: Creating Random Sequences with Rules

via SparkFun: Commerce Blog

When you put a bunch of electronics around trampolines in a room, and ask thousands of kids to jump on them, it’s only a matter of time before something fails. About three weeks after Boulder Bounces opened, we got an email telling us that it was failing on occasion.

alt text

Background of the project

We recently designed and installed an exhibit at the Museum of Boulder called Boulder Bounces. It’s a memory game much like the Simon Says Soldering Kit, but with trampolines. You can read more about it at this blog post, or watch the following video:

The original Simon Says uses the built-in random() Arduino function. While this works fine for the original game, Boulder Bounces needed some extra rules in the sequence generation to avoid “boring” bounce patterns. It’s not that fun to have many repetitions of the same trampoline, and any repetitions in the beginning of the sequence are not only difficult, but can lead to some serious confusion for the first-time player. Plus, when you’re playing with a group of jumpers (each standing on their own trampoline), it is loads more fun to ensure everyone gets to jump.

Let the investigation begin!

I have a lot of serial debug messages sending out from my Arduino Pro Mini on this project, so I was eager to plug in a FTDI basic and hear what was going on. My original email from the museum said that if they simply cycled power, it would start working again. Because of this, my first thought was that it was most likely failing in software, and not a hardware issue.

When I opened up the panel on the wall, it looked like the LEDs had been mistaken for buttons and pushed completely back into the panel. Those darn kids! I guess I can’t blame them; the gumdrop LEDs are big enough to be a button, but I needed to stay focused on the problem at hand.

Jumping right in

I played through an entire game once. It worked just fine. I played another round. No issue. Again, and again. Nothing. Then on the sixth game, right before I should have heard the winning sounds, it seemed to stall out.

I went to look at my serial debug, but it seemed to stop spitting out any serial debug at all. Hmmmm. When I am troubleshooting a code bug that involves a “stall out” like this, my first approach is to verify the point of failure and then work backward to find out the potential issue.

During my last game (right before the failure), I remember my serial debug was working properly. It was outputting each new sequence after each successful play correctly. But at my “win,” the serial debug stopped, so the failure must be occurring somewhere immediately after the last add_to_moves() was called.

A high-level look at the original code

Before we jump into any of the original code, I think it would be beneficial to share the high-level plan for gameplay, and my higher-level approach to creating the random sequence with rules.

The original gameplay code worked like this:

When you are playing a game, the Arduino will “play” back the sequence to you. At first, it only shows one trampoline light up, and you jump on it. Then the Arduino “randomly” chooses the next trampoline to add to the sequence. It plays back the entire sequence (which at this point is only two jumps long), and you must jump the sequence in order. Then it adds another, and so on. Once the sequence reaches eight and you successfully jump in the correct order, you win!

The specific part of the code that I’m talking about today is a function called “add_to_moves()”. This is a simple enough function in theory. Let’s take a look at the original function from the original Simon Says to start. Note, this code is from the button game, and was not used on the trampolines installation, but it’s a good place to start.

void add_to_moves(void)
{
  byte newButton = random(0, 4); //min (included), max (exluded)

  // We have to convert this number, 0 to 3, to CHOICEs
  if(newButton == 0) newButton = CHOICE_RED;
  else if(newButton == 1) newButton = CHOICE_GREEN;
  else if(newButton == 2) newButton = CHOICE_BLUE;
  else if(newButton == 3) newButton = CHOICE_YELLOW;

  gameBoard[gameRound++] = newButton; // Add this new button to the game array
}

First, you notice that the “random(0,4);” is generating the next “newButton” in the sequence. The following five lines of code are not really important in this discussion, but to quickly explain, we need to change them to the defined variables associated with each button choice available. For today, let’s just focus on the creation of newButton and then how it is added to the array, gameBoard[].

Looking at the original function add_to_moves(), it simply uses random() to add a new button to the sequence. This worked fine for the original Simon Says, but for Boulder Bounces, we needed to add in some rules to make it more interesting.

Add a while loop and some rules

My first approach to adding rules was to put it in a while loop. Inside this while loop, it would first grab a random newButton value from random(), then compare it against some rules. If it passes all the rules, then it would use it, and break out of the while loop. If it doesn’t pass a rule, then it would do nothing, stay in the while loop and try again.

alt text

The problem with this approach is that it is living on a prayer that random will eventually return something that will pass the rules. I knew this wasn’t perfect, but in all my development work on this project I never saw it get stuck. It usually tried a couple times at most, but eventually returned something that would work. It turns out that it can get stuck there, and something was causing it to stop trying.

For reference, the original code (with the actual rules - aka “if” statements) is as follows. You can see all of it here on my github commit. Specifically, here is my original add_to_moves():

void add_to_moves(void)
{
  while (1)
  {
    newButton = random(0, 3);
    if (!((newButton == gameBoard[gameRound - 1]))) // avoid repeats
    {
      // check to see if that button is already "maxed out"
      if ((newButton == 0) && (RED_seq_count == 2)); // do nothing
      else if ((newButton == 1) && (GREEN_seq_count == 3)); // do nothing
      else if ((newButton == 2) && (BLUE_seq_count == 3)); // do nothing
      //else if((newButton == 3) && (YELLOW_seq_count == 2)); // do nothing
      else break; // get out of this while loop and continue playing.
    }
  }

  // We have to convert this number, 0 to 3, to CHOICEs
  if (newButton == 0)
  {
    newButton = CHOICE_RED;
    RED_seq_count++;
  }
  else if (newButton == 1)
  {
    newButton = CHOICE_GREEN;
    GREEN_seq_count++;
  }
  else if (newButton == 2)
  {
    newButton = CHOICE_BLUE;
    BLUE_seq_count++;
  }
  else if (newButton == 3)
  {
    newButton = CHOICE_YELLOW;
    YELLOW_seq_count++;
  }

  gameBoard[gameRound++] = newButton; // Add this new button to the game array
}

You may also notice that my rules rely heavily on some new variables: RED_seq_count, BLUE_seq_count, etc. These are helping me keep track of how many times I’ve already included a specific color button in the sequence, so I can avoid favoring any button and ensure everyone gets to jump.

In an attempt to hone in on the problem, I added a little line of debug at the end of my add_to_moves() function.

if(debug) Serial.println("add_to_moves attempting...");

Now I would know whether it was trying at all, getting stuck in this while loop or stalling out elsewhere.

After much jumping and winning, I got another failure in the middle of a round. It stalled out, and my serial monitor looked like this:

alt text

Remember, my first failure was just before a “win.” Because this second failure was in the middle of a game, this was a new clue! This means that the failure is caused somewhere else in the code, and probably has nothing to do with the code just before a win.

Right before it stalled out, the entire serial monitor was filled with the message “add_to_moves attemping…” It was sending this message again and again as fast as my little Pro Mini could go. Something strange was going on. Why would it get stuck repeating this message, and then eventually give up?

The speed of the repetition of the debug message was also strange. When it seemed to be trying normally, the message would spit out to the terminal at a moderate pace. But when the failure would occur, the messages would speed up dramatically and eventually cause a stall out. After much finagling and many attempts to cause failures, I eventually gave up trying to find the root cause. I knew there was a better way, and so decided to start a different approach the the random generator with rules.

A better approach

alt text

To elliminate the possibility of any stall-outs, I introduced a new array called “on_deck_buttons[].” I would have my rules adjust this array, and then my random function can just choose from the good options. That way, random() will only be called once, and this removes the need to loop back around and try again and again.

I also beefed up my debug to get a better view into what was actually going on with all my variables and arrays.

Here is my new add_to_moves() function:

// Adds a new random button to the game sequence
void add_to_moves(void)
{
  byte newButton = random(0, 3); //min (included), max (exluded)
  int add_to_moves_counter = 0; // keep track of our while loop below for finding good new buttons, and see if this is jamming the game.
  if(gameRound == 0); // do nothing - newButton is randomly set above.
  else if((gameRound == 1) || (gameRound == 2)) // jumps 2 and 3 are important. for the first 3 jumps we want these to always hit each tramp once
  {
    while(1)
    {
      add_to_moves_counter++; // keep track of how many times we are trying to find a good new button to use (random might be stalling out here)
      int on_deck_buttons[2] = {0,0}; // these are used to help reandomize below
      newButton = random(0, 3); // pull in a first attempt at a nice new random button
      if((newButton == 0) && (RED_seq_count > 0))
      {
        on_deck_buttons[0] = 1;
        on_deck_buttons[1] = 2;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;
      }
      else if((newButton == 1) && (GREEN_seq_count > 0))
      {
        on_deck_buttons[0] = 0;
        on_deck_buttons[1] = 2;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;
      }
      else if((newButton == 2) && (BLUE_seq_count > 0))
      {
        on_deck_buttons[0] = 0;
        on_deck_buttons[1] = 1;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;        
      }
      //else if((newButton == 3) && (YELLOW_seq_count == 2)); // do nothing
      //else break; // get out of this while loop and continue playing. This means that the new button is good to go. 
      else
      {
        Serial.println("error");
        break;
      }
      if(debug) Serial.println("add_to_moves attempting...");
      if(debug) Serial.print("gameBoard[gameRound-1]:");
      if(debug) Serial.println(gameBoard[gameRound-1]);
      if(debug) Serial.print("gameBoard[gameRound-2]:");
      if(debug) Serial.println(gameBoard[gameRound-2]);      
    }
    if(debug)
    {
      Serial.print("add_to_moves_counter: ");
      Serial.println(add_to_moves_counter);
      Serial.print("RED_seq_count: ");
      Serial.println(RED_seq_count);
      Serial.print("GREEN_seq_count: ");
      Serial.println(GREEN_seq_count);
      Serial.print("BLUE_seq_count: ");
      Serial.println(BLUE_seq_count);
    }
  }  
  else // only after you make it to step 3.
  {
      // attempt 1, works.
      // while((newButton == gameBoard[gameRound-1]) && (newButton == gameBoard[gameRound-2])) newButton = random(0, 4); // keep pulling in more variables until this isn't true.
      // basically, if it's the same as the previous 2 buttons, then it will keep finding a random number until it's "fresh".

      // attempt 2, attempting to add in limit per button to avoid leaving one jumper out.
    while(1)
    {
      add_to_moves_counter++; // keep track of how many times we are trying to find a good new button to use (random might be stalling out here)
      int on_deck_buttons[2] = {0,0}; // these are used to help reandomize below
      newButton = random(0, 3); // pull in a first attempt at a nice new random button

      // This ensures it's not going to repeat same button 3 times
      //if((convert_to_choice_byte(newButton) == gameBoard[gameRound-1]) && (convert_to_choice_byte(newButton) == gameBoard[gameRound-2])); // do nothing, try again 
      // check to see if that button is already "maxed out" (aka it has been used twice already)

      if((newButton == 0) && (RED_seq_count == 2))
      {
        on_deck_buttons[0] = 1;
        on_deck_buttons[1] = 2;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;
      }
      else if((newButton == 1) && (GREEN_seq_count == 3))
      {
        on_deck_buttons[0] = 0;
        on_deck_buttons[1] = 2;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;
      }
      else if((newButton == 2) && (BLUE_seq_count == 3))
      {
        on_deck_buttons[0] = 0;
        on_deck_buttons[1] = 1;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;        
      }
      //else if((newButton == 3) && (YELLOW_seq_count == 2)); // do nothing
      //else break; // get out of this while loop and continue playing. This means that the new button is good to go. 
      else
      {
        Serial.println("error");
        break;
      }
      if(debug) Serial.println("add_to_moves attempting...");
      if(debug) Serial.print("gameBoard[gameRound-1]:");
      if(debug) Serial.println(gameBoard[gameRound-1]);
      if(debug) Serial.print("gameBoard[gameRound-2]:");
      if(debug) Serial.println(gameBoard[gameRound-2]);      
    }
    if(debug)
    {
      Serial.print("add_to_moves_counter: ");
      Serial.println(add_to_moves_counter);
      Serial.print("RED_seq_count: ");
      Serial.println(RED_seq_count);
      Serial.print("GREEN_seq_count: ");
      Serial.println(GREEN_seq_count);
      Serial.print("BLUE_seq_count: ");
      Serial.println(BLUE_seq_count);
    }
  }

  // We have to convert this number, 0 to 3, to CHOICEs
  if(newButton == 0) 
  {
    newButton = CHOICE_RED;
    RED_seq_count++;
  }
  else if(newButton == 1) 
  {
    newButton = CHOICE_GREEN;
    GREEN_seq_count++;
  }
  else if(newButton == 2) 
  {
    newButton = CHOICE_BLUE;
    BLUE_seq_count++;
  }
  else if(newButton == 3) 
  {
    newButton = CHOICE_YELLOW;
    YELLOW_seq_count++;
  }

  gameBoard[gameRound++] = newButton; // Add this new button to the game array
}

The trouble with failures that only happen once in a while is that it can require lots of data points and repeated testing to emulate the failure. For most software issues, this can sometimes be automated and done quickly, however, with exhibits like these that involve physical hardware, the true game play must be cycled again and again to create the failure.

The trampolines were failing randomly every 10-20 game plays, so that meant a lot of jumping. Never in my life have I had such a physically demanding code debug session! I did my fair share of jumping during the development of this project, but that paled in comparison to this debugging session.

If you have experienced any strange stall-out with the random() function, or have any other approaches to creating sequences like this, please share in the comments below. Also, please check out the github repo link below, and if you so feel inclined, we always love seeing any issues, forks, pull requests or comments. Thanks for reading and happy coding!

Boulder Bounces Github Repository

comments | comment feed