## Microcontroller Converts Frequency to Voltage with High Resolution

When you need to convert a measurement signal from the digital to the analog domain, this design is a suitable solution with only two chips. Frequency-to-voltage conversion has many applications in instrumentation circuits.

This design (Fig. 1) is based on the 14-pin PIC Microcontroller 16F753, which has an embedded 16-bit counter and a 9-bit digital-to-analog converter (DAC). The input frequency range for this design is within 0 to 50 KHz, and its output voltage is within the range of 0 to 4.99 V, with a resolution of 10 mV.

1. The PIC microcontroller is the center of this frequency-to-voltage converter.

To achieve the conversion, the input frequency is separated into four scales, which are manually selected by the inputs SEL1 and SEL2 (Fig. 2).

2. The input frequency is separated into four scales by a DIP micro switch.

The DAC can deliver a maximum value of 4.99 V when its input code is 1FFh (511d), and 0.000V for a 000h input value. For the first scale, we get maximum and minimum values that are substituted in the following conversion equation:

Substituting those values, we get two equations:

Solving both equations we get:

And solving for M, we get:

Substituting both values in Equation 1, we get the offset value, and the result is Equation 3:

Now Equation 3 can be implemented in PIC basic code. But first, we need to measure the input frequency in 1.00 second intervals using TIMER1 as follows:

TMR1L = 0;                    Clearing TIMER1 registers

TMR1H = 0;

T1CON.0 = 1;                TIMER 1 Enabled

PAUSE 1000;                 for 1.00 Seconds

T1CON.0 = 0;                TIMER 1 Disabled

COUNTER.BYTE0 = TMR1L;    Storing both register in two bytes

COUNTER.BYTE1 = TMR1H;

Now we can apply Equation 3 as follows:

DIV = COUNTER *1000

DAC = DIV32 9784

DAC = DAC + offset ;     freq offset = 0;

If we get 2,500 pulses in TIMER1, for example, we can get the DAC’s value by dividing the pulses read by the constant 9.784 that we found previously:

Then, converting this to the software code, we get:

Now we can determine how many pulses are equivalent to each bit measured (Fig. 3).

3. The table shows the frequency-to-voltage conversion for scale 2.

For each scale, it’s necessary to obtain the constants by doing the same method used for Equations 1, 2, and 3. Thus, for the second scale (5-10 kHz), we get Equation 4:

Then we determine how many pulses are equivalent to each bit (Fig. 4).

4. The table shows the frequency-to-voltage conversion for scale 3.

For the third scale (10-15 kHz), we get Equation 5:

Then, we determine how many pulses are equivalent to each bit (Fig. 5).

5. The table shows the frequency-to-voltage conversion for scale 3.

For the fourth scale (10-50 kHz), we get Equation 6:

Then, finally, we determine how many pulses are equivalent to each bit in Figure 6.

6. The table shows the frequency-to-voltage conversion for scale 4.

Figures 7 and 8 show two cases in the scope for different input frequencies with their respective voltage output. The code listing below shows the software code implemented in the PIC16F753.

7. The screenshot depicts an input frequency of 5.000 kHz applied in the scale of 0-5 kHz, and its respective output of 5.04 V.

8. This screenshot shows an input frequency of 1.000 kHz applied in the scale of 0-5 kHz, and its respective output of 1.00 V.

Ricardo Jimenez holds a Master’s degree in electronics. He is the author of the book “The PIC Microcontroller Notebook, Vol 3,” ISBN: 978-1-7325906-1-8.

Gabriel Lee Álvarez is an Electronics Engineering student at ITM.

Software Code for the Frequency-to-Voltage Converter Based on the PIC16F753

‘*  Name    : FREQ-TO-VOLTAGE.BAS

‘*  Authors : Ricardo Jimenez and Gabriel Lee Alvarez

‘*  Version : 1

;    PIC16F753

; Frequency to Voltage Converter

; 0hz – 5khz = 0v – 5 v;   1st Scale

;5khz – 10khz = 0 – 5v;   2nd Scale

;10khz – 15khz = 0 – 5v; 3rd Scale

;10khz – 50khz = 0 – 5v; 4th Scale

;pic16f753

; Oscillator and PORTS Configuration

OSCCON = \$26; = \$26; Clock set to 4 MHz

OSCTUNE = 0;

TRISA = %111110;     RA0 IS A OUTPUT, RA1:RA5 AS INPUTS

ANSELA = %000010; RA0:RA5 DIGIITALS

TRISC = %0000000;   RC0:RC2 AS INPUTS, RC3:RC5 AS  OUTPUTS

ANSELC = %000000;  RC0:RC5 AS DIGITALS

WPUA = %011100; RA2,RA3 PULL IS ENABLE

WPUC = %000000

DEFINE LCD_DREG PORTC ‘ PORTC is LCD data port

DEFINE LCD_DBIT 0 ‘ PORTC.0 is the data LSB

DEFINE LCD_RSREG PORTC ‘ RS is connected to PORTC.4

DEFINE LCD_RSBIT 4

DEFINE LCD_EREG PORTC ‘ E is connected to PORTC.5

DEFINE LCD_EBIT 5

DEFINE LCD_BITS 4 ‘ 4 data line are used

DEFINE LCD_LINES 2 ‘ It is a 2-line display

DEFINE LCD_COMMANDUS 1500 ‘ Use 1500uS command delay

DEFINE LCD_DATAUS 44 ‘ Use 44uS data delay

;———SETTING UP LCD——————————————————–

LCDOUT \$FE,\$28;  \$28 FUNCTION SET, 4 BITS

LCDOUT \$FE,\$10;  \$10 SHIFT DISPLAY

LCDOUT \$FE,\$0C;  \$0C DISPLAY ON

LCDOUT \$FE,\$06;  \$06 ENTRY MODE SET

;————TIMER CONFIG ———-

T1CON = %10000100;     \$84 TIMER 1 DISABLE

;—HPWM SET to 250 Hz, when needed remove semicolons —

;CCP1CON = %00001100; PWM mode selection and CCPx enabled

;PR2 = 79;     Value obtained from equation

;T2CON = %00000100;   enabling timer 2, PRESCALER 16

;CCP1CON.5 =0

;CCP1CON.4 =0

;CCPR1L = %000101000;

;——– DAC  CONFIG —————————————

DAC1CON0 = %11100000;\$E0, DAC ENABLED RIGHT JUSTIFIED

;———DECLARING VARIABLES

COUNTER VAR WORD;            DECLARING COUNTING VARIABLES

;COUNTER.BYTE0 VAR TMR1L

;COUNTER.BYTE1

DAC VAR WORD;               VARIABLE TO BE USED BY DAC

SEL VAR BYTE;                    SCALE SELECTOR

HZ VAR BYTE[5];                DIGITS FOR HERTZ

DIV VAR WORD;

IN VAR BYTE;

VBE var word

OUT VAR BYTE;

I VAR WORD;

I2 VAR WORD;

ID VAR BYTE[3];

VIN VAR WORD;

VID VAR BYTE[4];

VED VAR BYTE[4];

VIN2 VAR WORD;

INVERT VAR PORTA.2; PIN FOR INVERTING DATA

x var byte;

VO VAR WORD[4];

OPTION_REG.7 = 0;

;——–PROGRAM STARTING —————-

RPT:

;FIRST TEST, LET’S DO THE FIRST SCALE

;QUANTITY OF BITS IN THE DAC = 511, SO 5KHZ/511

;5KHZ/511 = 9.7843

;K=9.7843

FOR X = 0 TO 5; STARTING LOOPS

HZ[X] = “0”;

VO[X] = “0”;

VIN = 0;    CLEARING VARIABLES

IN = 0;

OUT = 0;

SEL = 0;

DAC = 0;

DIV = 0;

DAC = 0;

VID[X] = “0”;

ID[X] = “0”

NEXT X;

LCDOUT \$FE,\$C0,”WAITING FOR SCALE “

OBTAIN_PULSES:;

LCDOUT \$FE,\$80,”HZ= “,HZ[4],HZ[3],HZ[2],HZ[1],HZ[0],” Vout= “,VO[2],”.”,VO[1],VO[0];

TMR1L = 0;  CLEARING REGISTERS IN TIMER1

TMR1H = 0;

T1CON.0 = 1;    TIMER 1 ENABLED

PAUSE 1000;

T1CON.0 = 0;    TIMER 1 DISABLED

COUNTER.BYTE0 = TMR1L;  STORING LOW BYTE REGISTERS

COUNTER.BYTE1 = TMR1H;  STORING HI-BYTE REGISTERS

FOR X = 0 TO 4;

IN = COUNTER DIG X;    GETTING DIGITS

LOOKUP IN,[“0123456789”],OUT;  DECODING EACH DIGIT

HZ[X] = OUT;                   STORING DIGITS

NEXT X;

LCDOUT \$FE,\$80,”HZ= “,HZ[4],HZ[3],HZ[2],HZ[1],HZ[0],” Vout= “,VO[2],”.”,VO[1],VO[0];

;—–SELECTION————

;FOR X= 0 TO 255

SEL = (PORTA & %011000)>>3; READING PORTA ANS SHIFT RIGHT BITS 3 SPACES

;SELECTING SCALE

IF SEL = %00 THEN GOSUB ESC1;     0-5KHZ

IF SEL = %01 THEN GOSUB ESC2;    10K-50K

IF SEL = %10 THEN GOSUB ESC3;    10KHZ-15KHZ

IF SEL = %11 THEN GOSUB ESC4;    5KHZ-10KHZ

IF INVERT  = 0 THEN DAC = 511-DAC;   INVERT DATA IF = 0

GOSUB V_DAC;

LCDOUT \$FE,\$80,”HZ= “,HZ[4],HZ[3],HZ[2],HZ[1],HZ[0],” Vout= “,VO[2],”.”,VO[1],VO[0];

GOSUB DAC_OUT;

GOTO OBTAIN_PULSES; GO TO LABEL OBTAIN_PULSES;

;—————— FIRST SCALE  ——————————

ESC1:;                 0HZ A 5KHZ

;  getting Scale values

DIV = COUNTER *1000

DAC = DIV32 9784

IF (COUNTER >5000) THEN DAC = 0; ; EQUAL TO ZERO IF NOT IN RANGE

LCDOUT \$FE,\$C0,”0-5KHZ DAC= “,dec dac,”

RETURN;

;———————-4th SCALE——————-

ESC4:;                     10KHZ-50KHZ

DIV = COUNTER*100

DAC = DIV32 7827

DAC = DAC – 127;

IF (COUNTER >50000) OR (COUNTER

LCDOUT \$FE,\$C0,”10-50KHZ DAC= “,DEC DAC,”

RETURN;

;———————–3rd scale—————–

ESC3:                      ; ESCALA 10KHZ – 15KHZ

DIV = COUNTER*1000

DAC = DIV32 9784

DAC = DAC – 1022;

IF (COUNTER >15000) OR (COUNTER

LCDOUT \$FE,\$C0,”10-15KHZ DAC= “,DEC DAC,”

RETURN;

;——————————————————————————

ESC2:; SCALE 5KHZ – 10KHZ

; ————–getting the values for this Scale

IF (COUNTER >10000) OR (COUNTER

LCDOUT \$FE,\$C0,”5-10KHZ DAC= “,DEC DAC,”

DIV = COUNTER*1000

DAC = DIV32 9784

DAC = DAC – 511;

IF (COUNTER >10000) OR (COUNTER

LCDOUT \$FE,\$C0,”5-10KHZ DAC= “,DEC DAC ,”

RETURN;

;–VOLTAJE DAC———

V_DAC:

DISABLE

VO[1]= DAC*976;        GETTING VOLTAGE FROM DAC

VO[3]= DIV32 100;      WITH RESPECT TO NUMBER

ENABLE

FOR X = 0 TO 2;

IN = VO[3] DIG (X+1);    FIND THE RESPECTIVE DIGITS

LOOKUP IN,[“0123456789”],OUT;DECODING DIGITS

VO[X] = OUT;              STORE DIGITS

NEXT X;

RETURN;

;——————————————————————————-

DAC_OUT:

DAC1REFL = DAC.BYTE0;      modifying the DAC0 register

DAC1REFH = DAC.8;              modifying DAC0-bit 8

RETURN;

;——————————

END;