itp
Junior Member
Offline
Posts: 66
Thank You
-Given: 224
-Receive: 20
|
|
« on: December 11, 2014, 05:46:42 17:46 » |
|
Hi,
I need an idea to implement a Fully digital Voltage to Frequency converter. The input range is 0 to 4V and the required frequency range is 1kHz to 50kHz with 100Hz step.
It seems simple if we use a micro controller with built-in ADC and a PWM unit. In this technique the PWM unit trigger the ADC unit at PWM frequency. The ADC takes the samples at an interval of PWM period and update the PWM frequency. .But the problem with this technique is that, as the sampling interval varies the update rate of PWM frequency will also vary as we move from 1kHz to 50Khz. One solution to this problem is that let the ADC to convert faster and update the PWM frequency asynchronously. But this leads to the chances of Glitches in the PWM output, which is not acceptable. I need an constant update period of 5uSec.
Any suggestion or idea.
Thanks and regards Itp
|
|
|
Logged
|
|
|
|
Vineyards
Active Member
Offline
Posts: 168
Thank You
-Given: 64
-Receive: 37
|
|
« Reply #1 on: December 11, 2014, 06:01:48 18:01 » |
|
It seems you could do that however there may be a problem with the selected frequency range. You need to figüre out what sort of a crystal frequency could get you a range of frequencies at that range.
Why would you need to change the frequency immediately? This would probably introduce a lot of distortion and discontinuations. You normally initialize the PWM unit at a set frequency and then stop it and reinitialize which will take some time to implement and this would distort the signal output intermittently. I have never tried setting this frequency at anything other than standard numbers like 1k, 5k, 10k etc and I am not aware if it could be set like say 2450 Hertz. You will probably need a longer time base and modify the signal frequency at least 1 second later. You should check out the microprocessor's datasheet for a complete answer. If you will not use assembly language then you will also have to check out the compiler's requirements for PWM operation.
If the output will be hooked up to an analog frequency to voltage converter it would be best to use and analog voltage to frequency converter. I know you will say they are expensive but there is a reason for that too.
|
|
|
Logged
|
|
|
|
|
optikon
Cracking Team
Hero Member
Offline
Posts: 853
Thank You
-Given: 1105
-Receive: 2007
|
|
« Reply #3 on: December 11, 2014, 11:14:15 23:14 » |
|
Hi,
I need an idea to implement a Fully digital Voltage to Frequency converter. The input range is 0 to 4V and the required frequency range is 1kHz to 50kHz with 100Hz step.
It seems simple if we use a micro controller with built-in ADC and a PWM unit. In this technique the PWM unit trigger the ADC unit at PWM frequency. The ADC takes the samples at an interval of PWM period and update the PWM frequency. .But the problem with this technique is that, as the sampling interval varies the update rate of PWM frequency will also vary as we move from 1kHz to 50Khz. One solution to this problem is that let the ADC to convert faster and update the PWM frequency asynchronously. But this leads to the chances of Glitches in the PWM output, which is not acceptable. I need an constant update period of 5uSec.
Any suggestion or idea.
Thanks and regards Itp
Update a DAC / DDS at 5us with a high order low pass filter on the output?
|
|
« Last Edit: December 12, 2014, 12:26:49 00:26 by optikon »
|
Logged
|
I can explain this to you. I can't comprehend it for you.
|
|
|
Signal
Active Member
Offline
Posts: 200
Thank You
-Given: 113
-Receive: 81
|
|
« Reply #4 on: December 13, 2014, 01:25:44 01:25 » |
|
I need an idea to implement a Fully digital Voltage to Frequency converter. The input range is 0 to 4V and the required frequency range is 1kHz to 50kHz with 100Hz step. <...> I need an constant update period of 5uSec.
Your requirements do not look well-founded for me. And problems you mention do not look like problems. Your real task is hidden. If you think to use PWM we need to talk in terms of time not frequency. Then 50 kHz with 100 Hz step means 20 us and 20.0401 us. Looks natural for 25 MHz - periods are 500 and 501. Jitter will be at least comparable with resolution (not better). (UPDATE: not so bad with jitter, odd period values is not a jitter) If target receiver "measures" frequency through time interval between edges then fast response accuracy (without averaging sampled values) is worse than expected because of jitter. If it "measures" frequency by counting then it needs more than 500*20us=10 ms to get required precision (100 Hz step). For 1kHz transfer time is obviously not better than 1 ms. (UPDATE: 0.5 ms.) So If you want to pass information about voltage through frequency that scale there are no such times as 5 us at all. We know nothing about source of voltage. We know that we need not less than 10 bit of ADC precision (continue to think about ADC-PWM scheme). No problem for cheap uC. Of course there will be some noise. But taking into account slow transfer rate of supposed converter an averaging is not a problem. From my point of view: ADC is pooled from main loop continuously. In the same loop the sampled values are averaged somehow, new values for PWM settings are prepared. PWM timer is the only interrupt source. In ISR the PWM timings are updated by prepared values - 20 us is completely enough for that task. ADC stuff could be passed to second ISR with some arbitration between two interrupts - we do not need to update PWM each cycle as well we can bypass some ADC samples without any trouble.
|
|
« Last Edit: December 14, 2014, 10:50:37 22:50 by Signal »
|
Logged
|
Give a right name to a right game and play it right
|
|
|
SteveyG
Newbie
Offline
Posts: 23
Thank You
-Given: 4
-Receive: 9
|
|
« Reply #5 on: December 22, 2014, 04:04:15 16:04 » |
|
Are you just after 50% duty?
|
|
|
Logged
|
|
|
|
mare69
Junior Member
Offline
Posts: 89
Thank You
-Given: 50
-Receive: 85
|
|
« Reply #6 on: December 22, 2014, 08:02:15 20:02 » |
|
Check some nice S53MV designs. I think you could find some excellent ideas. http://lea.hamradio.si/~s53mv/
|
|
|
Logged
|
|
|
|
Signal
Active Member
Offline
Posts: 200
Thank You
-Given: 113
-Receive: 81
|
|
« Reply #7 on: December 22, 2014, 09:46:58 21:46 » |
|
Check some nice S53MV designs. I think you could find some excellent ideas.
Do you mind the specific design from advertised site that corresponds to current topic? Or all of them are just excellent?
|
|
|
Logged
|
Give a right name to a right game and play it right
|
|
|
itp
Junior Member
Offline
Posts: 66
Thank You
-Given: 224
-Receive: 20
|
|
« Reply #8 on: October 09, 2015, 11:21:33 11:21 » |
|
Hi all, Here I am giving a C-language code to test the V to F function using NCO (Numerically Controlled Oscillator) of PIC16F1718. It gives me a response time of 30uS for a step voltage input (0 to 5V). Actually I need much faster response about 10uS. I hope that if I write the while-loop in assembly language the response time would be better. I am not familiar with assembly language. Can anybody guide me to do this or any other suggestions to improve the speed. The C- code is given below.
Thanks and regards Itp
const unsigned int frq_tbl[]={ 131, 136, 141, 146, 151, 156, 161, 166, 171, 176, 181, 186, 191, 196, 201, 206, 211, 216, 221, 226, 231, 236, 241, 246, 251, 256, 261, 266, 271, 276, 281, 286, 291, 296, 301, 306, 311, 316, 321, 326, 331, 336, 341, 346};
void main(void) { SYSTEM_Initialize();
ADCON0bits.CHS = 0; // Channel 0 AN0 ADCON0bits.ADON = 1; // Turn on the ADC module __delay_us(ACQ_US_DELAY); // Acquisition time delay ADCON0bits.GO_nDONE = 1; // Start the conversion NCO1INCU = 0; // MSB of NCO written earlier // can somebody convert the while loop shown below // to Assembly language. while (1) { while (ADCON0bits.GO_nDONE) {} // Wait for the conversion to finish adc_val = ADRES; ADCON0bits.GO_nDONE = 1; // Start the conversion val = frq_tbl[adc_val]; NCO1INCH = val>>8; NCO1INCL = val;
}
}
|
|
|
Logged
|
|
|
|
h0nk
Senior Member
Offline
Posts: 257
Thank You
-Given: 226
-Receive: 231
|
|
« Reply #9 on: October 09, 2015, 12:56:59 12:56 » |
|
Hi itp, You should first measure with a GPIO-toggle how much time the ADC-conversion will take. while (ADCON0bits.GO_nDONE) {} // Wait for the conversion to finish GPIOx.y=0; adc_val = ADRES; ADCON0bits.GO_nDONE = 1; // Start the conversion GPIOx.y=1;
With a scope or a universal counter You can measure the time of the conversion. XC8 Pro does a fairly good job and im afraid there will be not much gain to rewrite the assignments to SFR-registers into assembler. But You may be able to simplify the address calculation, if You split Your table of frequencies into a high- and a low-table. That way the processor is operating on 8 bit data only. const unsigned char frq_tbl_lo[]={ 131 & 0xff, 136 & 0xff, 141 & 0xff, 146 & 0xff, ... const unsigned char frq_tbl_hi[]={ (131 << 8) & 0xff, (136 << 8) & 0xff, (141 << 8) & 0xff, (146 << 8) & 0xff, ...
And, if You are using XC8 You can instruct the compiler to generate an ASM-file of Your code. Best Regards
|
|
« Last Edit: October 09, 2015, 01:12:25 13:12 by h0nk »
|
Logged
|
|
|
|
zuisti
Senior Member
Offline
Posts: 409
Thank You
-Given: 242
-Receive: 780
|
|
« Reply #10 on: October 09, 2015, 02:38:50 14:38 » |
|
You should first measure with a GPIO-toggle how much time the ADC-conversion will take. .... XC8 Pro does a fairly good job and im afraid there will be not much gain to rewrite the assignments to SFR-registers into assembler.
But You may be able to simplify the address calculation, if You split Your table of frequencies into a high- and a low-table. That way the processor is operating on 8 bit data only. I completely agree .... But .... const unsigned char frq_tbl_ hi[]={ (131 >> 8 ), (136 >> 8 ), ...
|
|
« Last Edit: October 09, 2015, 02:44:05 14:44 by zuisti »
|
Logged
|
|
|
|
h0nk
Senior Member
Offline
Posts: 257
Thank You
-Given: 226
-Receive: 231
|
|
« Reply #11 on: October 09, 2015, 06:06:42 18:06 » |
|
Yes, zuisti You are right. I am not 100% sure if itp is using XC8, so i tried to write a more portable code. With XC8 you can use the high() and low() function also. const unsigned char frq_tbl_hi[]={ high(131), high(136), high(141), high(146), ...
Sorry for my mistake. Best Rergards
|
|
|
Logged
|
|
|
|
itp
Junior Member
Offline
Posts: 66
Thank You
-Given: 224
-Receive: 20
|
|
« Reply #12 on: October 10, 2015, 04:25:37 04:25 » |
|
Hi h0nk and zuisti,
I am using XC8 compiler. I am using the default optimization for compiling. It is a good idea to split the table to two 8bit parts. I will try your suggestions and let you know the result. Thanks and regards Itp
|
|
|
Logged
|
|
|
|
Signal
Active Member
Offline
Posts: 200
Thank You
-Given: 113
-Receive: 81
|
|
« Reply #13 on: October 10, 2015, 09:32:32 21:32 » |
|
Hi all, Here I am giving a C-language code to test the V to F function using NCO (Numerically Controlled Oscillator) of PIC16F1718. It gives me a response time of 30uS for a step voltage input (0 to 5V). Actually I need much faster response about 10uS.
At first, when you think about response time do not forget about analog filter delay, accuracy(noise) of ADC and native responsiveness of output signal of relatively low frequency. PIC16F1718 datasheet ( http://ww1.microchip.com/downloads/en/DeviceDoc/40001740A.pdf) page 415: ADC clock period (Tad): minimum 1 us Conversion time: 11*Tad Acquisition time: typ.: 5 us (see page 247: 21.4 ADC Acquisition Requirements to refine your values) Note: ADIF is 1 Tcy earlier than DONE So practical value for ADC conversion time without trade-offs is about 16-17 us (AD133+AD131+1Tcy+InterruptLatency). (see figures: 21-2, 34-13, 34-14) 1) You did not show in code the selection of clock source for ADC. 2) Acquisition time must be added before _each_ conversion. Not only at init stage. The purpose of that delay is to give enough time for "holding" capacitor to recharge to actual measured voltage through given serial resistance of voltage source. 3) I'm not sure about XC8 compiler if it adds run-time checks for indexes. Then 16(10)-bit index to 44 element array (frq_tbl[adc_val]) is not good, nor working (just draft dummy?). I suggest to use Fosc-based ADC clock (set Tad=1us), set Autoconversion trigger (See 21.2.5) to automatically set GO each say 17 us (refine your Tacq) through CCP and use ADC interrupt to handle new measured value. Note: ADRES register pair will be updated by ADC module only at very end of next conversion. I hope that it is not coincidence that you correctly update NCO1INCL last (20.1.4). If you want to further decrease response time (ADC conversion period plus data conditioning) then I'd try to adjust NCOx_clk (Fosc?) and ADRES justification to omit table conversion - to just copy ADRES to NCO1INCH:NCO1INCL. As a variant - simple shifts could be faster than two table reads. Another variant - use CCP instead of NCO with its fixed 20-bit period. More work though and use of NCO is much nicer. Posted on: October 10, 2015, 10:42:03 22:42 - Automerged
But You may be able to simplify the address calculation, if You split Your table of frequencies into a high- and a low-table. That way the processor is operating on 8 bit data only. const unsigned char frq_tbl_lo[]={ 131 & 0xff, 136 & 0xff, 141 & 0xff, 146 & 0xff, ... const unsigned char frq_tbl_hi[]={ (131 << 8) & 0xff, (136 << 8) & 0xff, (141 << 8) & 0xff, (146 << 8) & 0xff, ...
It needs tests to compare. For example for given processor the following code could be more effective without table split. movlw LOW conversion_table movwf FSR1L movlw HIGH conversion_table movwf FSR1H lslf ADRESL, W ;double index value rlf ADRESH, F addwf FSR1L, F ;add it to FSR movf ADRESH, W addwfc FSR1H, F moviw FSR1++ movwf freq_nco_inc_hi moviw FSR1++ movwf freq_nco_inc_lo
Though I know nothing about xc8 capabilities, it is quite usual operation so they could optimize 16-bit tables well. I personally prefer manual asm optimization in case of strict necessity. Posted on: October 10, 2015, 11:23:14 23:23 - Automerged
If FSR1 is not used elsewhere then following "swap" will reduce delay of updating NCO1INC. ADC_INT_handler: lslf ADRESL, W ;double index value rlf ADRESH, F addwf FSR1L, F ;add it to FSR movf ADRESH, W addwfc FSR1H, F moviw FSR1++ banksel NCO1INCH movwf NCO1INCH ;update NCO increment step moviw FSR1++ movwf NCO1INCL movlw LOW conversion_table ;prepare table address for next conversion movwf FSR1L movlw HIGH conversion_table movwf FSR1H banksel ADRESL ;if there is no banksel commands outside this interrupt handler then this banksel can be placed here
|
|
« Last Edit: October 11, 2015, 10:54:19 10:54 by Signal »
|
Logged
|
Give a right name to a right game and play it right
|
|
|
Signal
Active Member
Offline
Posts: 200
Thank You
-Given: 113
-Receive: 81
|
|
« Reply #14 on: October 11, 2015, 02:16:56 02:16 » |
|
For that small task I see no reason not to use asm. So the same itp's loop: conversion_table: ... ;TODO: init clock, ADC, NCO banksel ADCON loop: btfsc ADCON, DONE bra loop lslf ADRESL, W ;double index value rlf ADRESH, F addwf FSR1L, F ;add it to FSR movf ADRESH, W addwfc FSR1H, F moviw FSR1++ banksel NCO1INCH movwf NCO1INCH ;update NCO increment step moviw FSR1++ movwf NCO1INCL ;12-14 Tcy after DONE movlw LOW conversion_table ;prepare table address for next conversion movwf FSR1L movlw HIGH conversion_table movwf FSR1H call ACQ_DELAY banksel ADCON bsf ADCON, GO bra loop
ACQ_DELAY: ;TODO: nop-nop ;) return
My advises about autoconversion trigger and adif interrupt seems to be redundant and not worth for that single burden of PIC.
|
|
|
Logged
|
Give a right name to a right game and play it right
|
|
|
2N5109
Junior Member
Offline
Posts: 67
Thank You
-Given: 26
-Receive: 14
|
|
« Reply #15 on: October 27, 2015, 12:57:44 00:57 » |
|
First build a synthesizer with 100Hz steps that covers 1kHz-50kHz and settles in 5uS. See http://www.seattlerobotics.org/encoder/200205/ddsfgen.htmIf a DDS has too many spurs then build an indirect PLL synthesizer with a loop bw of ~500kHz at some convenient frequency and downconvert it to your range. Then drive it with an ADC. You adjust the gain for 50000/100=500 steps over 4 volts. Hardware seems more straightforward than software for a change!
|
|
« Last Edit: October 27, 2015, 01:37:22 01:37 by 2N5109 »
|
Logged
|
|
|
|
itp
Junior Member
Offline
Posts: 66
Thank You
-Given: 224
-Receive: 20
|
|
« Reply #16 on: November 05, 2015, 06:06:45 06:06 » |
|
Hi All,
I tried it with two separate lookup tables for low byte and high byte. frq_tbl_low[] and frq_tbl_high[]. But it was not showing any improvement in speed. Now I will try your other suggestions. Thanks and regards Itp
|
|
|
Logged
|
|
|
|
|