Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

control feedback code - help

Status
Not open for further replies.

elec123

New Member
Hi,

I am halfway through a project which involves using a dc to dc converter to boost the voltage from a solar panel to a constant 100V.

I have designed and successfully built the boost converter and have written a simple PWM code to boost 17V (rated output voltage from panel) to 100V:

#include <p16f877.h>


void main(void)
{
trisc = 0x00;
portc = 0x00;

pr2 = 0x18; //sets PWM period
ccpr1l = 0x14; //sets PWM duty cycle to 82%
t2con = 0x05; //enables timer 2 modules and sets the TMR2 prescale value to 4.
ccp1con = 0x2C; //Enables PWM mode

}

This is working fine.

Now I want to write additional code so i can send the correct PWM to the switch so i can maintain 100V output whatever the input voltage/light level i.e (input voltage 0-20V) - which will involve adjusting the duty cycle according to the input voltage. As i'm a beginner to programming it has been suggested to me that i use a control circuit consisting of op amps to reduce the input voltage range to 0-5V and feed this into the A/D input of the pic that I am using (PIC16F877A).

This is where I am stuck:

After reading the datasheet, I still don't understand how the A/D would convert the input voltage and where the 8bit digital number is stored? hence where i can call it from. Is the A/D simple to set-up?

Do you think the above method would work?

I'm really struggling with this feedback code, so any help or advice on the best way to implement a solution to what i'm trying to achieve would be greatly apreciated.

Thanks
elec123
 
Here is a tutorial on the ADC:

To use the PIC as a boost converter, you'll need to implement a PID algorithm to avoid an unstable control loop. Microchip has an application note on that:
**broken link removed**
You could use a simpler loop that uses the following logic:
Increase PWM if ADC reading drops below set value.
Decrease PWM if ADC reading rises below set value.
Maintain PWM if ADC reading equals set value.
However, this type of algorithm tends to be somewhat unstable and the 100V output would wander around a bit.
Here's another ap note from Microchip that you may be able to adapt:
https://www.electro-tech-online.com/custompdfs/2008/01/01047a.pdf
 
Last edited:
I have worked through the tutorial but am still having troubles setting up my adc for my boost converter.

It would be really helpful if you could look through my code and see where i'm going wrong as i'm really stuck!

At the start of the program i have two look up tables look1 and look2 each containing 256 values for ccpr1l and ccp1con (which i have calculated using an excel spreadsheet). then:

void main(void);
void Initialize_ADC(void);


void main()
{

unsigned char dig_input;

Initialize_ADC();

//Read_ADC

ADGO = 1; //captures analogue voltage on pin.

while (ADGO)
{
//dig_input = 0x00;
}


dig_input = ADRESH; //defines the digital input.


if (dig_input<128) //if solar panel (Vin) to boost converter is less than 10V don't boost.
{

CCPR1L = 0x00; //sets pwm to have duty cycle of zero.
CCP1CON = 0x00;
}

else
{

dig_input -= 128; //dig_input = dig_input-128
dig_input += dig_input; //multiplies dig_input by 2

CCPR1L = look1[dig_input];
CCP1CON = look2[dig_input];

}


}
void Initialize_ADC()
{
TRISA = 0x01;
TRISC = 0x00;
PORTC = 0x00;
PR2 = 0x18;
T2CON = 0x05;

ADCON0 = 0x80; //clear ADCON0 A2D starts sampling again.

//Set ADCON1

ADCON1 = 0x00; // clear ADCON1 register.//
ADCON1 = 0x02; // set PCFG1 bit i.e AN0 is analogue input.
ADON = 1;
};


Basically i want to read analogue input, convert it to digital, with this digital voltage assign ccpr1l and ccp1con the appropriate hex value so that the correct duty cycle is sent to the pwm output (want to have set period just change the duty cycle).

Can't see where i'm going wrong in the above code, was wondering if it was something to do with the required acquisition time of the adc? do i need to set this?

I have probable missed something obvious as i'm a beginner to all of this!

Any help would be greatly appreciated.

Thanks
 
Your code looks fine. You only need to worry about the acquisition time if you are changing channels, as you are only reading AN0 then you should be fine. Can you simply put a pot on the ADC input and see if it boosts below a certain level and doesn't above?

Mike.
 
I have programmed the code onto the PIC and tested it by varying the input voltage on AN0 from 0-5V and just get a "not square" square wave, and the duty cycle doesn't change at all, just the voltage level of the output signal.

In MPLAB, my code builds successfully but when i go to MPLAB SIM in the output box i get the message:

"ADC-W0010: A Minimum of 2 TADs are required before another conversion should be started.

Does this mean i need to add a delay somewhere in my program?

I have been reading this thread:

https://www.electro-tech-online.com/threads/pic18f452-adc.23175/

In which forum members describe the need for delays in the program, where should these delays be placed?

From my understanding of the datasheet, TAD is controlled by the ADCON0 register? I have to use the 32Tosc operation as my external oscillator crystal is at 8MHz, this corresponds to ADCS1:ADCS0 being 10, is this correct?

Help on this would be great,

Thanks
 
It seems to me that your main routine is executed once and the program might be not properly terminated (this might be compiler dependent and could yield unexpected results). It's good practice to use a while instruction in order to create an endless loop.

Code:
void main(){
   // initialization

  while(1){  // always true

      // ADC operation and control

  }

}
 
Last edited:
I don't know why you would get that error as you are only converting once (as pointed out by eng1 - I missed that). You should do as eng1 says and put a while(1) after the initialisation and put a short delay at the end of the while loop.

Mike.
 
I have added a delay (frank) which i thought would solve the problem:

void main(void);
void Initialize_ADC(void);


void main()
{

unsigned char dig_input;
unsigned char frank;

Initialize_ADC();

while(1)
{
//Read_ADC

ADGO = 1; //captures analogue voltage on pin.


frank = 0x10;
while(frank != 0x00)
{frank -= 1;}


while (ADGO)
{}

frank = 0xFF;
while(frank != 0x00)
{frank -= 1;}

dig_input = ADRESH; //defines the digital input.


if (dig_input<128)
{
CCPR1L = 0x00; //sets pwm to have duty cycle of zero.
CCP1CON = 0x00;
}

else
{
dig_input -= 128; //dig_input = dig_input-128
dig_input += dig_input; //multiplies dig_input by 2

CCPR1L = look1[dig_input];
CCP1CON = look2[dig_input];

}

}
};

void Initialize_ADC()
{
TRISA = 0x01;
TRISC = 0x00;
PORTC = 0x00;
PR2 = 0x18;
T2CON = 0x05;

ADCON0 = 0x80; //clear ADCON0 A2D starts sampling again.

//Set ADCON1

ADCON1 = 0x00; // clear ADCON1 register.//
ADCON1 = 0x02; // set PCFG1 bit i.e AN0 is analogue input.
ADON = 1;

};

Still getting the message:

"ADC-W0010: A Minimum of 2 TADs are required before another conversion should be started"

are the delays in the right position? not really sure on how long the delays need tobe....any ideas on how to solve this, and get the adc working properly?

thanks
 
You really need to put code tags around your code. Put
Code:
 and [/co de] (without the space) before and after your code and it will keep the formatting.

Mike.
 
Try something like,
Code:
void main(){
unsigned char dig_input;
unsigned int i;
    Initialize_ADC();
    While(1){
        //Read_ADC
        ADGO = 1; //captures analogue voltage on pin.
        while (ADGO);
        dig_input = ADRESH; //defines the digital input.
        if (dig_input<128){ //if solar panel (Vin) to boost converter is less than 10V don't boost.
            CCPR1L = 0x00; //sets pwm to have duty cycle of zero.
            CCP1CON = 0xc0; 
        }
        else{
            dig_input -= 128; //dig_input = dig_input-128
            dig_input += dig_input; //multiplies dig_input by 2
            CCPR1L = look1[dig_input];
            CCP1CON = look2[dig_input];
        }
    for(i=0;i<1000;i++);
    }
}

Mike.
Edit, I should have pointed out that I think setting CCP1CON to zero is not a good idea. I changed it above.
 
Last edited:
I am stilling having troubles with my code and would appreciate if someone could have a look at it for me....


The input from the solar panel is scaled down from 0-20V to 0-5V using a simple op-amp circuit. I'm defining the result of the analogue to digital converter as dig_input.

I have my two look up tables for ccpr1l and ccp1con each containing 256 values, where the 128th corresponds to 10V out of the solar panel (2.5V after the op-amps)

My code is as follows:

Code:
dig_input = 130; ///////////////REMOVE//////////////////
	
	if (dig_input<128) //if solar panel (Vin) to boost converter is less than 10V don't boost.
		{
		CCPR1L = 0x64; //sets pwm to 100% this gets inverteted to 0% by driver i.e don't boost.
		CCP1CON = 0x0C; 
		}

	else
			{
	
		dig_input -= 128; // scaling dig_input to number between 0-255
		dig_input += dig_input; 

		CCPR1L = look1[dig_input];
		CCP1CON = look2[dig_input];

when i was testing the code in MPLAB i put dig_input=130 to skip to the else section.

I get an error:

Error[477] : fixup overflow in expression (location 0x72 (0x72+0), size 2, value 0x804)

Anyone know what i'm doing wrong? and know how to solve this?

i've looked the error message and get the impression that this means the vaue is to big for the location, but still don't understand it.....

Any help on this would be greatly appreciated! (i'm probably doing something stupid!)

Thanks

elec123
 
Status
Not open for further replies.

Latest threads

Back
Top