Thursday, July 6, 2023
JP6 filter oscillations and latch-up
Tuesday, January 10, 2023
DCO Calibration issue
After fixing the issues with calibration related to the compiler bug, I hoped everything would go smoothly. Unfortunately that was not the case.
After calibration, when running through frequencies, I would sometime see a kind of discontinuity, where the wave amplitude would drop to zero and then build back up to the correct height again over two periods.
I looked at the DAC charging voltage and could see a kind of asymptotic behaviour where the charge voltage suddenly rose much faster than it should, and when it reached max, dropping back to zero but still rising with the same speed. Clearly the DAC output overflowed.
| DAC Voltage error. The first little drop is only due to missing calibration. The asymptotic looking one is where the interpolation overflows and voltage drops to 0. |
It took some testing to figure out what was going on: For a single sample in the calibration, the dac voltage was detected significantly lower than it should, and more importantly, lower than the previous sample. This meant that the slope multiplier should have been negative. But the slope multiplier is unsigned, so it overflowed and ended up with a large positive number instead.
Then, when interpolating between the two values, we would add a large number instead of subtracting, leading to the spike (and DAC overflow) we saw.
But why did we get the wrong value during calibration?
It happens during the first cycle of a single note calibration. For some reason, we detect that the wave amplitude is too high - higher than the comparator voltage - when in reality it is not. This leads to the binary search continuing in the wrong half of the voltage range and the calibrated voltage ends up being around 32768 instead of what it should have been.
| DAC voltage calibration - 7th cycle starts off too low and never reaches back up to the correct voltage. |
Debugging the issue is a pain in the ass, because we are dependent of the wave being reset at exactly the same point every time. If something changes, the voltage may not cross the comparator voltage, and while it seems we have fixed the error, it still might be there.
I strongly suspect that what happens is that the voltage reaches the comparator voltage AFTER we have changed the dac and timer to a new frequency, but before the interrupt handler resets the wave. My fix was to move clearing of the comparator flag into the interrupt routine, so we are guaranteed that a comparator interrupt stems from the current cycle, NOT anything before it. It looks like it works but who knows...
I also saw another strange thing - some of the cycles are of different lengths than they should be, by as much as +2us. But then, often the next cycle or the one after that is a bit shorter. I have not been able to properly explain what is going on. I suspected that the comparator interrupt may have been part of it, that it triggering would make the program enter the interrupt routine before the timer interrupt, and then staying there for long enough to delay the timer interrupt, but I have not been able to confirm this. My fix was to disable comparator interrupts once we get it once during the calibration period, to prevent the code from reentering the interrupt routine due to the comparator interrupt being high. When this was NOT done, we would probably enter the interrupt routine repeatedly until the timer interrupt fired and disabled the comparator.
Now everything seems to work properly and I've started working on a verify routine, one that runs through frequencies where I suspect the charge voltage may be too high (such as in the middle of interpolation) and checking if we hit the comparator voltage during normal operation.
| Low range sweep after calibration |
| High range sweep after calibration |
I do however suspect that that is not the case. Had the timer been exponential between two key points and the voltage linear we would see an error, but both are linearly interpolated meaning the voltage should match the frequency fairly well.
We have another error too - a strange falloff at the end. The charging voltage is too low even if the DAC has not maxed out. The consequence is rather low as this is in the > 20kHz range but I still want to figure out what is going on.
Thursday, March 31, 2022
Saving the DCOs
The "correct fix"
Easier fixes (?)
Charge current
Change nothing
Update 1:
Measurements from the DCO
This is weird. I did a lot of measurements and calculations. The DAC voltages follows the pitch, no errors as we go up the scale (apart from some tiny errors at the bottom that may as well be with my probes).
Update 2:
Update 3:
I replaced the input resistor Rin and measured the DAC output for various values. Then my hunch told me to compare it to what would happen if we measured the mid point of a resistor divider between Vref and GND, where the top resistor is equal to the DAC output impedance (6.25k) and the bottom resistor is equal to Rin.
Update 4:
Increasing max frequency
Update 5:
Friday, August 4, 2017
DCO: Culprit found but not fixed
The results from various opamps varied wildly, and results from positive and inverting buffering configs also varied a lot.
My best hit was with a UA741, in inverting mode the amplitude was perfect across the entire frequency range! Unfortunately, it was only a lucky strike, I retried several other UA741s and the result varied from around 7 to around 13V amplitude (when the real amplitude should be 10V).
The conclusion then is that at voltages very close to zero will experience a lot of variation even between specimens of the same family.
| Tested op amps |
![]() |
| UA741 variations |
I am not sure how the effects are over time and temperature, this must be tested.
If the effects are mostly production variations, it would be possible to calibrate each DCO.
This can be done in code even if DAC lookup tables must reside in program memory due to RAM limitations (1kB of memory is required for DAC keystep and rise-per-substep tables and the MCU only has 1kB of RAM in total). The PIC16F allows programmatical/runtime writes to flash program memory, and though there is a limit to the number of times this can be done (>10 000), even a write on every system startup would probably be possible.
Hopefully though, calibration will seldom be necessary. As a nice side effect, calibration will correct variances in both charging caps and resistors as well as opamps.
Calibration
Here is how I imagine it to be done:
A reference voltage is applied to one of the MCU pins. This is used as the reference voltage of one of the internal comparators.
First, apply the lowest frequency. By increasing and lowering the DAC output voltage until the comparator changes polarity, we figure out
- if the voltage is too high or too low
- if the amplitude error is within acceptable limits
A slightly too low amplitude is acceptable but a too high amplitude is not as this will trigger the comparator during normal operations, if we choose to use it as a reset-on-frequency-change trigger. The amplitude must also be adjusted to always be slightly lower than the comparator trigger point to prevent false triggers.
We also have to consider measuring the highest frequency amplitude error to see if errors are always either high or low. For now, I'll assume that they are always one or the other.
After finding the initial error, one loops through the remaining 255 samples, starting from the bottom.
For every frequency, the DAC voltage is increased or lowered (based on what we found for the lowest frequency) until the comparator changes polarity - this gives us the "correct" value for that step. To save time, we may stop checking once we reach a frequency where the error is small enough (and lower than the comparator voltage).
We should now have a correct lookup table for key samples. All that is needed now is to calculate the interpolation lookup table, and write everything to non-volatile flash memory.
To minimise the number of recalibrations, we could let the DCO check the keysamples on startup. If they are still within limits, no recalibration is necessary.
A different approach to finding the current amplitude would be letting the DCO control a PWM-based DAC to generate the reference voltage. It could then change the reference voltage instead of DAC output value to find the amplitude. Not sure that it's a better approach though.
PS: If the signal amplitude is 10V, using a resistor divider with R1 = 100k and R2 = 68k will get the amplitude down to 4.048V. This lets us use the internal 4.096V voltage reference with the comparator.
Wednesday, August 2, 2017
DCO: Switching to JFET to try to improve low frequency amplitude
I found no p-channel JFET in my parts box, but I had plenty of the J112 n-channel JFETs, so to make things easier I decided to go with the yusynth design.
The Yusynth design however, has a 0-5V saw wave, whereas mine is 0 to -10V. To make sure things would still work, I changed the core ever so slightly to get a 0-10V:
instead of tapping the charge voltage directly from the DAC using a positive opamp buffer, I switched to a unity gain negative amplifier. This would sink current instead of sourcing it, changing the charging direction. To make this works one also have to replace the 2n3906 PNP transistor with a 2n3904 NPN (One should also switch the polarity of the timer output, but as both a positive and negative going spike are generated, just slightly offset in time, this was not required for testing).
But testing this, I got a big surprise - the low frequency amplitude was no longer too low - it was too high! Previously I had to increase the DAC value from 60 to 80-something, now I had to reduce it from 60 to 48 (steps times 5V/65536).
This made me less certain that switching to a JFET would improve anything, but I still decided to try it.
I added an LM311 comparator, and set its negative input to 0.118V using a 120k and a 4k7 resistor. This would assure that when the positive input was just slightly higher than 0V, the output would spike up to 15V, and when the input was 0V the output would be -15V - similarly to the yusynth circuit, where the comparator outputs a negative voltage to turn off the JFET. The circuit worked instantly (!), but as suspected, nothing changed.
So, now I guess I've ruled out the reset transistor as the cause of the offset. Also, the fact that the amplitude error changes when I swap the charging polarity, makes me believe that the cap is not at fault either (though I will still check this).
That leaves either the DAC (which is unlikely for the same reason as the CAP) or the opamp buffer.
It could also be that a small difference in the power lines (measured to +15.01 and -15.00 volts) could cause this, I don't know. I will try recalibrating and also try different opamps to see if that changes anything.
For reference: Here is the original breadboarded circuit with the 0 to -10V output. I have since added the missing 2R2 resistor, however, that changed nothing. The DAC is connected where the 20k pot is in this drawing
Wednesday, February 22, 2017
ETI Vocoder article errors - internal excitation
Schematics says C11 is 22nF, parts list says 220nF.
C11 forms a low pass filter together with R39. Together with the 100k resistor on each channel of the analysis card - the whole setup is called an inverting amplifier filter or active inverting op amp low pass filter.
According to wikipedia:
https://en.wikipedia.org/wiki/Low-pass_filter
the cutoff frequency is 1 / 2 * pi * R*C
where R is the resistor in the feedback loop of the op amp.
For 22nF this is 1 / 6.28 * 47000 * 22 * 10^-9 = 154Hz
For 220nF it is 1 / 6.28 * 47000 * 220 * 10^-9 = 15.4Hz
In comparison, C12 and R40 gives:
1 / 6.28 * 10000 * 1 * 10^-6 = 1 / 0,01 = 15.9Hz.
The output from the analysis boards is the value of the envelope follower. If the volume of a frequency band is at its max continously, the envelope follower will be a DC voltage with a similar max value.
The two circuit parts sum up channels 1-9 (for the <2kHz input) and channel 13 and 14 (for the >4kHz input). For the sums to be comparable, the max sum of each parts must be the same.
R39 and R40 are selected to achieve this:
The gain of <2kHz is -10k/100k = -0.1
The gain of >4kHz is -47k/100k = -0.47
Multiplied by the number of channels on each input we get a 'maximum' sum for each input:
<2kHz: 9 channels * -0.1 = -0.9
>4kHz: 2 channels *-0.47 = 0.94
These are similar enough to be compared.
The low-pass filter is there to make sure the Vocoder only reacts to slow changes in envelope amplitudes. It is reasonable to assume that they should be roughly the same. The capacitor has been matched with the feedback resistor (R39, R40), which in turn was selected to give correct gain as described above.
The closest matching alternatives are then 15.4Hz and 15.9Hz. Thus, the correct value for C11 is 220nF.



