-
Notifications
You must be signed in to change notification settings - Fork 4
Alternative Designs
Per the FAQ, "Why are you using ADCs?" is a common question. The most common suggestions are something like:
That's an option. Just powering the LEDs with constant current, and then hooking the comparators up to enough GPIO pins that we could trigger interrupts from all of them would be an improvement over his design.
Since I want to have sensors on hammers and key sticks, and you need at least 2 comparators per sensor, that's 384 comparators. But that's not insurmountable.
Do almost what CyberGene did, but replace the trimpots with DACs since you don't want to adjust things manually.
The problem here is that DACs are "less common" than ADCs. Given the parts that you can buy, today, from electronic component manufacturers, it is easier to get ADCs than DACs. The ADCs are denser, and cheaper per channel than DACs.
This isn't immediately obvious to the naive Internet commentor. The two things sound like inverses, they know just enough to know that DACs do actually exist, etc, etc. Obviously hundreds of DACs just shouldn't be a problem.
I'm not positive why DACs are less common, but my expectation is that microcontrollers and electronics in general are used to take in sense information from a bunch of sources, and then synthesize it to control 1 thing. Hence, lots of sensors coming in via ADCs, and just a handful of control signals going back out via DACs. The motor control case is a common one. You put a single microcontroller on a motor to operate it, and it measures many channels of back EMF, plus input voltages, currents, temperatures, encoder outputs, vibration, etc. And the outputs will just be when to connect/disconnect motor phases from the bus power.
That was basically the original project. So, you could do that.
TODO clean this up a bit more
Teensies are relatively quite expensive. I don't remember my calculations from trying to work out such a design, but I believe the one design being worked on requires 11 Teensies, and still needs a bunch of external, relatively expensive, ADCs soldered onto a carrier board for the corresponding Teensy. That's about $300 in Teensies, compared to about $152 in microcontrollers for my system. The board-on-board soldering necessary to get high-speed interconnect between the Teensy and external ADCs is not a service offered by discount assembly houses. So any implementation is going to require standard price assembly houses (not cheap), if they'll even take the job.
(Note that "Raspberry Pi" is a company name. The product name is "Model $X", "Pico", "RP2040" or something. The Pico is wildly different from the the Models 1/2/3/4. It is powered by the RP2040 microcontroller. Familiarize yourself with the differences before proceeding.)
(Reference to Characterizing the Pico ADC here.)
We can get a ~20kHz sampling rate of the 22 channels on the STM32H7. What if you want a dramatically higher sampling rate, for whatever reason (and you're willing to lower your sampling resolution)?
The RP2040 has an ADC with a sampling rate of 500kS/s, and a 4 channel mux. So we can get 2 channels of 250kS/s or 4 channels of 125kS/s. Take your pick, we'd need somewhere between 6 and 11 of them on a single board. The RP2040 has no flash or nonvolatile storage of its own, so we'd also need to provide external storage for every one of them to hold its own. We also need to provide some linkage from the RP2040 to whatever is going to synthesize our system's final MIDI output. That's somewhere between 48 and 88 RP2040s communicating to something. There aren't many somethings which can receive "fast" data streams from that many devices. We'll need an intermediate. (We could also try to build some sort of network. Or a couple of separate networks. CAN and RS485 are options. RS485 would be easier. RS485 transceivers are somewhere between $0.75-$5.00/ea depending on model, features, availability, etc. You need one for each of those 48 to 88 RP2040s, plus another one on the main board end for every separate network you want to run, the more you run the less they interfere with each other.)
So we're back to something kind of like my current design, with ~8 ADC boards talking to a main board. But the ADC boards have 6-11 RP2040s, something to take digital data streams from them, and package it up into one outgoing stream for the main board.
11 * 500kS/s * 12 bit/sample = ~8.25Mbit/second. We could bring that over one or two SPI buses to a microcontroller. But we can't do much with it. 5.5MS/s would leave a 480MHz processor with 87 cycles per second, and we've got overhead to account for. Anything we could safely fit on there we could just run on the RP2040s themselves. They could then signal an interrupt when something interesting happens, and then store a record of whatever it was to be picked up by a SPI read. Our aggregating microcontroller then needs 11 inputs for these signals, 11 chip selects to signal which part to read from, and a SPI interface (CLK, MOSI, MISO). That's 25 digital IO. Then a UART for upstream communication, and we could fit all of this into a 44 pin part.
But what about program storage for the RP2040s? 11 flash chips seems like a pain, and will about double the cost of using the RP2040s.
Instead I think you could get the microcontroller to either pretend to be a QSPI device, and have the RP2040s read their program from it, or have it sequentially turn them on, so only one is attempting to read from the QSPI at once. If the first thing they do is copy their program to SRAM and run off of that, they might(?) be able to share.
Finally we've got to deal with the RP2040 package itself. They're leadless 0.4mm pitch 56-QFN devices. That is possible to hand solder, but you'd really want to use an assembly house for it.
Ok, we've established that DACs and comparators are a route, but DACs aren't common. But, we can actually make DACs, if we pipe a high frequency square wave through a low-pass filter, the output will be a voltage proportional to the duty cycle of the square wave. Where can we get high frequency square waves with varying duty cycle?
FPGAs could easily implement the logic necessary. For every "DAC" you run an N bit counter; at every cycle compare the counter value to some set target. As long as the counter is below the target, emit 1, above the target, emit 0. The output resolution of your DAC is equal to the bits of the counter. The output frequency of the square wave (which we want as high as possible, to make the low pass filter easier to impement), is cycle frequency / 2^N. You'd need a ~66MHz clock to get emit a 1kHz square wave from a 16 bit counter. ~666MHz for a 10kHz square wave. I think we'd want at least a 100kHz square wave. (I wouldn't be surprised if some FPGAs offer PWM circuitry already builtin.)
NOTE: There's probably a better architecture for such things. You could probably combine multiple outputs to reduce the demands, but that starts demanding more pins on the FPGA. We already need 1 per DAC.
I'm willing to assume that it is possible to make this part work, with some effort.
Now, comparators. We need a lot of them. Can we use purely digital FPGAs to implement analog comparators? In fact, we can. Many FPGAs have "differential" inputs, where they look at a pair of pins to determine if the input is 0 or 1. Instead of comparing the voltage coming in to some absolute reference, they instead compare two voltages to each other. If the P input exceeds the N input, then that's a 1. If the N input exceeds the P input, that's a 0. And that's great, that exactly what we need. We have to be careful to keep our inputs in the range the FPGA can tolerate, but I'm willing to assume that's possible.
Then what you want to do is, internal to the FPGA, have a very high resolution clock free running, at >=10MHz. Whenever one of these bits flip (and stays flipped for a couple of cycles) grab the value off that counter, and dump it, the bit flip direction, and an identifier for the pin into some queue which can be read out by a microcontroller. Pretty easy digital logic stuff.
Now, why didn't I pursue that?
We need 2 DACs and 2 comparators per sensor. The comparators are taking up two IO pins. That's 6 IO pins per sensor. Suppose we want to get 22 sensors onto a single FPGA, the same way my design gets 22 channels into a single microcontroller. That alone will consume 132 IO pins; there'd probably be a couple dozen power and debug pins, so we'd be looking at some >144 pin package. There are FPGAs in packages with leads, going up to about 240 total pins. Of the ones available from Digikey, they start at $16. I'm not sure the cheap ones would have enough programmable logic in them for the task. It looks like the ~$30 parts would be more appropriate. (Why not unleaded packages, like BGAs? They basically require professional assembly. I realize the average person reading this is probably convinced they couldn't assemble the boards I've designed, but since they don't possess the skills necessary, they're not actually qualified to asses how hard it would be to acquire the skills.)
Developing "firmware" or whatever you want to call it for FPGAs is also a more specialized skill. I've done it, and could probably do it again, but it would dramatically limit the set of people who could participate in the project. If the STCubeIDE development environment and low-level C looks intimidating, VHDL/Verilog would be worse. FPGA manufacturers still like to charge (lots of) money for their software tools, another limitation.
If you could design and spin ASICs, cramming a bunch of DACs and comparators onto a chip would be trivial. You could use standard DAC designs, without the fast clocks, and the DAC could be directly attached to the comparator internally, so you'd just bring one pin out per sensor. One or two chips could cover all the sensors in a piano easily.
If you get the design right the first time the first chip will cost you >$10k, and the rest a few pennies each.
See also Alternative Piano Mechanics.
The TIA design currently in use controls the voltage across the phototransistor, and then measures the current through it, amplifies that, and sends it over to the ADC.
(For reference, the CyberGene-style system controls neither voltage nor current, and then measures voltage.)
Instead, we could control the current through the phototransistor, with a very weak constant current source (0.5mA? 0.2mA? less? dunno), and then measure either the voltage which develops across the phototransistor, or some control voltage from the feedback loop necessary to control the current.
I've been looking at ways of doing this and don't immediately see a way to do it for cheaper than the TIA method. I'd expect we'd also introduce some additional nonlinearities into the measurement process, as we'd be sort of flipping around fig 6 of the CNY70 data sheet in strange ways. But if we could "undo" some of the 1/r^2 aspect of the reflectance sensing, and get something which is closer to being a linear function of distance, even if there are distortions, then it might ease interpretation of the readings from the ADC.
Idea here is that you differentiate the position signal in analog circuitry, so your ADC converts voltages which are directly proportional to velocity.
The problem is that physically realizable differentiators have limited bandwidth. I'm about 95% sure that the bandwidth necessary to stabilize a differentiator of our signals would require a prohibitive GBW from the op amps used. (Prohibitive means something between "the op amps simply don't exist" and "maybe they exist but i can't afford to buy a single one, let alone 176".)
An ideal differentiator would be great, but this seems to be one of the many cases where we can't reach ideal.
We'd probably still need to measure the position signal with an ADC. So we've doubled our ADC channel requirements. They might not all need to be measured very quickly, so that would "help". (Basically it adds enough extra complexity that I'm unwilling to take the time to bring that 95% above to 99.9%, because then I'd still have this hassle to deal with.)
Any use of magnetism would require some modification of the hammers, to add a magnet. Depending on their strength, they'd likely interfere with/wildly complicate the regulation of the piano, as adjacent hammers would begin to repel one another.
Ignoring that issue, the second problem is that containing magnetic fields is difficult. Again, perhaps the necessary magnets would be so weak as to make it a nonissue, but I'd plan on needing to add some mu metal shielding between every "lane" of hammer motion.
All that addressed, you have a couple of options. Hall effect sensors would allow the conversion of field strength into an analog voltage, the same as the optical reflectance sensors. I believe but am not sure that responsiveness would be similar.
The other possibility would be to lay out a linear stator on a PCB, near to the hammer's path of travel, and have the movement of the hammer induce current in the stator's elements. That current could then be measured. This would also induce drag on the hammer as it travelled, slowing it, and likely changing the feel of the action.