Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
November 23, 2024, 05:17:11 17:17


Login with username, password and session length


Pages: [1]
Print
Author Topic: Suggest a Fully digital Voltage to Frequency converter design.  (Read 5485 times)
0 Members and 1 Guest are viewing this topic.
itp
Junior Member
**
Offline 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 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
Ichan
Hero Member
*****
Offline Offline

Posts: 833

Thank You
-Given: 312
-Receive: 392



WWW
« Reply #2 on: December 11, 2014, 06:28:18 18:28 »

Microchip NCO seems perfect for this.

And the technical brief: Voltage-Controlled Oscillator with Linear Frequency Output.

-ichan
Logged

There is Gray, not only Black or White.
optikon
Cracking Team
Hero Member
****
Offline 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 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 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 Offline

Posts: 89

Thank You
-Given: 50
-Receive: 85



WWW
« 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 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 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 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.

Code:
        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.

Code:
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 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  Smiley
....
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 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.

Code:
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 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 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.
Code:
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.
Code:
  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.
Code:
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 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:
Code:
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 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.htm
If 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 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
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright © 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC