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

Help with 16x2 LCD
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
IamUche



Joined: 10 Aug 2016
Posts: 17

View user's profile Send private message

Help with 16x2 LCD
PostPosted: Wed May 03, 2017 6:42 am     Reply with quote

Hi,
For quite a long time now I've just been coding and simulating with proteus and every of my designs all works fine on simulation. But i tried building a physical device and decided to test out a 16x2 LCD with PIC16f877a microcontroller first but its not displaying anything even after working fine on proteus.
Here is the code and i can't really tell what I'm not doing right as it worked fine on simulation.

Code:

#include <16f877a.h>
#device adc=10    // Set ADC resolution to 10Bit
#fuses XT,NOLVP,NOWDT,NOPROTECT
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,ERRORS)
#include "flex_lcd.c"





void main()
{

                      // ADC module is slow, needs some time to adjust.
             
   /* Peripherals Configurations */
   lcd_init();                   // Turn LCD ON, along with other initialization commands
   
   
   while(1) // infinite loop
   { 
        lcd_gotoxy(1,1);              // point LCD cursor to col1 row1
   lcd_putc(" ASK UCHE SOME");  // print on LCD
   
        lcd_gotoxy(1,2);                 // point LCD cursor to col1 row2
     lcd_putc(" QUESTIONS ");  // print on LCD
   
   }
}
temtronic



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

View user's profile Send private message

PostPosted: Wed May 03, 2017 6:57 am     Reply with quote

OK, there are 100 things that 'could' be wrong.....

Start with the simple stuff...
Can you code/compile/run a 1Hz LED program ? If not, you'll never get the LCD program up and running.

The 877 requires caps for the xtal, are they there? correct values?
Is *MCLR properly connected ?
Is power properly connected ?

Yes, simple, basic questions but proteus is stupid, full of bugs and idiotic DRCs. I've yet to see ONE 'simulation' that would work in the Real World as drawn.

As for your code... you need a delay_ms(500) BEFORE the LCD_INIT() function. All LCD modules are slow and need some time to 'powerup'. This varies from model to model of LCD, but 500ms has worked for all in the past 20 years.

You should add PUT in your #fuses list. This will help the 877 properly initilize on power up.

report back when the LED blinks...

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Wed May 03, 2017 8:20 am     Reply with quote

and emphasize that this is one of the reasons there is a sticky about Proteus at the top of the forum.

Proteus does lots of things 'for you', and doesn't actually understand what is needed to make a processor work.
So it'll accept supply rails that are not connected to all the pins that are needed, and connect rails for you to the main pins, which you can easily forget.
It doesn't worry about smoothing.
It assumed you know what you are doing when you tell it the chip is clocked.
Real displays will also be much more fussy about their Ve connection voltage, and this can differ a lot between different displays....
IamUche



Joined: 10 Aug 2016
Posts: 17

View user's profile Send private message

PostPosted: Fri May 05, 2017 1:54 am     Reply with quote

Thanks so much for the awesome replies. Well the mistake I made was not connecting the two VDDs and VSSs of the microcontroller (PIC16F877a). But other basic connections (20 Mhz crystal with two 22pf capacitors and 10k resistors connected between the MCLR pin and +5v) are just fine. But following your advice i tried out the LED blinking programme but isn't working fine. The Led was supposed to delay for 1 sec High and 1 sec Low. but it just comes on for about 11 minutes and goes off permanently. Despite that behaviour i still ran the LCD program on the microcontroller which ended up displaying words at randomly at different columns and rows.
See the LED code below
Code:

#include <16f877a.h>
//#device adc=10    // Set ADC resolution to 10Bit
#fuses XT,NOLVP,NOWDT,NOPROTECT,PUT
#use delay(clock=20000000)
//#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,ERRORS)
//#include "flex_lcd.c"

void main()
{

   
       while(1);// is pinc0 low?
       { 
       output_high(PIN_B7);
           delay_ms(1000);
           output_low(PIN_B7);
         delay_ms(1000);
       }
}

Is there anything I could be doing wrong again or is the microcontroller bad?
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Fri May 05, 2017 2:07 am     Reply with quote

Get rid of the semi-colon at the end of the while(1).

Regards
IamUche



Joined: 10 Aug 2016
Posts: 17

View user's profile Send private message

PostPosted: Fri May 05, 2017 3:19 am     Reply with quote

I just removed the semicolon after while(1) and this time the LED just stays ON, permanently. I'm even considering buying another microcontroller
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Fri May 05, 2017 4:07 am     Reply with quote

I suspect the processor oscillator is dying.

Two things:

First what resistor have you got between the LED and the PIC?. There needs to be a resistor to limit the current, or when the LED comes on, it can cause the processor to lockup, when too much current is drawn. Typical red LED has a Vf of just under 2v. The PIC output will drive to perhaps 4.5v, so to draw 10mA, you need a resistor of perhaps 250R. 270R is commonly used. This could cause the PIC to hang, if the resistor is not there, or too small.

Then your oscillator setup is wrong. XT, is the fuse for a crystal up to 4MHz. Higher frequency crystals need more drive. HS is the selection for a 20Mhz crystal.
IamUche



Joined: 10 Aug 2016
Posts: 17

View user's profile Send private message

PostPosted: Sun May 07, 2017 3:49 am     Reply with quote

WoW!!!
@Ttelmah: It worked like Magic!
Everything is super Okay. The LED blinked just fine and the LCD program too.
Thank you so much (@temtronic,@Ttelmah,@alan) for the awesome support.
But I did a little modification on the code. Trying to have the LCD screen display:
1-Company name
2-voltage value(Voltage meter)
3-current value(Ammeter)
4-Power(in KVA)
All at a timed interval. I didn't want to use delay() function to keep time of interval because it messes up the smooth running of time. So i decided to use one of the timers of the microcontroller (PIC16F877a). I kinda used the timer to achieve multitasking. But my problem is that
1- the time interval between LED High and Low state is not uniform.
2- the Voltage and current reading has two decimal place each and the decimal numbers are vibrating and kinda blurry.

Please how can i solve these or are there better ways to achieve multitasking without using the timer.

Thanks in anticipation.
See code below!
Code:

#include <16f877a.h>
#fuses HS,NOLVP,NOWDT,NOPROTECT, PUT
#device adc=10    // Set ADC resolution to 10Bit
#use delay(clock=20000000) //clock oscillating at 20MHZ
//#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,ERRORS)
#include "flex_lcd.c"

    int16 read1, read2; //declaration of variables
    float current,voltage,power;//declaration of variables
    int count=0,value,a=0,b=11,c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0,k=0;//declaration and initialisation of variables
   
    void greeting_message(){   
    lcd_gotoxy(1,1);//sets place for lcd to display company name
    lcd_putc(" Impact Systems ");//displays company name on the lcd
   
    lcd_gotoxy(1,2);//sets place for lcd to display L2
    lcd_putc("    Wait....    ");//displays L2 on the lcd
    }
   
    void blank_space(){
    lcd_gotoxy(1,1);//sets place for lcd to display company name
    lcd_putc("                ");//displays company name on the lcd
   
    lcd_gotoxy(1,2);//sets place for lcd to display L2
    lcd_putc("                ");//displays L2 on the lcd
    }
   
    void company_name()
    {
    lcd_gotoxy(1,1);//sets place for lcd to display company name
    lcd_putc(" Impact Systems ");//displays company name
    lcd_gotoxy(1,2);//sets place for lcd to display serial number
    lcd_putc("(Serial  number)");//displays serial number of product
    }

    void voltage_display(){
    lcd_gotoxy(1,1);//sets place for lcd to display current(I)
    lcd_putc("Supplied Voltage");
   
    lcd_gotoxy(1,2);//sets character display point
    printf(lcd_putc,"     %.2fV        " voltage);//displays the voltage value of L1
    }

    void current_display(){
    lcd_gotoxy(1,1);//sets place for lcd to display current(I)
    lcd_putc("Current consumed");
   
    lcd_gotoxy(1,2);//sets character display point
    printf(lcd_putc,"      %.2fA       " current);//displays the current value
    }

    void power_display(){
     lcd_gotoxy(1,1);//sets place for lcd to display power(VA)
    lcd_putc("   Load Power   ");
   
    lcd_gotoxy(1,2);//sets character display point
    printf(lcd_putc,"      %.1fKVA     " power);//displays the power consumed by the load
    }
   
    void lcd_page(){
             switch(d){
    case 1:company_name();break;//displays company name
    case 2:voltage_display();break;//displays voltage value(voltmeter)
    case 3:current_display();break;//displays current value(ammeter)
    case 4:power_display();break;//displays load power consumption in KVA
                     }
    if(value==1){//set flag whenever timer_1 value is 1
    count++;//for everytime flag is set, 'count' value increments
    if(count==200){//set flag for everytime 'count' reaches 200
    d++;//for everytime 200 'count' reaches, 'd' increments
    count=0;//reset 'count' to 0
    if(d==5){//set flag for when 'd' equals 5
    d=0;}}} //reset d back to 0       
    }
   
    void blinky_alert(){
    output_low(pin_c5);//switch off relay pin
    switch(e){
    case 1://case1 displays 'ALERT!'
    lcd_gotoxy(1,1);//sets place for lcd to display current(I)
    lcd_putc("     ALERT!     ");//display alert notification
    output_high(pin_c0);//sets buzzer pin on
    break;
    case 2://case2 displays space giving a blinky effect
    output_low(pin_c0);//sets buzzer pin off
    lcd_gotoxy(1,1);//sets place for lcd to display
    lcd_putc("                ");//to clear lcd display
    break;
    }
    if(value==1){//set flag whenever timer_1 value is 1
    c++;//for everytime flag is set, 'count' value increments
    output_toggle(pin_c6);
    if(c==8){//set flag for everytime 'c' reaches 8
    e++;//for everytime 8 'c' reaches, 'e' increments
    c=0;//reset 'c' to 0
    if(e==3){//set flag for everytime 'e' equals 3
    e=0;//resets 'e' to 0
    }}}
    }
   
    void normal_led_blinky(){
    h++;//increment the value of 'h'
    if(h==1){//condition for led high
    output_high(pin_c6);}//turn pin for led on
    else if(h==5){//condition for led low
    output_low(pin_c6);}//turn pin for led off
    else if(h==100){//condition for led loop delay
    h=0;//reset 'h' to 0 to continue loop
    }
}
   
void main()
{
   output_c(0x00);//using portc as output and initialising all c ports to low
   /* ADC Initialization */
   setup_adc(ADC_CLOCK_INTERNAL); // initialize ADC with a sampling rate of Crystal/20 MHz
   setup_adc_ports(ALL_ANALOG);// set all adc ports for analog input
   delay_ms(100); // ADC module is slow, needs some time to adjust.
 
   lcd_init();// Turn LCD ON, along with other initialization commands
   /////Timer_1 initialisation/////////////
   set_timer1(0);
   setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_4 );
   enable_interrupts(INT_TIMER1);
   value=get_timer1();
   ////startup greeting message/////////////
   greeting_message();//function for display while system boot
   count=0;b=0;a=0;//reset all timing variables to 0
   output_c(0x00);//initialise port_c low
   delay_ms(1000);
   
   while(1){
 
   set_adc_channel(0);
   delay_us(100);//0.1ms delay for ADC stabilization
   read1=read_adc();
   voltage=read1*0.3; // voltage reading for 300v max
   
   set_adc_channel(1);
   delay_us(100);// 0.1ms delay for ADC stabilization
   read2=read_adc();
   current=read2*0.029325513;//current set for 30A
   power=(current*voltage)/1000;//calculation for power in KVA
   
   lcd_page();//timed pagination for the LCD display
   normal_led_blinky();//led blinks indicating normal working condition
   output_high(pin_c5);
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Sun May 07, 2017 5:44 am     Reply with quote

At heart a timer is the only thing that will give you 'code independent' time.
However with some care, you only need to read it, not actually do anything with it.
Have a look in the manual at #USE TIMER.
This allows you to setup a system 'tick'.
Now if you then have your code loop, and do things when the counts from this have changed by a specified amount (the manual entry has an example), then you can get a simple form of multi-tasking.

On the ADC, the first thing is don't use ADC_CLOCK_INTERNAL. Read the chip's data sheet. This is not recommended above 1MHz, unless the chip is put to sleep to do the conversion. Instead you need to be using a divisor from the master clock. The data sheet tells you what is needed.
This will improve things a little.
However you then need to be aware that using the chip's power rail as a reference, you will see noise on the display. To get much smoother operation really needs an accurate reference. Also though some damping.
Have a look at this thread:
<http://www.ccsinfo.com/forum/viewtopic.php?t=56005>

Well done on moving forwards.
Have Fun. Smile
temtronic



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

View user's profile Send private message

PostPosted: Sun May 07, 2017 6:01 am     Reply with quote

Have a look at the 'Software Real Time Clock' program in the code library. It's a great example of how to achieve what you want. it can easily be modified to 'alert' your main() program when to read the ADC, display data, flash LEDs, etc.

As Mr T points out, there are several things wrong about your ADC code. Realistically you'll never get more than 8 bits from it when using VDD as the Vref. The simple act of turning on an LED will drop VDD slightly, so reading the ADC then will be different than when the LED is off. This won't show on a DMM, as they update at a 2-3 Hz rate..very, very slow compared to a PIC !

Jay
IamUche



Joined: 10 Aug 2016
Posts: 17

View user's profile Send private message

PostPosted: Wed May 17, 2017 11:55 am     Reply with quote

Sorry It took me a while to reply. I moved to a place without internet coverage but I'm back.
Thanks a lot (@Ttelmah and temtronic ) for the great support.
I guess I'm making these mistakes coz i have a been trying to learn embedded c and its applications on my own without proper guide. But thanks a lot, I have to go back and read up extensively the datasheet of the microcontroller.
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Thu May 18, 2017 12:20 am     Reply with quote

Everybody makes mistakes.
The key is to learn and move forwards.
We get some posts here where people are given clues/routes to answers and three weeks later they are still asking the same questions. These get annoying!. However conversely, we get other posters who move forwards in 'leaps and bounds' and end up getting their project working and then moving on to do more complex things. These are really rewarding. Smile

There have been a couple recently where the posters have done 'great things' after threads here.

There is a lot of basic 'C' learning, and also so many diverse bits of reading to do, for every chip. Currently working on a project, and had a directory full of the data sheets, application notes, and my own notes about it, before even putting one chip on the board. Now coding, while the four prototypes are being built, and again get pages of comments at the head of the code, listing every pin function, peripheral setting etc..

Key thing is though that the code is being written in sections, and each will be got working separately, before trying to generate the final system. The first things I'll do before actually powering the board will be basic tests on power rails, and for shorts etc., then a simple test for clock speed, and functionality on each I/O port, before connecting power devices. Working 'step by step', is in the end much quicker than trying to 'leap ahead'. Tortoise and hare. As you get better, the actual steps get faster, and will often work 'first time', but they still need to be there....

Have fun. Very Happy
IamUche



Joined: 10 Aug 2016
Posts: 17

View user's profile Send private message

PostPosted: Sun May 21, 2017 2:34 pm     Reply with quote

@Ttelmah, Thanks a lot for the priceless tips.

On moving forward, I carried out several tests on the device which has been working just fine but I discovered one thing;
One of the pins on the bread board where I connected +5v from my power supply is a bit loose thereby causing partial contact when I shake the +5v power cable, then the partial contact is supposed to switch of the entire circuit and back on but what I see is the whole function goes on a kind of pause when the partial contact occurs. The blinking led stays on (or off depending on its state before the partial contact occurred) every thing just stands still. But I expected a kind of reset when a partial contact occurs instead of a pause.

Is there anything I can do about this or is a normal behavior of a microcontroller with respect to partial contacts?

Thanks for your awaited reply...
temtronic



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

View user's profile Send private message

PostPosted: Sun May 21, 2017 3:03 pm     Reply with quote

re: breadboards.

Some people hate them, other like them. I've got some 35 year old ones that still work fine. One problem is sticking too large a wire in the holes. As you've found out you can get erratic or random operation. They were designed fo 'IC pin' sized wires, say 22ga or smaller.
It does help to mount the boards onto a stiff piece of plywood as it keeps better pressure on the conductors, at least that's been my observation.

I don't know about the quality of the current boards, so maybe they won't last as long.

What I do know is that IF your project does work on a breadboard it WILL work as a real PCB.

Jay
IamUche



Joined: 10 Aug 2016
Posts: 17

View user's profile Send private message

PostPosted: Sun May 21, 2017 6:11 pm     Reply with quote

@temtronic,
I really don't have issues with the bread boards behavior. But I'm imagining a situation where I get a partial contact from my soldered project on a PCB so I want to know if there is a function that can make it reset whenever it experiences partial contact instead of freezing or pausing. Because the freeze or pause won't be good for my application of this design/circuit.
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