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.

LCD interfacing problem with PIC 16f877A

Status
Not open for further replies.

mugheesnawaz

Member level 1
Joined
May 1, 2013
Messages
39
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,605
i am using pic 16f877a with 8MHZ crystal and microC for pic for coding for buck and boost modules operation and i am using relays with the outputs of buck and boost so that only one output is received from buck and boost at a time(either buck will be on or boost will be on).
i am using port A for analog inputs,portB for LCD,Port E for buck boost enabling i.e i will set on pin ON and one pin OFF and will connect pins of this ports to relays of buck and boost.PORT C is used for PWM of buck and boost.now i am enabling buck and constantly decreasing 12V until it gets to 6V and then stop.i want to display simultaneously display this output of buck on LCD which i am facing problem in.
without LCD, i am getting correct results but when i interface LCD the operation stops i think due to delays of LCD_out command.kindly skip other parts of circuit as they will confuse you.
attached is image of cct diagram.
Code:
unsigned int ADCRead(unsigned char channel)
{
        unsigned char l_byte, h_byte;
        unsigned int ADR;
        ADCON0 = 0x81 | (channel << 3); //Change channel
        delay_us(50); //Acquisition Delay 50us
        GO_DONE_bit = 1; //Set GO_DONE bit to start conversion
        while (GO_DONE_bit == 1); //Wait for bit to be cleared
        //If bit is cleared, this means conversion is over
        l_byte = ADRESL;
        h_byte = ADRESH;
        ADR = (h_byte<<8)|l_byte;
        ADON_bit =0;   //switch off adc
        return ADR;
}

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

// LCD Pin direction
sbit LCD_RS_Direction at TRISB1_bit;
sbit LCD_EN_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB7_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB2_bit;
// End of LCD Pin direction


void main(void)
{
unsigned int Ch0, Ch1;
 float Form1,Form2;
unsigned short duty1=255;
float tempo=15.6;
char str_temp[60];
        CMCON = 7; //Disable ADC
        PORTA=0;
        TRISA=0xff;
        PORTB = 0;
        TRISB = 0;
        PORTC=0;
        TRISC = 0;
        PORTD = 0;
        TRISD = 0;
        PORTE = 0;
        TRISE = 0;
        ADCON0 = 0x81;
        ADCON1 = 0x80;
        Lcd_Init();                  // Initialize LCD
        Lcd_Cmd(_LCD_CURSOR_OFF);
        Lcd_Cmd(_LCD_CLEAR);        // Clear DisplayDelay_ms(30);
        Lcd_Out(1, 1, "MPPT Controller");
                 delay_us(1000);
                PWM1_Init(25000); // Initialize PWM1 for 25Khz
                PWM1_Start(); // start PWM1
                PWM1_Set_Duty(duty1); // Set current duty for PWM1
                PORTE.F0=0;
                PORTE.F1=1;
                while(1)
                {
                duty1=255;
                PWM1_Set_Duty(duty1);
                Ch0 = ADCRead(0); //Gets reading from channel 0
                delay_us(100);          // 0.1ms delay for ADC stabilization
                Ch1 = ADCRead(1); //Gets reading from channel 1
                delay_us(100);        // 0.1ms delay for ADC stabilization
                Form1= (10*(5*Ch0)/1023);
                PORTD = Form1;
                Form2= ((Ch1-123)/12);
                delay_us(100);   // 0.1ms delay for ADC stabilization
                while((Form1>9.80))
                {
                Ch0 = ADCRead(0); //Gets reading from channel 0
                delay_us(100);      // 0.1ms delay for ADC stabilization
                Ch1 = ADCRead(1); //Gets reading from channel 1
                delay_us(100);        // 0.1ms delay for ADC stabilization
                Form1= (10*(5*Ch0)/1023);
                delay_us(100);
                FloatToStr(Form1, str_temp);
                PORTD = Form1;
                Lcd_Cmd(_LCD_CLEAR);
                Lcd_Out(1, 1, "Battery Voltage=");
                // Ltrim(str_temp);
                Lcd_Out(2, 1, str_temp);
                 //delay_ms(1000);
                duty1-=2.55;  //255/100=2.55 for each instance 1% decreased
                PWM1_Set_Duty(duty1);
                }
                }
}
pwm.png
 
Last edited:

Now you have to make it work with interruptions only...

look for examples of ADC interrupts on the web, each time the ADC completes, you have to do a quick calculation for each Form1 and Form2 values...
then make a timer interrupt (maybe TMR0) and every time it interrupts, you check Form1 if it's higher than 9.8 and fix your duty1 according your test...

once all of this works via interrupts... you can add the FloatToStr and the LCD functions in the main program... it doesn't matter if it takes too long in the main program, the interrupts will keep your PWM according your limits...
 
if i use interrupts for adc restrictions will lcd display be still laggy? for now without lcd its rapid but with lcd system slows down.using interrupts would make both adc and lcd work fast?
 

no more lags, but remember to keep your interrupt subroutine quick and small (so don't put delays inside the interrupt, do it by timers)
yup, basically that's what interrupts are for...
 

i have changed the code as u told but still didnt help,lcd commands are creating trouble
Code:
unsigned int adc_data[4];
unsigned char analog_selected = 0;
unsigned char str[50];
unsigned short duty1=255;
float form1;
// LCD Module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D5 at RD3_bit;
sbit LCD_D4 at RD2_bit;
// End LCD module connections

// LCD Pin direction
sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;
sbit LCD_D7_Direction at TRISD7_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D5_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD2_bit;
// End of LCD Pin direction
void interrupt(){
  if (PIR1.ADIF) {
    PIR1.ADIF=0; // clear AD interrupt flag
    switch (analog_selected){
      case 0:
        adc_data[0] = (ADRESH << 8) | ADRESL; // read dadta from channel 0
        analog_selected++; // increase channel index
        ADCON0 = 0b11001001; // select channel 1
        break;
      case 1:
        adc_data[1] = (ADRESH << 8) | ADRESL; // read dadta from channel 1
        analog_selected++; // increase channel index
        ADCON0 = 0b11010001; // select channel 2;
        break;
      case 2:
        adc_data[2] = (ADRESH << 8) | ADRESL; // read dadta from channel 2
        analog_selected++; // increase channel index
        ADCON0 = 0b11011001; // select channel 3;
        break;
      case 3:
        adc_data[3] = (ADRESH << 8) | ADRESL; // read dadta from channel 3
        analog_selected = 0; // return channel 0
        ADCON0 = 0b11000001; // select channel 0;
        break;
    }
    Delay_Cyc(3); //wait acquisition time
    ADCON0.F2=1; //start conversion again
  }
}
                              // Loop variable

void main(){
  unsigned int i=0;
  float temp;
  CMCON = 7; //Disable ADC  Comparators
  TRISA=0xFF;
  TRISB=0;
  TRISC=0;
  TRISD=0;
  TRISE=0;
  ADCON1 = 0x82; // AN0->AN4 selected as analog input  1/FRC 0010 for AN0 to AN4
  ADCON0 = 0b11000001; // Configue analog mode
  INTCON.GIE = 1; //Enable global interrupt
  INTCON.PEIE = 1; //Enable peripheral interrupt
  PIE1.ADIE = 1; //Enable ADC interrupt
  Delay_us(20); //wait for acquisition time
  ADCON0.F2 = 1; //start conversion
  CCP2CON=  0x0B;       //wait for AD conversion and reset timer
  Lcd_Init();
  Lcd_Cmd(_LCD_CURSOR_OFF);
  PWM2_Init(25000); // Initialize PWM1 for 25Khz
               PWM2_Start(); // start PWM1
               PWM2_Set_Duty(duty1); // Set current duty for PWM1
                while(1)
               {

    temp = adc_data[i]; // read data from channel i
      i=0;
      form1=((temp*5)/1023) ;
   FloattoStr(form1,str);
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1, 1, "Battery Voltage=");
    Lcd_Out(2, 1, str);
    duty1-=2.55;
   PWM2_Set_Duty(duty1);
   }
}
 

Didn't I tell you to keep of the delay out of the interrupt?

use some available Timer module interrupt to start (and so synchronize) the ADC..

use the same timer interrupt (or maybe one 1/4 slower) to update duty1 (in this new program I don't see the control algorithm, just an in discriminated decrement (of 2.55))
 

how can i remove aqcuisition delay from interrupt function.
yes it is indiscriminated just to check the working of program.can you explain by changing the code i cant understand what you are referring to please
 

Get rid of the delay and restructure your code. Use the interrupt to recover the ADC result but do the channel selection and any storing of results in the main part of your code. The interrupt just tells you the result is ready (ADC conversion is finished) so don't use it for other purposes.

Brian.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top