Awhile back I modified a USB-to-Serial converter to be more of a USB-to-UART converter. While it was useful for a little while, I still found it to be a little clumsy to use. I wanted to make something a bit more usable.
Now there are plenty of FTDI chips out there, but I went with Microchip's MCP2200. It's a USB-to-UART device, but it also has some programmable GPIO pins that can be controlled from the PC.
For this board I wanted to address a couple needs: easy connectivity to a breadboard, serial communication at 3.3V or 5V, and providing power to my test circuits.
I combined the first and last items in the PCB layout. I designed it such that the board would span a typical breadboard's power rails, and plug directly into them. I provided jumpers to select which pins ground and power were output on so that I could also plug in along a power rail (I'll show in photos below). I also added a switch to choose between 3.3V or 5V, which is then supplied to the power output pin.
I also put in a female header to make it easy to jumper all the GPIO and TX and RX signals. The header also has dedicated 3.3V and 5V pins so that both voltages are always available to use, regardless of which is selected.
A simple enough board, but now I pretty much just leave it plugged into my breadboard all the time. More often than not, it's providing whatever voltage I need, and I just have to connect two wires and I'm talking with the PC.
This is not a project really, just a little board I made as a tool. I got a couple SAMD09 micros from Atmel, which are ARM Cortex M0+ based little guys I thought I'd play with (this was actually quite some time ago). I haven't done a ton with ARM processors and this micro was my way in. Only problems? It's a SOIC package and that programmer cable uses a 0.050" spaced plug.
Now the SOIC package is easy to deal with, you can dead bug it, or get DIP adapter board that'll fit nicely into a breadboard. The cable was the bigger obstacle. Again, it could be dealt with, but setting up the programmer has always kinda annoyed me. You gotta go to the datasheet and find which pins do what for you microcontroller and run the wires individually. And the same goes for your programmer; you gotta find the pinout, and the decide if they're showing you the cable end or the mating end in the diagram. Just a deterrent to getting started on things.
So I just did my own breakout board, with a couple extras: a debug header and a reset switch. That's it, nothing more nothing less. Here's the schematic:
For about $10 I got half dozen PCB's made and shipped to my door. Now whenever I was to use one of these devices, I just pop it in the breadboard and plug in the progarmmer and I'm ready to go.
As usual, the last bit to talk about is the software. The basic function is really really simple. It goes like this:
Hey, I'm on. Cool. Let's really quickly setup the I/O pins and PWM output.
Ok, am I on because the turn signal is on? Let's check.
If so, then load the duty cycle for the turn signal into the PWM, otherwise, let's load the duty cycle for the headlights/running lights.
Guess I'd better check again, let's go back to step 2.
For every blink of the headlight, it'll start from step 1. But we're talking microseconds from a power on condition to turning the LED on. In fact, I'll even go measure it right now.
Yellow: Power in Blue: PWM Out Looks like a I need a bit of power supply filtering.
630us it turns out. Actually a bit longer than I would have expected. But still insignificant considering the duration of each blink of the turn signal.
The buttons were actually a lot more work. I would just check them periodically and compare their states to previous states, and then pass the results to a function that would take the appropriate action based on the current state. The buttons themselves are labelled SET and ADJ.
The SET button is used to change states. So at power on it's in the running state and checking the input to determine which brightness to show. Pressing the SET button once moves to the Turn Signal Brightness adjust state (and it gives a blink to denote that the state has changed). Pressing it again changes to the Headlight Brightness adjust state. One more push puts us back in the running state (with a long pause of the LED off to let you know you're going leaving the adjust states).
The ADJ button simply increases the PWM duty cycle, but only when in an adjust state. It doesn't even have to care which adjust state.
You will see in the video below that when I leave the adjust states I actually get a series of blinks before the LED is switched off for a delay to denote the return to the running state. The blinks indicate that one ore more of the brightness levels changed and that they were stored on the microcontroller.
This part actually got me into a little bit of trouble. I neglected to check that the micro has EEPROM. It does not. EEPROM is used for long term data storage, and is retained after the device loses power. I can make all the changes in RAM I want while the device is running, but I'd lose the adjustments every blink. Not cool. Now many devices, this one included, are able to write and read program memory. So I could use a portion of the left over space that the firmware doesn't use and store the brightness levels. But there are some caveats. Program memory has to be written in rows. For the PIC10F322, that's 16 words. Each word is two bytes, making for 32 bytes total. You are generally supposed to read out the contents of the memory first, alter the byte locations you need to change, and write it all back. That would require half the available RAM. Now technically I don't need to, as I can just write all 0xFF or other dummy values to the unused space, and just grab the current brightness levels in RAM and store them where needed. But it's all kind of a hassle.
Instead I'm taking advantage of one of the features of the device: it has 4 bytes of USER ID space that is effectively the same as program memory, but can be written and read one byte at a time (technically each location is a 14bit value because that's width of program memory, but for practical use, the upper 6 bits are being ignored). Problem solved. Otherwise the project would have been more or less defeated. I would have only been able to hard code brightness values; any changes requiring re-programming the microcontroller. Also would have wasted all that board space for the buttons, and all that time and code handling the user input.
I just took a little video going through the different states and showing the device running both with "headlights on" and off.
As usual, it's been awhile since I've posted. But the purpose of this blog is not so much to produce content in a timely manner so much as just a means for me to document (and sometimes revisit) some of my projects as well as an incentive to complete them. So this one has more or less been done for quite some time and sitting on my desk.
We've already covered the important pieces of the circuit, now we just need to put it all together. The resulting schematic is too complicated for just being a turn signal, but this wasn't meant to be entirely a practical solution. You can obviously buy LED bulbs at the store (though they are still surprisingly pricey), but that's not the point of this project. So here we go:
I've additionally included S1 and S2 to the circuit, which you could argue is the whole reason this thing is so complicated. I wanted to be able to dial in the brightness of the bulbs without having to change resistor values or reprogramming the micro. I've done the debouncing in hardware because I didn't want to do it software. And with only two buttons, the effort and space on the board required is minimal.
The last item I think is the ICSP header. It's always handy (and sometimes necessary) to include one of these to make programming and debugging easier. Also best to make it the same as the cable on the programmer you are using, though occasionally you may have to do otherwise. But not having a convenient way to change your software will discourage you from finishing or improving your firmware in the future.
I did make a smallish PCB for this, and for the function it serves, yes, everything is kinda big. But hey, learning experience. Later.
Now the original problem I had was when water made its way into the bulb housing and corroded/shorted everything. I'll do my best to seal up the housing when I retrofit it... but what if it happens again?
We already do have the output current limited from the previous post, so no big deal right? Short the LED and we still only draw 0.5A. While true, it still has to drop some 14V(engine running). Calculate out the power and you get $W = V * I = 14V * 0.5A = 7W. Ouch. So how do we avoid that?
Well I pondered that for awhile, and came up with a solution, but it does use a lot of parts. Knowing that the LED drops some 10V or so, we can assume the voltage at the collector of the LED driver should be 10V less than the system voltage. Assuming 15V worse case, we can expect no more than 5V. If that voltage rises too far we need to disable the LED driver. I chose to use an 8.2V zener as shown below:
If D1 becomes shorted, Z5 starts to conduct. Q3 turns on and Q2 can no longer drive. It's simple enough I guess. I just don't like that it's more complicated than the driver itself. Oh well.
Another little quirk I almost overlooked (well, only half of it) is making sure that the flashers can't drive the headlights. It only takes a diode, but without it, every time the blinkers flash, so would all the headlights. Probably not ideal.
If you recall from the previous post, the circuit can be powered from either the flasher power or headlight power. D2 and D6 simply prevent either source from powering the other.
And the final thing I want to cover is detecting if the flasher is on. The flasher signal is the power used to drive the bulb itself, and is going to be the car voltage. Our micro is only gonna be 5V. You can't feed that directly into a GPIO pin. You may be tempted to say just use a voltage divider. That would probably actually work, but our input voltage can vary (usually 12-14V as stated before). You don't normally signal with the car off, but you may use the hazards, so we should consider both on and off conditions. This is again a decent job for a zener. I could have used a transistor as well, but I think this choice is slightly less complex(fewer parts). And I never get to use zeners.
Now we can get a reliable ~4.7V input to the micro whenever the signal is turned on. Just two components. R4 is an optional dummy load. The flasher timing unit relies on the turn signal bulbs drawing current in order to switch on and off. You can look up how the bi-metal strip works elsewhere, I won't get into it. The LED draws significantly less current than the incandescent bulbs, so we're probably gonna need to waste a bit of power to keep the timing somewhat similar.
That was a bit of a quick run rhru of the various circuits for this design. But its not a complicated board, though still complicated considering what it actually does. We'll take a look at the full schematic next time.
So I previously defined the basic parameters of this project, but let's throw out a block diagram to make things clearer.
That's pretty much it. You may have noticed that there is no "input power". And you'd be correct. The input supply voltage comes from either the headlights being turned on or from the turn signal flashing. They powered the incandescent bulb, a little microcontroller and LED should be no problem.
It also may have occurred to you then that the mcu would be unpowered between signal flashes. Again you'd be correct. Every time the signal flashes, the micro will have to start up and figure out what's going on, and do the right thing. But not a problem really, it'll be instantaneous as far as anyone will be able to tell.
Since an LED is already picked out, the next course of action would be to figure out how to drive it. We know we need to achieve at least two brightness levels, and we also know we that we don't know what those brightnesses will be. We're gonna need a PWM. The other requirement is constant brightness over our expected voltage input (roughly 12 to 14 volts). This can be handled in hardware using a constant current source.
A simple but handy circuit. I've always that this was a clever design. We don't know what V+ will be at any given time and we cant change R2, so how do we regulate the current thru D1? With Q1. Since the base-emitter junction of Q1 is effectively a diode, we know that its going to be a pretty consistent 0.7V (approximately... whatever it's actual value is, it won't really vary with V+).
Q1 will regulate how current goes into the base of Q2 to ensure this. Now we just need to figure out what current we want. Determining the resistor then becomes: $R = \frac{0.7V}{I_{desired}}$. I am aiming for about 0.5A.... giving: $R = \frac{0.7V}{500mA} = 1.4\Omega$. We'll just round to $1.5\Omega$.
Another alternative would have been to use the built in ADC of the microcontroller and try to compensate the PWM duty cycle. But what a hassle, and we're going to be short on I/O as it is. There would need to be look up tables and scaling done to improve accuracy and more work than is worth doing. This method may ultimately be less parts too.
I'll quit here for now. As a head's up, the microcontroller to be used will be a PIC10F322. This heavy hitter has 6 pins, 64 bytes of RAM, and 512 words of program memory. Yup, this little guy barely has the RAM to store this sentence. Barely. And the text of this post probably wouldn't even fit into it's program memory. But we don't need to get that much done.
After an interesting winter with a mix of snow and temps on either side of freezing, water made its way into some of the light housings of my car... namely the front turn signals. The bulb sockets corroded and rusted to the bulbs, making things messy and more or less unusable. Everything is all just kinda shorted together. Now I can order new housings for around $70, but why not mod the ones I have? I can't ruin them any further. Let's throw in an ultra-bright LED.
Now this actually presents an interesting set of challenges. You can't simply throw an LED and resistor in there and watch it work (well, you actually kinda could, but that's no fun). But here are a few items to consider:
- The vehicle voltage can vary, especially if the engine is running or not. The battery will read a pretty steady 12V, but may sag under the load of you headlights an other accessories. Running, the system voltage is often around 14V. If using a current limiting resistor, you'll see some different intensities depending the actual voltage present. This is actually already an issue with the standard bulbs, but one that can be addressed.
- The current bulb is a typical 1157. It has two filaments; one to act as a running light when the headlights are turned on, and the other for the actual signaling. I'm only adding one LED element for both purposes.
- The 1157 has a low output filament which produces about 38 lumens at around 8W and a high output filament that'll do 402 lumens at 27W (see table). My particular LED is capable of outputting 900 lumens. But I'm not what exact current is gonna be needed to produce the right amount of brightness for either function. I'd like to have a little adjustment.
- The original bulb uses 27W for the turn signal. The signal timing relies on the 2 point something amps being drawn to toggle a bi-metallic switch.
- I want this project to be fun.
As always, seems like a good opportunity to use a microcontroller. What can't they do? With a really basic micro and a bit of circuitry we should be able to make something that operates over a varied input range, performs two output functions, and has adjustable brightness. And some sort of short circuit protection... cause that's part of the original problem.... water.
So, I was supposed to be continuing on with the MIDI keyboard, but I've had to press the big red button. Turns out I want this to be a USB keyboard now (still MIDI, but plug right into the PC). So that means a new microcontroller, somewhat new layout, using USB power, and a bunch of firmware redesign. I'm going to do a PCB spin this time around to hopefully speed up prototyping. Now its the USB-MIDI Keyboard Controller!
I'm just going to dive right in. Be sure to have read Part 1, and maybe even have it open for reference. So continuing the discussion where we left off, I mentioned there is a potential issue of feeding 5V into the 3,3V power rail.
Now normally this wouldn't be a huge deal. Perhaps isn't even in this case. When one of the buttons is pushed, current flows into the 1K resistor, thru ESD1 and into the 3.3V power rail. So you'd expect that current (without D1 or R2) to to be something like: $\frac{V_{B+}-V_{ESD1}-V_{CC}}{1K} = \frac{5V-.3V-3.3V}{1K} = 1.4mA$. Not a lot, right? But that 3.3V supply isn't magic. Let's take a look at the output of our regulator:
It only lets current into the circuit, it doesn't let any out. Those two resistors between the output and ground measure out to about $125K\Omega$. Without D1 & R2, I was finding the 3.3V rail would rise above 4V whenever a button was pressed. The only current paths were back into the regulator and whatever draw the microcontroller had.
The circuit without D1 & R2
So by adding a 3.3V zener and a small resistor (so it wouldn't really turn on in normal operation), I'm able to keep the voltage from rising too much. Interestingly though, the fact that the voltage was above the "safe" operating voltage may not have been too dangerous for the MCU. The 1K resistor between the button and the input limits any current into the circuit to 5mA, and that's if the microcontroller tried to short anything to ground.
Also, there was probably an easier solution had I not already soldered things and had better tools to undo my work: just use diodes on the outputs instead of resistors (I was expecting active low, not high). They'd block the 5V from feeding into the 3.3V circuit and ultimately reduce idle current (the zener draws a couple mA all the time, so sleeping the micro doesn't even buy much). The only drawback might be the diode drop means you're only supply 2.6V to the input of the clock's processor, which is expecting 5V, and I don't know the logic type of those inputs.
But anyhow, that's not a super exciting discussion. It is however, all that's needed for this project to work. There's a little bit of firmware involved:
It has to monitor the UART for a "snooze\r\n" or a "off\r\n" from the bluetooth module and act accordingly. Throw away all other messages.
It has a timer set for about 9 minutes (the sleep time of the clock is 8 minutes). This allows disabling the alarm between snoozes. Whenever the buzzer goes, the timer is reset.
After the timer is up, turn off the bluetooth and go to sleep.
That's almost the last thing. We need a phone app. While I've used the various incarnations of the Android studio or SDK's in the past, I actually did this one in Visual Studio. Nothing too fancy. A giant "snooze" button that's easy to hit. A smaller "off" button that requires a long press to activate, and a sort of "reset" button. The app stores the address of a paired bluetooth device so there is no need to fumble thru choices everytime you launch it. It recalls the stored device and opens a socket, no questions asked. Should the need to use a new paired address arise, then the "reset" button just clears it, and the app will then ask.
At this time, I've had this working in the alarm clock for a few months now, pretty much trouble free. Not the most important project I've ever done, or necessary, or all that worthwhile, but still a lot of fun. It was a small and compact project that spanned embedded to Android. Here's a little clip of it in action:
(the app loads slow because.... well I was filming, so something had to not work normally. The blinking on the alarm clock shows that the alarm is still active, after long pressing the "off" button, the blinking stops as the alarm is disabled)
Occasionally you get an idea that is way too much work and complication to justify going thru with it. This is one such idea, but a good learning experience. It should also lead to another, hopefully more worthwhile project.
I have an old Sony alarm clock from maybe junior high that I still use to this day as it has a nice loud and obnoxious alarm that is guaranteed to wake you up. But it has a drawback... it's loud and obnoxious. Due to it having a combo CD-player it actually has a decent pair of speakers and a some amplification. So, what is there to fix?
Well truly, not that often. Again, this idea is not worth the effort. I'm typically the person who hits the snooze a few times in the morning. On occasion, I'll get up with the intent to start my day, but ultimately end up on the couch.... And then the alarm goes off from the bedroom. What to do?
Let's Bluetooth the alarm clock.
The Plan
First we should define our main objectives:
Emulate the "snooze" button
Emulate the "off" button
The circuit should sleep while the alarm is not going off
The Bluetooth module should be easily removable, so that I can use it for other projects if I need it.
Like most things we'll probably need a microcontroller (I've chosen the PIC12F1572). Nothing fancy, just a few I/O. We're gonna want to tie into the physical buttons, and mimic a button press.We're also gonna want to listen to some signal indicating that the alarm is currently sounding.
Connection to the Clock
So where to start? Well, fortunately, there is a service manual, complete with schematics and drawings. Shown below is how the circuitry for the buttons on the alarm clock.
The button inputs to the processor for the alarm clock are pulled low thru 100K resistors to the ground. Pushing the button puts 5V across the 10K and 100K voltage divider (essentially 5V goes to the clock input).
The capacitor is just there for debouncing, it smooths out the transition from low to high and back down as the mechanical button is pushed. We can more or less ignore it for our intuitive analysis.
Controlling the input ourselves is as simple as emulating the button. Just make one of our microcontroller lines drive high.
A 1K resistor is added just to protect the output driver of the MCU. I actually should have done something different... but we'll get into that a little later.
The buzzer signal is also going to be an easy tie-in (although tough to solder to such a small area). I hooked it up to the scope to get a look at it, a series of 5V pulses at the frequency of the alarm. Perfect for triggering an interrupt on change pin. Instead of a 1K resistor like the buttons, I threw in a 10K. Shown below is the buzzer portion of the clock schematic, where I soldered in after R428. And that is all our signal connetions. 5V was picked up near the buttons above, and ground was everywhere.
Buzzer 5V square pulses
Buzzer has five quick beeps followed by a long pause.
Other bits
We still need to incorporate a Bluetooth serial module. The particular module I have is some kind of BC04 variant (same pinouts). All it really needs is power and serial connections. That's it. And in our case we only need to receive data from the Bluetooth module. On power up it goes right into pairing, and defaults to 9600 baud. You can literally just connect with your phone and start sending serial data. However, it does run off of 3.3V, and is the most power hungry part of the Disalarmer. We'll need a voltage regulator, and some way of switching power to it.
Before I show the finished circuit, I just wanted to bring up a minor hiccup. The microcontroller I had turns out to be a PIC12LF1572; that 'L' indicating low voltage. Not a huge deal as we already need a 3.3V regulator. But the 5V clock signals present a little bit of a challenge. But first, the schematic.
Switching the Bluetooth module on and off is as simple as a PNP transistor. Pull the base to ground and you've got power. Outputs to the buttons are just thru series resistors R4 & R7. Drive high to "push" the snooze or off buttons, and tri-state them otherwise.
You may also have noticed D1 and R2. These are my mediocre solution to the 5V input problem. But this is enough for now. We'll look at interfacing the 3.3V and 5V circuits in the next post.
So last time we went over how to read all 61 piano keys into a 28 pin micro, but we still have a few more I/O signals to worry about:
I2C Data and Clock lines for LCD display and EEPROM
Three system buttons for UI
RX and TX for MIDI
Two analog inputs for both joystick axes, another for volume, and one more for an external input
Two footswitches
We can actually knock a few of these out really quick. The I2C bus requires two lines for data and clock. There isn't anything we need to do there, just commit two I/O pins for that purpose (I2C will be done thru bit banging, as there are no free peripherals to support it). MIDI also requires two pins, which will use the available UART on the PIC16F916. And guess what, those two footswitches will also use two pins. That's six total I/O's used right there.
In a later post I will show the circuit in its entirety for the sake of putting all the pieces together. For instance, I'm excluding the debounce components for the footswitches as well as the specific circuitry for the MIDI interface (which I've already discussed in the Virtual Whammy Bar project). Really what we're concerned about right now is allocating the microcontroller I/O.
Now what about those three "system" buttons? We actually already have what we need for these. Going back to the piano keys we have eight banks, each capable of reading eight inputs. But we only have 61 physical keys. The last bank only reads in five, meaning we have room for another three. By using the same diode configuration the keyboard does, we can add the system buttons to the last bank. It will require the firmware to differentiate them, but that's not a problem. No more I/O's used. We have the eleven pins used for the keyboard and the six we just figured out above for a total of 17. There are only the analog inputs left.
The literature for the PIC16F916 says that it has 8 ADC channels. However, it really only has one actual ADC. They just allow you the option of hooking eight analog sources directly to the chip if desired, and can perform one conversion at a time. Although we only need four, and I kinda have the pins available to do so, I'm gonna multiplex again (also, it's already soldered in place). I may in the future decide to add more features to the keyboard, don't want to eat up all the I/O.
Using a 74HC4051, we can actually borrow from Bank Select circuit. The 4051 will give us eight possible analog inputs, for which we already have three signals set aside to select with. Granted, this will go thru X4 to X7, but these we can simply ignore in software. We have the potential of adding four more analog inputs with very little work.
The remaining I/O actually turned out to be rather painless. Everything is accounted for, and there is still a little room for future need.
So we're gonna make a MIDI controller, what exactly does that mean? At the very least we can say it's an embedded system, there is some digital communication. It's also going to be rather I/O intensive. Let's do a basic layout:
Even without any pretty pictures, it's already easier to grasp. I'm using the Microchip PIC16F916 as the microcontroller, which comes in a 28 pin dip package. However, between power, ground, and reset five pins are used up right off the bat, leaving us only with 23 available for I/O. How about we take a look at some more in depth requirements:
I2C Data and Clock lines for LCD display and EEPROM
Three system buttons for UI
RX and TX for MIDI
Two analog inputs for both joystick axes, another for volume, and one more for an external input
Two footswitches
61 Piano keys
I/O Design
By my count, that's a total of 75 total signals. Way more than we have room for. What do we do? We employ and key matrix. Rather than reading every key all the time, we look at them in groups at a time. For convenience, and because the fine people at Korg already added in diodes to make it so, we will look at them in groups of 8. That's one byte's worth per read. We'll call each group a bank, and we'll need a minimum of 8 banks for our 61 keys.
I'm showing the first two banks of keys above. The keys are all connected to an 8-bit wide bus thru diodes. These diodes prevent a pressed key from an inactive bank affecting the reading of a key within an active one. To read the keys, you pull the appropriate "Bank Select" low and read the bus. A pressed key will read as a '0', and an unpressed key will read as '1'. I should point out that Key 0-Key 7 need to have pull-up resistors somewhere in the circuit.
Now that we can read the keys in, we still need to be able to select the banks individually. We could simply commit another eight I/O pins, but we could improve on that. By using a 74HCT138, we only need three. A 3-bit number has eight different possible values, exactly what we need.
If you are familiar with reading schematics, you'll notice that the outputs are inverted. This means our active line is low. Just what we want. Where we started with 61 I/O, we now have 11. Not too bad. Almost done here.
Rather than tie directly into the microcontroller, I shoved a Schmitt inverting buffer in the middle. Initially I did this with the intent of using the output enables, but that ended up not being a thing. It does invert our logic though. Pressed keys are now a '1', and unpressed are '0'. You can see the pull-up resistors I mentioned earlier, but also take note of the caps. These help in debouncing our switches. Any high frequency jitter is shunted to ground.
Yellow line is the key press, green is the output of the Scmitt inverter. Notice that the yellow line doesn't go all the way to ground due to the diode in line with each key. The green line however is rail to rail, and nice and square.
I soldered most of circuit together before thoroughly testing each section with the general knowledge that it would work. And for the most part it did. With the MIDI hooked up to my computer I was able to play normally and everything appeared to work great. Then, while showing it to my girlfriend, she pressed three adjacent keys simultaneously and the notes all stopped playing. This caught me by surprise as I had been able to play chords using all of my fingers with no problem up until then. But not all combinations of three adjacent notes caused this problem, and I had had the foresight to write the number of each key within its bank on each key just for debugging. Any three keys within a bank was the problem. It's surprising how rarely that happens during regular playing.
My first thought after checking all my soldering was dig into the firmware. I looked at all my code for any logic that could cause this anomaly and saw none. Then I started running with breakpoints, and sure enough, it was reading in all the notes as off if I played more than two in a bank. Time to pull out the scope. Using the oscilloscope I was able to watch the outputs from the Schmitt inverter. Curiously, as I pressed a third note, the outputs would jump low. What was going on?
The cause was subtle. If you look at the yellow line in the scope capture above, it sits about one diode drop above 0V. As you press more notes in the same bank something interesting happens: that line moves a tiny bit further away from 0V, until it triggers the Schmitt input high. How? Why?
Turns out this one was kinda my bad. All the current going thru the pressed keys is sunk into the output of the 74HCT138. That output is a semiconductor with non ideal characteristics. If you read the datasheet, as the current increases, so does the offset between the output and ground. Looking at my design (and ignoring the diode) each key is going to source about 5mA ($5V/1K\Omega$). That's actually kind of a lot for this circumstance. Three keys would be 15mA. The combination of the output error plus the diode drop was enough fake out the inverter.
So how do we solve this? Everything is already soldered in place, it would be a huge hassle to put larger resistors in place. Let's rethink the problem Our pull-ups are all in parallel, meaning that each additional key press makes matters worse as the total resistance between Vcc and the 74HCT138 output gets smaller. If all eight keys are pressed, the eight 1K resistors in parallel total 125$\Omega$. That's a huge 40mA at 5V. I don't even think it's supposed to be able to handle that much current....
We do know that two keys works just fine though. The trick is to make that our worst case scenario. The total resistance of two key presses is 500$\Omega$. If we just add a resistor in series between Vcc and the pull-ups, we can guarantee that the total resistance will never be less than 500$\Omega$, even if we could press an infinite number of keys. And this fix requires very little rework. Much harder to track down than to fix.
We'll continue the design in the next post. I've added a clip above of me testing the software and hardware for your enjoyment.
While I was breadboarding the Virtual Whammy Bar I decided I could do more than just send some MIDI messages. So I grabbed a little MOSFET and a small motor, used a PWM output on the PIC16F916, and wrote a bit of code. Nothing more than just an experiment. I drew a red dot on the output pulley of the motor (not that it helps much in the video) to see the movement. It's probably easier to hear the change in speed. Also, I believe I did this before I gave the light sensor more of a log response (in code, via a lookup table), so after a certain point, the speed changes rapidly with very little movement of my hand. But this was just for the sake of doing it.
For some reason or another, I was tearing into a couple of laptops that didn't need reassembling. Or maybe they weren't worth reassembling. But either way, I ended up plucking the track pad out of one of them. I noticed that the module only connected to the rest of the computer via only a few contacts. At least have to be power and ground, meaning it's likely a serial interface. After a little bit of research on the Synaptics chip at the heart of things, turns out it's PS/2.
I had always assumed that PS/2 was more or less obsolesced, only continuing to be supported because so much consumer hardware is out there, and for industrial settings. If I had to guess, a track pad would have been internally tied into USB. In any case, it's a serial protocol, I can probably talk to it from a microcontroller.
Leads soldered to flex circuit.
PS/2 is a bit odd, almost like I2C in reverse. I never actually found a definitive resource on the protocol, just gleaned a few things from various websites and from the Synaptics literature. There is a data and a clock line, which require pull-ups, but the device controls the clock. The host must create a start condition to get the device to begin clocking, and have the data available on rising edges. Unfortunately, I couldn't see a way to use the peripherals of a PIC16F916 to emulate the protocol, so I had to bit bang it in software. The micro didn't have to do much else though, as I just wanted to output MIDI (I know it seems like all I do, but it's just a fast way to make a device talk to other existing devices and accomplish something).
I definitely learned a lot going thru the Synaptics implementation guide. For instance, the pad has both a relative and absolute mode, as well as a polling mode. It was much easier to use absolute positioning, and since I was emulating the protocol in software, the polling mode meant I didn't have to constantly keep track of the clock pin. I would know when to expect data. I can choose my own update rate and just grab the track pad data as needed.
Synaptics track pad packet format
Once configured, whenever my host requests data, it receives the packet above. An interesting piece of information is that "Z pressure." Maybe I can play with that. You'll see in the video later in this post where I enable Z interaction while holding down one of the buttons.
Communication between the PIC and track pad
As this is merely an anecdotal post, I won't go into much detail. I wrote up a small bit of code to setup the track pad and talk to my PC over MIDI and experimented a bit. I just wanted to know I could. Perhaps I'll come up with a good use for the track pad, but until then, here's some footage of it in action:
Some time ago I acquired an old Korg DW-6000 synthesizer from a friend's dad. This thing was at least a couple decades old, and showed it. But it was a true synth with programmable sounds, and I was interested in playing around with it.
As someone who plays music regularly with various groups, it was not really worth lugging around. It was big, rather heavy (35 lbs), and didn't have very good piano sounds. Newer keyboards that people had were full of high quality orchestral sounds, lighter, and also had velocity sensitive keys (hitting the keys harder makes a louder note). However, it's synthy sounds were nice, as well as could be customized. So what to do? Well I decided to rip the guts out and make a rack mounted synth from it. Then I could install it with the mixer and PA, and people (including myself) could bring their nicer keyboards, and when wanting to use the DW-6000 sounds, plug into it via MIDI. That however is another project. For this one, I'm going to use the existing keys and make my own MIDI controller.
Most of the devices you would consider to be a keyboard or synth are actually a combo of two elements: a controller and a synthesizer. The controller is generally the thing that allows user input (though arpeggiators, drum machines, and playback devices also count). Most often it is in the form of a piano keyboard and includes the foot pedals and expression wheel. But there are other forms they can take, from digital drum kits to electronic clarinets and keytars, or even my Virtual Whammy Bar. These devices all capture the performance and create MIDI commands to send to other devices. The synth is what you'd expect: it makes the sound. A controller will tell it to turn notes and and off, or how much vibrato, or a variety of other pieces of info that can affect how the music will be produced. Again, the controller and synth are often combined into a single package, but can still be used independently most of the time. A keyboard with MIDI OUT can control another synth, and if it has MIDI IN, there is a good chance another controller manipulate it.
So really, I'm dividing the Korg into its separate functions. Except, I can capture the performance in more ways than the original DW-6000 could. I can add a few modern features and a couple more inputs:
The ability to divide the keyboard up into zones (3 or 4 max). This means you could control more than one instrument from the same controller. The lower octave or two could be used to control a bass and the rest of the keyboard could control strings for example. Of course you need a receiving synth capable of performing different patches simultaneously, which is not uncommon. A PC would do. Or most modern synths.
The ability to set octaves for each zone independently. If you were doing trumpet and clarinet at the same time, you wouldn't want to only be able to play low notes on the trumpet simply because it's using the lower part of the keyboard, nor only high notes on the clarinet because it lies on the upper portion. The instruments tonally overlap, and by adjusting their octaves this can be achieved.
Transposition. Ever learned a song in an easy key like G, but then been asked to play down half a step because the singer can't hit the high notes (I'm usually that singer, and it's usually more than half a step)? A transposing feature allows you to adjust the note you're playing by any number of semitones so that you can keep playing it the way you learned. It is very similar to a guitar capo.
Patches for different keyboard layouts. You might have a variety of zone arrangements, each with octave, channel, or even volume settings which you would want to recall whenever you play a specific song. A store and recall function would prevent having to redo setup work every time.
Additional input. The keyboard current has a sustain pedal input, and a joystick which does pitch bend, modulation, and VCF. I'm adding input connectors for an additional on/off function as well as one more analog input.
Assignable functions to all pedal and analog inputs. Depending on the synth, there are a ton of parameters that can be varied in real-time to affect the sound. This can help achieve more techno sounds, or control more traditional things such as sustain, damper, volume, or whether a chorus effect is on or off.
A character LCD and some buttons for a UI. Users will need to be able to do tasks like load up patches, set the keyboard octave, transposition, or channel on the fly. Maybe not everything can be done at the keyboard, but at least all the things you may need to do while jamming with others.
A PC program for advanced configuration. Configuring zones and inputs is going to be a much easier process on a computer than thru the limited inputs on the keyboard itself. MIDI can be used for dumping and editing patches.
That's more or less the things I want to do. I have pretty much a set of plastic keys and a joystick to start with. We'll start blocking it out next time.
With a working amp design and a suitable power supply, I was able to make the device. Just a bit of soldering, drilling, and hand filing (a 15/16 bit is hard to come by) I had a final product.
Whiteboarding, with random calculations to try and explain circuit to a
non-math person (including how to ruin an LED)
Blank Canvas
Solder Side
Component Side, nearly done
It assembled nice and cleanly, and worked well. Should get installed soon, and that's that.