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 please it is urgent
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
erendogan83



Joined: 12 Aug 2016
Posts: 13

View user's profile Send private message

help please it is urgent
PostPosted: Fri Aug 12, 2016 1:21 am     Reply with quote

hello dear friends

I am amateur friend of you about pic programming.

I am making a pic circuit about temperature measuring and writing to LCD screen using pic 16f877a.

Compiler reporting no error but my interrupt not working correctly.

Here is proteus scheme of my circuit:
http://i.hizliresim.com/7Am5LN.jpg

and my code is below.

I hope you experts give an advise to this amateur.

love u all thanks
Code:

#include <16f877.h>     

#device ADC=10

#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD

#use delay (clock=4000000)

#use fast_io(a)

#use fast_io(b)

#use fast_io(d)

#define use_portb_lcd TRUE   

#include <lcd.c>

#int_timer0

unsigned long int bilgi;
float voltaj,sicaklik;   

timer0_kesmesi()
{
   if (sicaklik>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);   
}

void main ( )
{
   setup_psp(PSP_DISABLED);        // PSP birimi devre dışı
   setup_timer_2(T2_DISABLED,0,1); // T2 zamanlayıcısı devre dışı
   setup_CCP1(CCP_OFF);            // CCP1 birimi devre dışı
   setup_CCP2(CCP_OFF);            // CCP2 birimi devre dışı
   set_tris_a(0x01);  // RA0 Giriş olarak yönlendiriliyor
   set_tris_d(0x00);
   output_d(0x00);
   setup_timer_0(RTCC_INTERNAL |RTCC_DIV_4);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   setup_adc(adc_clock_div_32);   // ADC clock frekansı fosc/32
   setup_adc_ports(AN0); //RA0/AN0 girişi analog
   lcd_init();   // LCD hazır hale getiriliyor
   set_adc_channel(0);   // RA0/AN0 ucundaki sinyal A/D işlemine tabi tutulacak
   delay_us(20);         // Kanal seçiminde sonra bu bekleme süresi verilmelidir
   printf(lcd_putc,"\fSicaklik="); // LCD'ye yazı yazdırılıyor
   while(1)   // sonsuz döngü
   {
      bilgi=read_adc();  // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor
      voltaj=(0.0048828125*bilgi)*1000;   // Dijitale çevirme işlemine uğrayan sinyalin mV olarak gerilimi hesaplanıyor
      sicaklik=(voltaj/10)+2;    // Her 10mV'ta 1 derece artma
      lcd_gotoxy(10,1); // İmleç 1. satır 10.sütunda
      printf(lcd_putc,"%5.1f'C",sicaklik); // LCD'ye sıcaklık değeri yazdırılıyor
      delay_ms(100); // 100 msn gecikme
   }
}
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Aug 12, 2016 3:23 am     Reply with quote

First, please read:
https://www.ccsinfo.com/forum/viewtopic.php?t=47549
Better you build the circuit on a prototyping board and make first a led to blink from a pin via a 560 ohm resistor at 1 second as the first stage of the program.
A few remarks regarding the hardware, regarding the software have people with much better knowledge than me to answer except why you need sophisticated calculations for the analog reading as 10 mV is 1 degree Celsius?

* You are stating that you want to measure temperature and display it on the LCD
* What the transistor supposed to do? Why driving it with a 200 ohm resistor and not let's say 4.7K ?
* How you are intending to program the PIC?
If ICSP, better drive the LCD from other ports and not B6 (PGC) and B7 (PGD).
* You will need MCLR pin also for programming with ICSP
* You have a power connection named VDD and one +VS. What is the supply to the PIC? 5V will be the best for the 16F877A

Best wishes
Joe
erendogan83



Joined: 12 Aug 2016
Posts: 13

View user's profile Send private message

PostPosted: Fri Aug 12, 2016 4:34 am     Reply with quote

I love you man Smile

I read your link before I posted my problem

but my problem not about proteus

problem is my interrupt not working neither in proteus nor in real circuit

I am wondering is it because of my codes or am I asking too much current from ports?

I will make changes you ask me to do

gjs_rsdi wrote:
First, please read:
https://www.ccsinfo.com/forum/viewtopic.php?t=47549
Better you build the circuit on a prototyping board and make first a led to blink from a pin via a 560 ohm resistor at 1 second as the first stage of the program.
A few remarks regarding the hardware, regarding the software have people with much better knowledge than me to answer except why you need sophisticated calculations for the analog reading as 10 mV is 1 degree Celsius?

* You are stating that you want to measure temperature and display it on the LCD
* What the transistor supposed to do? Why driving it with a 200 ohm resistor and not let's say 4.7K ?
* How you are intending to program the PIC?
If ICSP, better drive the LCD from other ports and not B6 (PGC) and B7 (PGD).
* You will need MCLR pin also for programming with ICSP
* You have a power connection named VDD and one +VS. What is the supply to the PIC? 5V will be the best for the 16F877A

Best wishes
Joe
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Fri Aug 12, 2016 8:21 am     Reply with quote

if (sicaklik>30)

Now sicaklik is declared as a 'float' value (ugh).
This comparison will take about 565uSec to do (actually more, since the '30', will first have to be converted to a float). Now your interrupt triggers every 1024 instructions (Fosc/(4*256*4)), so every 1024uSec. So straight away over half your processor time is being used by the interrupt. Think again. This should be done using an integer....

Float is _slow_. Until you realise just how slow, you will have problems.

Then the comparison is unlikely to work. The sicaklik value is being calculated and changed outside the interrupt. The interrupt may well receive it when it is half way through being calculated....

Then the interrupt declaration wants to be the line before the function. So:
Code:

#INT_TIMER0
void timer0_kesmesi(void)
{
   if (sicaklik>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);   
}


Now forget 'volts', and floating point numbers. The silly think is that you are almost doing the maths 'right' to work in mV, then throwing it all away.

Now your test for '30', starts from a voltage value that scaled as 5000 for 5v. /10 +2.

So '30' would occur for 0.28v, Is this what you want?.
Code:

//leaving out the initialisation

#define DEG_TO_MV(x) (x)*10
//This way the calculation can be done by the compiler, not the PIC
//for constants

//Got rid of the 2 offset. This is _not correct_ for the LM35

int16 bilgi, voltaj, sicaklik;   

#INT_TIMER0
timer0_kesmesi()
{
   if (sicaklik>DEG_TO_MV(30))
      output_high(pin_d1);
   else
      output_low(pin_d1);   
}

//again omitting the stuff between

   while(TRUE)   // sonsuz döngü
   {
      bilgi=read_adc();  // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor
      voltaj=(bilgi*39)/8;   //This gives integer 0 to 5000 for 0 to 5v.
      //_efficiently_.
      disable_interrupts(GLOBAL);
      sicaklik=voltaj; //copy with interrupts disabled
      enable_interrupts(GLOBAL);

      lcd_gotoxy(10,1); // İmleç 1. satır 10.sütunda
      printf(lcd_putc,"%5.1LW'C",(voltaj+20)); // LCD'ye sıcaklık değeri yazdırılıyor
      delay_ms(100); // 100 msn gecikme
   }


This is doing it with integer maths.

Then tell us the sensor. Are you sure about the '2' offset?. Sure it is not 20?. I can't think of any sensor on the market that is offset by just 2 degrees. Some are offset by 273. Some by 20C.

Looking at the circuit, you are using an LM35. This is not offset by 2C, it just can't output a voltage below 2C, unless you use a -ve bias.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Aug 12, 2016 5:17 pm     Reply with quote

LM35
http://www.ti.com/lit/ds/symlink/lm35.pdf
From the data sheet, the LM35 range is -55 to +150 degree Celsius
Starts at 0V (-55 degree), every degree is 10mV, 2050mV at +150
If the analog Vref+ is 5V (the VDD) at ADC=10 you will have 4.89mV/bit,
at ADC=8 will be 19.61mV/bit
Fastest is to make a table for bit/degree, but some work to do
You can make also the +Vref to a value that will give you mV/bit without fractions.

Best wishes
Joe
erendogan83



Joined: 12 Aug 2016
Posts: 13

View user's profile Send private message

PostPosted: Sat Aug 13, 2016 6:37 am     Reply with quote

thank you big chief for your help

yes it is LM35

I used float type because heat is analog wave

but now I see that it slows my cpu after I add interrupt to my code

I hope it works fine this time

I will add my thanks to you and gjs_rsdi

Ttelmah wrote:
if (sicaklik>30)

Now sicaklik is declared as a 'float' value (ugh).
This comparison will take about 565uSec to do (actually more, since the '30', will first have to be converted to a float). Now your interrupt triggers every 1024 instructions (Fosc/(4*256*4)), so every 1024uSec. So straight away over half your processor time is being used by the interrupt. Think again. This should be done using an integer....

Float is _slow_. Until you realise just how slow, you will have problems.

Then the comparison is unlikely to work. The sicaklik value is being calculated and changed outside the interrupt. The interrupt may well receive it when it is half way through being calculated....

Then the interrupt declaration wants to be the line before the function. So:
Code:

#INT_TIMER0
void timer0_kesmesi(void)
{
   if (sicaklik>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);   
}


Now forget 'volts', and floating point numbers. The silly think is that you are almost doing the maths 'right' to work in mV, then throwing it all away.

Now your test for '30', starts from a voltage value that scaled as 5000 for 5v. /10 +2.

So '30' would occur for 0.28v, Is this what you want?.
Code:

//leaving out the initialisation

#define DEG_TO_MV(x) (x)*10
//This way the calculation can be done by the compiler, not the PIC
//for constants

//Got rid of the 2 offset. This is _not correct_ for the LM35

int16 bilgi, voltaj, sicaklik;   

#INT_TIMER0
timer0_kesmesi()
{
   if (sicaklik>DEG_TO_MV(30))
      output_high(pin_d1);
   else
      output_low(pin_d1);   
}

//again omitting the stuff between

   while(TRUE)   // sonsuz döngü
   {
      bilgi=read_adc();  // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor
      voltaj=(bilgi*39)/8;   //This gives integer 0 to 5000 for 0 to 5v.
      //_efficiently_.
      disable_interrupts(GLOBAL);
      sicaklik=voltaj; //copy with interrupts disabled
      enable_interrupts(GLOBAL);

      lcd_gotoxy(10,1); // İmleç 1. satır 10.sütunda
      printf(lcd_putc,"%5.1LW'C",(voltaj+20)); // LCD'ye sıcaklık değeri yazdırılıyor
      delay_ms(100); // 100 msn gecikme
   }


This is doing it with integer maths.

Then tell us the sensor. Are you sure about the '2' offset?. Sure it is not 20?. I can't think of any sensor on the market that is offset by just 2 degrees. Some are offset by 273. Some by 20C.

Looking at the circuit, you are using an LM35. This is not offset by 2C, it just can't output a voltage below 2C, unless you use a -ve bias.
erendogan83



Joined: 12 Aug 2016
Posts: 13

View user's profile Send private message

PostPosted: Sat Aug 13, 2016 7:30 am     Reply with quote

Hello guys,

It is me again and still not working.

My pin_d1 shouldn't give output while condition not satisfied
but don't know why I always getting output from that pin.

Here is my code below:
Code:

#include <16f877.h>     

#device ADC=10

#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD

#use delay (clock=4000000)

#use fast_io(a)

#use fast_io(b)

#use fast_io(d)

#define use_portb_lcd TRUE

#define DEG_TO_MV(x) (x)*10

#include <lcd.c>

#int_timer0

int16 sensor, voltaj, temp; 

timer0_interrupt()
{
   if (temp>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);   
}

void main ( )
{
   setup_psp(PSP_DISABLED);       
   setup_timer_2(T2_DISABLED,0,1);
   setup_CCP1(CCP_OFF);           
   setup_CCP2(CCP_OFF);           
   set_tris_a(0x01); 
   set_tris_d(0x00);
   output_d(0x00);
   setup_timer_0(RTCC_INTERNAL |RTCC_DIV_4);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   setup_adc(adc_clock_div_32);   
   setup_adc_ports(AN0);
   lcd_init();   
   set_adc_channel(0);   
   delay_us(20);         
   printf(lcd_putc,"\ftemp=");
   while(TRUE)   
   {
      sensor=read_adc();  // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor
      voltaj=(sensor*39)/8;   //This gives integer 0 to 5000 for 0 to 5v.
      //_efficiently_.
      disable_interrupts(GLOBAL);
      temp=voltaj; //copy with interrupts disabled
      enable_interrupts(GLOBAL);
      lcd_gotoxy(10,1);
      printf(lcd_putc,"%5.1LW'C",(voltaj+20));
      delay_ms(100);
   }
}
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Sat Aug 13, 2016 10:42 am     Reply with quote

I don't have the 877 so can't test it in the real life but I copy your program and run it with MPLAB v8.92
This part:
Code:
timer0_interrupt()
{
   if (temp>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);
}

Gives when I compile it:
Quote:
Function not void and does not return a value timer0_interrupt

Also if I put break points the MPLAB can't resolve them.
Your code above is not an interrupt routine.
Replace it with:
Code:
#INT_TIMER0
void  TIMER0_isr(void)
{
   if (temp>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);
}

And the interrupt works in the simulator.

Iyi geceler
Best wishes
Joe
erendogan83



Joined: 12 Aug 2016
Posts: 13

View user's profile Send private message

PostPosted: Sat Aug 13, 2016 11:05 am     Reply with quote

Dear Joe,

can you copy paste of your full code pls?

I dont know why not happening

can it be reason we disabling interrupt in while loop?

and we not using TIMER_0 interrupt in while loop either

gjs_rsdi wrote:
I don't have the 877 so can't test it in the real life but I copy your program and run it with MPLAB v8.92
This part:
Code:
timer0_interrupt()
{
   if (temp>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);
}

Gives when I compile it:
Quote:
Function not void and does not return a value timer0_interrupt

Also if I put break points the MPLAB can't resolve them.
Your code above is not an interrupt routine.
Replace it with:
Code:
#INT_TIMER0
void  TIMER0_isr(void)
{
   if (temp>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);
}

And the interrupt works in the simulator.

Iyi geceler
Best wishes
Joe
erendogan83



Joined: 12 Aug 2016
Posts: 13

View user's profile Send private message

PostPosted: Sat Aug 13, 2016 11:31 am     Reply with quote

good news good news good news

guys it is working Smile

but it interrupts at 5 celcius

my condition is

if(temp>30)

I dont understand why

any comments?
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Sat Aug 13, 2016 12:02 pm     Reply with quote

Code:
#include <16f877.h>

#device ADC=10
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=4000000)
#use fast_io(a)
#use fast_io(b)
#use fast_io(d)
#define use_portb_lcd TRUE
#define DEG_TO_MV(x) (x)*10
#include <lcd.c>
//#int_timer0
int16 sensor, voltaj, temp;
/*
//whwn compiled gives: Function not void and does not return a value  timer0_interrupt
timer0_interrupt()
{
   if (temp>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);
}
*/
#INT_TIMER0
void  TIMER0_isr(void)
{
   if (temp>30)
   output_high(pin_d1);
   else
   output_low(pin_d1);
}

void main ( )
{
   setup_psp(PSP_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_CCP1(CCP_OFF);
   setup_CCP2(CCP_OFF);
   set_tris_a(0x01);
   set_tris_d(0x00);
   output_d(0x00);
   setup_timer_0(RTCC_INTERNAL |RTCC_DIV_4);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   setup_adc(adc_clock_div_32);
   setup_adc_ports(AN0);
   lcd_init();
   set_adc_channel(0);
   delay_us(20);
   printf(lcd_putc,"\ftemp=");
   while(TRUE)
   {
      sensor=read_adc(); // ADC sonucu okunuyor ve bilgi degiskenine aktariliyor
      voltaj=(sensor*39)/8; //This gives integer 0 to 5000 for 0 to 5v.
      //_efficiently_.
      disable_interrupts(GLOBAL);
      temp=voltaj; //copy with interrupts disabled
      enable_interrupts(GLOBAL);
      lcd_gotoxy(10,1);
      printf(lcd_putc,"%5.1LW'C",(voltaj+20));
      delay_ms(100);
   }
}

Regarding:
Quote:
but it interrupts at 5 celcius
my condition is
if(temp>30)

Something wrong in your calculations or the ADC reading
By the way, why the enable/disable Global?

Best wishes
Joe
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Sat Aug 13, 2016 1:20 pm     Reply with quote

My calculations:
If your +Vref is VDD and the LM35 gets also VDD (5V) the ADC reading will be 0 to 2050mV for - 55 to 150 degree
At 150 degree 10*205=2050mV, ADC reading 419 (from 1023)
voltaj=(sensor*39)/8; 419*39/8=2042
At 30 degree 10*85=850mV, ADC reading 173 (from 1023)
voltaj=(sensor*39)/8; 173*39/8=843
At – 51 degree 10*4=40mV, ADC reading 8 (from 1023)
voltaj=(sensor*39)/8; 8*39/8=39; already above the 30 in your program
By the way, I don't think you need sensor to voltaj and the voltaj to temp.
Make directly sensor to temp
The best in my opinion is to make a table, otherwise you will need complex mathematics

Best wishes
Joe
erendogan83



Joined: 12 Aug 2016
Posts: 13

View user's profile Send private message

PostPosted: Sun Aug 14, 2016 1:06 am     Reply with quote

bro I am having some difficulties about understanding your calculations (my brain mostly works slow)

we have -55 to +150 temp range total makes 205

and 10 bit A/D converter so 2^10 = 1024

so 1 degree change in weather equals 1023/205 = 5 bit

now I see why my circuit interrupts at 6 degree

because I typed if(temp>30)

30/5 = 6 degree

am I right?
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sun Aug 14, 2016 4:38 am     Reply with quote

The sensor does not have a -55 degree range, unless you use a -ve bias resistor so it can give outputs below 0v. The ADC cannot read below 0v anyway.

The sensor output is simple. +10mV/C. That is all.

At +20C, it gives 200mV out.

Without an external bias it can't actually output below 20mV, so gives 2C minimum.

With a 5v supply on the PIC ADC (honestly, using this you are not going to get better than perhaps a 1C repeatable resolution anyway, because of noise and inaccuracy in this voltage.... - so displaying to 0.1C, is actually pointless).
temtronic



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

View user's profile Send private message

PostPosted: Sun Aug 14, 2016 5:26 am     Reply with quote

Mr. T is 100% right about the LM35, as I've used the *F version (LM34) for decades in my remote energy control systems. The LM34 is a bit better(no pun intended) but these days the World 'thinks' *C. 21*C = 210mv for LM35 but 698mv for the LM34. The larger sensor voltage is less susceptable to noise. It's easy for the PIC to convert *F to *C for display purposes. However for 'control' use, just use the ADC 8 bit data in integer format NEVER use Floating Points !
To get better than +-1*, I used an opamp unity buffer with 3 pole R-C filters in the PSU for it, as well as the LM34 output to the buffer. That allowed for solid, stable readings over 100' of CAT5 ( twisted pair cable). 8 bit data is more than sufficent for any 'human' related temperature control projects.

Jay
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, 3  Next
Page 1 of 3

 
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