CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

MPPT type boost /16f883/ programmation

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
coyotte4845



Joined: 16 Mar 2017
Posts: 4

View user's profile Send private message

MPPT type boost /16f883/ programmation
PostPosted: Thu Mar 16, 2017 8:46 am     Reply with quote

Hello,

Can you help me with this code (16f883) ?

This code has to search for the mpp for a solar regulator type boost.

The PIC has a power supply fixed to 3v.

The pic has to measure 3 values from AN0(Upanel), AN1 (Ubatt), AN3(Ipanel pin5).

I used a max4376 and a current sensor, the output is directly connected to input AN3.

My problem is: impossible to read AN3.

Thanks for your help.

PCWH 4.0.38
Code:

#include "C:\Documents and Settings\Moi\Bureau\PICC\MPPT citea 3V\main.h"
#bit godone=0x1F.1
#bit ADIF=0x0C.6
#byte ADCON0=0x1F
#byte ADCON1=0x9F
#byte ADRESL=0x9E
#byte ADRESH=0x1E
#byte ANSEL=0x188
#define LED pin_b7

#int_TIMER1
TIMER1_isr()
{   
   int i;
   i++;
   if(i>=30)
      {output_high(LED);
    delay_ms(100);
    output_low(LED);
    i=0;
   }
   
}

void main()
{
   unsigned int16 PWM=0,t=0,i=0;
   unsigned int16 ADVp=0,ADVpt=0,CompADVp=0;
   unsigned int16 ADVb=0,ADVbt=0;
   unsigned int16 ADI=0,ADIt=0;
   unsigned int16 SADI=0,SADVb=0,SADVp=0;
   unsigned int32 Pow=0,CompPow=0;
   float fADVp=0,fADVb=0,fADI=0;
   Set_tris_b( 0b00000000 );    //Pin B0-B7 output
   Set_tris_a( 0b11111111 );    //Pin A0-A1 input
   setup_adc_ports(sAN0|sAN1|sAN3|VSS_VDD);
      setup_adc(ADC_CLOCK_DIV_32);
      setup_spi(SPI_SS_DISABLED);
      setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_wdt(WDT_2304MS);
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
      setup_timer_2(T2_DIV_BY_1,62,1);
   enable_interrupts(INT_TIMER1);
        enable_interrupts(GLOBAL);
      setup_ccp1(CCP_PWM);
      set_pwm1_duty(0);
   output_low(LED);

while(1)
   {

//Capture, traitement et envoi de Vpanel START

   ADCON1=0b10000000;            //Activation de l'ADC
   delay_us(25);

   ADCON0=0b10000101;            //Choix du canal à échantillonner
   delay_us(25);

   while(i<10)               //Capture de 10 mesures successives
   {   
      godone=1;
      while(godone);
      ADVpt=read_adc();
      SADVp=SADVp+ADVpt;            //Somme des tensions
      i++;
   }
   ADVp=SADVp/10;            //Moyenne effectuée
   SADVp=0;
   ADVpt=0;
   i=0;
   
   if(t==4000)
   {
    fADVp=(float)ADVp/131.02;         //Conversion en valeur décimale (float)
    printf("\n\nSTART----------------------------------------");
    printf("\n\nPanel voltage : %1.1fV",fADVp);
   }

//Capture, traitement et envoi de Vpanel END

//____________________________________________________________   
//Capture, traitement et envoi de Ipanel START

   ADCON0=0b10001101;            //Choix du canal
   delay_us(25);
   
   while(i<10)               //Capture de 10 mesures successives
   {   
      godone=1;
      while(godone);
      ADIt=read_adc();
      SADI=SADI+ADIt;               //Somme des courants
      i++;
   }
   ADIt=0;
   ADI=SADI/10;               //Moyenne effectuée
   SADI=0;
   i=0;
   if(t==4000)
   {
      fADI=(float)ADI/511;
      printf("\n\nPanel current : %1.3fA",fADI);   
   }

//Capture, traitement et envoi de Ipanel END
   
//____________________________________________________________

//Capture, traitement et envoi de Vbatterie START

//____________________________________________________________   



   ADCON0=0b10000001;            //Choix du canal
   delay_us(25);
   
   while(i<5)               //Capture de 5 mesures successsives
   {   
      godone=1;               
      while(godone);
      ADVbt=read_adc();
      SADVb=SADVb+ADVbt;
      i++;
   }
   ADVb=SADVb/5;
   ADVbt=0;
   SADVb=0;
   i=0;   

   if(t==4000)
   {   
      fADVb=(float)ADVb/65.51;
      printf("\n\nAccu voltage : %2.1fV",fADVb);
   }

//Capture, traitement et envoi de Vbatterie END

//____________________________________________________________

//routine de comparaison des Pow calculées

Pow=ADVp*ADI;

   if(ADVb>904)                        //Vb>13,8V
   {set_pwm1_duty(0);}
   else{
    if((Pow>=CompPow)&&(ADVp>305)&&(PWM<230))
      {   PWM++;
         set_pwm1_duty(PWM);}

   
   if(Pow<CompPow)
      

      { if((ADVp>CompADVp)&&(PWM<230)&&(ADVp>305))      //ADVp>3,1V
         {    PWM++;
            set_pwm1_duty(PWM);      
         }   
        else if((ADVp<CompADVp)&&(PWM>0))
         {   PWM--;
            set_pwm1_duty(PWM);
         }
      }

   }

CompPow=Pow;
CompADVp=ADVp;
t++;
restart_wdt();

}

   
}
temtronic



Joined: 01 Jul 2010
Posts: 9100
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 16, 2017 9:36 am     Reply with quote

Ok...
first there's no PIC type header... should (must) be 1st line of code...

2nd you probably have to disable the comparator that's ALSO on that AN3 pin

3rd there's a LOT of code that can be done a LOT 'cleaner' and easier to read using the CCS functions

4th disable the WDT ! Unless you're making a commercial product and 99.9999% finished with Real worlde testingyou do NOT 'need' the WDT feature of the PIC.
#5 NEVER EVER put a delay inside an ISR. ISRs are supposed to be fast,small and simple.

6th. averages. do 8,16 or 4 readings,it'll be a LOT faster.

7th do not use floating point.....takes a huge amount of time and NOT required.


that's a start.....

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19217

View user's profile Send private message

PostPosted: Thu Mar 16, 2017 9:44 am     Reply with quote

A lot of things wrong:

Now, first a question. How fast are you clocking the chip?. At 3v it is only rated for 10Mhz max.

Then Just use 'set_adc_channel(3);'. Get rid of all the code accessing the registers. Not necessary.

Then the setup_spi is wrong. This is enabling the SPI, with the slave select disabled. To disable the spi, you want setup_spi(FALSE);

Then you don't show your header, so there may be lots of problems here.

Then when sampling the ADC repeatedly, you need to delay for Tacq between each successive read.

Then as another comment, use 8, or 16 samples. /10, involves hundreds of lines of code. The binary divisions (2,4,8,16 etc.), will be done by simple rotations. Smaller code and faster....

Comparator is on that pin. Needs to be disabled.

Using FP maths in code is a sure sign of somebody not 'thinking embedded'...

You have a delay in an interrupt. Except for a tiny 'delay_cycles' type delay for specific chip timings, this should never be done. Much better to use another interrupt, or just a 'tick' wand wait for a cycle of this.

Ugly code. Learn to layout and comment. It'll make it easier for _you_.
coyotte4845



Joined: 16 Mar 2017
Posts: 4

View user's profile Send private message

PostPosted: Thu Mar 16, 2017 1:17 pm     Reply with quote

Hello,

Many thanks for your suggests and also for your honesty,

i'm beginner in langage C

please follow the modified code:


Code:

#include <16F883.h>
#device adc=10

#FUSES NOWDT                    //Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES PROTECT                  //Code protected from reading
#FUSES MCLR                     //Master clear Pin enabled
#FUSES NOCPD                    //No EE protection
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV21                   //Brownout reset at 2.1V
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOWRT                    //Program memory not write protected
#FUSES PUT                      //Power Up Timer



#use delay(clock=8000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define LED pin_b7


void main()
{
   unsigned int16 PWM=0,t=0,i=0;
   unsigned int16 CompADVp=0;
   unsigned int16 ADVpt=0,ADIt=0,ADVbt=0;
   unsigned int16 ADVb=0;
   unsigned int16 ADI=0,ADVp=0;
   unsigned int32 SADI=0,SADVb=0,SADVp=0;
   unsigned int32 Pow=0,CompPow=0;
   float fADVp=0,fADVb=0,fADI=0;
   Set_tris_b( 0b00000000 );    //Pin B0-B7 output
   Set_tris_a( 0b11111111 );    //Pin A0-A1 input
   setup_oscillator(OSC_8MHZ);
   setup_comparator(FALSE);
   setup_adc_ports(sAN0|sAN1|sAN3|VSS_VDD);
      setup_adc(ADC_CLOCK_DIV_32);
      setup_spi(FALSE);
      setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
      setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
      setup_timer_2(T2_DIV_BY_1,24,1);
      setup_ccp1(CCP_PWM);
      set_pwm1_duty(PWM);
   output_low(LED);
   delay_us(25);

while(1)
   {

//Capture, traitement et envoi de Vpanel START



   set_adc_channel(1);            //Choix du canal à échantillonner
   delay_us(25);

   while(i<16)               //Capture de 10 mesures successives
   {   
      ADVpt=read_adc();
      SADVp=SADVp+ADVpt;            //Somme des tensions
      delay_us(5);
      i++;
   }
   ADVp=SADVp/16;            //Moyenne effectuée
   SADVp=0;
   ADVpt=0;
   i=0;
   
   if(t==4000)
   {
    fADVp=(float)ADVp/131.02;         //Conversion en valeur décimale (float)
    printf("\n\nSTART----------------------------------------");
    printf("\n\nPanel voltage : %1.1fV",fADVp);
   }

//Capture, traitement et envoi de Vpanel END

//______________________________________________________________________________________________________________
   
//Capture, traitement et envoi de Ipanel START

   set_adc_channel(3);               //Choix du canal
   delay_us(25);
   
   while(i<16)               //Capture de 10 mesures successives
   {   
      ADIt=read_adc();
      SADI=SADI+ADIt;            //Somme des courants
      delay_us(5);
      i++;
   }
   ADIt=0;
   ADI=SADI/16;               //Moyenne effectuée
   SADI=0;
   i=0;
   if(t==4000)
   {
      fADI=(float)ADI/511;
      printf("\n\nPanel current : %1.3fA",fADI);   
   }

//Capture, traitement et envoi de Ipanel END
   
//______________________________________________________________________________________________________________


//Capture, traitement et envoi de Vbatterie START

//______________________________________________________________________________________________________________
   



   set_adc_channel(0);               //Choix du canal
   delay_us(25);
   
   while(i<16)               //Capture de 5 mesures successsives
   {   
      ADVbt=read_adc();
      SADVb=SADVb+ADVbt;
      delay_us(5);
      i++;
   }
   ADVb=SADVb/16;
   ADVbt=0;
   SADVb=0;
   i=0;   

   if(t==4000)
   {   
      fADVb=(float)ADVb/65.51;
      printf("\n\nAccu voltage : %2.1fV",fADVb);
   }

//Capture, traitement et envoi de Vbatterie END

//______________________________________________________________________________________________________________
   



//routine de comparaison des Pow calculées

Pow=ADVp*ADI;

   if(ADVb>904)                        //Vb>13,8V
   {   set_pwm1_duty(0);
   }
   else{
    if((Pow>=CompPow)&&(ADVp>589)&&(PWM<230))
      {   PWM++;
         set_pwm1_duty(PWM);}

   
   else if(Pow<CompPow)
      

      { if((ADVp>CompADVp)&&(PWM<230)&&(ADVp>589))      //ADVp>3,1V
         {    PWM++;
            set_pwm1_duty(PWM);      
         }   
        else if ((ADVp<CompADVp)&&(PWM>0))
         {   PWM--;
            set_pwm1_duty(PWM);
         }
      }

   }

CompPow=Pow;
CompADVp=ADVp;
t++;
}

   
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19217

View user's profile Send private message

PostPosted: Fri Mar 17, 2017 3:32 am     Reply with quote

READ.

We have all been beginners, but you need to start by doing some basic exercises and actually starting to learn the language before trying to write more complex things. It's a bit like saying you don't start learning French and immediately try to give a lecture. Instead you work through often 'silly' things like "where is my aunt's pen"....

Actually look at some examples. Don't just put values into things, and when they don't work, come back here.

Is 'FALSE', the way to turn off the comparators (NO)....

Every command has it's own syntax. This is what the manual. Header file. Examples, C manual, and a search here will give.

As well as the comparator problem, you are still insisting on using float (not wanted or needed). Then is 1.3, actually a legal printf format?. (No - read a C textbook on what the value before the decimal actually is...).

I'll code part to show:
Code:

int16 ADC_times16(int8 chan)
{
    int16 sum=0; //initialise to zero
    int8 loop_ctr;
    set_adc_channel(chan); select channel
    for (loop_ctr=0;loop_ctr<16;loop_ctr++)
    {
        delay_us(5); //Tacq
        sum+=read_adc();
    }
    return sum;
}
//then one channel in main
    int16 value;
    //Then reading your first value becomes
    value=ADC_times16(0); //Give 16* the ADC reading - channel _0_.
    //Now basing this on your maths, which gives 7.0808 as the maximum
    //value for 1023 from the ADC
    value /=231;
    //This will give (1023*16)/231 = 70.8 (but stored as an integer)
    printf("\n\nSTART----------------------------------------");
    printf("\n\nPanel voltage : %3.1LWV",value);
    //display this as 7.0



Note no float. Just a suitably scaled integer.
't' doesn't seem to be reset anywhere after the start.
coyotte4845



Joined: 16 Mar 2017
Posts: 4

View user's profile Send private message

PostPosted: Fri Mar 17, 2017 4:28 am     Reply with quote

Ok TT, understood ;)

i will work with your remark, i come back.

A question about max4376, can i connect directly the output on adc input?

needed for a low pass filter?

thanks,
temtronic



Joined: 01 Jul 2010
Posts: 9100
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Mar 17, 2017 6:49 am     Reply with quote

Yes, providing VCC is = to VDD
a low pass filter would be 'nice' to smooth out the readings. While it can be done in software a little 'help' from hardware is good !
If this is for battery monitoring then sampling say at a 1Hz rate is more than adequate.
On my remote equipment, I did a load test every 24 minutes to confirm batteries were 'good'.

A lot depends upon your actual application....

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19217

View user's profile Send private message

PostPosted: Fri Mar 17, 2017 8:00 am     Reply with quote

Yes.

However to get anything even remotely approaching 10bit accuracy, you need to be using an external Vref to the ADC. 2.2v min for the ADC (2.5v is a common value).
coyotte4845



Joined: 16 Mar 2017
Posts: 4

View user's profile Send private message

PostPosted: Fri Mar 17, 2017 8:41 am     Reply with quote

Ttelmah wrote:
Yes.

However to get anything even remotely approaching 10bit accuracy, you need to be using an external Vref to the ADC. 2.2v min for the ADC (2.5v is a common value).


Why Telmah?

i can't use Vdd as Vref? In my case, Vdd comes from Vpanel via regulator LDO 3v
Ttelmah



Joined: 11 Mar 2010
Posts: 19217

View user's profile Send private message

PostPosted: Fri Mar 17, 2017 8:59 am     Reply with quote

Seriously. Regulator say 1% accuracy at best (10 bit is potentially 0.1%). Even this though you won't get. Every single device drawing power, _will_ introduce ripple and spikes onto the supply. The PIC itself, and every other device on the supply.

As a typical example, look at this thread:
<http://www.ccsinfo.com/forum/viewtopic.php?t=56005>

Now his situation was even worse (trying to get a 12bit ADC to work), but look what made it start to give sensible readings....

The supply is fine, if you are looking at large changes, and don't need great accuracies, but for anything better, you need to be using a more stable and accurate source, that is not being modulated by other things.

On chips that have a separate AVdd, what you can do is to improve the smoothing on this (series inductor, and extra capacitors), to get rid of the ripple (still leaves the poor actual accuracy, but at least improves the repeatability), but if you honestly need anything above perhaps 7bit operation, then 'think again' about using the supply as a reference..... Sad
newguy



Joined: 24 Jun 2004
Posts: 1901

View user's profile Send private message

PostPosted: Fri Mar 17, 2017 9:06 am     Reply with quote

A regulator isn't designed to output a perfectly stable, low ripple (or ripple free) voltage. Just to contradict myself: a regulator can output a relatively "electrically quiet" and stable output, but only if it is driving just one load.

Your A/D compares a reference voltage and an input voltage and will output a digital number which tells you how many "counts" of the reference = your input. What happens if your reference isn't solid? What happens if it's fluctuating a little bit? What happens if it fluctuates a little bit more when your processor is also driving a relay or if it's generating CAN traffic?

Voltage regulators = designed to keep the output voltage relatively steady under widely varying loads. Good for supplying Vdd to a bunch of devices.
Voltage references = designed to keep the output voltage absolutely rock steady, but cannot drive much load current. Good for supplying a voltage reference to an A/D, but not for supplying Vdd power to anything.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group