So, I got a housewarming gift in the form of some pieces from an SEM control panel (it really is the people you know that helps). My default answer these days is to adapt the controls to an esp8266 and throw it on mqtt. This turned out to be the perfect project to show off the multiplexing capabilities of the esp8266, or put another way, how to mux your inputs to work on a microcontroller with very very few inputs.
This control panel is kinda cool in the fact that it has 3 lighted buttons, 3 toggle switches, 1 LEDs, and 3 analog controls so that no matter what you want to control it will probably work pretty well.
The first thing I’ll cover is the analog. The ESP8266 only has one analog input, and that is limited to 1v. I don’t know why that is the case considering the rest of the esp is a 3.3v device, but it just is. It’s better than being a higher voltage since you can always apply a resistor divider to the ADC and sense a larger voltage, but sensing a smaller voltage requires amplifiers which are more complicated and prone to noise and power concerns (power concerns says the guy who just suggested burning off power over resistors). The ADC is 10bit, which seems to have become standard on microcontrollers these days even if you usually only see 8bit pwm.
So, how do you use a pot on a 3.3v microcontroller as an analog input to a 1v ADC? more resistor dividers! A potentiometer has 3 pins (usually) being either end of the piece of resistive material and a center tap which selects the ratio of resistance. This means that a potentiometer can be though of as a variable resistor divider (or a resistor divider can be used to replace a potentiometer if you need a fixed value). Normally I would hook the outside legs of the potentiometer to the power rails and the wiper to the analog input, but in this case giving between 0 and 3.3v to the ADC is not desirable. There are two ways to accomplish what the esp needs, you can either change the reference voltage for the potentiometer, or you can scale the input to the ADC. I chose to scale the input to the ADC because I have 3 potentiometers and want to keep the analog voltage as high as possible until the last possible moment to shrink the impact that noise has on the signal.
That was how to use a POT to drive the ADC on an ESP8266 (acronyms and abbreviations get thrown around a lot, don’t they), but how do we use 3 of them at once? There are multiple answers to this question, and continuing cheapness of i2c chips make the economics not as clear as they once were. My tendency is to use the least number of chips, and the least complicated ones to do the job. In my experience this leads to easier debugging (thy do you want to worry about high-speed signal capacitance when all you’re doing is reading a POT with an MCU?). For this I chose the 405X. The 4051, 4052, and 4053 are different combinations of analog multiplexer (4051 is a 1:8, 4052 is 2 1:4, 4053 is 4 1:2). Since I have one analog pin and 3 sources of analog voltage I could use the 4051 (and have unused inputs) or a 4052 (and have an unused mux and one unused input). Driving them is identical (tie unused address lines high or low, just be consistent) so it doesn’t matter which I used (check the pictures, I’m writing this before taking them).
Now, before we talk about the outputs let’s talk about the switches themselves. These are fairly nice switches, they pop out, have inserts for text, easily replaceable bulbs… Bulbs. Nope, those have to go. It’s not just that they are less efficient than LEDs, but they’re also something like 28v bulbs which is just not reasonable to have to step up the voltage for. If you’re doing this with precious vintage equipment that you can’t bear to modify then I’ll recommend a step up converter and some FETs. I broke the bulbs, soldered to the filament, and potted with hot glue. It seemed like the easiest way to add LEDs without messing with the mechanical beauty of the switches.
The LEDs also need current limiting resistors, I picked ones that put out a reasonable amount of light and work with my 3.3v power supply. The choice of LED was ‘what looks good that will fit and I have lying around’ and the choice of resistor was ‘what works with that LED’ so you need to pick your own for LED-moding your electronics. The resistors I put in-line with the input to the bulb socket and heatshrunk over.
So, now let’s deal with the outputs for these panels. The white LEDs I just explained, how I set them up to be driven with 3.3v, but we also have 2 red LEDs. The red LEDs had both positive terminals wired together and apparently used low side drive to switch them, I decided to make all the outputs on this project high side drive so I unwired the LEDs and rewired them with resistors that make them pleasing to look at at 3.3v (as I do more projects I care less and less what amperage my lights are, they just need to be ‘pleasing’ and ‘not going to burn out’. Since these LEDs are driven over shift registers I can’t use the hardware PWM to control the brightness, it’s important to choose a light leven that is comfortable because it will be hard to dim (although one could low side drive the common light ground to dim them all as one).
The chips I chose for input and output were a complete pain. There are so many complimentary parallel-serial chips it can get overwhelming picking them. The 74xx595 and 597 are very modern and the go-to standard of many hackers (including myself) but they have extra control lines for the latches which means they can’t be used with just hardware SPI. The 74xx164 and 165 are closer but they are still not exactly right. I eventually settled for the 74HC595 and the 4021. I really don’t think I should have to mix families to accomplish this, and I couldn’t tell you exactly what the problem was anymore with the other chips, but using this combination I can use hardware SPI commands and it works every time. Credit goes here because I would never have thought of that. The difference in my design is that I decided not to waste any cycles and I wired the SS pins together so every time I read the input I update the output (well, I could but didn’t if you check the code).
Now, just to make sure everything’s consistent I recommend you pull all the buttons and switches either up or down (be consistent) and have them connect to the opposite rail on activation. You may think that I wouldn’t need a pull down resistor with the toggle switches and I could have definite states for both positions, you would be right but I decided not to add any more wires so that means only two wires per switch.
There you go, that’s how to multiplex analog and digital signals with some basic logic chips so your esp can control more things. Of course there will be people that think everything should be done over i2c, but there are serious problems when trying to do fast input and output on a shared bus. I’m already planning another couple features before I call this done so you may see it again soon.
I’ll close by saying that I’m leaving this a bit open-ended. There are so many things you can do here I won’t try to write a firmware that works for them all. I was originally thinking this could be a thermostat, but now I’m leaning more toward a lighting controller (light intensity, warm and cool tint knobs, indicator to see if the lighting has been overridden, buttons to control the rest of the first floor lights). Whatever it becomes I now have example code to chain as many parallel inputs, outputs, and analog inputs (you can run the multiplexer off the 595 if you want) into an ESP8266.
pictures are here.
The rest of this series can be gotten through from the home page here.