Mic input & audio output - aliasing effect
================================================================
The two-pin "feedback via inverter" method used by the microphone input circuit on the demo board
even if simulated using cog-code may be subject to severe high-frequency coupling effects.
================================================================
A MYSTERY... FINALLY EXPLAINED:
11,025 times per second I have a "SoundObject" cog which updates the FRQa register associated with the cog's CTRa which is configured for "duty cycle" mode. The result is beautiful audio output (after low pass filtering!). In an attempt to control which portion of the audio gets playback, I discovered an abandoned wired video-editor remote control. It has various buttons (STOP, PLAY, FWD, REV, ETC) which when pressed connect a unique resistor across the remote's two-pin plug. Now all I needed was a way to determine which button was pressed so that I could fast forward, rewind, or replay the audio clip.
I read some of the forum discussions regarding the microphone input using the CTRa configured for FEEDBACK (via an inverter) MODE of operation using one output pin and one input pin. I thought I could simply substitute the capacitively coupled signal from the electret mic with a 100K resistor coupled to a voltage from a resistive divider formed by a 3K resistor attached to 3.3v, with the other end of the 3k attached to my remote control switch fed to GND. The 100K resistor is connected to the propeller input pin. Pressing the button selects a particular voltage at the divider which then causes a current to flow through the 100K to the propeller input pin ( which is kept at about 1.45v by feedback from an RC network from the propeller output pin ).
I soon discovered this did not work, and a little more research on the forum uncovered why. Chip had discovered early on that the microphone must be located very close to the Propeller pins for proper operation. Another forum member presented some code in this discussion which revealed how he had essentially performed the "Feedback with Inversion" function normally handled by CTRa hardware by using assembly code instead. This assembly-code-based approach was apparently immune from the high-frequency (40Mhz) effects that had required Chip's short mic-to-pin distances. A possible solution ?
Starting with the example offered in this forum discussion, I decided to scale down the sampling frequency even further, as I only needed 10 Hz bandwidth for my button-sensing algorithm. Given that I was already driving the audio output 11025 times per second, it seemed that this was a good rate to read the high/low state of the "mic/remote" propeller input pin, and drive the "mic/remote" propeller output pin to the opposite state. After 1000 cycles (about 1/11th of a second later), the value of a counter that was incremented only when the propeller input was found to be HIGH (during the past 1000 cycles) is recorded. The counter is then reset to zero and another 1000 cycles later the counter value is read again.
The RC time constant of the mic-out filter at the propeller output pin was chosen so that its 'amplitude' is attentuated by about 60db (x1000) across the capacitor output. Thus 3.3v is reduced to around 3.3mV by the RC filter. This feedback voltage continually maintains the voltage at the propeller input pin to within a few mVs of the pin's logical threshold voltage (which was measured at about 1.45 volts). To a first order approximation, the circuit behaves (after RC filtering) like an inverting-op-amp.
I was most surprised when all this apparently seems to work ! I could press a button and have the propeller send me via its serial interface the counter value recorded during the most recent 1/11th of a second. It seemed too good to be true (it was of course): the counter values were stable to perhaps as little as 5 counts out of a full-scale 1000 counts. BUT WAIT, what is this ? After 20 or 30 seconds, this apparently very stable reading of the counter JUMPED by 100s of counts to another very stable value. Closer observation revealed that the counter reading would alternate between these two stable values in a very periodic fashion every 27 seconds with a 54 second period (does 54 seconds ring anybody's bell ?). WHAT WAS GOING ON ?
I discovered that when my audio output pin (hardware duty-cycle modulated) was turned 'off' the oscillation of the recorded "mic/remote" counter value also disappeared. So the audio output was interferring with the audio (mic/remote) input ? So I experimented with the audio pin......
I tried writing a DC level of &H80000000 to FRQa. Sure enough, no oscillation. But wait, when I write &H7FFFFFFF to the FRQa (and don't let it vary with time), the oscillation returns !! Even more fascinating, FRQa = &H80000010, at the audio output pin caused the mic/remote counter value to oscillate at a higher frequency with a 3.4 second period. If FRQa were set to &H800080, the oscillation had an even shorter period of 0.42 seconds. WHAT ON EARTH WAS GOING ON ?
A little math uncovered a neat relationship: if FRQa were set to &H80000000 + &H1B (or 27 decimal), then the oscillation in the mic counter value had a period of (2^32/x) / 80Mhz = 2.0 seconds, where x=27. It seems 160 million additions of 27 to a 32-bit counter at a rate of 80Mhz will cause the counter to overflow in 2.0 seconds. (CLUE #1)
It gets even more interesting ... but I will spare all the details. You can even change the duty cycle of this oscillation ! FRQa = &H8000001B yields a 50% duty cycle, half the time at one mic counter value, half at the other. FRQa = &HB000001B generates a 5/16th duty cycle !
Recalling how the DUTY CYCLE CTRa mode behaves, I realized that &H80000000 + 27 was being added to CTRa 80 million times a second. Since &H80000000 is effectively "half of full scale" (2^32-1), every other addition on average would be generating a "CARRY" overflow. This CARRY is the output logic state at the audio output pin in duty cycle mode. But how could these very tiny alterations of the "half of full scale" value ( in this case, just 27 is being added to &H80000000) - which results in only a slight shift in output frequency away from 40Mhz at the audio output pin - contribute to such a LARGE effect (+20% shift) of the mic counter value ?
More observations revealed that capacitive-coupling alone of the audio-output pin to mic/switch input pin could cause these oscillations. Merely touching the end of a 6" wire attached to the audio-output pin with its FRQa set to a FIXED VALUE could cause dramatic oscillations in the mic counter value to appear. (CLUE #2.)
So now I knew that the period of oscillation depends on FRQa's value and that the approximately 40 Mhz signal on the audio output pin was being capacitively coupled to the propeller mic/switch input pin.
I decided to write some simulator code in Visual Basic. I instructed the software to display a time graph which showed the state of the audio output pin (carry result) at each of the 11025 moments each second that the mic/switch propeller input pin was being tested. Low and behold, there it was, on the graph ....the state of the audio output pin held steady for about a second (always at a high state at the moment the mic input pin was sampled) and then for about another second it stayed steady at a logical low (it was always at a low state the moment the mic input pin was sampled.) FINALLY, AN ANSWER:
The state of the mic/switch propeller input pin as measured 11025 times each second determines (after 1000 such measurements) the recorded mic/switch counter value (11 times per second). Disturb this input measurement and you will alter the resulting mic counter value. In this case, just a few pF of capacitive coupling between the 40 Mhz audio output pin and the capacitor at the mic/switch propeller input pin (forming a capacitive voltage divider) is all that's required to interfere with the sensitive input logic state measurement. Consider that feedback action from the mic propeller output pin already holds the propeller input pin to within a few millivolts of its logic threshold voltage. The audio output (carry result) state -when transitioning high- serves to repeatedly jerk the input reading at the mic input pin high; and when it transitions low, the input reading is repeatedly pulled low. In effect, we are measuring two signals with the mic/switch input pin ... the voltage due to the pushed button, and the voltage present at the audio output pin at the moment of sampling. The 40Mhz audio output signal is being highly undersampled at a frequency of 11.025 kHz. Just like a digital oscilloscope set to observe a low frequency signal, if much high frequencies are present on the signal being measured, these may appear "aliased" to an apparently much lower frequency which appears to "roll across the display" slowly changing phase with time.
LESSON:
Beware. You have with the Propeller the ability to observe very rapidly changing inputs. The assembly code can be running at 20 MIPS ! If you couple this ability with a circuit which is intentionally designed to keep an input pin to within millivolts of its logic threshold level, you've got some trouble coming your way !! Keep those leads short.
As for the button-detector, I recently came across an excellent article (overlooking a few math errors) which may be found on page 75 of the 8.16.07 issue of Electronics Design entitled "Power-Saving Keypad Controls Multiple Keys Through One MCU Pin". Prof. Ozbek's approach uses a single bi-directional pin to sense up to 15 keys distinguished by resistor value alone. While using the well-known "RC charging rate" approach, it differs by avoiding polling and significant power consumption. I intend to adapt his approach to the Propeller and post my first item to the Object Exchange soon !
HERE IS THE COG CODE EXECUTED 11,025 TIMES EACH SECOND:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'Drive Audio Output
'
mov frqa, sample_data 'Output data byte to audio pin !
'Sample Audio Input
'
'Mic_Fb_Pin = INV(Mic_In_Pin)
'============================
test Mic_In_Mask, Ina WZ 'Z = not(Mic In Pin), Z=1 if (v1 AND v2) == 0
'Z==1 if Mic_In_Pin = LOW, Vi < Vth, will pull Mic_In low
IF_NZ add Mic_Cnt, #1 'If Mic_In_Pin = High (Vi > Vth), Incr Count
'Using IF_NZ, insures that high Vi levels generate
'numerically high Mic_Sample values, no inversion
muxz outa, Mic_Fb_Mask 'Mic Fb Pin = Z
djnz Accum_cnt, #:SKIP_AVG
'After Accum_Cnt cycles
'======================
mov Mic_Sample, Mic_Cnt 'sample_level := mic count
mov Mic_Cnt, #0 'reset
mov Accum_Cnt, Accum_Cnt_Max 'reset for next 'Accum_Cnt_Max' cycles
The two-pin "feedback via inverter" method used by the microphone input circuit on the demo board
even if simulated using cog-code may be subject to severe high-frequency coupling effects.
================================================================
A MYSTERY... FINALLY EXPLAINED:
11,025 times per second I have a "SoundObject" cog which updates the FRQa register associated with the cog's CTRa which is configured for "duty cycle" mode. The result is beautiful audio output (after low pass filtering!). In an attempt to control which portion of the audio gets playback, I discovered an abandoned wired video-editor remote control. It has various buttons (STOP, PLAY, FWD, REV, ETC) which when pressed connect a unique resistor across the remote's two-pin plug. Now all I needed was a way to determine which button was pressed so that I could fast forward, rewind, or replay the audio clip.
I read some of the forum discussions regarding the microphone input using the CTRa configured for FEEDBACK (via an inverter) MODE of operation using one output pin and one input pin. I thought I could simply substitute the capacitively coupled signal from the electret mic with a 100K resistor coupled to a voltage from a resistive divider formed by a 3K resistor attached to 3.3v, with the other end of the 3k attached to my remote control switch fed to GND. The 100K resistor is connected to the propeller input pin. Pressing the button selects a particular voltage at the divider which then causes a current to flow through the 100K to the propeller input pin ( which is kept at about 1.45v by feedback from an RC network from the propeller output pin ).
I soon discovered this did not work, and a little more research on the forum uncovered why. Chip had discovered early on that the microphone must be located very close to the Propeller pins for proper operation. Another forum member presented some code in this discussion which revealed how he had essentially performed the "Feedback with Inversion" function normally handled by CTRa hardware by using assembly code instead. This assembly-code-based approach was apparently immune from the high-frequency (40Mhz) effects that had required Chip's short mic-to-pin distances. A possible solution ?
Starting with the example offered in this forum discussion, I decided to scale down the sampling frequency even further, as I only needed 10 Hz bandwidth for my button-sensing algorithm. Given that I was already driving the audio output 11025 times per second, it seemed that this was a good rate to read the high/low state of the "mic/remote" propeller input pin, and drive the "mic/remote" propeller output pin to the opposite state. After 1000 cycles (about 1/11th of a second later), the value of a counter that was incremented only when the propeller input was found to be HIGH (during the past 1000 cycles) is recorded. The counter is then reset to zero and another 1000 cycles later the counter value is read again.
The RC time constant of the mic-out filter at the propeller output pin was chosen so that its 'amplitude' is attentuated by about 60db (x1000) across the capacitor output. Thus 3.3v is reduced to around 3.3mV by the RC filter. This feedback voltage continually maintains the voltage at the propeller input pin to within a few mVs of the pin's logical threshold voltage (which was measured at about 1.45 volts). To a first order approximation, the circuit behaves (after RC filtering) like an inverting-op-amp.
I was most surprised when all this apparently seems to work ! I could press a button and have the propeller send me via its serial interface the counter value recorded during the most recent 1/11th of a second. It seemed too good to be true (it was of course): the counter values were stable to perhaps as little as 5 counts out of a full-scale 1000 counts. BUT WAIT, what is this ? After 20 or 30 seconds, this apparently very stable reading of the counter JUMPED by 100s of counts to another very stable value. Closer observation revealed that the counter reading would alternate between these two stable values in a very periodic fashion every 27 seconds with a 54 second period (does 54 seconds ring anybody's bell ?). WHAT WAS GOING ON ?
I discovered that when my audio output pin (hardware duty-cycle modulated) was turned 'off' the oscillation of the recorded "mic/remote" counter value also disappeared. So the audio output was interferring with the audio (mic/remote) input ? So I experimented with the audio pin......
I tried writing a DC level of &H80000000 to FRQa. Sure enough, no oscillation. But wait, when I write &H7FFFFFFF to the FRQa (and don't let it vary with time), the oscillation returns !! Even more fascinating, FRQa = &H80000010, at the audio output pin caused the mic/remote counter value to oscillate at a higher frequency with a 3.4 second period. If FRQa were set to &H800080, the oscillation had an even shorter period of 0.42 seconds. WHAT ON EARTH WAS GOING ON ?
A little math uncovered a neat relationship: if FRQa were set to &H80000000 + &H1B (or 27 decimal), then the oscillation in the mic counter value had a period of (2^32/x) / 80Mhz = 2.0 seconds, where x=27. It seems 160 million additions of 27 to a 32-bit counter at a rate of 80Mhz will cause the counter to overflow in 2.0 seconds. (CLUE #1)
It gets even more interesting ... but I will spare all the details. You can even change the duty cycle of this oscillation ! FRQa = &H8000001B yields a 50% duty cycle, half the time at one mic counter value, half at the other. FRQa = &HB000001B generates a 5/16th duty cycle !
Recalling how the DUTY CYCLE CTRa mode behaves, I realized that &H80000000 + 27 was being added to CTRa 80 million times a second. Since &H80000000 is effectively "half of full scale" (2^32-1), every other addition on average would be generating a "CARRY" overflow. This CARRY is the output logic state at the audio output pin in duty cycle mode. But how could these very tiny alterations of the "half of full scale" value ( in this case, just 27 is being added to &H80000000) - which results in only a slight shift in output frequency away from 40Mhz at the audio output pin - contribute to such a LARGE effect (+20% shift) of the mic counter value ?
More observations revealed that capacitive-coupling alone of the audio-output pin to mic/switch input pin could cause these oscillations. Merely touching the end of a 6" wire attached to the audio-output pin with its FRQa set to a FIXED VALUE could cause dramatic oscillations in the mic counter value to appear. (CLUE #2.)
So now I knew that the period of oscillation depends on FRQa's value and that the approximately 40 Mhz signal on the audio output pin was being capacitively coupled to the propeller mic/switch input pin.
I decided to write some simulator code in Visual Basic. I instructed the software to display a time graph which showed the state of the audio output pin (carry result) at each of the 11025 moments each second that the mic/switch propeller input pin was being tested. Low and behold, there it was, on the graph ....the state of the audio output pin held steady for about a second (always at a high state at the moment the mic input pin was sampled) and then for about another second it stayed steady at a logical low (it was always at a low state the moment the mic input pin was sampled.) FINALLY, AN ANSWER:
The state of the mic/switch propeller input pin as measured 11025 times each second determines (after 1000 such measurements) the recorded mic/switch counter value (11 times per second). Disturb this input measurement and you will alter the resulting mic counter value. In this case, just a few pF of capacitive coupling between the 40 Mhz audio output pin and the capacitor at the mic/switch propeller input pin (forming a capacitive voltage divider) is all that's required to interfere with the sensitive input logic state measurement. Consider that feedback action from the mic propeller output pin already holds the propeller input pin to within a few millivolts of its logic threshold voltage. The audio output (carry result) state -when transitioning high- serves to repeatedly jerk the input reading at the mic input pin high; and when it transitions low, the input reading is repeatedly pulled low. In effect, we are measuring two signals with the mic/switch input pin ... the voltage due to the pushed button, and the voltage present at the audio output pin at the moment of sampling. The 40Mhz audio output signal is being highly undersampled at a frequency of 11.025 kHz. Just like a digital oscilloscope set to observe a low frequency signal, if much high frequencies are present on the signal being measured, these may appear "aliased" to an apparently much lower frequency which appears to "roll across the display" slowly changing phase with time.
LESSON:
Beware. You have with the Propeller the ability to observe very rapidly changing inputs. The assembly code can be running at 20 MIPS ! If you couple this ability with a circuit which is intentionally designed to keep an input pin to within millivolts of its logic threshold level, you've got some trouble coming your way !! Keep those leads short.
As for the button-detector, I recently came across an excellent article (overlooking a few math errors) which may be found on page 75 of the 8.16.07 issue of Electronics Design entitled "Power-Saving Keypad Controls Multiple Keys Through One MCU Pin". Prof. Ozbek's approach uses a single bi-directional pin to sense up to 15 keys distinguished by resistor value alone. While using the well-known "RC charging rate" approach, it differs by avoiding polling and significant power consumption. I intend to adapt his approach to the Propeller and post my first item to the Object Exchange soon !
HERE IS THE COG CODE EXECUTED 11,025 TIMES EACH SECOND:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'Drive Audio Output
'
mov frqa, sample_data 'Output data byte to audio pin !
'Sample Audio Input
'
'Mic_Fb_Pin = INV(Mic_In_Pin)
'============================
test Mic_In_Mask, Ina WZ 'Z = not(Mic In Pin), Z=1 if (v1 AND v2) == 0
'Z==1 if Mic_In_Pin = LOW, Vi < Vth, will pull Mic_In low
IF_NZ add Mic_Cnt, #1 'If Mic_In_Pin = High (Vi > Vth), Incr Count
'Using IF_NZ, insures that high Vi levels generate
'numerically high Mic_Sample values, no inversion
muxz outa, Mic_Fb_Mask 'Mic Fb Pin = Z
djnz Accum_cnt, #:SKIP_AVG
'After Accum_Cnt cycles
'======================
mov Mic_Sample, Mic_Cnt 'sample_level := mic count
mov Mic_Cnt, #0 'reset
mov Accum_Cnt, Accum_Cnt_Max 'reset for next 'Accum_Cnt_Max' cycles
Comments
1) Please use the [noparse][[/noparse] code ] and [noparse][[/noparse] /code ] tags around any code you post. It's not very readable otherwise.
2) It's not the microphone that has to be close to the Prop's I/O pins, just the resistor/capacitor network.
If located more than a few (1-2) inches away, you'll need to use shielded cable since there's a lot of
electrical noise flying around
3) There have been some good discussions recently here about the sigma-delta ADC, how to choose the
R/C values, and some general comments on how it works. Also check out www.emesystems.com,
always a good source for information on sensors. There's a good discussion there about a similar, but slower
scheme using a Stamp's RCTIME statement (or the Propeller equivalent) to measure slowly changing voltages
(like a battery voltage).
Here is a little article I have on the RCtime approach for the Stamp. There have been a number of clever methods posted on these lists.
www.emesys.com/BS2rct.htm#switches
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Tracy Allen
www.emesystems.com
Post Edited (Tracy Allen) : 10/24/2007 8:17:01 AM GMT
Note that the problem lies not in the fact that you have a "mean AC voltage" of 3.3 mV - this is determined by the duty cycle of the signal and will be much lower in many applications (down to pV
The constituting pulses have an amplitude of 3V3, of course.
The "duty cycle mode" of the timers sounds great, but they produce just "spikes". You have to take a lot of care to work with it!
The approach of just using capacitor discharge is well proven, given in the basic training material for the Propeller and has also been used with the well known 16 key/resistor matrices (some postings here in the forum)
Post Edited (deSilva) : 10/24/2007 5:41:29 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
The more I know, the more I know I don't know.· Is this what they call Wisdom?