The Vending Machine Saga, Part 1


So, we have an old Snapple-badged Dixie-Narco/ECC glass-front vending machine, which one of our members bought for a song a few years ago. It was heavily discounted because the compressor was dead and the mainboard was pretty much dead. But it has 54 slots for drinks and is way more volumetrically efficient to store lots of drinks than the white fridge we had been using for the purpose, so we have basically just been using it as a high-capacity fridge (after we replaced the compressor you see).

Dixie-Narco/ECC DN2145 / ECC2100 Glass-front drop soda machine

Dixie-Narco/ECC DN2145 / ECC2100 Glass-front drop soda machine

However. The mechanics all work. And every piece of hardware in it is super easy to talk to (with two exceptions but I will get to that). And I have been itching for another embedded design project for a long while now because, while I love my job, it makes use of almost none of the parts of my degree that I really enjoyed in college.

So. Enter the Dixie-Narco Soda Machine project, to replace the dead controller with a modular open-source one designed around modern hardware.


Every project has to start somewhere, and a great place to have started this one would have been a roadmap of tasks. Below is that roadmap, had we actually done one. 🙄

  1. Minimum Viable Product
    1. Drive all 54 slots to dispense product
    2. Fault-tolerance using the existing vend-confirm sensor
    3. Talk enough MDB to work with the new coinmech and bill recirculator, to accept money and return change
    4. Drive a display on the unit
    5. Read the keypad on the unit
    6. Monitor system temperature
    7. Maybe take over compressor control from the bimetal thermostat which is a little wonky
    8. Monitor the existing door switch
    9. Local database
      1. inventory
      2. product information
      3. pricing
  2. Gen2
    1. Add barcode reader to system for inventory add/remove
    2. EAN/UCC-13 information integration (probably UPC Database)
    3. Inventory reporting/control website
    4. Transaction history
  3. Drink Your Dues Away
    1. RFID reader on machine for 125kHz member keyfobs
    2. Tie into the new CRM for account information for cashless vending
    3. Can we should we accept dues payments through bill recirculatory?
  4. The Bleeps and the Bloops
    1. MQTT interface
      1. Telemetry
        1. Temperature/humidity
        2. Compressor status
        3. Vend activity
        4. Door switch activity
      2. Control – Remote vend????
      3. Integration – Existing Tasmota RGB(W) LED controller for machine lighting
    2. Slack bot
      1. Inventory query
      2. Inventory alerts
      3. Vend activity
      4. Door switch activity
      5. Remote vend????
    3. Mailing list
      1. Inventory alerts


In order to come up with a better controller, we had to reverse-engineer the machine’s hardware.

Vending Slots

There are 54 slots in the machine, each with an escapement actuated by a 24VDC ~5A (that becomes important later) spring-return solenoid. The slots are arranged in 6 modular, removable rows of 9 columns each. The solenoids are pinned out to a 10-position Molex 2695KK connector with a common line and 9 control lines.

The original machine board controlled these with a 6 by 9 BJT matrix, which for non-obvious reasons had a whopping 108 PTH diodes. We were stumped by this, as 54 makes sense as flyback suppression, but the other 54 were not routed as flyback diodes and it was not clear as to what they were for.

Old controller of Dixie-Narco vending machine

Old controller of Dixie-Narco vending machine


Old Display

The machine’s original display is 8 red LED starburst (14-segment with decimal points) digits, run by an OKI (MS)C1937-01 14/16-segment 16-digit LED driver. This unit uses a 3M C-GRID 2×13 connector.

However, as much as everyone seems to really have the feels for the nineties, I just could not bring myself to develop a display driver for the SPI controller…and end up with a starburst display. No further work was done on this display, and it was handed off to the electronics lab as a salvageable component for someone else’s project.

New Display

I figured as long as I was going to be putting in effort developing display code, I may as well end up with something more useful and modern. As it turns out, the NHD-3.12-25664UCB2 from Newhaven Display pretty much fit that ticket. With an SSD1322 driver running a 256×64 pixel blue OLED array, I can make a more modern, information-rich output. Also as it turns out, there is an open-source Python module (luma.oled) that can drive it (go figure!). This display requires 20 pins to drive, but most of those are static mode bits and do not need to be driven actively.


This is a simple 6 x 3 membrane matrix, on a 10-position Molex 2695KK connector. Pin 7 is unconnected. The pad has digits 0-9, letters A-F, a star (*) and a CLR button.

Vend-Confirm Sensor

This appears to be an off-the-shelf industrial-style retroreflective beam-break sensor, which spans the entire landing area for drinks. It uses a 12-position Molex 2695KK connector. Pins 2-4, 6-8, and 10-12 were unpopulated.

Because I had no intention to waste board space on 9 unused pins, we repinned this connector to a 3-position Molex 2695KK connector, salvaged from the door switch.

Door Switch

This is a simple plunger-style switch, on a 3-position Molex 2695KK connector. Pin 1 is unpopulated. The switch is open when the door is.

Because I needed a 3-position header for the vend-confirm sensor, we repinned this connector to a 2-position Molex 2695KK connector, salvaged from a random fan.

Temperature Sensor

Old Sensor

Labeled CR0023212-0.2-163400024, this is supposedly a SPI-connected temperature probe. However, no response could be elicited from it. It uses a 6-position Molex 2695KK connector, with pin 6 unpopulated.

Old temperature sensor in condenser fins

Old temperature sensor in condenser fins

New Sensor

New temperature sensor is an AM2302, serial number 15120F902. It uses a 3-position JST-XHP connector. As a bonus, we get humidity monitoring with this sensor too.


To take control of the compressor, two things need to happen:

  1. The controller needs to short out the bimetal thermostat (NO relay in parallel with thermostat)
  2. 2. The controller needs to be able to interrupt the ~5A @ 120VAC current to the compressor (NC relay in series with compressor)

In addition, since this is an untrustworthy system (because it is under development), the control needs to revert easily back to the bimetal strip. Thus, all of the control needs to be on the actively-driven side of the respective relays. A common off the shelf 4-channel relay board will be used to run the compressor, giving us a couple spare points for…whatever comes up.

Cash Handling

Bill Acceptor

There was no bill acceptor with the unit. Len bought the original part number, but we had issues getting it working and then the original mainboard died.

Rather than replace it again, we bought a bill recirculator, since long-term, we are thinking about allowing the purchase of more-expensive things, like dues or Arduinos, and giving change back in quarters is no-one’s idea of a fun time (Jackpot!). The new recirculator is a Mars standard part that directly fit the machine and talks MDB.


There was no coinmech with the unit. Len bought the original part number, but we had issues getting it working and then the original mainboard died. The new coinmech is a Mars standard part that directly fit the machine and talks MDB.


As with many such machines, the old controller largely ran on loosely regulated 24VDC. Unfortunately, the 24VDC supply in the machine is unreliable. Since my last SBC project had some…exciting…power supply issues, I felt it was wise to know my own limits and use a COTS 5VDC supply for logic as well. An RD-125B from Meanwell fit the ticket, with 4.6A each on 24VDC and 5VDC (more on that later…).


The Happy-Go-Lucky Phase

Initially, I was going to design around the Beaglebone series of ARM SBCs, partly because i3Detroit is swimming in them (Hi Jason!), partly because I was thinking about driving the slots as a matrix like the original board, and partly because n8vi was offering to write PRU code to talk the 9-bit crusty serial for MDB. That meant I needed 36 pins to drive this thing, plus a powerful need for programmable bitbang units. Sounds like a Beaglebone to me!


Slots 6 rows x 9 columns 15
Display MOSI, SCLK, CS, RST, and DC 5
Keypad 6 rows x 3 columns 9
Vend-Confirm 1 input 1
Door Switch 1 input 1
Temperature/Humidity 1 one-wire 1
Compressor 2 output 2

The Interim

Then I sat and did nothing on the project for like a year. It happens. Sailing, life, depression, actually finally coming out of the closet entirely, getting on hormones, work, life. You know, the usual.

Then some discussion was made about how the snack zone must be losing money due to forgotten payments and fridge cards not checked off. So, hey, what the hell, I have some spare time and I am feeling good again, so I should design some stuff!

Design Deux

Talking with n8vi, it seemed like he was pretty unlikely to be able to do the thing (yay toddler!), so I found an off-the-shelf module that converted MDB to 8-bit serial via USB. Yay! No PRUs, and two pins down (34 now) to boot!

Also, I was having a really hard time coming up with a sensible way to do the solenoid matrix without spending an absolute fortune on a circuit board. Those square inches really add up. But…the slots are organized into rows. What if we ditched the matrix concept entirely, and drove the solenoids directly, individually? Enter the MCP23017 16-bit I2C I/O expander. Being I2C, I could make identical stacking boards that took 5VDC, 24VDC, and I2C on a common bus, and drove the 9 solenoids per row directly using a simple FET low-side drive. Suddenly I went from like 100in2 to like…4in2. Also, my pin count dropped precipitously. I replaced the 15 pins for the matrix and the 2 pins for the compressor relays with…2 pins for the I2C bus. 17 total pins needed. This looks like the job for a Pi.


Slots 6 rows x 9 columns 0
Display MOSI, SCLK, CS, RST, and DC 5
Keypad 6 rows x 3 columns 9
Vend-Confirm 1 input 1
Door Switch 1 input 1
Temperature/Humidity 1 one-wire 1
Compressor 2 output 0

I drew up schematics and board art for a simple mainboard (power input, row driver bus, display, keypad [and buffers for ESD!], door switch, temperature, and vend-confirm), and a simple row driver (9 bits used for solenoids, 1 tied to a status LED for diagnostics, and 4 wired to a header matching the COTS 4-channel relay board input; not to be populated on any but the first in the stack). A few rounds of board critiques on Slack (thanks Nate, Roger, Charlie, and Mike), and I had boards I was happy with. On went the i3 logo and the OSHW logo, and up the art went to GitHub.

Board art for Dixie-Narco mainboard

Board art for Dixie-Narco mainboard

Schematic for Dixie-Narco mainboard

Schematic for Dixie-Narco mainboard

Board art for Dixie-Narco row driver

Board art for Dixie-Narco row driver

Schematic for Dixie-Narco row driver

Schematic for Dixie-Narco row driver

An order went out to SeeedStudio for their maker-tier board pricing; 10 of each design on the way for pennies a square inch. Another order went out to Digikey for components. I now had almost as much skin in the game as Len did with the cash handlers, the carcass itself, and the compressor.

The Compressor Meltdown

So, remember how I said we had to replace the compressor? Well, we had to replace the compressor shortly after we got the carcass in. Len bought us a really nice new compressor, hijinks related to trying to cold-trap the R134a ensued, everyone had LN2 ice cream and decided to just vent the R134a instead, lines were brazed. And the compressor roared to life and we had a cold box in the shape of a vending machine.

Yeah. So for funsies, Mike put a Sonoff POW with a DS1820 temperature probe on the unit, which reported system power (100% compressor and fans) and temperature (in the cold chamber somewhere near the condenser). A few weeks ago, we noticed that the machine had apparently basically not turned off in like 3 months. Which, you know, is bad…

Then one of our members posts on Slack, “Hey, did you guys know the Snapple machine is like 95°F?”. Well, I mistakenly assumed that, due to some issues with the brazing process, maybe we had killed the compressor. I asked Len to buy us a new compressor just in case, and when it came in, I poked around in the back of the unit, and noticed something odd; the compressor was running fine. However, the fan on the condenser was not. I poked the fan blade, and it started right up.

No wonder the unit was hot! I pulled out the fan, ran about a quart of WD40 through the fan body and hopefully the bearings, and another pint of silicone lube to hopefully keep this from happening again, then reinstalled it. Since the condenser was absolutely filthy and packed with shop dust, I vacuumed and blew out the fins, and installed the 10” x 20” x 1” paper filter that should have been between the drop target tray and the condenser fins. Machine cooled down quickly, everyone happy. Right?

Yeah, that lasted like 18 hours. So, I bought a new fan motor from Grainger (aside: did you know there are like 8 total options for 9W fan motors? Apparently the entire refrigeration industry runs on the same motors) and installed it once it came in. Now the machine is fully functional, everything is happy and great.

Actually Doing A Thing

So while I was waiting for the boards, the components came in. I played around with the power supply and realized I had been too clever for my own good. This is a dual-rail supply. As such, it cannot hit regulation unless there is load on both rails; in my design, the 24VDC rail will be mostly unused other than the draw from the MDB, unless I am actively driving a solenoid. So the power supply cycles at about a hertz, and squeals.


A 50Ω high-power resistor did the trick enough to turn the supply on, but it still whines. I should have just used two supplies.

Finally the boards came in and I started production.




I really ought to have bought the stencils.

So I got one of the row drivers made up, and the mainboard. I did some proof of concept work with the mainboard and the display, to ensure that connector worked as well as the breadboard did, then played with the row driver. Everything worked great on the bench, and I even got a 24VDC solenoid to actuate!

I moved to the machine.

Plugged a row connector into the driver header.

And powered on the stack.

And promptly cratered one of my FETs.


Turns out, the MCP23017 boots up in HiZ mode (which is sensible really). This means I committed the cardinal sin of FETs; I had neglected to positively assure the state of the gates at powerup, and so at least one was floating somewhere in the non-saturated area and blew up.

I manually added 10k pulldowns to the board after replacing the FET, and tried it again. All the channels worked flawlessly.

Then I spent the next several hours making the other 5 boards, and putting the bodges in. I tested those too and cratered another FET.

New controller stack for Dixie-Narco vending machine

New controller stack for Dixie-Narco vending machine

Shit. Looks like the solenoids actually take around 5A for pull-in, not the 3A I tested back 18 months ago. So my 5.6A-rated FETs with no heatsinking vias were unhappy with continuous duty.

I threw a 2.5A polyfuse on the 24VDC rail into the board, and made a note that the software must only drive the solenoid channels for like 500ms, and everything seems to be working great now.

Build and Wiring

We were pretty confident in the stack now, so it was time to start putting it all into the machine.

I had ordered weld-on standoff footers along with the standoff hardware, with the thought that we could weld directly to the sheet metal inside the machine. Mark suggested that was a dumb idea for maintenance and that I should make a subplate instead. Great idea Mark.

So I grabbed a chunk of 1/8” steel and TIG welded the footers to it, using extra boards to get the locations right. A quick coat of paint, and it was ready for mounting.

Laying out the hardware prior to TIG work on the standoff feet

Laying out the hardware prior to TIG work on the standoff feet

Once we had all the hardware stacked onto it, I drove 4 sheet metal screws through it into the inside wall of the machine. Removable, but slim.

New controller in its home inside the machine

New controller in its home inside the machine

Then began the wiring and routing and tidying.

Wired up and ready to be programmed!

Wired up and ready to be programmed!

That is where it sits now. Next time, we will start programming the thing!

Laser Cut X-Wing Game Tray – Made at i3

xwing_lasercut_gametray1 xwing_lasercut_gametray2

These game trays for X-Wing were made with the Laser Cutter at i3Detroit.

Show and Tell October 2016

Mike & Lichtenberg Display Stand

Mike showing off his Lichtenberg Light Stand – Acrylic


Lichtenberg Display Stand

Lichtenberg Ball and Light Up Stand – Acrylic



Guitar Food Switches

Brandon showing his Foot Guitar Switch Panel – Diamond Plate Aluminum




i3Detroit Ironing Board

Jan showing off the New i3Detroit Ironing Board

Need to Test Some LEDs?

I’ve been buying some 3W LEDs from various sources for a project.  Each of those sellers makes wildly improbable claims about the brightness and chromaticity of their LEDs, but I didn’t have a good way to verify them and see which are best.  I found a light meter in the i3 Detroit eLab, but getting consistent readings from that was difficult.  The readings depend upon ambient lighting, angle to the LED’s axis, distance from the emitter, etc.  I finally came up with an idea for a (relatively quick) little jig to get consistent readings which at least allow me to compare LEDs to each other.  As a bonus, the materials are very cheap and it’s easy to build.

Complete LED tester

Complete LED tester

LED mounted on the base of the jig.

LED mounted on the base of the jig.

The LED is mounted under a piece of shim stock cut to form electrodes.  The electrodes can either contact the pads on the heatsink, or the leads on the LED itself.

This is the view from the end where the light meter probe fits into the laser-cut opening.  Because no problem worth solving cannot be solved with a laser cutter.

The interior of the chamber is painted with flat black paint to reduce the effects of any light leakage at the joints and reflections from the walls due to angle of view of the LED.

View of LED from the business end of the jig

View of LED from the business end of the jig

This jig is easy to connect to a current-limiting power supply, and it blocks out ambient light well (the meter reads 0 lux with the power off).  What it does not do well is provide removal of heat from the LED’s heatsink.  So it’s important to run the LED at a current level that does not generate a lot of heat, possibly wrecking the chip.  I used 600 mA for an LED rated at 700 mA and wavelength of 660 nm.  Blue LEDs generate more heat, so they would have to be tested at an even lower power level.  But the point here is to compare LEDs within the same lot or between lots, not to get calibrated readings that can be compared to standards.  That would require a much more expensive meter.

Why buy all these LEDs?  I’ll save that for a future post.