Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Need help to solve the problem in the code

Status
Not open for further replies.

ADGAN

Full Member level 5
Full Member level 5
Joined
Oct 9, 2013
Messages
295
Helped
4
Reputation
8
Reaction score
4
Trophy points
18
Visit site
Activity points
1,837
Hello everybody! I need some help for my project software. What I want to do is this. I'm accumulating pulses coming from an energy measurement IC and its multiply with some value to determine the KWh. It will only display the monthly usage. After the month is passed it will be zero. It will be saved to the EEPROM and also will be send to the GSM modem. The algorithm is like this.

. First it will read the monthly usage from the EEPROM
while(1)
. The pulses that are currently coming will be added to this.
. Calculate Kwh
. Save the monthly usage to the EEPROM

I'm facing some problems in my code. When I tried it in Proteus, the pulses are counting very swiftly even though the pulse frequency is low as 0.34Hz. When I tried it in hardware LCD shows garbage data and some time the whole LCD blinks. When I tested each and every part separately they all worked well. i.e. I tested the energy measurement ic, EEPROM, RTCC and GSM modem. All this parts are working fine separately. I can't find the error that I have done. I'm using PIC16F887 with 4MHz crystal. This has been written in MikroC pro. Pls help me since this is the last part of the project.

Code:
// RTC Definitions
#define RTC_ADDR  0xD0

#define Highest(param) ((char *)&param)[3]
#define Higher(param) ((char *)&param)[2]
#define Hi(param) ((char *)&param)[1]
#define Lo(param) ((char *)&param)[0]

// LCD module connections
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections


unsigned char txt1[] = "ENERGY CONSUMPTION";
unsigned char txt2[] = "FROM";
unsigned char txt3[] = "TO";
unsigned char txt4[] = "20";
unsigned char txt5[] = "KWh";

unsigned short lowByte, highByte, higherByte, highestByte, p_address;
unsigned char txt[14],txt6[14];
unsigned char SMS[14] ;
unsigned long count = 0;
unsigned long pulses = 0;
unsigned long monthly_consumption;
double Meter_reading = 0;
const double Meter_Constant = 0.001;


void EEPROMWriteInt(unsigned short p_address, unsigned long int p_value) {
        lowByte = Lo(p_value); 
        highByte = Hi(p_value); 
        higherByte = Higher(p_value);
        highestByte = Highest(p_value);

        EEPROM_write(p_address, lowByte);
        EEPROM_write(p_address + 1, highByte);
        EEPROM_write(p_address + 2, higherByte);
        EEPROM_write(p_address + 3, highestByte);

        lowByte = 0x00;
        highByte = 0x00;
        higherByte = 0x00;
        highestByte = 0x00;

}

unsigned long int EEPROMReadInt(unsigned short p_address)
        {
        Lo(Monthly_consumption) = EEPROM_read(p_address);
        Hi(Monthly_consumption) = EEPROM_read(p_address + 1);
        Higher(Monthly_consumption) = EEPROM_read(p_address + 2);
        Highest(Monthly_consumption) = EEPROM_read(p_address + 3);

        return Monthly_consumption;

}

/**************************************************************************************************
* Interrupt service routine
**************************************************************************************************/
void interrupt(){
if (PIR1.TMR1IF)
{
count++;
PIR1.TMR1IF=0;
}

}


void Energydisplay(double V){

  unsigned char a,b,c,d,d1,d2,d3;
  double n;
   if(v==0000.00){
   Lcd_Chr(4,5,48);
   Lcd_Chr(4,6,48);
   Lcd_Chr(4,7,48);
   Lcd_Chr(4,8,48);
   Lcd_Chr_CP('.');
   Lcd_Chr(4,10,48);
   Lcd_Chr(4,11,48);
   Lcd_Chr(4,12,48);
   }
   else{
   a=(V/1000);
   b=((V-(1000*a))/100);
   c=((V-(1000*a)-(100*b))/10);
   d=V-(1000*a)-(100*b)-(10*c);
   
   n=((V-(1000*a)-(100*b)-(10*c)-d)*10000);
   d1=(n/1000);
   d2=((n-(d1*1000))/100);
   d3=((n-(d1*1000)-(d2*100))/10);

   Lcd_Chr(4,5,a+48);
   Lcd_Chr(4,6,b+48);
   Lcd_Chr(4,7,c+48);
   Lcd_Chr(4,8,d+48);
   Lcd_Chr_CP('.');
   Lcd_Chr(4,10,d1+48);
   Lcd_Chr(4,11,d2+48);
   Lcd_Chr(4,12,d3+48);
  }
  }

 
/**************************************************************************************************
* Main function
**************************************************************************************************/
void main()
{
     ANSEL = 0;
     ANSELH = 0;
     TRISA = 0;
     C1ON_bit = 0;                      // Disable comparators
     C2ON_bit = 0;
     PORTA.RA0 = 1;
     TRISB = 0;
     PORTB = 0;
     PORTC = 0;
     TRISC = 0x99;
     INTCON = 0xC0;

     PIE1.TMR1IE = 1;
     PIR1.TMR1IF = 0;

     T1CON = 0x03;
     TMR1L = 0;
     TMR1H = 0;

     Lcd_Init();
     Delay_ms(100);                  // Delay 100ms
     Lcd_Cmd(_LCD_CURSOR_OFF);
     Lcd_Cmd(_LCD_CLEAR);
     I2C1_Init(100000);

     LCD_Out(1,2,txt1);
     LCD_Out(2,1,txt2);
     LCD_Out(3,1,txt3);
     LCD_Out(2,14,txt4);
     LCD_Out(3,14,txt4);
     LCD_Out(4,14,txt5);

     UART1_Init(9600);
     Delay_ms (100);

         Monthly_consumption = EEPROMReadInt(0x00);


      while(1){

       
        pulses = (count*65535)+ (TMR1H<<8 | TMR1L);
        Monthly_consumption += pulses;

      if(day == 31 && hours == 23 && minutes == 59 && seconds == 57)
      {
      SMS_Send(Meter_reading);
      }

      if(day == 1 && hours == 0 && minutes == 0 && seconds == 1)
      {
       Monthly_consumption = 0;
      }

      Meter_reading = Monthly_consumption*Meter_Constant;

      Energydisplay( Meter_reading);
      EEPROMWriteInt(0x00, Monthly_consumption);
      Delay_ms(20);

      }
   }
 
Last edited:

I guess you are getting "IRP bit must be set manually..." message in the Compiler. Bank switching is a problem with PIC16F and mikroC. You can use CopyConstToRam function to display constant strings. If the problem still occurs (garbage data on LCD) for real time string data then you have switch to PIC18F.


Edit: Also try to disable Watch Dog Timer.

Go to Project>Edit Project... Watch Dog Timer > Disable
 
Last edited:

No I'm not getting any errors or messages from the compiler. I found some errors in my code and solved it. Now as usual system is working in Proteus but not working in hardware. It displays some garbage data on the line which shows the measurement. I have disabled the watch dog timer. I'm going to try it again.

- - - Updated - - -

and also the LCD back light has is also switching off even though its directly connected to 5v and 0v respectively.
 

Actually it not displaying garbage data its displaying Japanese:-?
 

hello,


I did some comparative test with

Code:
void Energydisplay(double V):
void FloatToLCD(float fval);
 unsigned char *fltToa (float x, unsigned char *str,char precision)

and the result is clear, only the third function is OK
the other can give wrong ( garbage) results.
Even test is made with Uart output instead of LCD, test is on ascii value result..
Image1.jpg

here is my test programme in C18, but can easily be converted in mikroc
without using fprintf.

Code:
unsigned char CRam1[32];
float F1;
unsigned int i,j,k;


 unsigned char *fltToa (float x, unsigned char *str,char precision)
{
/* converts a floating point number to an ascii string */
/* x is stored into str, which should be at least 30 chars long */
unsigned char *adpt;
int ie, i, k, ndig;
double y;
adpt=str;
ndig = ( precision<=0) ? 7 : (precision > 22 ? 23 : precision+1);
ie = 0;
/* if x negative, write minus and reverse */
if ( x < 0)
  {
  *str++ = '-';
  x = -x;
  }
/* put x in range 1 <= x < 10 */
if (x > 0.0) while (x < 1.0)
  {
  x *= 10.0;        // a la place de =*
  ie--;
  }
while (x >= 10.0)
  {
  x = x/10.0;
  ie++;
 }
// in f format, number of digits is related to size 
 ndig += ie;                // a la place de =+
//round. x is between 1 and 10 and ndig will be printed to
// right of decimal point so rounding is ... 
for (y = i = 1; i < ndig; i++)
  y = y/10.;
x += y/2.;                    
if (x >= 10.0) {x = 1.0; ie++;} 
if (ie<0)
  {
   *str++ = '0'; *str++ = '.';
   if (ndig < 0) ie = ie-ndig;
   for (i = -1; i > ie; i--)  *str++ = '0';
  }
for (i=0; i < ndig; i++)
  {
  k = x;
  *str++ = k + '0';
  if (i ==  ie ) *str++ = '.';
  x -= (y=k);    
  x *= 10.0;    
  }
*str = '\0';
return (adpt);
}


void aligne8()
{
 j=strlen(CRam1);
 while ( j<8)
 {
   k=fprintf(_H_USART,"x");   // replace "x" by " "
    j++;
  }
 k=fprintf(_H_USART,"%s%c",CRam1,9);
}





// in main program .........................
// test flottant to ascii 
 F1=34.5789;
  //k=fprintf(_H_USART,"F1=34.5789 -> %s\r\n",fltToa(F1,CRam1,4));
  k=fprintf(_H_USART,"F1=34.5789 -> %s%c",fltToa(F1,CRam1,4),9);
  aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 

 F1=0.3244;
  k=fprintf(_H_USART,"F1=0.3244 ->  %s%c",fltToa(F1,CRam1,4),9);
  aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 

 F1=1.9876;
  k=fprintf(_H_USART,"F1=1.9876 ->  %s%c",fltToa(F1,CRam1,4),9);
  aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 

 F1=22.5431;
   k=fprintf(_H_USART,"F1=22.5431 ->  %s%c",fltToa(F1,CRam1,4),9);
   aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 

F1=352.1234;
  k=fprintf(_H_USART,"F1=352.1234->  %s%c",fltToa(F1,CRam1,4),9);
  aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 


F1=0.0;
  k=fprintf(_H_USART,"F1=0.0->   %s%c",fltToa(F1,CRam1,4),9);
  aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 
 
F1=65537.9872;
  k=fprintf(_H_USART,"F1=65537.9872->   %s%c",fltToa(F1,CRam1,4),9);
 aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 

  F1=9998887654321.1234;
  k=fprintf(_H_USART,"F1=9998887654321.1234->   %s%c",fltToa(F1,CRam1,4),9);
  aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 

F1=-128.4567;
  k=fprintf(_H_USART,"F1=-128.4567-> %s%c",fltToa(F1,CRam1,4),9);
  aligne8();
  Energydisplay(F1);
  Put_RS(TAB);
  FloatToLCD(F1);
   CRLF(); 
  
  Tempo(100000L) ;
do
{}
while(1);
......

nota: i used x instead of space to be able to see the result on terminal
and for my test i used
#define lcd_putch Put_RS
to have output on Terminal instead of LCD.
 
Last edited:

There is also a conceptual error in the code, it will only report the readings at the end of the 31st day of the month. It will not work in February or any month with 30 days.
Try changing:
Code:
 if(day == 31 && hours == 23 && minutes == 59 && seconds == 57)
      {
      SMS_Send(Meter_reading);
      }

      if(day == 1 && hours == 0 && minutes == 0 && seconds == 1)
      {
       Monthly_consumption = 0;
      }

to

Code:
if(day == 1 && hours == 0 && minutes == 0 && seconds == 1)
{
   SMS_Send(Meter_reading);
   Monthly_consumption = 0;
}

So it works every month, the result will only arrive four seconds later! Depending on your compiler, you may have to bracket the individual day/time checks as well.

Brian.
 

@paulfjujo how do I convert it in MikroC without fprintf? The function that I have used here worked when using it separately. But I would like to try your code. Since I can't correct this.

@betwixt your correct I missed that point. Thanks for correcting it.

- - - Updated - - -

I changed it to :

Code:
   if((day == 1) && (hours == 0) && (minutes == 0) && (seconds == 0))
      {
      SMS_Send(Meter_reading);
      }

      if((day == 1) && (hours == 0) && (minutes == 0) && (seconds == 4))
      {
       TMR1L = 0;
       TMR1H = 0;
       count = 0;
       temp = 0;
       Monthly_consumption = 0;
      }
 

hello,


Another way as fprintfto write result on LCD in fixed position of comma.
End of floating point value always end at 12em position , and then " KWH".
So at the beginning of the LCD line you have the choice ,
pass over caractere in front of begin of float value..or put Space value to erase previous data.
Now in the code use of "x" to see how it's work.

example of display values LCD 2x16 cars
xxxx199.4567 KWH
xxx9876.1224 KWH
xxxxxx1.2567 KWH
xxxxxx0.9876 KWH

Energydisplay( Floating value, LCD line number);
project mikroc in zip
nota:
i only have MickroC limited to 2K ( not registered)..
I used 16F877 IrdA demo board with LCD 2x16

View attachment _16F877_float2asc_LCD.zip
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top