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

Code weirdness

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

Code weirdness
PostPosted: Sun Apr 26, 2009 1:26 pm     Reply with quote

I'm using a 16F876A and ccs 3.249 (tried it with 4.007 also)
I'm reading an I2C temp sensor and displaying the value on some 7-segment leds. If I read the sensor and display it directly then it is fine. IF I convert the reading from C to F then I get a wrong reading, even if I Display the original variable.

So If I use the first DisplayNumber below it is ok, but If I comment that line out and use one of the other ones below I always get a 30. It is not the match because displaying Tempnumber there still gives a 30. What am I missing here.
Code:

tempnumber=ReadTempI2C(144);// address of MCP9801 ranges from 144 to 160
// DisplayNumber(tempnumber);//this works perfectly, I get a 22 or 23C reading

TC=tempnumber;
tempnumber2=tempnumber;
TF=(tempnumber * 1.8) +32;

DisplayNumber(tempnumber); //This always outputs a 30.
//  DisplayNumber(TF);//This always outputs a 30.
//  DisplayNumber(tempnumber2);//This always outputs a 30.
//  DisplayNumber(TC);//This always outputs a 30.



Complete code
Code:
//#include "18f2221.h"
#include "16f876a.h"
#fuses hs,nowdt,noprotect,put,nolvp
#device *=16
#device adc=10
#use delay(clock=20000000)
//#priority ext
#include "stdlib.h"
#use I2C(master, sda=PIN_c4, scl=PIN_c3,slow)
//#define    BAUD_RATE                 115200 //19200
//#define BAUD_RATE          19200
#define thermoC            PIN_A0
#define local_temp         PIN_A1

#define SW1           PIN_B4//high limit left
#define SW2           PIN_B5//high limit right
#define SW3           PIN_B6//low limit left
#define SW4           PIN_B7//low limit right


#define DIG0           PIN_C1
#define DIG1           PIN_C5
#define DIG2           PIN_C6
#define DIG3           PIN_C7
#define DIG4           PIN_B0
#define RELAY           PIN_C5
//#define LED2_PIN           PIN_C6
//#define LED1_PIN           PIN_C7

#define A           PIN_B5
#define B           PIN_B4
#define C           PIN_B3
#define D           PIN_B2
#define E           PIN_B1
#define F           PIN_B6
#define G           PIN_B7

#define Relay_off   output_low(RELAY)   
#define Relay_on    output_High(RELAY)   


//#define one     0x18    //0x18 is sent to port B to turn on correct segments to show a "one"
#define one     0xE7    //0x18 is sent to port B to turn on correct segments to show a "one"
#define two     0x49 //0xB6    //0xB6 is sent to port B to turn on correct segments to show a "two"
#define three   0x43//0xBC       
#define four    0x27//0xD8
#define five    0x13//0xEC
#define six     0x31//0xCE
#define seven   0xc7//0x38
#define eight   0x01//0xFE
#define nine    0x07//0xF8
#define zero    0x81//0x7E
#define CEE     0x79//0x86    //0x86 is sent to port B to turn on correct segments to show a "C" for celcius
#define EFF     0x1d//0xE2    //0xE2 is sent to port B to turn on correct segments to show a "f" for Fahrenheit
#define H       0x25
#define L       0xB9
int digits[10]={zero,one,two,three,four,five,six,seven,eight,nine};
#byte port_b = 0xF81
int HighLimit, LowLimit;
int _HighLimit, _LowLimit;
int function=0; //0 = F, 1=C, 2=H, 3=L


//long int heartbeat_counter=0;
void itos(char s[],signed int n);
void BlinkLeds (void);
void toggle_led();
void init_PIC();
void heartbeat();
int ReadTempI2C(int ADDRESS);
void DisplayNumber(int Num);
void CheckPots();

/*****************************************************
void main() --
*****************************************************/

void main()
{
   int i;
//   int timeon=3;
   //long int j;
//   int testnum=0;
    int Mynumber;
    int Tc;
    int Tf;
    int tempnumber;
    int tempnumber2;
   init_PIC();
   Relay_off;
   set_tris_b(0); // all outputs
   port_B=0xff;// all high
   output_b(0xff);
   //turn off all segments
   output_high(dig1);
   output_high(dig2);
   output_high(dig3);
   output_high(dig0);

   while (1)
   {
//      set_adc_channel( 1 );
//      delay_ms(1);
//      HighLimit = Read_ADC();
//      set_adc_channel( 2 );
//      delay_ms(1);
//      LowLimit = Read_ADC();


//        CheckPots();
//    get reading frm I2C bus
//        number=ReadTempI2C(144);// address of MCP9801 ranges from 144 to 160
//         DisplayNumber(number);

        tempnumber=ReadTempI2C(144);// address of MCP9801 ranges from 144 to 160
//        DisplayNumber(tempnumber);

        TC=tempnumber;
        tempnumber2=tempnumber;
        TF=(tempnumber * 1.8) +32;

         DisplayNumber(tempnumber);
//         DisplayNumber(TF);
//         DisplayNumber(tempnumber2);
//         DisplayNumber(TC);

//        for(i=0;i<20;i++)
//        {
//            function=1; //display C
//            mynumber=TC;//celcius
//            if(i<10)
//            {
//                function=1;  //Display F
//                mynumber=TC;//farenheight
//            }             
//            DisplayNumber(mynumber);
//        }
//        if(TF >= HighLimit)
//            Relay_on;
//        if(TF <= LowLimit)
//            Relay_off;   
           
           

    }//end while
}//end main


void DisplayNumber(int Num)
{
   int number,ones,tens,hundreds;
   long int j;
    int timeon=3;


    hundreds=number/100;
   tens=(number-(hundreds*100))/10;
   ones=(number-(hundreds*100)-(tens*10));
    for(j=0;j<50;j++)
    {
        output_b(digits[ones]|0);
       output_low(dig2);//turn on segment 1
       delay_ms(timeon);
       output_high(dig2);//turn off segment 1

       output_low(dig3);//turn on segment 2
        output_b(digits[tens]|0);
       delay_ms(timeon);
       output_high(dig3);//turn off segment 1

        if(hundreds >0)
        {
            output_b(digits[hundreds]|0);
           output_low(dig4);//turn on segment 1
           delay_ms(timeon);
           output_high(dig4);//turn off segment 1
        }
       output_low(dig1);//turn on segment 2
       if(function==0)
            output_b(eff);
       if(function==1)
            output_b(CEE);
       if(function==2)
            output_b(H);
       if(function==3)
            output_b(L);

       delay_ms(timeon);
       output_high(dig1);//turn off segment 1


//         if(hundreds >0)
//                port_b=port_b | digits[hundreds];/
//         else
//                port_b=port_b | 0;
//         output_low(dig0);//turn on segment 1
//            port_b=port_b & 0x1; // set all off but digit
//            port_b=port_b | eff;
//         delay_ms(1);
//         output_high(dig0);//turn off segment 1
    }       
}

void CheckPots()
{

      set_adc_channel( 1 );
      delay_ms(1);
      HighLimit = Read_ADC(); //0-1024
      HighLimit /= 5;  //0-204 F
      
      set_adc_channel( 2 );
      delay_ms(1);
      LowLimit = Read_ADC();
      LowLimit /= 5;  //0-204 F
      
      if (HighLimit != _HighLimit)
          {
              function=2;
              DisplayNumber(HighLimit);
          }
         
      if (LowLimit != _LowLimit)
          {
              function=3;
              DisplayNumber(LowLimit);
          }
         
      _HighLimit = HighLimit;   
      _LowLimit = LowLimit;
}



int ReadTempI2C(int ADDRESS)
{
    int ValueH=0;
    int ValueL=0;
    i2c_start();   // restart condition
    i2c_write(ADDRESS + 1);
    valueH = i2c_read(1);
    valueL = i2c_read(0);
    i2c_stop();
return(ValueH);   
   
}
/***************************************************
void init_PIC() -- Initializes variables
***************************************************/
void init_PIC()
{
// int i;
//short int dummy_variable;

setup_adc_ports(All_ANALOG);
setup_adc( ADC_CLOCK_INTERNAL );

setup_spi(FALSE);
//setup_psp(PSP_DISABLED);
//enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
//output_low(PIN_A0);
//output_low(PIN_A1);
output_low(PIN_A2);
output_low(PIN_A3);
output_high(PIN_A4);
output_low(PIN_A5);
output_low(PIN_B0);
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_B3);
output_low(PIN_B4);
output_low(PIN_B5);
output_low(PIN_B6);
output_low(PIN_B7);
output_low(PIN_C0);
//output_low(PIN_C1);
//output_low(PIN_C2);
output_low(PIN_C3);
output_low(PIN_C4);
output_low(PIN_C5);
output_low(PIN_C6);
//output_low(PIN_C7);RX
}

/************************************************
void BlinkLeds (void)
*************************************************/
void BlinkLeds (void)
{
//   int i;
//   for(i=0;i<10;i++)
//   {
//      LED1_ON;
//      LED2_Off;
//      delay_ms(150);
//      LED1_OFF;
//      LED2_On;
//      delay_ms(150);
//   }
}

/************************************************
 void heartbeat()
************************************************/
void heartbeat()
{
//   heartbeat_counter++;
//   if (heartbeat_counter >= 100)
//   {
//      heartbeat_counter=0;
//      toggle_led();
//   }
}
/************************************************
 toggle_led()
 ***********************************************/
void toggle_led()
{
//   static short Toggle=0;
//   Toggle=1-Toggle;
//   if ( Toggle==1)
//   {
//      LED1_on;
//   }
//   else  LED1_OFF;
//   return;
}


_________________
Ringo Davis
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 1:28 pm     Reply with quote

Quote:
It is not the match

Should be
It is not a math thing
_________________
Ringo Davis
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 1:40 pm     Reply with quote

The Line
TF=(tempnumber * 1.8) +32;
is definitey the problem. Without this line then I can display TempNumber, or Tc without a problem. Adding that line somehow screws up the other variables. I also tried
TF=((tempnumber * 1.8) +32);
just in case but extra () did not help.

I'm using 9% of Rom and RAM so that is not an issue.
Anybody have any ideas here?

Thanks
Ringo
_________________
Ringo Davis
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 1:47 pm     Reply with quote

Make two test programs.

1. Make a test program to check your display routine. Count up from
00 to 99 (or whatever the max limit of your display is) with a for() loop.
Put a half second delay after you display each number, so it's long
enough for you to see it. Verify that your display routine works.

2. Make a test program to check your C to F conversion routine.
Make a for() loop and have it count through the expected range of C
values, and display the F results in a terminal window on your PC.
(Not with the 7-segment display). Verify that the F values are correct.

If both of these tests work OK, then the problem is likely in the interface
between the two routines. In other words, it's in the passing of the
variables between the two routines.

Don't use PCH vs. 4.007. It can't possibly be reliable.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 2:08 pm     Reply with quote

I've got a routine to test the display and it works fine.
I can reduce the problem down to this
This works fine
tempnumber=ReadTempI2C(144);// address of MCP9801 ranges from 144 to 160
TC=tempnumber;
// TF=(tempnumber * 1.8) +32;
DisplayNumber(TC);



This does not
tempnumber=ReadTempI2C(144);// address of MCP9801 ranges from 144 to 160
TC=tempnumber;
TF=(tempnumber * 1.8) +32;
DisplayNumber(TC);


Notice I'm not even using TF, just doing the conversion screws up TC.
How can I figure this out?

If I warm up the sensor, without the conversion it goes 22,23,24,etc.
With the conversion in place it goes 30,37,44,52 (difference of 7,7,9)
This is still without even using TF. TC gets these new weird values.
Ringo
_________________
Ringo Davis
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 2:12 pm     Reply with quote

Use a printf statement to a terminal window to trouble-shoot the
conversion. I don't have any suggestions beyond that.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 3:28 pm     Reply with quote

1 more thing, Now it acts like it is not getting re-programmed.
I changed the code to always to display the same number like this

tempnumber=ReadTempI2C(144);// address of MCP9801 ranges from 144 to 160
TC=tempnumber;
TC=99;
DisplayNumber(TC);

But it is still displaying to temp in C, Touching the sensor raises the temp a degree or 2 so it really is working, and ignoring the 99 thing. It programs and verifies which is the weird part. So either the compiler is ignoring the 99 line, or the pic is not really getting programmed. has anybody ever seen anything like this?

Ringo
_________________
Ringo Davis
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 3:54 pm     Reply with quote

Code:
void DisplayNumber(int Num)
The variable Num is never used in DisplayNumber. So whatever value you pass to DisplayNumber, it doesn't matter... Cool
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 3:57 pm     Reply with quote

One of the points no clear from your post is, if you also tried the C/F conversion in a minimal application, without the sensor control and the display routine? If the problem still persists, then it's proven related to the said conversion.

I just saw, that the conversion expression works well - standalone and compiled with a recent PCM version.

P.S.:
Quote:
The variable Num is never used in DisplayNumber
Something similar could be expected.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 4:00 pm     Reply with quote

Quote:

The variable Num is never used in DisplayNumber. So whatever value
you pass to DisplayNumber, it doesn't matter...

That means that this statement was in error:
Quote:
I've got a routine to test the display and it works fine.


This means I am proven right. Mr. Green
My "strict regime" of testing would have found this problem (if followed).
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 4:10 pm     Reply with quote

Quote:
That means that this statement was in error
Could be determined, if we see the test. There is a certain chance to produce a false positive result by accidentally getting the source variable overlaid with the unconnected subroutine variable. But systematic test is the right way though.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Apr 26, 2009 4:17 pm     Reply with quote

Just a few other notes on the code:
- Next time post a small as possible program demonstrating your problem, it will get you more, quicker and better responses. The program as posted has 81 lines with code commented out...
- Don't start variable names with an '_' character. Somewhere in the C standards it is described that these variable names are reserved for compiler internal usage only.
- port_b for a PIC16 is not located at 0xF81.
- The CCS compiler by default handles the TRIS register settings for you, unless you set the #use fast_io directive. You don't have this directive set so you might corrupt the compiler's TRIS management and at least are generating extra code. I suggest you remove all TRIS related code.
- The function toggle_led can be replaced by the more efficient CCS function output_toggle.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Mon Apr 27, 2009 10:55 am     Reply with quote

I found the problem.
In DisplayNumber I'm passing in Num but using Number in the calculations. Number was never initialized to anything.
The weird part is I put a test at the top of the code, just a for loop to count from 1 to 255 and it works.
The other code worked unless I did the C to F conversion, so I'm assuming what was happening was the number in the for loop, or the C value was either in the Working register, or on the stack or something and the un-initialized "number" picked up that value. However doing the conversion screwed that up. I would have thought "number" would always be a random value, but in this case it almost worked. Of course the day after I called the project done it probably would have started being random :-)

Thanks
Ringo
_________________
Ringo Davis
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Apr 27, 2009 4:43 pm     Reply with quote

Ringo42 wrote:
I found the problem.
In DisplayNumber I'm passing in Num but using Number in the calculations. Number was never initialized to anything.

Eh, yes. That's what I said too.

Ringo42 wrote:
The weird part is I put a test at the top of the code, just a for loop to count from 1 to 255 and it works.
The other code worked unless I did the C to F conversion, so I'm assuming what was happening was the number in the for loop, or the C value was either in the Working register, or on the stack or something and the un-initialized "number" picked up that value.
The same conclusion as FvM.

Glad to hear your problem is solved.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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