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

I2C problem?

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



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

I2C problem?
PostPosted: Sun Dec 15, 2013 10:26 pm     Reply with quote

Hi,
I'm using PIC18LF2520, CCS 4.114

My program goes more than 1500 lines. Thats the reason i cannot post the file.

i2c reads wrong value.

in my program,

timer0 interrupt
incrementing a variable for every 1ms

timer1 interrupt
displaying seven segment display using timer1 for every 250us

main loop,
using mcp3421, reading the adc value and formula used to display the value from 0 to 9999.

When i use 2Mhz oscillator, everything works good.
But when i change the oscillator to 4Mhz, display values are wrong. I have set the timer values for 4Mhz.
Why is it so? timer1 executes very fast. will it creates the problem?
I have already test a sample program in reading only adc value using mcp3421. It was working good with 4Mhz during that time.
Why it is creating problem now?
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Mon Dec 16, 2013 2:08 am     Reply with quote

You need to learn to debug.

Start by getting the I2C working without the 1500 lines of other code.
Once it is working add back the other stuff 'section by section'. After each section is added test if the I2C goes wrong. When it does, you have identified the part where the problem appears.
temtronic



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

View user's profile Send private message

PostPosted: Mon Dec 16, 2013 6:30 am     Reply with quote

hmm.... displaying seven segment display using timer1 for every 250us

comment: are you using 4, seven segment displays to show your data and you're 'mulitplexing' them using the PIC as the controller?

if so, as Mr. T say, cut simpler code. Just the 'display' section,that you said worked at 2MHz and edit to run at 4MHz.

a description of the hardware would be very helpful but if you're using LED 7SDs, I suspect a 'timing' issue between muxing and updating the displays.

hth
jay
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Mon Dec 16, 2013 9:10 pm     Reply with quote

Thanks Ttelmah & temtronic,

I debug the code using pickit3.
I comment 250us interrupt routine, & read the adc value. Values are perfect.

then, i uncomment the 250us interrupt routine, now the adc value varies. sometimes, it reads 0, some other value, sometimes correct value.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Dec 17, 2013 2:56 am     Reply with quote

OK.
I'd be looking at an update problem. Something reading/writing a variable that is updated in the interrupt, or used in the interrupt. Remember that any variable that is more than 8bits, could be half updated when the interrupt occurs, which then would give screwy results.....

Best Wishes
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Sun Dec 22, 2013 9:38 pm     Reply with quote

thanks Ttelmah.
Interrupt occurs separately and displaying the value.

In the while loop only, i'm reading the adc value.

Then how to read 16 bit adc value without getting screwy results?

below is the function used to read adc value,
Code:
int16 get_adc()
{
   int16 upper, lower, config, ans; 
   
   i2c_start ();     
   i2c_write (0xD0);  // 1101 0000 -address byte write  (SELECT ADDRESS  A0  AND SET IN WRITE MODE) FOR MCP3421A0           
   i2c_write (0x88);  // ADC Gain 1
   
   i2c_stop();
   
   i2c_start ();     
   i2c_write (0xD1);  // 1101 0001 - CHANGE TO READ MODE  (ADDRESS A0)   FOR MCP3421A0     
   
   upper = i2c_read (1); // read slave data
   lower = i2c_read (1); // read slave data     
   config = i2c_read (0); // read slave data     
   i2c_stop ();
   
   ans =( upper * 256) + lower;
   
   if(ans>32767 )
   {
      ans=0;
   }   
   return ans;
}
alan



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

View user's profile Send private message

PostPosted: Mon Dec 23, 2013 12:11 am     Reply with quote

You will have to supply more data.

1) How are your chip setup, Continious conversion, no of bits?
2) How long do you spend in your interrupt routine? Possibly post code for the int.

Regards
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Mon Dec 23, 2013 2:11 am     Reply with quote

Yes.

'Occurs separately'. No it doesn't. If it is 'displaying the value', this has to come from somewhere.

Best Wishes
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Tue Dec 24, 2013 11:09 pm     Reply with quote

ADC value keeps on changing? below is the sample compiled code
Code:
#include "18F2520.h"
#fuses INTRC_IO
#use delay(clock = 4000000)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)

#use fixed_io(b_outputs= PIN_B3,PIN_B4,PIN_B5)

#define Digit1 PIN_B3
#define Digit2 PIN_B4     
#define Digit3 PIN_B5     
#define Digit4 PIN_C0   


const unsigned char CA_LED[37][8] = {
   // 0 - indicates ON, 1 - indicates OFF
//      a,   b   ,  c,    d,     e,   f,     g,   dp
   {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xFF, 0x7F},         //   0     
   {0xFF, 0xFD, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},         //   1 
   {0xFE, 0xFD, 0xFF, 0xF7, 0xEF, 0xFF, 0xBF, 0x7F},         //   2
   {0xFE, 0xFD, 0xFB, 0xF7, 0xFF, 0xFF, 0xBF, 0x7F},         //   3 
   {0xFF, 0xFD, 0xFB, 0xFF, 0xFF, 0xDF, 0xBF, 0x7F},         //   4   
   {0xFE, 0xFF, 0xFB, 0xF7, 0xFF, 0xDF, 0xBF, 0x7F},         //   5 
   {0xFE, 0xFF, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F},         //   6
   {0xFE, 0xFD, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},         //   7 
   {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F},         //   8 
   {0xFE, 0xFD, 0xFB, 0xFF, 0xFF, 0xDF, 0xBF, 0x7F},         //   9   
   {0xFE, 0xFD, 0xFB, 0xFF, 0xEF, 0xDF, 0xBF, 0x7F},      //   A
   {0xFF, 0xFF, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F},      //  b
   {0xFF, 0xFF, 0xFF, 0xF7, 0xEF, 0xFF, 0xBF, 0x7F},      //    c
   {0xFF, 0xFD, 0xFB, 0xF7, 0xEF, 0xFF, 0xBF, 0x7F},      //    d
   {0xFE, 0xFF, 0xFF, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F},      //   E
   {0xFE, 0xFF, 0xFF, 0xFF, 0xEF, 0xDF, 0xBF, 0x7F},      //   F
   {0xFE, 0xFD, 0xFB, 0xF7, 0xFF, 0xDF, 0xBF, 0x7F},      //   g
   {0xFF, 0xFD, 0xFB, 0xFF, 0xEF, 0xDF, 0xBF, 0x7F},      //   H
   {0xFF, 0xFD, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},         //   l
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},      //   J wrong value
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},      //   K wrong value
   {0xFF, 0xFF, 0xFF, 0xF7, 0xEF, 0xDF, 0xFF, 0x7F},      //   L
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},      //   M wrong value
   {0xFF, 0xFF, 0xFB, 0xFF, 0xEF, 0xFF, 0xBF, 0x7F},      //   n
   {0xFF, 0xFF, 0xFB, 0xF7, 0xEF, 0xFF, 0xBF, 0x7F},      //   o
   {0xFE, 0xFD, 0xFF, 0xFF, 0xEF, 0xDF, 0xBF, 0x7F},      //   P
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},      //   Q wrong value
   {0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xBF, 0x7F},      //   r
   {0xFE, 0xFF, 0xFB, 0xF7, 0xFF, 0xDF, 0xBF, 0x7F},         //   S
   {0xFF, 0xFF, 0xFF, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F},      //   t
   {0xFF, 0xFF, 0xFB, 0xF7, 0xEF, 0xFF, 0xFF, 0x7F},      //   u
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},      //   v wrong value
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},      //   w wrong value
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},      //   x wrong value
   {0xFF, 0xFD, 0xFB, 0xF7, 0xFF, 0xDF, 0xBF, 0x7F},      //   y
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F},      //   z wrong value
   {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}      //   No character
};

unsigned int16 digits[4];
unsigned int current_digit = 0;
unsigned int SEGMENT = 0;
int16 adc_value;
unsigned int Decimal_point_value = 0;
int1 decimal_point;

void value_with_decimal();

int16 variable;

#INT_TIMER1
void timer1_isr()
{
   if(interrupt_active(INT_TIMER1))
   {

      output_low(Digit4);
      output_b(0x00);
      output_a(0x00);


      variable++;
     
      switch(SEGMENT)
      {
         case 0: output_a(CA_LED[digits[current_digit]][0]);
               break;
         
         case 1: output_a(CA_LED[digits[current_digit]][1]);
               break;
         
         case 2: output_a(CA_LED[digits[current_digit]][2]);
               break;
         
         case 3: output_a(CA_LED[digits[current_digit]][3]);
               break;
         
         case 4: output_a(CA_LED[digits[current_digit]][4]);
               break;
         
         case 5: output_a(CA_LED[digits[current_digit]][5]);
               break;
         
         case 6: output_a(CA_LED[digits[current_digit]][6]);
               break;   
         
         case 7:
               if(decimal_point == 0)
               {         
                  output_a((CA_LED[digits[current_digit]][7]) | 0b11111111);  // for no decimal point selection
                  break;   
               }
               
               else if(decimal_point == 1)            // For decimal point selection
               {
                  output_a(CA_LED[digits[current_digit]][7]);
                  break;     
               }
      };
     
      if(SEGMENT++ == 8)
      {
         SEGMENT = 0;
         current_digit++;
      }
     
      value_with_decimal();
     
      if(current_digit > 3)
      {
         current_digit = 0;
      }
     
   set_timer1(0xFF05); // 250us
      clear_interrupt(INT_TIMER1);
   }
}

void timer1_init()
{
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);   // setup interrupts
   
   set_timer1(0xFF05);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   
}

int16 get_adc()
{
   int16 upper, lower, config, ans; 
   
   i2c_start ();     
   i2c_write (0xD0);  // 1101 0000 -address byte write  (SELECT ADDRESS  A0  AND SET IN WRITE MODE) FOR MCP3421A0           
   i2c_write (0x88);  // ADC Gain 1
   
   i2c_stop();
   
   i2c_start ();     
   i2c_write (0xD1);  // 1101 0001 - CHANGE TO READ MODE  (ADDRESS A0)   FOR MCP3421A0     
   
   upper = i2c_read (1); // read slave data
   lower = i2c_read (1); // read slave data     
   config = i2c_read (0); // read slave data     
   i2c_stop ();
   
   ans =( upper * 256) + lower;
   
   if(ans>32767 )
   {
      ans=0;
   }   
   return ans;
}


void main()
{

   set_Tris_a(0b00000000);
   set_Tris_b(0b00000111);
   

      output_low(Digit4);
      output_b(0x00);
      output_a(0x00);


   setup_comparator (NC_NC_NC_NC);
   
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF|ADC_TAD_MUL_0);

   timer1_init();      // Timer1 Initialization

   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

    decimal_point_value = 0;

      adc_value = get_adc();

   while(1)
   {
      adc_value = get_adc();

      digits[0] = (adc_value/1000)%10;   
      digits[1] = (adc_value/100)%10;
      digits[2] = (adc_value/10)%10;   
      digits[3] = (adc_value%10);   

      variable = 0;
      while(variable == 300);
      
   }
}

void value_with_decimal()
{
   if(decimal_point_value == 0)   // No Decimal Point
   {
      if(current_digit == 0)
      {
      output_high(DIGIT1); output_low(DIGIT2);output_low(DIGIT3);output_low(DIGIT4);   
         decimal_point = 0; 
      }
   
      if(current_digit == 1)      // for digit 2
      {     
      output_low(DIGIT1); output_high(DIGIT2);output_low(DIGIT3);output_low(DIGIT4);
         decimal_point = 0;
      }
     
      if(current_digit == 2)      // for digit 3
      {
      output_low(DIGIT1); output_low(DIGIT2);output_high(DIGIT3);output_low(DIGIT4);
         decimal_point = 0;           
      }
     
      if(current_digit == 3)      // for digit 4
      {
      output_low(DIGIT1); output_low(DIGIT2);output_low(DIGIT3);output_high(DIGIT4);
         decimal_point = 0;         
      }
   }
}
temtronic



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

View user's profile Send private message

PostPosted: Wed Dec 25, 2013 7:16 am     Reply with quote

comment: One thing I noticed is that you create a 16 bit adc value from the actual ADC chip (ans= 0 to 65536) but if >32767 you 0 it, so 32766 would be 'legal', yet your LED display can only display 0 to 9999. You're trying to display a 5 digit result on a 4 digit display.

For debugging purposes you should take the ADC result and send it to a PC using a serial link. That will show whether the 'bad reading' is actually an analog problem (noise, wiring, etc.) or digital (logic or code).

hth
jay
temtronic



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

View user's profile Send private message

PostPosted: Wed Dec 25, 2013 11:03 am     Reply with quote

comment: I've downloaded the MCP3421 datasheet and it appears you've got it configured for 16bit mode so data should be -32767 to 32767.
Still 32767 won't fit into 9999 unless I'm misreading something here.

Also 1 bit is 62uV ! Put a scope on the analog line and see how much NOISE you have, as well as the power supply lines. It is CRITICAL that proper anaolg PCB layouts are done, shielding, etc.

Again, dump the raw ADC data to a PC in terminal mode to see what the data is. Either you've got 'bad data' or 'bad conversion' of good data to the display.

hth
jay
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