PDA

View Full Version : 16f877 generate pwm according 2 analog input



madxice
- 23rd December 2008, 19:48
Hello everybody,

I am trying to make buck converter and control it with 16f877. The logic is simple. If the output voltage of the buck is higher than reference voltage the pwm duty cycle will decrease, if the output voltage is lower than the reference the duty cycle will increase. It seems very simple, but I couldn't be able to write the program:( I write but i doesn't work. I am new at pic programming. Help me please!!!

My crystal is 20MHz.

And it gives an error " ADC conversion clock period (1e-7) is possible invalid for device clock frequency" in proteus simulation.





DEFINE OSC 20
DEFINE ADC_BITS 8
DEFINE ADC_SAMPLES 50

TRISA=%00000011
TRISB=00
TRISC=00
TRISD=00
TRISE=00


Reference var byte
Voltage var byte

CCP1CON=%000011100
CCP2CON=%000011100
T2CON=%00000101 'timer 2 on, 1:1 postscale, 1:4 prescale
PR2= 49
CCPR1L=%00011001


get_reference:
ADCON1=%00000000
' Set LEFT Justification
' Enable ALL ADC's (using PIC16F87x as example)
ADCON0=%11000001

' Set ADC Channel 0 (RA0/AN0)
' Enable ADC Module
PauseUS 50
' 50uS Pause to allow sampling Capacitor to charge
ADCON0.1=1
' Start Conversion
While ADCON0.1=1:Wend
' Wait for conversion to complete
Reference=ADRESH
' Read 8-bit Result
return

get_voltage:
ADCON0=%11001001
' Set Fosc/32
' Set ADC Channel 1 (RA1/AN1)
' Enable ADC Module
PauseUS 50
ADCON0.1=1
While ADCON0.1=1:Wend
Voltage=ADRESH
return

azalt:
CCPR1L=CCPR1L-1
return

arttir:
CCPR1L=CCPR1L+1
return

sabit:
CCPR1L=CCPR1L
return

main_loop:
Gosub get_Reference ' Get reference value
Gosub get_voltage ' Get voltage value
if Reference>Voltage then azalt
if Reference< Voltage then arttir
IF Reference=Voltage then sabit
goto main_loop ' Do it forever

end

mackrackit
- 23rd December 2008, 22:32
Welcome to the forum.

First thing I see in the code "main-loop" it just stops, no return, goto or even a THEN to go with the IF.

Second thing. If the only place you are trying this is on a simulator, good luck.
Use a bread board for your simulator.

Darrel Taylor
- 24th December 2008, 06:27
There's more to the code.
For some reason vBulletin saw "Reference&lt;Voltage" as being HTML and it messed up the post. I added a space, and now it shows the whole thing.<hr>
I think Proteus is complaining about using ADCON0=%11000001.
A/D Clock mode 3 is not recommended at 20mhz, but I wouldn't call it an error.
Using ADCON0 = %10000001 might clear the problem, by selecting FOSC/32, which is what the comments say you wanted anyhow.

But I think the biggest problem is that the execution from the beginning falls into the get_reference Subroutine.
When it hits the RETURN, it has no idea where to go, because nothing GOSUB'd to it to begin with.
You should have a GOTO main_loop before that point.

You should also put some limits on CCPR1L.
It shouldn't go above PR2 (49) or try to go below 0.
Just some IF statements will fix that.

hth,

Archangel
- 24th December 2008, 06:43
Hello everybody,

I am trying to make buck converter and control it with 16f877. The logic is simple. If the output voltage of the buck is higher than reference voltage the pwm duty cycle will decrease, if the output voltage is lower than the reference the duty cycle will increase. It seems very simple, but I couldn't be able to write the program:( I write but i doesn't work. I am new at pic programming. Help me please!!!

My crystal is 20MHz.

And it gives an error " ADC conversion clock period (1e-7) is possible invalid for device clock frequency" in proteus simulation.





DEFINE OSC 20
DEFINE ADC_BITS 8
DEFINE ADC_SAMPLES 50

TRISA=%00000011
TRISB=00
TRISC=00
TRISD=00
TRISE=00


Reference var byte
Voltage var byte

CCP1CON=%000011100
CCP2CON=%000011100
T2CON=%00000101 'timer 2 on, 1:1 postscale, 1:4 prescale
PR2= 49
CCPR1L=%00011001


get_reference:
ADCON1=%00000000
' Set LEFT Justification
' Enable ALL ADC's (using PIC16F87x as example)
ADCON0=%11000001

' Set ADC Channel 0 (RA0/AN0)
' Enable ADC Module
PauseUS 50
' 50uS Pause to allow sampling Capacitor to charge
ADCON0.1=1
' Start Conversion
While ADCON0.1=1:Wend
' Wait for conversion to complete
Reference=ADRESH
' Read 8-bit Result
return

get_voltage:
ADCON0=%11001001
' Set Fosc/32
' Set ADC Channel 1 (RA1/AN1)
' Enable ADC Module
PauseUS 50
ADCON0.1=1
While ADCON0.1=1:Wend
Voltage=ADRESH
return

azalt:
CCPR1L=CCPR1L-1
return

arttir:
CCPR1L=CCPR1L+1
return

sabit:
CCPR1L=CCPR1L
return

main_loop:
Gosub get_Reference ' Get reference value
Gosub get_voltage ' Get voltage value
if Reference>Voltage then azalt
if Reference< Voltage then arttir
IF Reference=Voltage then sabit
goto main_loop ' Do it forever

end


I do not know how or if it will affect your code, but I did notice your CCP1CON and CCP2CON register settings have 9 bits.

madxice
- 1st January 2009, 10:13
Hello again,

For my buck problem, I found a good example. With little changes I applied to my circuit. Now it is working. This circuit was maintaining the voltage.It was infiinite loop.

Now, I want to use SPI module of 16f877 for TLC5941 led driver IC. It uses CLK, SDO outputs continuously. This should be infinite loop too.

May be it will be a silly question. But is there any way to use same pic for 2 different infnite loops? Do I have to use 2 pics. I can use, but if it is available I want to do it with one pic. Because I think to use rgb leds. And if I use 2 pics for one color, it will increse the total number of pics in my whole project.

art-666
- 24th May 2009, 13:11
Hello again,

For my buck problem, I found a good example. With little changes I applied to my circuit. Now it is working. This circuit was maintaining the voltage.It was infiinite loop.

How nice you found code, but why not share it so we can follow.

surfies
- 9th July 2009, 14:47
Yes I would also like to see that code