Projects - PIC

 

1kHz sinusoidal with PIC


Generate a sine with microcontroller.

A waveform can be generated by any microcontroller using a DA converter.

Unfortunately, it is a device present only on some chips and, where there is not, the alternative is to use an external chip, which, in turn, requires a SPI or I2C communication, which has to be implemented. 

The most common solution becomes to use a R-2R network outside.
Here, however, we have the necessity of a number of digital I / O equal to the definition of the network: for 8-bit will have 8 pin engaged.

When we are to have a smaller number of pins, as in the case of the chip in a container 8 pin, this is not possible and it is necessary to use a different technique.

We know that, in a PWM modulation where the frequency is kept fixed and varying the duty cycle, moves to 'output a variable percentage of energy.
We can use the PWM signal in different ways, of which the most common are:

  • use the PWM directly for drive the load, also with a buffer, to vary, for example, brightness of the LED or speed of motors
  • or, by inserting a low pass filter which isolates only the DC component, obtaining a variable voltage. In this case, the low pass filter will eliminate any alternating component, including the fundamental frequency.

But we can also apply a filter that eliminates the high harmonics of the fundamental, while maintaining this and pulling it out as alternating component with a constant frequency, the level of which will vary according to the variation of the duty cycle.

The CCP module / PWM is present on many PIC, also with the possibility of multiple channels; is also found in small 8-pin chip, like the 12F683, microcontroller Midrange fairly widespread and that we will use in this application. Obviously you can replicate it for any other PIC with CCP / PWM.

One may wonder what is the benefit of using the microcontroller to generate a waveform. This is essentially due to the high precision frequency that depends on the 'crystal oscillator clock. The sinusoid output will have the same precision clock oscillator, difficult to achieve with precision analog circuits, which require components of RC values are not always easily available.

Here, we want to get 1kHz, base frequency for a large number of measures.

The idea is taken from a work of Roman Black.


The circuit

We can create a circuit based on these principles.

It uses a 20MHz crystal oscillator or, alternatively, an external oscillator. In the scheme are given both, but, of course, only one will be wired.
The external oscillator, against a higher cost, provides greater accuracy and stability.
A classic crystal + capacitors oscillator have a compensator to adjust the frequency. The values of the capacitors depends on the quartz used and are between 18 and 33pF; prototypes were used, with quartz from different manufacturers, the capacitors from NP0 22pF.

With the clock to 20 MHz, we have a cycle of education 200ns. This allows us to obtain a precise PWM from CCP module with a cadence of 20us.

The program includes an auxiliary output to 50kHz that can be used, as we shall see, for the next filter. From the same output is also the possibility of obtaining an alternative 1MHz (duty cycle 40%), both to facilitate the calibration that for general use. This function is achieved by closing the S1 button.
A two-color LED with two pins is used to report the mode of operation. When S1 is closed, the microcontroller port pin GP0 at high level, turning on the red LED (R) through R1; the led light orange. When S1 is open, GP0 will be brought to 0, and only the green LED (G) is on through R2.

The components are:

R1 R2 R3 C1 C2 C3 C4 C5 Q1/QG1 S1 LED
820 820 47k 18-33p 3-30p 100n 100n 100u 20MHz interr. bicol.


The signal at 1 kHz is sent to a low pass filter that suppresses the harmonics and the output of which will be found the sinusoid with minimal distortion.
A first solution is given by a series of RC filters:

This is three low pass the first of which also includes an inductance. The advantage is given by the zero consumption on 'power and by a relative low cost; despite a precise calculation requires values uncommon, you too can achieve positive results with easily obtainable components. By contrast, introduces a degree of attenuation. C4 is a non-polarized, which eliminates the continuous component.
The values are:

R1 R2 R3 L1 C1 C2 C3 C4
330 330 820 2.2mH 0.33uF 68nF 68nF 10uF np

The values are approximated to those of the most common commercial series.

A second solution, a little more complex, is to use a digital filter. We can choose one of several integrated designed for this purpose, based on switched capacitor and produced by various manufacturers. Lend themselves well MAX295 / 296 Maxim, which have a ratio 50: 1 between clock frequency and frequency filtered.
Here we use a MAX296, Bessel's eighth order.

The power supply is filtered with a LG (L1 / C5 / C6) that separate very well the filter from digital noise induced on 'power.
PWM clock and are sent directly to the MAX; this is expected for a dual power supply, that, if desired implement, provides the best results. However, here the circuit is intended for a single power supply is necessary and a virtual ground formed by R1 / R2 / C8.
R6 is a protective resistor that separates the connector from the circuit X2.
The MAX29x also incorporate an operational amplifier (pins 3-4) which is used as an additional low pass (Sallen-Key topology multiple feedback):

The components:

R1 R2 R3 R4 R5 R6 C1 C2 C3 C4 C5 C6 C8 L1
10k 10k 16.5k 14.7k 14.7k 50 22nF 10uF
 np
100uF 4nF7 10nF 100uF 4uF7
tant.
1mH

The resistor's values are approximated to those of the most common SND commercial series 

Development is possible with ease using the card LPCuB:

The filters are made externally on breadboard for a quickly modify of the components.
The final version may then be carried out on a specific printed circuit.


Software.

In the program, the PWM is supplied with the clock at 20MHz: for a loop, established from PR2, 100 clock pulses, we will obtain a frequency of 50kHz.

; initialize CCP module for PWM
; Microchip suggestion on data sheet

       clrf    CCP1CON   ; CCP Module is off
       clrf    TMR2      ; clear Timer2
       banksel PR2
       movlw   (.100-1)
       movwf   PR2
       banksel GPIO
       clrf    INTCON    ; clear T0IF
       banksel TRISIO
       bcf     Sout      ; make pin output
       banksel GPIO 
       clrf    PIR1      ; clear peripheral interrupts Flags
; CCP1 ON, and set to PWM mode

       movlw   b'00001101'
       movwf   CCP1CON
       movlw   .52       ; first value from the table
       movwf   CCPR1L
; and start TRM2
       movlw   b'00000100'
       movwf   T2CON

For each output pulse of the PWM signal is associated with a different duty cycle value, taken from a table of 50 steps, thereby obtaining a sinusoidal variation of the same duty cycle between about 15 and 85% each kilohertz.
The Directive dt compiles quickly retlw table.

; "harmonic compensated" sine table
sinetable addwf PCL,f

 dt 52,57,62,66,70,74,77,80,82,84,85,86,86
 dt 86,85,83,81,78,75,72,69,65,61,56,52
 dt 48,44,39,35,31,28,25,22,19,17,15,14,14
 dt 14,15,16,18,20,23,26,30,34,38,43,48

At the same time it generates a square wave signal of 50 kHz which will be used for the digital filter. This signal has a duty cycle of 50% as active filters require this to work best; it is simply obtained within the loop update of the PWM, with a pulse at high level of 50 instruction cycles.

; 50kHz pulse
     bsf    Faux    ; pulse start
     movlw  0x10    ; 49 cycles
     movwf  d1
dcyc decfsz d1, f
      goto  dcyc
     bcf    Faux    ; pulse end

Given that the next pulse will be triggered at the end of a PWM cycle that lasts 100 instruction cycles, here we have the correct duty cycle.

An added bonus is supplied from the switch S1, the closing of which deflects the 'running on a stretch of program that generally a square wave with duty cycle of 40% and a frequency of 1MHz, which can be used for the calibration of' oscillator. L 'asymmetry is due to the necessity of the test on the state of the switch that switches the manner and to the loop, since the instruction cycle is 200ns.

; Calibrate mode: make a 1MHz fixed freq on pin Faux
; 5 instructions per cycle,
; output squarewave 1MHz with 40% on duty.

cal_mode:            
       clrf  CCP1CON   ; CCP1 module is turned OFF

; MHz mode - LED red on
       LEDRED

loop_1MHz:
       bsf   Faux      ; output high
       nop         
       bcf   Faux      ; output low
       btfsc btn       ; test switch for SINE mode
        goto done_1MHz ; switch hi - exit go to SINE mode
       bsf   Faux      ; no - output high
       nop             
       bcf   Faux      ; output low
       goto  loop_1MHz ; loop

done_1MHz:             ; out from MHz mode
       goto  sine_mode ; back to sine mode

The switch is also equipped with a debounce time, to avoid the bounces generate random states of outputs.
The two-color LED is controlled depending on the position of S1.


The box.

Was made a version portable, battery.
Here, 4 NiMH batteries are used I provide a variable voltage between 4.8V (loads) and 4.4V (discharges), which within the capabilities of the microcontroller, although it is likely that the variation of the supply voltage reflects poorly on the stability. It was used the passive filter, which does not consume power, extending battery life (the entire circuit draws approximately 7.5 mA).
The oscillator is a crystal and the capacitive trimmer allows an adjustment of the frequency.

A version of "counter" is easily accomplished with the usual 78L05 regulator and an external wall plug. Here you have implemented the digital filter and the oscillator clock is an external 14-pin module.

The firmware is identical for both versions; goes only modified the initial config where you want to use the external oscillator:

; config per oscillatore a quarzo 
 __config _HS_OSC & _WDTE_OFF & _PWRTE_ON & _BOREN_OFF & _IESO_OFF & _FCMEN_OFF & _MCLRE_OFF

; config per oscillatore esterno
 __config _EC_OSC & _WDTE_OFF & _PWRTE_OFF & _BOREN_OFF & _IESO_OFF & _FCMEN_OFF & _MCLRE_OFF

The output signal from the PWM should be considered in its alternating component at the fundamental frequency. However, since the variation of the duty cycle is not continuous, but in steps, sensitive components are introduced at multiple frequencies, which are to be torn down by the low pass filter. In particular, the second harmonic is the most obvious, while the sampling errors of the above values are secondary.

Both the passive filter that makes the active satisfactory results.
Passive filter, first cell RLC and output. Next, the FFT data from 'oscilloscope.
All 'beginning of the filter you notice the strong presence of harmonics, which are then reduced to' output.

The sine wave output amplitude to a vacuum of about 1.4V.
Tweaking the equalizer you can adjust the frequency of 'oscillator. With the tools available has been recognized as the best value of the frequency of 1.000.070 MHz.
Here we see the 'output and the 50kHz to 1MHz:


This is the output waveform of the digital filter:. 

 


C vs. Asm

The original idea has a C source in which there is a significant intrusion of Assembly.
This is because it is not possible to use the C in order to ensure a total control at the level of individual instructions as in this case, where the timings, for example, that to generate the MHz, are stringent.

Assembly offers a full control of the times, so that, for example, the' insertion of the clock at 50kHz is extremely simple, while the C would have required more sections asm.

Here we preferred an approach entirely Assembly, which is much better calibrated on the application, which does not require complex calculations or logical structures, but only an optimal management of the bits of I / O. And, for what concerns the audit logs of the CCP module / PWM, there is no real difference between C and Assembly in the form and in the understanding of the source.

As a bonus, the 'executable produced by the Assembly source size is significantly smaller and requires less RAM.
Finally, one can notice that, for programs where you have to do primarily with I / O and SFR and must comply timing critical, l 'approach in C is not always the best one, and should be reserved to other areas, especially in small PIC with limited resources and little optimized for this language.

The source was compiled for the 12F683, but is adaptable with great ease to any other PIC module equipped CCP / PWM, simply by adjusting the schedule to access the digital I / O (excluding the alternate functions), while the management of the PWM remains essentially unchanged through other Midrange, Enhanced Midrange and even PIC18F. It 'also easily adaptable to 10F32x, who MSSP and external clock input, or to give up the auxiliary clock indication LEDs (due to the low number of pins).

And, given the simplicity of the source, it will not be difficult to overtake even Microcontrollers other manufacturers.
The principle may be applied to obtain different values the of the output frequency, by modifying the clock and / or the PWM.



The Assembly Source.

;******************************************************************************
; Sine1kHz.asm Precision 1kHz sinewave generator
; from an idea of www.RomanBlack.com/
;
; PIC 12F683 - 20MHz xtal
;-----------------------------------------------------------------------------
; I/O pins;
;
#define LED  GPIO,GP0  ; Out LED Red
#define Faux GPIO,GP1  ; Out Faux
#define Sout GPIO,GP2  ; Out CCP1
#define btn  GPIO,GP3  ; In button
                       ; GP4 oscout
                       ; GP5 oscin

;--------------------------------------------------------------------
;
           LIST p=12F683 r=DEC
           #include <p12F683.inc>


; for chrystal oscillator
 __config _HS_OSC & _WDTE_OFF & _PWRTE_ON & _BOREN_OFF & _IESO_OFF & _FCMEN_OFF & _MCLRE_OFF
; for external oscillator module
; __config _EC_OSC & _WDTE_OFF & _PWRTE_OFF & _BOREN_OFF & _IESO_OFF & _FCMEN_OFF & _MCLRE_OFF

;*********************************************************************
; Data RAM area

     CBLOCK 0x20
  pwmstep  ; PWM step 0-49
  debounce ; debouncing switch input
  d1       ; temporary for delay
     ENDC

;********************************************************************
; LOCAL MACROS

; CFLSB Compare File to Literal and Skip if Below
; Compare register with literal and jump next line if
; file < literal

CFLSB MACRO file,lit
       movlw (255-lit+1) ; W = -lit
       addwf file,W      ; W = file + W = file + (-lit)
       skpnc             ; C=0 for file<lit, than skip next line
      ENDM               ; C=1 for file>=lit, than execute next line

LEDGREEN MACRO
       bcf LED
         ENDM
LEDRED MACRO
       bsf LED
         ENDM

;=====================================================================
; MAIN

RESVEC ORG 0x00

Main goto init

; "harmonic compensated" sine table
sinetable addwf PCL,f

 dt 52,57,62,66,70,74,77,80,82,84,85,86,86
 dt 86,85,83,81,78,75,72,69,65,61,56,52
 dt 48,44,39,35,31,28,25,22,19,17,15,14,14
 dt 14,15,16,18,20,23,26,30,34,38,43,48

;--------------------------------------------------------------------
init:
; preload GPIO output latch
      movlw   0
      movwf   GPIO

;comparators OFF, all pins digital
      movlw   b'00000111'
      movwf   CMCON0

; analog off and all possible as out
      banksel ANSEL
      clrf    TRISIO
      clrf    ANSEL

; TMR0 not used, but clear T0CKI
      movlw   b'10001000'
      movwf   OPTION_REG
      banksel GPIO

; setup any variables before main loop
      clrf    pwmstep
      clrf    debounce

;--------------------------------------------------------------------
; Sine mode: use PWM to make the sine out pin
sine_mode:
; LED green is on, red is off
      LEDGREEN

; initialize CCP module for PWM
; Microchip suggestion on data sheet
      clrf    CCP1CON ; CCP Module is off
      clrf    TMR2    ; clear Timer2
      banksel PR2
      movlw   (.100-1)
      movwf   PR2
      banksel GPIO
      clrf    INTCON ; clear T0IF
      banksel TRISIO
      bcf     Sout   ; make pin output
      banksel GPIO
      clrf    PIR1   ; clear peripheral interrupts Flags
; CCP1 ON, and set to PWM mode  
      movlw   b'00001101'
      movwf   CCP1CON
      movlw   .52    ; first value from the table
      movwf   CCPR1L
; and start TRM2
      movlw   b'00000100'
      movwf   T2CON

; loop: load new PWM value every TMR2 cycle
slp0  incf  pwmstep,f    ; inc to next step in sinewave
      CFLSB pwmstep, .50 ; sine has 50 steps
      clrf  pwmstep
      movf  pwmstep,w    ; read new PWM value
      call  sinetable    ; from sinetable

slp1  btfss PIR1,TMR2IF  ; wait for TMR2 cycle to restart
      goto  slp1
      movwf CCPR1L       ; load new value
      bcf   PIR1,TMR2IF  ; clear TMR2 int flag

; 50kHz pulse
      bsf    Faux
      movlw  0x10        ;49 cycles
      movwf  d1
dcyc  decfsz d1, f
       goto  dcyc
      bcf    Faux        ; pulse end

; also check for switch being low, if so go to calibrate mode
      btfsc  btn
       goto  slp2
      incf   debounce,f
; if debounce > 250 goto cal_mode.
      CFLSB  debounce, .250
       goto  cal_mode
      goto   slp0
;else debounce = 0;
slp2  clrf   debounce
      goto   slp0       ; back to loop

;--------------------------------------------------------------------
; Calibrate mode: make a 1MHz fixed freq out pin Faux
; 5 instructions per output cycle,
; output squarewave 1MHz with 40% on duty.
cal_mode:
; CCP1 module is turned OFF
     clrf   CCP1CON

; CAL mode LED red is on
     LEDRED

loop_1MHz:
     bsf   Faux        ; output high
     nop 
     bcf   Faux        ; output low
     btfsc btn         ; test switch for SINE mode
      goto done_1MHz   ; switch HI, so exit this mode and go back to SINE
     bsf   Faux        ; output high
     nop 
     bcf   Faux        ; output low
     goto  loop_1MHz   ; loop

done_1MHz:             ; out from cal_mode
     goto sine_mode    ; cal mode is done, back to sine mode

;-----------------------------------------------------------------------------

    END

 


 

 

Copyright afg. Tutti i diritti riservati.
Aggiornato il 19/04/15.