The Digital Circuitry
As a follow-up to his article “The Teensy Audio Station: Part 1” in the September issue #386 of Circuit Cellar, Brian dives into the digital circuitry of his Teensy Audio Station project.
In “The Teensy Audio Station: Part 1,” published in Circuit Cellar’s issue #386 in September, I described a project that encompassed a two-in, two-out digital audio interface, which included control surface functionality. The project interfaced with a PC using a USB port, which handled both the digital audio stream as well as the MIDI messages that provided the control surface functions. Although I started the project using the top-of-the-line Teensy 4.1 module, I determined that the older Teensy 3.6 module would have more than enough power to handle everything. The two modules are almost pin-compatible, so the switch to the Teensy 3.6 was simple. This month let’s start by examining the digital circuitry surrounding the Teensy 3.6 MCU.
THE TEENSY MCU AND DIGITAL CIRCUITRY
Although the two schematic diagrams for the project break it down into MCU/digital and mixed-signal/analog, the actual circuitry on each board is not organized in exactly this way. Instead, the Teensy 3.6, fader motor controller, ADC, DAC, and front-panel user interface circuitry are all mounted on the larger Vector 8001 protoboard. All the strictly analog circuitry, plus the DC-DC converters that power them, are contained on a second, smaller protoboard.
In the last article, I described the analog and mixed signal circuitry. Now we’ll look at the digital circuitry. Please refer to Figure 1. All 14 pushbutton switches are connected to individual GPIO pins on the Teensy 3.6. I make use of the pin-change interrupts on all of these GPIO lines to respond to the pressing of the pushbuttons, without the need to constantly poll all of them in the operational “loop” portion of the program. No pull-up resistors are shown, as the GPIO lines have an internal pull-up option specified in the “setup” function. The display is an Adafruit 128×64 OLED Featherwing, which interfaces with the Teensy via an I2C port. The display is powered by 3.3V from the Teensy’s onboard regulator. The Banggood optical encoder provides 100 pulses per revolution and puts out clean 3.3V pulses on both the A and B outputs.
An LM1086CT-5 regulator supplies 5V analog for the headphone amplifier. To reduce its dissipation, I use 16.4Ω to drop the 12V main power supply down somewhat before feeding the LM1086CT-5.
A separate 7805 regulator (with an 8.2Ω dropping resistor at the input) powers the TB6612FNG dual H-Bridge driver chip used for the fader motor.
THE MOTORIZED FADER POT
This project was partially conceived to fulfill my desire to build an audio project using a 100mm motorized fader potentiometer (which are now priced reasonably enough to make them attractive to me). Professional music studios have long used motorized faders, even in older analog mixers. This allowed them to automate the mixing process somewhat by “recording” the fader movements made by the audio engineers during the recording process, and “playing” them back later in the recording cycle.
Not having worked in that industry, I never had a chance to take any of these professional mixers apart, but I am quite sure that those 100mm (4”) motorized faders were well-made assemblies that probably cost hundreds of dollars. Today, however, Bourns makes very nice 100mm motorized faders for about $20. This price drop is likely due to the proliferation of commercial “semi-pro” sound mixing equipment, which sometimes features these devices. Figure 2 shows a bottom and side view of the Bourns PSM01-081A-103B2 100mm motorized fader that I use for this project. Figure 3 is a schematic diagram of the part. It uses a tiny brushed DC motor coupled to a slide-type potentiometer via a small, toothed belt. The pot actually contains two potentiometer tracks. One section of the pot is reserved for whatever the user wants the pot to control, and the second section is used as the feedback element for the servomotor’s control loop.
These Bourns motorized faders are available with either linear tapers (B-code) or various pseudo-logarithmic tapers (A-code). For conventional analog circuits, one of the various pseudo-logarithmic tapers would be used. However, for volume faders on digital audio equipment, the logarithmic response that is needed to match the wide-range human hearing response is mapped to a linear range and stored as a 14-bit integer. Since I was designing a digital mixing unit, I chose the Bourns PSM01-081A-103B2, which features a 10k pot with a B2 linear taper. Figure 4 shows the B2 taper. Basically, it provides a linear response throughout the full travel of the potentiometer but allows for a 10% mechanical over-travel at both the top and bottom of the slider’s travel. This makes an accurate servo response somewhat easier to achieve at both extremes of the pot.
For this project, I use an industry-standard communication/control protocol: the Mackie Control Universal (MCU) protocol. This was designed by the Mackie company, which makes studio mixers. For Mackie protocol fader control, the full travel of the slide fader (or rotary pot) is linearly mapped onto a range of ±8,192. The “zero” end of the pot is mapped to -8,192 and the 100% end is mapped to +8,192. Being a linear mapping, the mid-point of the pot is mapped to 0. Converting this linear response to the necessary logarithmic attenuation of the audio signal is left to the mixing software itself.
If you are well-versed in the MIDI protocol, you will notice that this ± 8,192 range looks suspiciously like the range used by the MIDI Pitchbend control message. You’re not wrong—the MCU protocol uses MIDI Pitchbend messages to transmit slide fader positions. The audio track (referred to as “the channel” in MCU protocol) that this Pitchbend message affects is determined by the MIDI channel
(1-16) on which the Pitchbend message is sent. Since large commercial mixers generally contain more than 16 channels, these channels can be further broken down into a number of banks, with each bank containing up to eight channels.
When the motorized slide fader is used in the above manner, it turns out that one of the fader’s potentiometer sections can serve a dual purpose, leaving the second section unused. To do this, we will feed the fader potentiometer with a fixed 3.3V and connect the pot’s slider terminal to an ADC contained in the Teensy MCU. The MCU can easily determine the position of the fader from the ADC voltage reading. This ADC reading can then be scaled into the ±8,192 range and sent out as a fader position message (i.e., a Pitchbend message) to the digital mixer—generally, digital audio workstation (DAW) software running on a PC.
That same ADC reading (representing fader position) can also be used as a feedback input to a servo control algorithm. This allows the MCU to send the fader to whatever position is called for, by any fader position control messages arriving from the DAW software.
To control the DC motor that moves the fader pot, you need a bipolar voltage to be able to drive the motor in two directions. Rather than using a variable DC voltage to control the speed of the motor, it makes more sense to use a fixed voltage and switch it on and off using a high-frequency PWM signal. This approach is routinely handled by what is called an H-Bridge, and specifically one in which the motor drive voltage can be modulated by a PWM signal.
Before I even started designing this project, I closely studied the Bourns motorized fader datasheet. The motor was specified as a 10V unit needing 800mA starting current. Based on that, I decided that I would use a 12 VDC power adapter to run the unit. That would handle the fader pot’s motor easily. I would also use that 12 VDC power supply to power the isolated ±15V DC-DC converters for the analog amplifier circuits as well as the ±24V isolated DC-DC converter which provides the microphone’s 48V “phantom” power. The Teensy 3.6 board’s MCU and support circuitry get their power via the USB connection to the PC.
Modern H-Bridge IC devices meant to handle small motors are generally packaged in tiny SMD packages. I decided to use the Toshiba TB6612FNG device, which can handle motor supply voltages up to 15V at currents of up to 1.2A (avg). It contains two discrete H-Bridges, only one of which I needed. The TB6612FNG comes in a SSOP24 package and would have been hard for me to adapt or mount on the Vector 8001 protoboard that I was using. However, Sparkfun makes the ROB-14451 breakout board, which contains the TB6612FNG, and I decided to use that.
The TB6612 contains three control lines for each H-Bridge circuit. Two of those lines control direction, braking, and idle, and the third line is the PWM signal input. I used GPIO02 and GPIO03 for the control lines and configured GPIO4 for PWM signal output.
The Teensy 3.6 can generate a wide range of PWM frequencies at various resolutions. Generally, the higher the PWM frequency, the better it is for smooth motor control (within reason). I chose 14,648 Hz as the PWM frequency—this gave a resolution of 12 bits, which is more than adequate. This PWM frequency is high enough that I can’t hear any audible whine when the fader is moving it (younger readers might if they haven’t attended too many rock concerts!).
I knew I would need some form of PID algorithm to take the target fader position and convert that into a motor control PWM value/ motor direction command. The error term would be derived from the ADC reading that corresponds to the fader pot’s current position.
The ADC contained in the MK66FX1M0VMD18 MCU on the Teensy 3.6 board is specified as a 16-bit ADC, but it only has an effective number of accurate bits (ENOB) of 13. I am executing the servo control algorithm at about a 50 Hz rate, but the Teensy 3.6’s ADC can be read hundreds of thousands of times per second if desired. I settled upon reading the ADC once per servo control loop, but using an IIR filter with an alpha of 4.0 to smooth the ADC values a bit (without introducing significant lag in the servo response).
My past work experience with PID control algorithms was strictly concerned with temperature control. Here, I figured I’d have to “play around” with different control parameters and just watch how the fader responded. Given this trial-and-error method, I initially decided it was prudent to limit the motor voltage to less than the 10V rating shown in the datasheet. I didn’t want it whipping around uncontrollably while I was figuring out the PID code and coefficients. Therefore, I manually hooked up the motor to a variable DC power supply to determine the minimum voltage needed to move the fader at an acceptable rate. It turned out that 5V was plenty for my purposes.
Although I designed the project’s 12V main power supply based on the motor’s 10V datasheet specification, I probably could have replaced the 12V power adapter with a 5V power adapter and used matching DC-DC converters to derive the ±12V power rails needed for the analog circuitry and the 48V “phantom” power supply. But since I already had a 12V main power supply baked into the design, I supplied the fader motor’s H-Bridge driver IC with a dedicated 5V supplied from an LM7805 regulator. I used a few dropping resistors between the 12V and the 7805’s input to lower its power dissipation.
The servo algorithm that I settled on is simply a proportional control (no integral or derivative terms). With a motor power supply of just 5V, it took a minimum PWM duty cycle of about 55% to get it started from rest. Therefore, I added a minimum 55% PWM value to the proportional algorithm calculation. The full travel of the fader pot is represented by the ± 8,192 range of the fader position MIDI command. Similarly, the full travel range of the fader pot corresponds to the full-scale value of the ADC. I use the 12-bit resolution setting of the “ADC_read” function (part of the Teensy library) and I scale that 12-bit value into the ± 8,192 range. As mentioned earlier, I also do IIR filtering on the ADC readings.
Within the ± 8,192 range of the fader’s travel, I incorporate a 150 count “dead-band” into the control algorithm. This is a bit less than 1%, which corresponds to about 1mm of fader travel. This is as fine an adjustment as you can do with the human hand, and this “dead-band” is needed to eliminate a constant “hunting” around the target position. Such hunting would wear out the pot’s carbon tracks prematurely. When the pot is positioned within this dead-band, the PWM signal sent to the motor is set to a duty-cycle of 0%—i.e., off.
You might wonder how I determine who or what has control of the positioning of the fader—the operator or the fader position command messages sent from the DAW. The DAW software has option buttons for Automation Read and Automation Write, and my unit has both Automation Read and Automation Write buttons that send the appropriate messages to activate those options. However, the fader has a metal actuator for manual operation that is isolated from ground (and anything else). This actuator is connected to a dedicated “touch sense” terminal on the fader.
I use an Atmel (now Microchip) AT42QT1010 touch sensor IC to sense when the fader has been touched by the operator. The AT42QT1010 comes in a tiny SOT-23 SMD package, and I mount it, along with a few passive components, onto an SOT-23 to DIP adapter PCB as shown in Figure 5. This small assembly is covered in heat-shrink tubing and mounted right next to the fader’s “Touch” terminal. The AT42QT1010’s Sense terminal connects directly to the “Touch” terminal of the fader pot. Luckily, I keep these in stock, as they are one of the ICs that are now out-of-stock due to chip shortages.
While I didn’t actually try it, there’s a small possibility that the Teensy 3.6 MCU would have been able to handle this task using one of its touch-sense capable GPIO pins. I somehow doubt it, though, since it would have required a 4” (possibly shielded) wire to connect the fader’s touch pin and a Teensy MCU GPIO line that can be configured for touch-sense operation. In contrast, the AT42QT1010 is directly connected to the fader’s “touch” terminal, eliminating any stray capacitance, RF signals, etc. Also, the Teensy MCU’s touch-sensing library function is certainly not as robust as the dedicated algorithm contained within the AT42QT1010. The AT42QT1010 has a digital output signal which is read by the Teensy 3.6’s GPIO6 pin, and this signal is not affected by noise, etc., in any way.
GENERATING THE FIRMWARE
The source code for the AudioStation firmware is available on Circuit Cellar’s support website. I developed the program using the Teensyduino tool for Arduino, version 1.54. This works properly with the latest Arduino version, 1.8.15, which is what I use. There are a couple of Adafruit libraries needed for the Adafruit OLED display. These are listed among the #includes at the start of the program and can be added using Arduino’s library manager. After loading the .INO file, you have to set the target board for Teensy 3.6. For the USB type, you must enter “Serial + MIDI + Audio.” This is important—without this setting, the program won’t even compile!
As soon as the Teensy is plugged into the PC USB port, it will enumerate as an HID device with the Teensy title. After the firmware is programmed into the Teensy 3.6, it will reboot and present itself to the PC as a “new” composite USB device. Wait a few minutes for your PC to enumerate the Teensy as three “new” devices: Serial, MIDI, and Audio. Some messages will likely pop up on the screen as this is happening. Once this is done, you should open the Device Manager utility and check the Ports (COM & LPT) where you should see a new USB Serial Device (COMxx) port. In Device Manager, looking in the Sound, video and game controller tab, you should see two new instances of Teensy MIDI/Audio. One is the MIDI port and the other one is the Digital Audio port. If you select the tiny speaker icon in the task tray, there should be a ^ symbol on the right. Selecting that, you will have the option to choose “Digital Audio Interface – Teensy MIDI/Audio” if that has not already happened. At this point, if you open any program that provides sound, you should hear it in headphones connected to the Teensy AudioStation. This sound will also be present at the line outputs and can be heard if an amplifier is attached.
CONNECTING TO A DIGITAL AUDIO WORKSTATION PROGRAM
There are numerous DAW software packages available for the PC computer. Most of them are rather expensive, including the Cakewalk Sonar package which I have used and constantly upgraded over a 20+ year period. The Cakewalk company only produced DAW software for all of those years, quite successfully. However, about six years ago they were purchased by Gibson Brands, Inc., as part of a whole rash of acquisitions. A few years later, Gibson was teetering on the edge of bankruptcy and the Cakewalk Sonar software was sold off to a Malaysian company called BandLab. The same expensive software that I have been using for years has now been made available for free by BandLab under the title “Cakewalk by BandLab.” Since this is what I am currently using, I’ll describe how my Teensy AudioStation interfaces with this software.
After starting Cakewalk by BandLab for the first time, it will generally take you through a series of steps to set up the MIDI and Audio ports. If it doesn’t automatically prompt you to do this, you go to the Edit -> Preferences menu and use the MIDI Devices tab to pick Teensy MIDI/Audio for both the input and output. See Figure 6.
Next you need to choose the Digital Audio port. Using Edit -> Preferences, choose the Audio Devices tab and select Digital Audio Interface (Teensy …) for both input and output. See Figure 7.
The last thing to set up is the Control Surfaces. As mentioned earlier, I am using the Mackie Control Universal protocol. That is the most common Control Surface and is available as a choice in the Edit -> Preferences -> MIDI Control Surfaces tab.
There may be a bit of a complication here. At least with earlier versions of Sonar that I was using, the “Mackie Control” option used a driver that was not optimal. When I chose this option in the past, for an earlier control surface device that I had built (also MCU protocol compatible), it failed to work. After some investigation, I determined that the Sonar Mackie Control driver sent out a “Device ID Request” System Exclusive message, and simply waited until a corresponding “Device ID” System Exclusive message was returned from the control surface. With my earlier device, this never arrived, with the result that it appeared like the Mackie control surface was not present. Therefore, on that unit, I mounted a separate switch labelled “Connect” which sent out the expected system Exclusive Device ID response message:
F0 00 00 66 14 1B 58 59 5A 00 00 00 00 F7
I later found an improved Mackie driver file which had an option to ignore this handshaking routine at startup. This was written by MS McLeod and can be found on Github .
Cakewalk by BandLab now comes with this improved driver. So, you now choose the MMcL Mackie Control #1 option. Once you have picked this driver, you must set the option to ignore the handshake at startup. Right click in the upper toolbar and select “Show All Modules.” A new Control Surface window will appear in the toolbar including a box saying “MMcL Mackie Co….” Click on the list icon at the lower left corner of the Control Surface window. Referring to Figure 8, you can see where you have to check off the “disable handshake” box. Also note the settings for Jog Wheel (Ticks) and Transport Resolution (Beats). Lastly, set the F1 Function Button to “Go to start (RTZ)” and F2 to “Key press Ctrl + Z.” The latter two settings are needed to allow the Rewind and Undo buttons to work properly.
In this project I removed the sending of the System Exclusive message listed in the left column, due to the availability of the new driver which eliminates the need for it.
If everything is working properly, the highlighted track in Cakewalk should follow what you set on the AudioStation by clicking on the Chan button and turning the Jog wheel. The other buttons should also work accordingly. The Jog wheel encoder will either set the active channel, adjust the Pan setting, or move around the recording in steps of 1/1000 of a second (which Cakewalk calls a “Tick”). Pressing either the Chan or Pan buttons toggles the adjustment mode for Channel or Pan, and when neither are active the jog wheel moves the cursor around the recording in time.
Table 1 shows a list of all the MIDI messages that are sent out in response to the various buttons and the Jog wheel encoder.
Thanks to the efforts by the Teensy community in developing the Teensy Audio library, writing the software was not a very large part of the project. Instead, building all the circuitry took a lot of time, the bulk of which was spent designing and building the various analog signal chains.
Unlike a commercial product where all the switches, pots, and input/output jacks would be mounted on a PCB or two, this project contained a lot of hand-wiring between the two boards and the top/rear panel. I hate to admit it, but the inside of this project’s enclosure is a bit of a rats’ nest.
During my long career, which involved a fair share of servicing electronic instruments, I sometimes muttered under my breath, “Who designed this? They never thought about the poor service man.” For this project, anyway, I’m one of those thoughtless designers!
Teensy 3.6 Arm MCU module:
ROB-14451 motor control module with TB6612FNG:
Adafruit 128X64 oLED display ID 4650:
Bourns PSM01-081A-103B2 Motorized slider pot
AT42QT1010 Touch Sensor:
Cakewalk by BandLab:
 Github link Mackie driver file written by MS McLeod: https://github.com/msmcleod/Cakewalk-Control-Surface-SDK
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • NOVEMBER 2022 #388 – Get a PDF of the issueSponsor this Article