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

Problem when using both HLVD interrupts and Brownout Func
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

Problem when using both HLVD interrupts and Brownout Func
PostPosted: Thu Mar 26, 2015 8:08 pm     Reply with quote

Hi.
I'm have a problems when try using both HLVD interrupts and Brownout in my program.
My circuit have a large capacitor (~22000uF/5.5V) make a power backup for PIC to save data when unplug power.
So that, I used Brownout function to against PIC hang when power fast restart.
I think it conflict because I can't save data to eeprom when using HLVD with Brownout func.
Here's my config for HLVD and brownout:
Code:

#fuses H4,PUT,PROTECT,NODEBUG,NOLVP,NOWDT,NOPBADEN,NOMCLR, BROWNOUT, BORV21


Code:
   setup_low_volt_detect(  LVD_TRIGGER_BELOW| LVD_36);
   while(IRVST_BIT==0);
   wait_vdd_stable();     
   LVDIF_BIT=0;
   enable_interrupts (int_lowvolt);

I'm using CCS C ver5.021, PIC18F4680
Thanks
_________________
Begin Begin Begin !!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 26, 2015 8:38 pm     Reply with quote

Quote:
setup_low_volt_detect(LVD_TRIGGER_BELOW | LVD_36);

What's your Vdd voltage for the PIC ? Is it 5 volts ? If so, then why set
the LVD trigger voltage to 3.6 volts ? Why not use LVD_45 instead.
That would give you more time to save to eeprom.
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

PostPosted: Thu Mar 26, 2015 8:54 pm     Reply with quote

Thanks for your reply.
My circuit is supplied by 5v-> diode 1N4007-> VCC pic, so that the power to PIC is ~4.4V.
_________________
Begin Begin Begin !!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 26, 2015 9:56 pm     Reply with quote

You could use LVD_42 or LVD_40.
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

PostPosted: Thu Mar 26, 2015 10:43 pm     Reply with quote

Thanks u reply.
I tried all but the result no change, I afraid the errors make by the Brownout reset?
_________________
Begin Begin Begin !!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 26, 2015 11:15 pm     Reply with quote

Put an oscilloscope on your PIC's Vdd power pin and turn off the power.
Observe and estimate how much time it takes for the Vdd to drop down
to the Brownout voltage. (ie., from 4.4v to 2.1v) Tell us what you see.

Also, explain why you have the 1N4007 diode in there. Is it for reverse
voltage protection ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Fri Mar 27, 2015 3:32 am     Reply with quote

Take a deep breath.

Time is everything.

Now PCM_Programmer is pointing at the first key thing. You need to know just how fast your supply rail falls. Having a 22000uF capacitor, means nothing, if the load on this is an amp (4.4R), the rail will fall 2.5v in 80mSec. However if the load is only a few mA, then it'll hold up for ages. This is why you need to actually measure the discharge rate.

Start by working out the loads on the rail. What current is drawn?. This then allows you to estimate the discharge rate. Remember that large capacitors like this are often +/-50% on their 'specified' value. You need to work with the minimum value.

Then how much data are you trying to store?. Given that the EEPROM on your chip takes 4mSec/byte, you need to allow for perhaps 50instruction times to get into the routine to actually perform the write, and then 4mSec/byte for every byte you are storing. If you are storing 20bytes, you need something like 85mSec 'guaranteed' between the point where LVD triggers, and you reach brownout.

Then, with your strange power supply (again PCM has asked an important question - why not use a Schottky diode for example), why not feed the LVD detection from the supply _before_ the diode?. This is normally how LVD is used. Monitoring something like the incoming supply (with a suitable divider), so it triggers when this drops, before the actual chip supply begins to drop. This all gives you extra time from the detection moment, till brownout.

Then you have to look at 'worst case' figures. BORV at 2.1v nominal, can trigger as high as 2.16v. LVD at (nominal) 4v can actually trigger at 4.2 to 4.01v. with your origanal 3.6v (3.63 to 3.8v), you then have the calculation as time from 3.63v to 2.16v. Is this longer than the time needed to write the EEPROM?.

Then there are other questions.
How does your code handle the LVD going off after it has triggered?. Your code in the ISR, must not return to the main routine until this happens, otherwise you can get repeated triggers. So a flow something like:

1) LVD triggers
2) Switch off any circuits you can to reduce the supply load. This extends your available time.
3) Write the data.
4) Sit now monitoring the LVD input. Has it gone 'good' again?. Loop if not.
5) Wait a time (0.1seconds perhaps). Is the LVD still good?. No, go back to 3. Yes. Switch circuits back on, and exit the interrupt.

You must ensure that the code does not exit the interrupt till the supply is 'good', and has stayed good for a while. Otherwise you risk multiple triggers, which will result in the data being corrupted. Also, anything you can do to reduce the current consumption helps give you extra time.
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

PostPosted: Fri Mar 27, 2015 8:39 pm     Reply with quote

Thanks for all yours reply.
Really I have make a circuit for a long time but I haven't ensure test the HLVD.
With my circuit, from main power supply (5V DC)-> two branch with 2 diode ( I have replaced by 1N4148 Schottky diode, because I think the DC voltage is switching slower frequency than diode ), one is power supply for loads ( 3 red leds, 1 LCD 16X2, 1 RFID reader board, 2 opto couplers, IC 74HC14), and another is power supply for PIC and external EEPROM, this power is backup by 0.22F capacitor, as an image:
https://drive.google.com/file/d/0Bz215_lkn4g-cEdfV3ZiNlNFVkE/view?usp=sharing
The first time, I used the HLVD pin of PIC18F4680 to detect power down, but it's seem not stable for controlling HLVD interrupts (can by your program isn't good when processing) so that I change to used internal voltage detect for HLVD.
As Ttelmah told, I have a problems when control HLVD ISR, if I set HLVD trigger near a power supply voltage (setup 4V for HLVD trigger), it'll switch to HLVD ISR when power on, so that I try to set HLVD trigger lower.
Adding, I also using WDT function in my program to against PIC hang.
I'll show some short program for process:

1) Config fuses
Code:

#include "18F4680.h"                   
#fuses H4,PUT,PROTECT,NODEBUG,NOLVP,NOWDT,NOPBADEN,MCLR, BROWNOUT, BORV21                                                                           
#use delay(clock=40000000)                                                                         
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, errors)


2) Config bit HLVD

Code:
#bit HLVD_EN_BIT  = getenv("SFR:HLVDCON").4                                                                                                                   
#bit IRVST_BIT    = getenv("SFR:HLVDCON").5                                                                                                                       
#bit LVDIF_BIT    = getenv("SFR:PIR2").2   


3) HLVD ISR

Code:
#int_lowvolt
void ngat_hlvd(void)
{     
   HLVD_EN_BIT=0;
   pwr_loss=1;
}


4) check power stable
Code:
void wait_vdd_stable(void)
{
   int16 timeout_count;       
   timeout_count = 0xFFFF;   // Many milliseconds
   
   while(timeout_count--)
   {
      if( LVDIF_BIT==1)
      {
         LVDIF_BIT=0;
         timeout_count = 0xFFFF;
         delay_ms(10);
         leds_on;
      }
   }           
}


5) Main program (be shorted)
Code:


void main(void)
{
.....
   setup_low_volt_detect(  LVD_TRIGGER_BELOW| LVD_38);
   while(IRVST_BIT==0);
   wait_vdd_stable();     
   LVDIF_BIT=0;
   enable_interrupts (int_lowvolt);
   enable_interrupts (int_rb);                                                                 
   enable_interrupts (int_rda);
   enable_interrupts (global); 
   setup_wdt(WDT_ON|WDT_2S);   

for(;;)
{
   restart_wdt();
   if(pwr_loss==1)
  {
         pwr_loss=0;
         disable_interrupts(global);
         #fuses NOBROWNOUT                         // turn off Brownout reset
         setup_timer_0( T0_OFF);
         setup_timer_1( T1_DISABLED);
         setup_timer_2( T1_DISABLED,195,16 ); 
         read_Pointer_from_eeprom....
         write_20_byte_to_eepom....
         LVDIF_BIT = 0;                                    // Clear the LVD interrupt flag
         enable_interrupts(INT_LOWVOLT);
         #fuses BROWNOUT                               // turn on Brownout
  }
  else
  {
         perform_task_main....
  }

}


}


Thanks.
_________________
Begin Begin Begin !!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 27, 2015 9:07 pm     Reply with quote

Quote:
write_20_byte_to_eeprom....

Is this routine a for() loop, with 20 sequential calls to write_ext_eeprom() ?
Or are you using page mode ?

Post the part number of the external eeprom.

Also post your #use i2c() statement. Or is it an SPI eeprom ?
In that case, post your #use spi() or setup_spi() statement.

What driver file are you using for the eeprom ? If it's a CCS driver file,
post the filename.
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

PostPosted: Fri Mar 27, 2015 9:28 pm     Reply with quote

PCM programmer wrote:
Quote:
write_20_byte_to_eeprom....

Is this routine a for() loop, with 20 sequential calls to write_ext_eeprom() ?
Or are you using page mode ?

Post the part number of the external eeprom.

Also post your #use i2c() statement. Or is it an SPI eeprom ?
In that case, post your #use spi() or setup_spi() statement.

Thanks PCM
In mys circuit using AT24C128 EEPROM (http://tme.vn/Product.aspx?id=687#page=pro_info)
And in this program, I reduced to save ~9byte and I read and write bytes sequential after check flag ok, also I'm using <24128.c> CCSC driver for external EEPROM
Here is my program in this case:

Code:

if(pwr_loss==1)   
      {   
         pwr_loss=0;
         disable_interrupts(global);
         #fuses NOBROWNOUT
         setup_timer_0( T0_OFF);
         setup_timer_1( T1_DISABLED);
         setup_timer_2( T1_DISABLED,195,16 ); 
                 
         if(save_tag_eepr==1)
         {     
            if(app_code==0)
            {
               app_code= app_code_new;
            } 

            pt_eepr_hi= read_ext_eeprom(0); 
            delay_us(100);
            pt_eepr_lo= read_ext_eeprom(1);
            pt_eepr   = make16(pt_eepr_hi, pt_eepr_lo);
           
            if(pt_eepr==0) {  pt_eepr=20;}                         
            pt_eepr+=1;                                                                                                                                       
            if(chk_offset_pc_new==1) write_ext_eeprom(pt_eepr, 0xC0);
            else write_ext_eeprom(pt_eepr, 0x80);     
            delay_us(100);
                                                                         
            pt_eepr+=1;                                               
            write_ext_eeprom(pt_eepr, make8(count_ac,2));   delay_us(100);                 
            pt_eepr+=1;                                                             
            write_ext_eeprom(pt_eepr, make8(count_ac,1));   delay_us(100);
            pt_eepr+=1;                                               
            write_ext_eeprom(pt_eepr, make8(count_ac,0));   delay_us(100);   
           
            pt_eepr+=1;                                                                                             
            write_ext_eeprom(pt_eepr, make8(app_code,2));   delay_us(100);
            pt_eepr+=1;                                                   
            write_ext_eeprom(pt_eepr, make8(app_code,1));   delay_us(100);
            pt_eepr+=1;
            write_ext_eeprom(pt_eepr, make8(app_code,0));   delay_us(100);

            write_ext_eeprom(0, make8(pt_eepr,1));          delay_us(100);
            write_ext_eeprom(1, make8(pt_eepr,0));          delay_us(100);

            save_tag_eepr=0;
         }
         while(IRVST_BIT==0);
         wait_vdd_stable();     
         LVDIF_BIT=0;
         delay_ms(100);
         while(IRVST_BIT==0);
         wait_vdd_stable();     
         LVDIF_BIT=0;         
         enable_interrupts (int_lowvolt);
     
         #fuses BROWNOUT
      }


My config for I2C
Code:
#define EEPROM_SDA  PIN_C4                                           
#define EEPROM_SCL  PIN_C3
#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL)

Thanks.
_________________
Begin Begin Begin !!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 27, 2015 9:45 pm     Reply with quote

Quote:
I'm using <24128.c> CCSC driver for external EEPROM

That file has a 10 ms delay after each write. See below:
Code:

void write_ext_eeprom(long int address, BYTE data)
{
   .
   .
   .
   .
   . 

delay_ms(10);
}

I count 10 sequential writes to external eeprom in your code.
That's 10 x 10 ms = 100 ms to write all bytes.

Did you measure the power-down time for Vdd with an oscilloscope or
some other instrument ? I don't see it in your post.

Do you have 100 ms available before the power goes too low ?
That's the question. How much time do you have ?

Or, can you use page mode to speed up the write operation, or can
you switch to FRAM to really speed it up ?
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

PostPosted: Fri Mar 27, 2015 9:54 pm     Reply with quote

Sorry, I don't have an oscilloscope to view it clearly, I using digital multimetter and saw the VDD when power loss about ~3V, it's difficult for me to measure it.
I'm trying and find if I don't enable Brownout after save eeprom, PIC can save data but if power on fast again it's seem hang, must wait a long time (10s).
I'll try edit in my program and send back the result later.
Thanks
_________________
Begin Begin Begin !!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Sat Mar 28, 2015 4:00 am     Reply with quote

As well as the much worse timings for this apporach, you have another problem.

What is the minimum specified voltage for your EEPROM to work?. 2.7v.....

You only have the time for the supply to droop from the LVD triggering to 2.7v now....

Then you have fuses scattered through the code - won't work. Fuses are _one time_ when the chip is programmed, they are not code lines.

Then even worse, you are not servicing the writing inside the interrupt handler, instead you call the interrupt handler, set a flag, exit from this, and have to poll the flag in the main. Each of these operations takes yet more time. Smile

Your approach is fundamentally flawed.
tienchuan



Joined: 25 Aug 2009
Posts: 175

View user's profile Send private message Yahoo Messenger

PostPosted: Tue Mar 31, 2015 1:16 am     Reply with quote

Thanks for your repply.
Really I don't have enough equipment to check time discharge of capacitor to LVD trigger
But i have found a error but I think the voltage of capacitor can discharge enough time to save EEPROM.
In my program, when I send a data from PC to MCU node, if after that power loss, it can save data to EEPROM. Otherwise it can't save data to EEPROM.
I checked in sub program when received data from CAN bus, it only update the data on LCD, haven't change anthing.
Is there problems between CAN RCV with HLVD ISR?
Really I don't have a way to fix this problems, so that I can only checking my program.
Thanks
_________________
Begin Begin Begin !!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Tue Mar 31, 2015 1:48 am     Reply with quote

Seriously, not having even a basic oscilloscope, really isn't where to start working with microprocessors. I built my first scope, then my first computer. Nowadays second hand scopes are very cheap, and even better, there are basic LCD models, that are very cheap indeed.
It's like a workman coming to fix your TV, and not even having a screwdriver to open the case....

I suspect you are going to find when you actually put a scope on the power rails, that your system has supply problems, which is why when you start using the microprocessor's ability to monitor these, things do not behave as you expect.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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