![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
IamUche
Joined: 10 Aug 2016 Posts: 17
|
Help with 16x2 LCD |
Posted: Wed May 03, 2017 6:42 am |
|
|
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
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9178 Location: Greensville,Ontario
|
|
Posted: Wed May 03, 2017 6:57 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19384
|
|
Posted: Wed May 03, 2017 8:20 am |
|
|
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.... |
|
![](templates/subSilver/images/spacer.gif) |
IamUche
Joined: 10 Aug 2016 Posts: 17
|
|
Posted: Fri May 05, 2017 1:54 am |
|
|
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? |
|
![](templates/subSilver/images/spacer.gif) |
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Fri May 05, 2017 2:07 am |
|
|
Get rid of the semi-colon at the end of the while(1).
Regards |
|
![](templates/subSilver/images/spacer.gif) |
IamUche
Joined: 10 Aug 2016 Posts: 17
|
|
Posted: Fri May 05, 2017 3:19 am |
|
|
I just removed the semicolon after while(1) and this time the LED just stays ON, permanently. I'm even considering buying another microcontroller |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19384
|
|
Posted: Fri May 05, 2017 4:07 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
IamUche
Joined: 10 Aug 2016 Posts: 17
|
|
Posted: Sun May 07, 2017 3:49 am |
|
|
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);
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19384
|
|
Posted: Sun May 07, 2017 5:44 am |
|
|
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](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9178 Location: Greensville,Ontario
|
|
Posted: Sun May 07, 2017 6:01 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
IamUche
Joined: 10 Aug 2016 Posts: 17
|
|
Posted: Wed May 17, 2017 11:55 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19384
|
|
Posted: Thu May 18, 2017 12:20 am |
|
|
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.
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](images/smiles/icon_biggrin.gif) |
|
![](templates/subSilver/images/spacer.gif) |
IamUche
Joined: 10 Aug 2016 Posts: 17
|
|
Posted: Sun May 21, 2017 2:34 pm |
|
|
@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... |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9178 Location: Greensville,Ontario
|
|
Posted: Sun May 21, 2017 3:03 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
IamUche
Joined: 10 Aug 2016 Posts: 17
|
|
Posted: Sun May 21, 2017 6:11 pm |
|
|
@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. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|