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 CCS Technical Support

I got very slow response, help

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



Joined: 23 Sep 2013
Posts: 14

View user's profile Send private message

I got very slow response, help
PostPosted: Sat Nov 30, 2013 2:53 pm     Reply with quote

Sir just make a solid state switch that switch over among two power sources while active source goes down,
The main problem is that i got a large enough delay to switch over,

REMEMBER plz there is two do-while loops, working for two sources, when i used only first loop. I can switch over Source A to B quickly,
but when i write a secound part of code for switch to Source B to A, it works but slow enough, i dont know what happens there.

here is a code

Code:

#include <Static_sw.h>
#include "flex_lcd.c"   //Mdified lcd file, only contained in project directory


int1 lcd_volt_flag=0;

//=========Timer0 intrupt====================

#define R1 1.7   //Range 1
#define R2 1.8   //Range 2
#define R3 1.9   //Range 3
#define R4 2.0   //Range 4
#define R5 2.1    //Range 5
#define R6 2.2   //Range 6
#define R7 2.3
#define R8 2.4
#define R9 2.5
#define R10 2.7
#define R11 2.8
#define R12 2.9
#define R13 3.0
#define R14 3.1
#define R15 3.2
#define R16 3.3


int range(float a)
{

if(a>R4 && a<=R5)
{
return 5;
}
else if(a>R5 && a<=R6)
{
return 6;
}

if(a<=R1 )
{
return 1;
}
else if(a>R1 && a<=R2)
{
return 2;
}
else if(a>R2 && a<=R3)
{
return 3;
}
else if(a>R3 && a<=R4)
{
return 4;
}
if(a>R4 && a<=R5)
{
return 5;
}
else if(a>R5 && a<=R6)
{
return 6;
}
else if(a>R6 && a<=R7)
{
return 7;
}
else if(a>R7 && a<=R8)
{
return 8;
}
else if(a>R8 && a<=R9)
{
return 9;
}
else if(a>R9 && a<=R10)
{
return 10;
}
else if(a>R10 && a<=R11)
{
return 11;
}

else if(a>R11 && a<=R12)
{
return 12;
}
else if(a>R12 && a<=R13)
{
return 13;
}

else if(a>R13 && a<=R14)
{
return 14;
}
if(a>R14 && a<=R15)
{
return 15;
}
else if(a>R15 && a<=R16)
{
return 16;
}
else if(a>R16)
{
return 17;
}
}


void main()
{

setup_adc_ports(AN0_AN1_AN3);
setup_adc(ADC_CLOCK_DIV_64); 
  set_adc_channel(Output);                       // Built-in A/D setup function
 
   

 
 int16 sample;

 int16 max=0;
 int16 min=65335;

 

float value;
float maximum=0.0;

float volt=0.0;

unsigned int8 i=0;

int val[3]={10,11,12};
int1 inc=0;
int1 lcd_flag=0;



  lcd_init();  // LCD initilized

  lcd_putc("\fAslam-u-Alicum!");
  delay_ms(500);


//==========Main Program============


for(;;)
{
                   

  do {
     
     output_low(L2);
     delay_ms(100);
     output_high(L1);
     
     if(lcd_flag==0)
     {
     lcd_gotoxy(1,1);
     lcd_putc("Primery Supply:");
     lcd_flag=1;
     }
 
      sample = read_adc();                 // Built-in A/D read function
      delay_us(400);
     
   
     
     if(max<=sample)
     {
     max=sample;
     }
     else if(min>=sample)
     {
     min=sample;
     }
   
     
     

     value=sample*0.004887585532746823069403714565;
     
     val[0]=range(value);
   
    if(val[0]==val[1])
    {
    delay_us(100);
    sample = read_adc();
    value=sample*0.004887585532746823069403714565;
     
    val[1]=range(value);
    if(val[0]==val[1])
    {
    i++;
    }}
    else if(val[0]!=val[1])
    {
    val[1]=val[0];
    i=0;
    }
    if(i>=3)
    {
    inc=1;
    lcd_flag=0;
    lcd_volt_flag=0;
     break;
      }
 
   
     
     maximum=max*0.004887585532746823069403714565; // divide by 1023
   
    volt=(2.5-maximum)*438.571428; // convert to mains voltages
       
     lcd_gotoxy(1,2);
     printf(lcd_putc, " %4.4f", volt);
 
}while(!inc);
   
   
   do{
      output_low(L1);
      delay_us(100);
      output_high(L2);
     
      if(lcd_flag==0)
     {
     lcd_gotoxy(1,1);
     lcd_putc("Alternate Supply:");
     lcd_flag=1;
     }
     
      sample = read_adc();                 // Built-in A/D read function
      delay_us(400);
     
     
     if(max<=sample)
     {
     max=sample;
     }
     else if(min>=sample)
     {
     min=sample;
     }
   
     
     

     value=sample*0.004887585532746823069403714565;
     
     val[0]=range(value);
   
    if(val[0]==val[1])
    {
    delay_us(100);
    sample = read_adc();
    value=sample*0.004887585532746823069403714565;
     
    val[1]=range(value);
    if(val[0]==val[1])
    {
    i++;
    }}
    else if(val[0]!=val[1])
    {
    val[1]=val[0];
    i=0;
    }
    if(i>=3)
    {
    inc=0;
     break;
    }
   
     
     maximum=max*0.004887585532746823069403714565; // divide by 1023
   
     volt=(2.5-maximum)*438.571428; // convert to mains voltages 
   
     lcd_gotoxy(1,2);
     printf(lcd_putc, " %4.4f", volt);
 
}while(inc);
 
    }}
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

Simplify simplify, simplify.
PostPosted: Sat Nov 30, 2013 4:44 pm     Reply with quote

It's difficult to tell what you're expecting the code to do.
There are no useful comments to help.
I don't care to work through it in detail.

You appear to be working though a series of tests using floats.
Floats are notoriously slow.
If you do a return after most of the tests you'll get a response which is much slower than if you return after only a few tests.

Use say MPLAB to find out how long the various paths through your tests take.
Then compare those times to what you get in practice.
You don't actually tell us what the delays are.

Above all I suggest you both simplify what you're doing and avoid floats.

Mike
temtronic



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

View user's profile Send private message

PostPosted: Sat Nov 30, 2013 6:15 pm     Reply with quote

Mike is right !

You're best to get rid of floating point math. Read up about 'scaled integers', a topic covered here several times.

You refer to 'mains voltage' which I assume is 240 volts.If you use an 8bit integer to be 'volts', it'll be good up to 255 volts, so 1 bit equals 1 volt.
8bit integer math is super fast compared to floats.

Also as you are using 'mains voltage' please be very,very careful with connections !!!

hth
jay
Shaheers



Joined: 23 Sep 2013
Posts: 14

View user's profile Send private message

PostPosted: Sat Nov 30, 2013 11:04 pm     Reply with quote

Thanks for reply both of you,

actually i am measuring the AC voltages by using following arrangement



using op-amp i am down grading voltage to TTL level and after that measuring it, when mains power is off the output of op-amp output is 2.5volts

on power is available its about say 2.5+1 and 2.5-1 volts

series of test checks that weather the volts are varying or not

the hardware i use is describe in following link

http://www.paulmonigatti.com/2011/09/reading-ac-voltages-with-a-microcontroller/
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Sun Dec 01, 2013 3:45 am     Reply with quote

Ongoing, a 'float', in CCS, has typically 6.5 digits of accuracy. You have values with like 20digits involved. Totally pointless. Worse, the values are just wrong as well. Do a bit of research on the transfer function of the PIC ADC, and find 'why' you do not want to divide by 1023.
Remember every float value test involves a float subtraction. Doing this against two values, two subtractions.
With a bit of thought, scaled integers will give you _better_ results, and a lot quicker too. Remember that unless you are paying a premium price, the odds are that every resistor in your division etc., is only 1% accurate, so trying to use huge accuracies is totally pointless.
Though not 'great', since it still involves one float multiplication, this should be a 'drop in' replacement for your 'range' function. Think about what it'll give:
Code:

int range(float a)
{
   int rnum;
   signed int16 ival;
   ival=a*10.4999;
   ival-=17;
   if (ival<=0) return 1;
   for (rnum=2; rnum<17;rnum++)
   {
      ival--;
      if (ival<=0) return rnum;
   }
   return rnum;
}

Preferably though redesign your maths throughout, to use integers from the start.

Best Wishes
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Dec 01, 2013 5:06 am     Reply with quote

The range() function now uses all regular intervals and can be simplified to:
Code:
int range(float a)
{
  if (a <= 1.7)
  {
    return 1;
  }

  if (a > 3.3)
  {
    return 17;
  }

  return (a - 1.7) * 10;
}


Now, coming back to the earlier mentioned 'scaled integers' method you can improve the performance dramatically.
You are comparing the float values with only 1 digit after the dot. If you multiply all the float values by 10, then you have values with no important digits after the dot. Hey... that means you can remove all those digits and just use integer math! That's the 'scaled integer' method.
Only on presentation to the user you have to convert the multiplied integer value back to a float representation again. Think about it like calculating in dollars or in cents. $1.23 is a float value. 123 cents is an integer. Both are equal value but integer arithmetic is 100 times more efficient for the PIC processor.
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Sun Dec 01, 2013 1:15 pm     Reply with quote

As a general comment, you need to rethink your basic approach.

You need something like a single loop, reading the ADC, and scaling it.
This then advances to a state machine. This decides what to 'do' with the value. For delays, start a timer, then advance a state. In the next state check for the timer having expired, and until this happens _keep looping_. The whole point is you don't actually 'delay' anywhere. As it's prime job, this machine tests for the events that need to make things happen _before_ doing anything else.
Either use custom timers, started as outlined, or have a single 'tick' interrupt at (say) 10mSec, then have a variable that is decremented until it is zero in this. So a 400mSec delay would be done by loading this variable with '40', and then looping waiting till this gets to 0.
The whole point is that checking for things that must happen quickly, happens all the time, whatever else is going on.

Best Wishes
Shaheers



Joined: 23 Sep 2013
Posts: 14

View user's profile Send private message

PostPosted: Wed Dec 04, 2013 11:55 am     Reply with quote

Thank you very very much, one more point that can I count frequency from that arrangement, I mean by giving the stepdowned mains sinusoidal voltage at counter input or CCP module or I need it to convert to square wave first
temtronic



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

View user's profile Send private message

PostPosted: Wed Dec 04, 2013 12:07 pm     Reply with quote

You need to convert to a square wave first.

Also be sure to isolate the mains voltage from the PIC usually using an optocoupler ( typ: 4N35) fed into a comparator to get clean waveforms.

Have a 'Google' at typical circuits,some will just use transistors or opamps.
Since you already have an opamp, maybe a spare section can be used?

hth
jay
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