FoxyRick
Advanced Member level 4
- Joined
- Jan 8, 2004
- Messages
- 1,249
- Helped
- 321
- Reputation
- 640
- Reaction score
- 277
- Trophy points
- 1,373
- Location
- England, UK
- Activity points
- 12,979
Can someone help me solve the following please:
I'm trying to measure the time between the rising edges on two equal frequency, slow (~2Hz), almost in phase square waves. They are within about 500nS but can go down to almost 0ns. One has a random jitter of +/-25ns, the other <<1ns and signal 1 normally leads signal 2 (I can adjust the phase difference for testing). A dsPIC with CTMU seems ideal and I'm using one in the circuit anyway: dsPIC33EP128MC202
I've been at it for two days, going around in circles, re-reading all the datasheets, trying all sorts of variations and repeating the tests. No matter what I try I can't seem to get a sensible response from the CTMU/ADC. It always does the same thing:
It seems to be basically working, but the readings just don't make sense. In particular, when I lower the pulse separation from 400ns to zero, the ADC readings don't really change accordingly although they do get lower.
With a 5.5uA current, and with the ADC (+stray) capacitance of ~5pf, I should get an ADC reading of ~0.44V = 136 counts (3.3V supply, 10 bits, V=T.I/C). I get around 350 counts.
With the current set at 0.55uA, which should give a tenth of that, I get readings around 270 for 400nS. Setting 55uA makes the ADC go full scale instantly. As I bring the pulse difference down to zero, the ADC reading gets to around 180 counts (regardless of the current) before the pulses reverse and the ADC goes full scale as expected. :???:
Discharge time for the sampling capacitor makes no difference; I've tried adjusting that too.
Below is the reduced (and now somewhat messy looking) code I've done for testing, along with an output log from a constant ~400ns (with jitter) pulse separation, and a log where I slowly ramp Pulse_2 closer to Pulse_1, eventually swapping order. Note that I've written the code in CCS C, but I also rewrote it with xc16 last night and got the same results (although for some reason (bug?) in xc16 the CTMU will not trigger the ADC to read, despite setting the registers correctly and the CTMU functioning as expected otherwise. I had to read the ADC manually).
The pulses were observed on a 200MHz oscilloscope throughout. The waves are nice and clean and I can't see anything in the signals to explain the above.
I'm trying to measure the time between the rising edges on two equal frequency, slow (~2Hz), almost in phase square waves. They are within about 500nS but can go down to almost 0ns. One has a random jitter of +/-25ns, the other <<1ns and signal 1 normally leads signal 2 (I can adjust the phase difference for testing). A dsPIC with CTMU seems ideal and I'm using one in the circuit anyway: dsPIC33EP128MC202
I've been at it for two days, going around in circles, re-reading all the datasheets, trying all sorts of variations and repeating the tests. No matter what I try I can't seem to get a sensible response from the CTMU/ADC. It always does the same thing:
It seems to be basically working, but the readings just don't make sense. In particular, when I lower the pulse separation from 400ns to zero, the ADC readings don't really change accordingly although they do get lower.
With a 5.5uA current, and with the ADC (+stray) capacitance of ~5pf, I should get an ADC reading of ~0.44V = 136 counts (3.3V supply, 10 bits, V=T.I/C). I get around 350 counts.
With the current set at 0.55uA, which should give a tenth of that, I get readings around 270 for 400nS. Setting 55uA makes the ADC go full scale instantly. As I bring the pulse difference down to zero, the ADC reading gets to around 180 counts (regardless of the current) before the pulses reverse and the ADC goes full scale as expected. :???:
Discharge time for the sampling capacitor makes no difference; I've tried adjusting that too.
Below is the reduced (and now somewhat messy looking) code I've done for testing, along with an output log from a constant ~400ns (with jitter) pulse separation, and a log where I slowly ramp Pulse_2 closer to Pulse_1, eventually swapping order. Note that I've written the code in CCS C, but I also rewrote it with xc16 last night and got the same results (although for some reason (bug?) in xc16 the CTMU will not trigger the ADC to read, despite setting the registers correctly and the CTMU functioning as expected otherwise. I had to read the ADC manually).
The pulses were observed on a 200MHz oscilloscope throughout. The waves are nice and clean and I can't see anything in the signals to explain the above.
Code:
// Include file not shown but has nothing of relevance to the issue
// CTMUICON bits
#word CTMUICON = getenv("SFR:CTMUICON")
// CTMUCON1 bits
#word CTMUCON1 = getenv("SFR:CTMUCON1")
#bit CTMUEN = getenv("BIT:CTMUEN") // Enable CTMU
#bit CTMUSIDL = getenv("BIT:CTMUSIDL")
#bit TGEN = getenv("BIT:TGEN")
#bit EDGEN = getenv("BIT:EDGEN") // 0 = Software, 1 = Hardware edges
#bit EDGSEQEN = getenv("BIT:EDGSEQEN") // 1 = Edge 1 must occur before Edge 2
#bit IDISSEN = getenv("BIT:IDISSEN") // Enable current discharge
#bit CTTRIG = getenv("BIT:CTTRIG") // CTMU triggers ADC
// CTMUCON2 bits
#word CTMUCON2 = getenv("SFR:CTMUCON2")
#bit EDG1STAT = getenv("BIT:EDG1STAT")
#bit EDG2STAT = getenv("BIT:EDG2STAT")
// ADC Registers
#word AD1CON1 = getenv("SFR:AD1CON1")
#bit ADON = AD1CON1.15 // Enable ADC
#bit SAMP = AD1CON1.1 // 1=Sampling, 0=Holding
#bit DONE = AD1CON1.0 // 1=Conversion finished
#word AD1CON2 = getenv("SFR:AD1CON2")
#word AD1CON3 = getenv("SFR:AD1CON3")
#word AD1CHS0 = getenv("SFR:AD1CHS0")
#word ADCBUF = getenv("SFR:ADC1BUF0")
long int CTMUvalue;
// Initialise the CTMU
void initCTMU() {
CTMUICON = 0b0000000100000000; // 0.55uA, no trim
CTMUCON2 = 0b1100110011001100; // Rising Edges, CTED1=Pulse_1, CTED2=Pulse_2
CTMUCON1 = 0b0000010100000000; // CTMU Off, EDGSEQEN, CTTRIG
AD1CON1 = 0b0000000011000000; // 10-bit, CTMU triggers conversion
AD1CON2 = 0; // Supplyr rail Vrefs, CH0
AD1CON3 = 0b0000000000000101; // ADC uses system clock, (5+1)*Tcy=120ns
AD1CHS0 = 0b0001111100011111; // ADC MUX to Open for CTMU
ADON=1; // Enable ADC
SAMP=1; // Set ADC to Sampling
IDISSEN=1; // Ground the current source
delay_us(100); // Time to discharge the sample capacitor
IDISSEN=0; // Disable discharge
CTMUEN=0; // Disable CMTU
CTMUCON2=0b1100110011001100; // Reset EDGxSTAT
EDGEN=1; // Enable hardware edges
CTMUEN=1; // Enable CTMU
}
#int_CTMU
void CTMU_Interrupt(void) {
if (EDG1STAT && EDG2STAT) {
while (!DONE) {}
DONE=0; // Clear ADC done flag
CTMUvalue = ADCBUF;
printf("%lu\r\n",CTMUvalue);
// Reset for next trigger
CTMUEN=0; // Disable CTMU
SAMP=1; // Set ADC to Sampling
IDISSEN=1; // Ground the current source
delay_us(100); // Time to discharge the sample capacitor
IDISSEN=0; // Disable discharge
CTMUCON2 = 0b1100110011001100; // Reset EDGxSTAT
CTMUEN=1; // Enable CTMU
}
}
void main() {
setup_oscillator(OSC_CLOCK,100000000,10000000);
#use delay(clock=100000000)
set_uart_speed(57600,UART_PORT1,100000000);
printf("\r\nI'm Alive\r\n");
enable_interrupts(INT_CTMU);
enable_interrupts(GLOBAL);
initCTMU();
while (1) { }
}
Code:
0.55uA current. Pulse_2 lags Pulse_1 by about 400nS with 20nS jitter.
ADC Counts
----------
270
270
268
269
267
271
... continues similar to above
0.55uA Current, bringing Pulse 2 gradually closer to Pulse 1 until they are in phase and then swap order.
ADC Lag, ns
counts (approx)
------ -----
242 400
268
276
228
253
251
256 300
221
245
250
208
233
201 200
228
222
237
192
215
214 100
184
212
217
174
195
165 0
... reverses order
1022
...
1023
...
the pulses reverse order and the readings go full scale every other pair