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 support@ccsinfo.com

Read-value from i2c-bus is always 255.

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



Joined: 02 Apr 2004
Posts: 15

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

Read-value from i2c-bus is always 255.
PostPosted: Tue Apr 13, 2004 12:34 pm     Reply with quote

Hi.

I am using an A/D converter (Philips PCF8591) with a i2c-bus to give input to my 16F84A. I have 2.2k ohm resistors between the bus and the +5V.

However, no matter what I try, I just get the value FF (255) out of the i2c-bus.
I am not good at C-programming, but the rest of the code seems to be working, so I don't think I have done everything wrong. I have tried everything, but it just is not working. I keep getting the value 255 out of the i2c bus.

Does anybody have any idea what can be wrong?

The code does not look very good, I know, but here it is anyway:
Code:

#include "16F84.h"
#use delay(clock = 4000000)
#use i2c(MASTER, Slow, SCL=PIN_B5, SDA=PIN_B4)
int biff1;

void main( void)
{
biff1 = 0;
output_bit(PIN_B0,0);
output_bit(PIN_B1,0);
output_bit(PIN_B2,0);

i2c_start();
i2c_write(0b10011111);
i2c_write(0x00);
i2c_stop();
set_TRIS_B(0b11001000);  /* RB0 - RB2 out, R34 in    */

   while(1)
   {           
      while(input(PIN_B3) == 1)
      {
         output_bit(PIN_B0,1);
         delay_ms(300);
         output_bit(PIN_B0,0);
         delay_ms(300);
      }                     
      while(input(PIN_B3) == 0)
      {
         output_bit(PIN_B0,0);
         output_bit(PIN_B1,0);      
         output_bit(PIN_B2,0);
         delay_ms(500);

         i2c_start();
         i2c_write(0b10011111);    
         biff1 = i2c_read(0);
         i2c_stop();
         delay_ms(500);

         if(biff1 < 7)
         {
            output_bit(PIN_B0,1);
            output_bit(PIN_B1,0);      
            output_bit(PIN_B2,0);
            delay_ms(1000);
         }
         if ((biff1 < 200) && (biff1 > 6))
         {
            output_bit(PIN_B0,0);
            output_bit(PIN_B1,1);      
            output_bit(PIN_B2,0);
            delay_ms(1000);
         }         
         if (biff1 > 199)
         {
            output_bit(PIN_B0,0);
            output_bit(PIN_B1,0);      
            output_bit(PIN_B2,1);
            delay_ms(1000);
         }

      }
   }
}

All the code I have written is just to test the read-value from the A/D converter, as you can see. When I change the conditions, it turns out that the value I get is always 255, and I am clueless... Embarassed

I would be thankful for any suggestions.
Thx
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 13, 2004 5:47 pm     Reply with quote

The problem is that you are not using the proper
method to send commands to the chip. I don't
have time to write you a driver.
Peter Anderson has some code here. At the end
of the code, you'll find his routine to read the A/D.
http://www.phanderson.com/PIC/PICC/CCS_PCM/8591.html
His routines have much more low-level code than
you really need when using CCS. He manually
does ACK, etc. That's built-in to the CCS i2c functions.
So it would take a little work to convert his code
to CCS. Not much, but I don't have time to do it,
and I have no chip to test it with.

A few other comments:

Your main problem (as stated) is that you cannot read the
A/D converter. Your program (as posted) contains lots of
code that has nothing to do with getting the A/D chip working.
You should cut that code out. Just make a test program
for the A/D chip. Keep it as minimal as possible.

Your Device Select bits in the PCF8591 address byte are set
to all ones. That means that you must have pins 5, 6, and 7
connected to Vdd (same voltage as pin 16). Do you have that ?
Normally, people connect the address pins to Ground, on chips
like this. Then the device address bits become 0's in the address
byte. It's easier to use. For example, the i2c write address
becomes 0x90 (you don't have to use binary to write it out
in your code). The read address becomes 0x91.

Another point is that the data sheet says when you use the
internal oscillator, the EXT pin (pin 12) must be connected to Ground.
Do you have that done ?

This is not the easiest chip for a newbie to use. It's not a terrible
chip, but there are a reasonable number of details to watch.
Converting Anderson's code may be too difficult for you.
I don't know. You'll have to try it.
Guest








PostPosted: Tue Apr 13, 2004 6:36 pm     Reply with quote

As a starting point, like the following. EXT tied to ground.

Code:

#include <16F84.h>
#use delay(clock = 4000000)
#use i2c(MASTER,SCL=PIN_B5,SDA=PIN_B4)

// Addresses with address pins A2,A1 and A0 tied to ground
#define PCF8591_ADD_W 0x90 // i2c write address
#define PCF8591_ADD_R 0x91 // i2c read address
#define CNTL 0x44          // Control byte, four single ended inputs, auto increment

int8 biff1;

void main( void)
{
   // Using software i2c so have to float the SCL and SDA lines
   output_float(PIN_B5);
   output_float(PIN_B4);
   delay_ms(100);          // Allow time to settle
     
   i2c_start();
   i2c_write(PCF8591_ADD_W);
   i2c_write(CNTL);        // Send control byte
   i2c_write(0);           // Dac byte
   i2c_stop();


   while(1)
   {           
      i2c_start();
      i2c_write(PCF8591_ADD_R);   
      biff1 = i2c_read(0);       // 1st byte is last byte so NACK
      i2c_stop();
      etc

Guest








PostPosted: Tue Apr 13, 2004 7:36 pm     Reply with quote

I forgot to also mention that the analog to digital converter needs a reference voltage. Connect Vref (pin 14) to Vdd (pin 16). Also AGND (pin 13) to Vss (pin 8).
Later you may like to use a more stable reference than the power supply voltage.
Guest








Still no solution...
PostPosted: Wed Apr 14, 2004 8:33 am     Reply with quote

Hi.

Thx guys for your help.
Unfortunately nothing of what you have said helps me at all.
I must have missed something fundamental.

What really freaks me out now, is that as soon as the voltage on the analogue input gets below a certain value, everything hangs. I have some blinking LEDs on three of the pins on the 16f84 like in the code above, just to check out if it is awake or not (and to get an idea of what the value from the PCF8591 might be), and as soon as the analogue input voltage gets below 2.9 V, the LEDs stop blinking, and no more input is possible.
Has anybody heard of anything like this?

The PCF8591 is cabled as follows:

pin 01 analogue input
pin 02 ground
pin 03 ground
pin 04 ground
pin 05 ground
pin 06 ground
pin 07 ground
pin 08 ground
pin 09 SDA => also connected with a 2.2k ohm to VDD
pin 10 SCL => also connected with a 2.2k ohm to VDD
pin 11 -------- (nothing)
pin 12 ground (EXT)
pin 13 ground (AGND)
pin 14 VDD (Vref)
pin 15 -------- (nothing)
pin 16 VDD

Now, since I followed your advice, the value I get from the PCF8591 is not FF anymore, but a value between 70 and 185.
SteveS



Joined: 27 Oct 2003
Posts: 126

View user's profile Send private message

PostPosted: Wed Apr 14, 2004 8:44 am     Reply with quote

Quote:
as soon as the analogue input voltage gets below 2.9 V, the LEDs stop blinking, and no more input is possible.


Sounds like the LED and/or PIC power may be tied to the analog input somehow?
guest
Guest







init I2C
PostPosted: Wed Apr 14, 2004 2:21 pm     Reply with quote

at initialize

void main() {

SSPADD=4; //I2C frequency=20Mhz / (4x(SSPADD+1))
SSPCON1=0x28; //start I2C
..
..
..
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

PostPosted: Wed Apr 14, 2004 2:37 pm     Reply with quote

it's likely you are getting the last conversion result, not
the current one. see the example below, but note that
is not a full fledged library so you'll need to go read the
datasheet (again). note that in this example you'll need
to fix up the device addressing statements.

regards,
jds

Code:


////   Routines for the Philips PCF8591 8 bit A/D & D/A chip
////   (c) j.d.s. 1998
////   read_ad_4sing(n);   for 4 single ended inputs
////   set_da();      set the value of the 8 bit d/a port


void   pcf8591_set_da(int data)
   {
   i2c_start();
   i2c_write(0b10010010);      /*  a/d i2c address is 1, mode is write */
   i2c_write(0b01000000);      /*  control byte for enabling analog output */
   i2c_write(data);      /*  this is the d/a output value  */
   i2c_stop();
   }

int   pcf8591_read_ad_4sing(int input_id)   /*  0 <= input_id <= 3  */
   {
   int ad_result;
   i2c_start();
   i2c_write(0b10010010);      /*  a/d i2c address is 1, mode is write */
   i2c_write(0b01000000 | (input_id & 0b00000011);   /*  control byte for setting up inputs  */
   i2c_stop();         /*  terminate the write  */
   i2c_start();
   i2c_write(0b10010011);      /*  a/d i2c address is 1, mode is read  */
   ad_result = i2c_read();      /*  this byte contains the last conversion result.  */
   ad_result = i2c_read(0);   /*  this byte is real data  */
   i2c_stop();

   return(ad_result);
   }
Wridmuld



Joined: 02 Apr 2004
Posts: 15

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

PostPosted: Thu Apr 15, 2004 5:36 am     Reply with quote

I have read and tried everything you guys have been posting, but it still is not working.

I now have to sort out the different pieces of this project to be able to find the error. I suspect there might be more than one error, but it is really hard to find the source of the strange read-values.

1 - Both Guest and jds-pic writes that the second byte send to the PCF8591 should look like this: 0b0100yyyy. What does that 4 mean? The PCF8591 datasheet says that this is the Analogue Output Enable Flag. (Analogue output active if 1). Now this is not what I am trying to do - or have I misunderstood the meaning of this? I am not going to OUTPUT analogue data, I am going to retrieve analogue data and convert it do digital.
So as I understand it, this should be 0b00000000.
I want to take an analogue value from the PCF8591 and convert it to digital values. I am only using AIN0, and so I do not want any autoincrement (at least not till I get this working), and I want the analogue input to be single-ended.
So - why this 4?


2 - Guest is writing:
Quote:
at initialize

void main() {

SSPADD=4; //I2C frequency=20Mhz / (4x(SSPADD+1))
SSPCON1=0x28; //start I2C
..
..
..


I do not find the SSPADD command anywhere in the CCS Compiler Reference Manual, and the compiler does not understand it, so I get an error back. What does the SSPADD and SSPCON1 commands mean?
(see question 4 as well - it seems somehow to be related to this)


3 - Another question I got is how the frequenzy of the crystal connected to the 16F84A might be causing these problems. I am using a 4 MHz crystal for the 16F84A, but as I have understood it, the 20MHz is the maximum speed, and not a must. Am I wrong about this? All the other tests and programs I have made before I started trying the i2c out have been working excellent. Even the time is correct.


4 - What is the effect on the tris-register when I dedicate two I/O-ports to i2c? I am not sure whether to set these two ports as inputs or outputs when they are used by the i2c. Do the two i2c-ports on the 16F84A get affected in any way by the tris-register?


5 - I now get the value 128 (0x80) out of the i2c-bus. First I thought that I got the value from the previous cycle, but now throw the first two values away. This does not help, as I still get the value 128 out of it.

Here is the code now:


Code:
#include <16F84A.h>
#use delay(clock = 4000000)
#use i2c(MASTER,SCL=PIN_B5,SDA=PIN_B4)

// Addresses with address pins A2,A1 and A0 tied to ground
#define PCF8591_ADD_W 0x90 // i2c write address
#define PCF8591_ADD_R 0x91 // i2c read address
#define CNTL 0x00          // Control byte, four single ended inputs
            // I have tried the value 0x40 as well
int8 biff1;

void main( void)
{
   // set_TRIS_B(0b11001000);  /* RB0 - RB2 out, RB3 in. What about rb4 and rb5 ??  */

   // Using software i2c so have to float the SCL and SDA lines
   output_float(PIN_B5);
   output_float(PIN_B4);
   delay_ms(100);          // Allow time to settle

   i2c_start();
   i2c_write(PCF8591_ADD_W);
   i2c_write(CNTL);        // Send control byte
   i2c_stop();

   while(1)
   {   
         
      i2c_start();
      i2c_write(PCF8591_ADD_R);
      biff1 = i2c_read();      // Throw the first away
      biff1 = i2c_read();      // Throw away the second as well...
      biff1 = 0;                                  // Just to make sure I get a value out of the i2c bus.
      biff1 = i2c_read(0);
      i2c_stop();

      if(biff1 < 128)         // The code below is used to test the value I get from the PCF8591
      {
         output_bit(PIN_B0,1);
         output_bit(PIN_B1,0);
         output_bit(PIN_B2,0);
         delay_ms(500);
      }
      if ((biff1 > 127) && (biff1 < 129))   // it is now always 128 no matter how I change
      {                  // the input voltage
         output_bit(PIN_B0,0);
         output_bit(PIN_B1,1);
         output_bit(PIN_B2,0);
         delay_ms(500);
      }
      if (biff1 >128)
      {
         output_bit(PIN_B0,0);
         output_bit(PIN_B1,0);   
         output_bit(PIN_B2,1);
         delay_ms(500);
      }
   }
}


[/code]
Wridmuld



Joined: 02 Apr 2004
Posts: 15

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

PostPosted: Thu Apr 15, 2004 3:31 pm     Reply with quote

I would really like to know how the tris register is related to the i2c-bus defined I/Os. I do not know much about this.

/Wridmuld
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 15, 2004 3:51 pm     Reply with quote

Here is a very simple test program. I wrote it, based on
Peter Anderson's code, and also while consulting jds_pic's code.
I don't have a PCF8591 chip to test, so I don't know for sure
if it will work. But it's the type of ultra-simple test program
that you need to be using. I don't see that you have
RS-232 enabled. You should add it, so you can display
the results of this program. I have a printf statement
in the code below, but I commented it out, since you
don't have a #use rs232 statement.

With regard to TRIS, for the CCS software routines, you
set both pins as inputs. (Which you have done).

I suggest that you try this program with as few alterations
as possible.

Code:
#include <16F84A.h>
#use delay(clock = 4000000)
#use i2c(Master,SCL=PIN_B5,SDA=PIN_B4)

//----------------------------------------------
#define PCF8591_I2C_WRITE_ADDRESS  0x90
#define PCF8591_I2C_READ_ADDRESS   0x91

#define PCF8591_A2D_CONFIG  0x40     // Force internal osc to stay on

//----------------------------------------------
// FUNCTION PROTOTYPES
void init_pcf8591_ad(void);
char read_pcf8591_ad(void);

//============================================
main()
{
char result;

output_float(PIN_B5);
output_float(PIN_B4);

init_pcf8591_ad();

while(1)
  {
   result = read_pcf8591_ad();
//   printf("%x \n\r", result);
   delay_ms(500);
  }

}
//============================================

void init_pcf8591_ad(void)
{
i2c_start();
i2c_write(PCF8591_I2C_WRITE_ADDRESS);
i2c_write(PCF8591_A2D_CONFIG);   
i2c_write(0x00);        // Set D/A output to be 0          
i2c_stop();      
}

//--------------------------------------------
// This will read the channel that was set in the
// init routine above.   (ie., channel 0, as specified
// in the PCF8591_A2D_CONFIG constant).

char read_pcf8591_ad(void)
{
char retval;

i2c_start();
i2c_write(PCF8591_I2C_READ_ADDRESS);
i2c_read();                // Throw away the first byte
retval = i2c_read(0);      // No ACK on last read
i2c_stop();
}
Wridmuld



Joined: 02 Apr 2004
Posts: 15

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

PostPosted: Thu Apr 29, 2004 5:38 am     Reply with quote

Now it finally works.

The problem I had from the start was because I had not put resistors between BOTH the bus and the devices AND between the bus and Vcc.

Once I did that, using the table in the i2c manual from Phillips, it worked without a problem.

Thx guys for the help with your code.
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