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

Need help for i2c communication with FDC2214
Goto page 1, 2, 3, 4, 5  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ressas



Joined: 15 Nov 2019
Posts: 135

View user's profile Send private message

Need help for i2c communication with FDC2214
PostPosted: Tue Nov 19, 2019 12:39 am     Reply with quote

Hello to everyone. I am trying to communicate the PIC microcontroller with i2c with FDC2214 integrated. I need to set bit R / W = 1 to read. So I need to increase the address of the address by one: 0x2a + 1 = 0x2B.
However, the address 0x2B belongs to another register, so I can not communicate and constantly comes to 0XFF information. So I can't read, and probably not write. Any idea?
I have adapted the CCS C code from the Arduino code in this link:
https://github.com/zharijs/FDC2214
Code:

#include <18F46k22.h>
#device ADC=10
//#include <math.h>
//#INCLUDE <stdlib.h>

#fuses XT,NOWDT,NOBROWNOUT,NOPUT,NOWRT,NODEBUG,INTRC_IO, NOMCLR, NOPROTECT, NOWDT, NOLVP

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,sda=PIN_c4,scl=PIN_c3,fast=400000,FORCE_HW)
//#use i2c(Master,Fast,sda=PIN_c4,scl=PIN_c3,F,FORCE_HW)


#use fast_io(a)
#use fast_io(b)
#use standard_io(c)
#use fast_io(d)
#use fast_io(e)
//----------------------------------------------
// Address is 0x2A (default) or 0x2B (if ADDR is high)
#define FDC2214_I2C_ADDR_0   0x2A
#define FDC2214_I2C_ADDR_1   0x2B
//bitmasks
#define FDC2214_CH0_UNREADCONV 0x0008         //denotes unread CH0 reading in STATUS register
#define FDC2214_CH1_UNREADCONV 0x0004         //denotes unread CH1 reading in STATUS register
#define FDC2214_CH2_UNREADCONV 0x0002         //denotes unread CH2 reading in STATUS register
#define FDC2214_CH3_UNREADCONV 0x0001         //denotes unread CH3 reading in STATUS register
//registers
#define FDC2214_DEVICE_ID               0x7F
#define FDC2214_MUX_CONFIG              0x1B
#define FDC2214_CONFIG                  0x1A
#define FDC2214_RCOUNT_CH0              0x08
#define FDC2214_RCOUNT_CH1              0x09
#define FDC2214_RCOUNT_CH2              0x0A
#define FDC2214_RCOUNT_CH3              0x0B
#define FDC2214_OFFSET_CH0                0x0C
#define FDC2214_OFFSET_CH1              0x0D
#define FDC2214_OFFSET_CH2              0x0E
#define FDC2214_OFFSET_CH3              0x0F
#define FDC2214_SETTLECOUNT_CH0         0x10
#define FDC2214_SETTLECOUNT_CH1         0x11
#define FDC2214_SETTLECOUNT_CH2         0x12
#define FDC2214_SETTLECOUNT_CH3         0x13
#define FDC2214_CLOCK_DIVIDERS_CH0      0x14
#define FDC2214_CLOCK_DIVIDERS_CH1      0x15
#define FDC2214_CLOCK_DIVIDERS_CH2      0x16
#define FDC2214_CLOCK_DIVIDERS_CH3      0x17
#define FDC2214_STATUS                  0x18
#define FDC2214_DATA_CH0_MSB              0x00
#define FDC2214_DATA_CH0_LSB            0x01
#define FDC2214_DATA_CH1_MSB              0x02
#define FDC2214_DATA_CH1_LSB            0x03
#define FDC2214_DATA_CH2_MSB              0x04
#define FDC2214_DATA_CH2_LSB            0x05
#define FDC2214_DATA_CH3_MSB              0x06
#define FDC2214_DATA_CH3_LSB            0x07
#define FDC2214_DRIVE_CH0               0x1E
#define FDC2214_DRIVE_CH1               0x1F
#define FDC2214_DRIVE_CH2               0x20
#define FDC2214_DRIVE_CH3               0x21

// mask for 28bit data to filter out flag bits
#define FDC2214_DATA_CHx_MASK_DATA          0x0FFF
#define FDC2214_DATA_CHx_MASK_ERRAW         0x1000
#define FDC2214_DATA_CHx_MASK_ERRWD         0x2000
//------------------------------------------------
#define CHAN_COUNT 4

unsigned int16 _i2caddr = FDC2214_I2C_ADDR_0;

int dec_hex(int zahl)
{
int einer,zehner,ergebnis;
ergebnis=0;
zehner=zahl/10;
einer=zahl-(zehner*10);
ergebnis=(zehner<<4)|einer;
return ergebnis;
}
void write16FDC(unsigned int16 address, unsigned int16 data) {
  //printf("write16FDC");
  i2c_start();
  i2c_write(_i2caddr);
  i2c_write(address & 0xff);
 
  i2c_write(data >>8);
  i2c_write(data);
  i2c_stop();
  delay_ms(11);
}
unsigned int16 read16FDC(unsigned int16 addresss) {
  unsigned int16 data;
  i2c_start();
  i2c_write(_i2caddr);
  i2c_write(addresss);
  i2c_start();
  i2c_write(_i2caddr);
  data = i2c_read();
  data<<=8;
  data |= i2c_read();
  i2c_stop();
  delay_ms(11);
  return data;
 
 
}



int1 FDC2214_begin(unsigned int8 chanMask, unsigned int8 autoscanSeq, unsigned int8 deglitchValue, int1 intOsc) {
 // Wire.begin();
 //printf("FDC2214_begin");
  delay_ms(1);
  int devId = read16FDC(FDC2214_DEVICE_ID);
 // putc(devId, HEX);
  dec_hex(devID);
  putc(devID);
  if (devId != 0x3054) {
    if (devId != 0x3055) {
      //two valid device ids for FDC2214 0x3054 and 0x3055
      return false;
    }
  }
  else
  //int devId =0x3054;*/
  putc(devID);
  return true;
}

void loadSettings(unsigned int8 chanMask, unsigned int8 autoscanSeq, unsigned int8 deglitchValue, unsigned int1 intOsc) {
  printf("loadSettings");

  if (intOsc) {
    write16FDC(FDC2214_CONFIG, 0x1C81);  //set config 0x1C81
  } else {
    write16FDC(FDC2214_CONFIG, 0x1E81);  //set config 0x1E81
  }
  //If channel 1 selected, init it..
  if (chanMask & 0x01) {
    //settle count maximized, slow application
    write16FDC(FDC2214_SETTLECOUNT_CH0, 0x6400); // 0x6400
    //rcount maximized for highest accuracy
    write16FDC(FDC2214_RCOUNT_CH0, 0xFFFF); //0xFFFF
    //no offset
    write16FDC(FDC2214_OFFSET_CH0, 0x0000);
    // Set clock dividers
    write16FDC(FDC2214_CLOCK_DIVIDERS_CH0, 0x2001); //0x2001
    //set drive register
    write16FDC(FDC2214_DRIVE_CH0, 0xF800); //0xF800
  }
  // Init chan2, if selected by channel init mask
  if (chanMask & 0x02) {
    write16FDC(FDC2214_SETTLECOUNT_CH1, 0x6400);
    write16FDC(FDC2214_RCOUNT_CH1, 0xFFFF);
    write16FDC(FDC2214_OFFSET_CH1, 0x0000);
    write16FDC(FDC2214_CLOCK_DIVIDERS_CH1, 0x2001);
    write16FDC(FDC2214_DRIVE_CH1, 0xF800);
  }
  if (chanMask & 0x04) {
    write16FDC(FDC2214_SETTLECOUNT_CH2, 0x6400);
    write16FDC(FDC2214_RCOUNT_CH2, 0xFFFF);
    write16FDC(FDC2214_OFFSET_CH2, 0x0000);
    write16FDC(FDC2214_CLOCK_DIVIDERS_CH2, 0x2001);
    write16FDC(FDC2214_DRIVE_CH2, 0xF800);
  }
  if (chanMask & 0x08) {
    write16FDC(FDC2214_SETTLECOUNT_CH3, 0x6400);
    write16FDC(FDC2214_RCOUNT_CH3, 0xFFFF);
    write16FDC(FDC2214_OFFSET_CH3, 0x0000);
    write16FDC(FDC2214_CLOCK_DIVIDERS_CH3, 0x2001);
    write16FDC(FDC2214_DRIVE_CH3, 0xF800);
  }
 
  unsigned int16 muxVal = 0x0208 | ( (unsigned int16)autoscanSeq << 13) | deglitchValue;
  //
 
  write16FDC(FDC2214_MUX_CONFIG, muxVal);  //set mux config for channels
}

unsigned int32 getReading28(unsigned int8 channel) {
//    Serial.println("getReading28");
  int timeout = 100;
  unsigned int32 reading = 0;
  unsigned long long fsensor = 0;
  int status = read16FDC(FDC2214_STATUS);
  unsigned int8 addressMSB;
  unsigned int8 addressLSB;
  unsigned int8 bitUnreadConv;
  switch (channel) {
    case 0:
      addressMSB = FDC2214_DATA_CH0_MSB;
      addressLSB = FDC2214_DATA_CH0_LSB;
      bitUnreadConv = FDC2214_CH0_UNREADCONV;
      break;
    case 1:
      addressMSB = FDC2214_DATA_CH1_MSB;
      addressLSB = FDC2214_DATA_CH1_LSB;
      bitUnreadConv = FDC2214_CH1_UNREADCONV;
      break;
    case 2:
      addressMSB = FDC2214_DATA_CH2_MSB;
      addressLSB = FDC2214_DATA_CH2_LSB;
      bitUnreadConv = FDC2214_CH2_UNREADCONV;
      break;
    case 3:
      addressMSB = FDC2214_DATA_CH3_MSB;
      addressLSB = FDC2214_DATA_CH3_LSB;
      bitUnreadConv = FDC2214_CH3_UNREADCONV;
      break;
    default: return 0;
  }

  while (timeout && !(status & bitUnreadConv)) {
    status = read16FDC(FDC2214_STATUS);
    timeout--;
  }
  if (timeout == 100) {
   
    reading = ((unsigned int32) read16FDC(addressMSB) & FDC2214_DATA_CHx_MASK_DATA) << 16;
    reading |= read16FDC(addressLSB);
    while (timeout && !(status & bitUnreadConv)) {
      status = read16FDC(FDC2214_STATUS);
      timeout--;
   //   PUTC(status);
    }
  }
  if (timeout) {
    //read the 28 bit result
    reading = ((unsigned int32) read16FDC(addressMSB) & FDC2214_DATA_CHx_MASK_DATA) << 16;
    reading |= read16FDC(addressLSB);
    return reading;
  } else {
    // Could not get data, chip readynes flag timeout
    return 0;
  }
}


void main() {
   set_tris_a(0x00);
   set_tris_b(0x00);
  // set_tris_c(0b10000000);
   set_tris_d(0x00);
   set_tris_e(0x00);
   
 /*  output_a(0x00);
   output_b(0x00);
   output_c(0x00);
   output_d(0x00);
   output_e(0x00);*/
    //  printf("test");

  int1 capOk = FDC2214_begin(0xF, 0x0006, 0x5, false); //setup all four channels, autoscan with 4 channels, deglitch at 10MHz, external oscillator

  if (capOk)
    printf("open");
  else
    printf("close");

while(true) {
//  Serial.println("Loop");
  //fdc_hazirmi();
  unsigned long capa[CHAN_COUNT]; // variable to store data from FDC
  for (int i = 0; i < CHAN_COUNT; i++) { // for each channel
    // ### read 28bit data
    capa[i] = getReading28(i); //
    // ### Transmit data to serial in simple format readable by SerialPlot application.
    puts(capa[i]);
   
   
    if (i < CHAN_COUNT - 1) printf(", ");
    else printf("-");
  }
 
  // No point in sleeping
  delay_ms(250);
  //printf("test");
 
}}
temtronic



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

View user's profile Send private message

PostPosted: Tue Nov 19, 2019 5:38 am     Reply with quote

comments / questions...

1st. Get rid of use fast_Io and set-tris lines of code. let the compiler handle that ! Too easy to wrongly configure I/O !
2nd what is the VDD voltage of the PIC ?
3rd with all I2C devices, you should copy/compile/run PCM P I2C scanner program located in the 'code library' forum. It'll confirm the PIC CAN communicate with the I2C device AND it's address !
4th 0x2A is the SEVEN bit address, which is 0x54 in 8 bit addressing. PCM P's pgm wil report 0x54. however the ardunio code requires 7 bit which always confuses me....
5th post a 'link' to the FDC22xxx device so we can get the datasheet.
6th if you're using a 'module' not just the 'chip', post a 'link' to that as well.

OK.....
this..
Quote:
// Address is 0x2A (default) or 0x2B (if ADDR is high)
#define FDC2214_I2C_ADDR_0 0x2A
#define FDC2214_I2C_ADDR_1 0x2B

change 0x2A to 0x54, and 0x2B to 0x55. CCS I2C routines use 8 bit address mode NOT 7 bit. You need to 'rotate left' 7 bit addresses to become 8 bit with embedded R/W bit.

also this..
Quote:
unsigned int16 _i2caddr = FDC2214_I2C_ADDR_0;

needs to be just 8 bit (1 byte) .
I use CHAR as I think that CHARacters go from 0 to 255. What it is, is an unsigned int8 bit value.


Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Tue Nov 19, 2019 2:08 pm     Reply with quote

and:
Code:

unsigned int16 read16FDC(unsigned int16 addresss) {
  unsigned int16 data;
  i2c_start();
  i2c_write(_i2caddr);
  i2c_write(addresss);
  i2c_start();
  i2c_write(_i2crdaddr); //this is the one place for the read address
  data = i2c_read();
  data<<=8;
  data |= i2c_read();
  i2c_stop();
  delay_ms(11);
  return data;
}


Don't confuse device addresses with register addresses.
It is the I2C device address that has to have 1 added to it. This is
not a register address.
ressas



Joined: 15 Nov 2019
Posts: 135

View user's profile Send private message

PostPosted: Tue Nov 19, 2019 3:01 pm     Reply with quote

Ttelmah wrote:
and:
Code:

unsigned int16 read16FDC(unsigned int16 addresss) {
  unsigned int16 data;
  i2c_start();
  i2c_write(_i2caddr);
  i2c_write(addresss);
  i2c_start();
  i2c_write(_i2crdaddr); //this is the one place for the read address
  data = i2c_read();
  data<<=8;
  data |= i2c_read();
  i2c_stop();
  delay_ms(11);
  return data;
}


Don't confuse device addresses with register addresses.
It is the I2C device address that has to have 1 added to it. This is
not a register address.


Burada yazan _i2crdaddr ifadesi zaten 0x2a ya eşit. yani cihaz adresi eksik değil. i2c_write(_i2caddr); ile cihaz adresini ekliyoruz.
ressas



Joined: 15 Nov 2019
Posts: 135

View user's profile Send private message

PostPosted: Tue Nov 19, 2019 3:12 pm     Reply with quote

temtronic wrote:
comments / questions...

1st. Get rid of use fast_Io and set-tris lines of code. let the compiler handle that ! Too easy to wrongly configure I/O !
2nd what is the VDD voltage of the PIC ?
3rd with all I2C devices, you should copy/compile/run PCM P I2C scanner program located in the 'code library' forum. It'll confirm the PIC CAN communicate with the I2C device AND it's address !
4th 0x2A is the SEVEN bit address, which is 0x54 in 8 bit addressing. PCM P's pgm wil report 0x54. however the ardunio code requires 7 bit which always confuses me....
5th post a 'link' to the FDC22xxx device so we can get the datasheet.
6th if you're using a 'module' not just the 'chip', post a 'link' to that as well.

OK.....
this..
Quote:
// Address is 0x2A (default) or 0x2B (if ADDR is high)
#define FDC2214_I2C_ADDR_0 0x2A
#define FDC2214_I2C_ADDR_1 0x2B

change 0x2A to 0x54, and 0x2B to 0x55. CCS I2C routines use 8 bit address mode NOT 7 bit. You need to 'rotate left' 7 bit addresses to become 8 bit with embedded R/W bit.

also this..
Quote:
unsigned int16 _i2caddr = FDC2214_I2C_ADDR_0;

needs to be just 8 bit (1 byte) .
I use CHAR as I think that CHARacters go from 0 to 255. What it is, is an unsigned int8 bit value.


Jay

1- Okay, I'il take that part
2-PIC 18F46K22 and supply voltage 5V
3- I do not understand what you mean here, please explain with code
4- In the datasheet, 0x54 does not pass, only 0x2a and 0x2b expressions. How do you get 0x54?
5- To reach the datashhet of any integrator, type the name of the integrator in google and type pdf. exm; "fdc2214 pdf"
http://www.ti.com/lit/gpn/fdc2212
6- Thanks for your help. I will be really grateful if my problem is solved
temtronic



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

View user's profile Send private message

PostPosted: Tue Nov 19, 2019 3:30 pm     Reply with quote

re: 2. You cannot connect a 5 volt PIC directly to a 3 volt peripheral.You need some kind of 'logic level conversion', or easier, just run the PIC at 3 volts.That PIC( my favourite) will run at 3 volts AND at high speed( not all will..)

re: 3 . In the 'code lbrary' there is a program called 'I2C Scanner'. It will show you the addesses of all I2C perhipherals connected to a PIC ! It should be run to confirm the PIC IS communicating with the I2C device. It will also show you the address. Ardunio's tend to use 7 bit device addressing, whereas CCS uses 8 bit device addresing.

re: 4 'Ardunio ' 7 bit address has to be left shifted 1 bit position to become CCS 8 bit addresses, so 0b00101010 becomes 0b01010100. 0x2A becomes 0x54. What's interesting is that all device registers contain 16 bit ( 2 byte) values and the default 'device address' is 0x3054. the LSB is 54 same as what I calculated.



I prefer to think in 8 bit addressing, the CCS standard, as most( all ?) all data transfers are 'byte' wide for I2C peripherals
ressas



Joined: 15 Nov 2019
Posts: 135

View user's profile Send private message

PostPosted: Tue Nov 19, 2019 5:24 pm     Reply with quote

temtronic wrote:
re: 2. You cannot connect a 5 volt PIC directly to a 3 volt peripheral.You need some kind of 'logic level conversion', or easier, just run the PIC at 3 volts.That PIC( my favourite) will run at 3 volts AND at high speed( not all will..)

re: 3 . In the 'code lbrary' there is a program called 'I2C Scanner'. It will show you the addesses of all I2C perhipherals connected to a PIC ! It should be run to confirm the PIC IS communicating with the I2C device. It will also show you the address. Ardunio's tend to use 7 bit device addressing, whereas CCS uses 8 bit device addresing.

re: 4 'Ardunio ' 7 bit address has to be left shifted 1 bit position to become CCS 8 bit addresses, so 0b00101010 becomes 0b01010100. 0x2A becomes 0x54. What's interesting is that all device registers contain 16 bit ( 2 byte) values and the default 'device address' is 0x3054. the LSB is 54 same as what I calculated.



I prefer to think in 8 bit addressing, the CCS standard, as most( all ?) all data transfers are 'byte' wide for I2C peripherals


As you said yes, I saw the value 0x54 using the i2c scanner. But even though I make the necessary changes, I still can't get results.

Code:

void write16FDC(unsigned int16 address, unsigned int16 data) {
  //printf("write16FDC");
  i2c_start();
  i2c_write(_i2caddr);
  i2c_write(address & 0xff);
 
  i2c_write(data >>8);
  i2c_write(data);
  i2c_stop();
  delay_ms(11);
}
unsigned int16 read16FDC(unsigned int16 addresss) {
  unsigned int16 data;
  i2c_start();
  i2c_write(_i2caddr);
  i2c_write(addresss);
  i2c_start();
  i2c_write(_i2caddr);
  data = i2c_read();
  data<<=8;
  data |= i2c_read();
  i2c_stop();
  delay_ms(11);
  return data;
 
}


I think there is a problem with the functions, I created this order with reference to page 22 of the datasheet. If that's okay, can you look at that page and tell me if I'm doing it right?
Secondly, should I only use 0x54 address in read operation or 0x2a instead of 0x2a in both read and write operations; Let me use my 0x54.
My time is really low. Thank you in advance for your help
temtronic



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

View user's profile Send private message

PostPosted: Tue Nov 19, 2019 6:45 pm     Reply with quote

Use 0x54 to write TO the device, and 0x55 to read FROM the device. CCS uses 8 bit combined 7 bit device address and a 1 bit R/*W .

Consider renaming some variables.
Something like 'dev_adrs' for the base address of the I2C device, then perhaps 'reg_adrs' for the 'registers' inside of the device. On pages 22-23 there's a 'register map', which shows what they are for.

These register addresses are only 8 bits( a byte) to taht variable should be an unsigned int8 not a 16 bit.

this line...
unsigned int16 read16FDC(unsigned int16 addresss) {
looks like one too many 's' in addresss.

Also it should be unsigned int8 ( value from 0x00 to 0xFF )


this...
data = i2c_read();
data<<=8;
data |= i2c_read();

could be recoded as

datahigh=i2c_read(); //get high byte of dataword
datalow=i2cr_ead(); //get low byte of dataword
data=make16(datahigh,datalow); //make a 16bit word from 2 bytes

While your code is probably correct, mine is easier to understand and might be faster or more efficent.

You should add //comments at the end of most lines of code. They 'cost' nothing but allow you and others to understand what you're trying to do.

Also I don't like the underscore for a variable name. It's hard for me to see. Maybe it's a proper C convention, but I was never taught C. So far I've spent 1/2 my 66 years cutting C code for PICs, so anything that makes it easier for me I do !

I'm sure others will help if they can

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 19, 2019 8:36 pm     Reply with quote

You need to make the corrections shown in bold below. These items
are shown in the following diagram in the FDC2214 data sheet on pg. 22:
Figure 17. I2C Read Register Sequence
Data sheet:
http://www.ti.com/lit/gpn/fdc2214
Quote:

unsigned int16 read16FDC(unsigned int8 addresss) {
unsigned int16 data;
i2c_start();
i2c_write(_i2caddr);
i2c_write(addresss);
i2c_start();
i2c_write(_i2caddr+1); // Set R/W bit = 1 to read bytes
data = i2c_read();
data<<=8;
data |= i2c_read(0); // 0 parameter means "NAK"
i2c_stop();
delay_ms(11);
return data;


}

Here is the link to the code for the i2c bus scanner program:
http://www.ccsinfo.com/forum/viewtopic.php?t=49713
ressas



Joined: 15 Nov 2019
Posts: 135

View user's profile Send private message

PostPosted: Wed Nov 20, 2019 4:17 am     Reply with quote

Thank you both for your help. Very Happy The program started running (successfully?). The only problem is that when I run the Arduino code in the Github link, the value I get for 4 channels is as follows;

Quote:
15502595, 15632122, 15254700, 15034835


But I get these values in ccs c code;
Quote:
20669 ,17646 ,-15545 ,-27884


I'm getting 2 bits missing and it comes in negative value as well.
1) How can negative values come after defining variables as unsigned int?
2) How do I get the missing two bits? Very Happy
temtronic



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

View user's profile Send private message

PostPosted: Wed Nov 20, 2019 5:28 am     Reply with quote

Please post your complete program. There are a LOT of 'setup' or 'configuration' bits that need to be seen.

Also,according to teh datasheet, a 12 bit result is stored as 16 bit and it must be rightshifted 4 bits BEFORE you use it.

It could be your print statement, hard to tell without seeing all your code.
So two possible answers as to why the numbers are different.

At least you're making PROGRESS !!!

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Wed Nov 20, 2019 7:08 am     Reply with quote

Two things:

1) Don't use terms like 'unsigned long'. The problem is thes change with
different processors. To define an Arduino 'unsigned long' on the PIC, you need
to use 'unsigned int32'. To make the variable explicitly 32bit.
Generally it is always better when writing code to use 'explicit' sizes,
not terms that may have different interpretation on different chips.
2) Defining a variable as 'signed' or 'unsigned', does not control how it is
printed. If you send an unsigned int32 to another program, or to 'printf',
it prints this how you tell it. So if using printf for example, it needs to use
%LU to print such a variable as an unsigned value. Sounds to me as if your
output is incorrectly using %LD (which will assume the value to be 'signed').
ressas



Joined: 15 Nov 2019
Posts: 135

View user's profile Send private message

PostPosted: Wed Nov 20, 2019 7:46 am     Reply with quote

This code was created with the contributions of "temtronic" and "PCM programmer"
Code:

This code was created with the contributions of  "temtronic" and "PCM programmer"
// (?) I'm not sure about the explanations with this mark

#include <18F46k22.h>
#device ADC=10
#INCLUDE <stdlib.h> //Required to send make16()
#fuses XT,NOWDT,NOBROWNOUT,NOPUT,NOWRT,NODEBUG,INTRC_IO, NOMCLR, NOPROTECT, NOWDT, NOLVP

#use delay(clock=4000000) //When you do 8, 16 or 32 you do not get a result
#use  rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,sda=PIN_c4,scl=PIN_c3,slow=400000,FORCE_HW)
//----------------------------------------------

///////////////////fdc221 datasheet page 22///////////////////////

// Address is 0x2A = 0x54 (default) or 0x2B = 0x55 (if ADDR is high)
#define FDC2214_I2C_ADDR_0   0x54
#define FDC2214_I2C_ADDR_1   0x55
//bitmasks
#define FDC2214_CH0_UNREADCONV 0x0008         //denotes unread CH0 reading in STATUS register
#define FDC2214_CH1_UNREADCONV 0x0004         //denotes unread CH1 reading in STATUS register
#define FDC2214_CH2_UNREADCONV 0x0002         //denotes unread CH2 reading in STATUS register
#define FDC2214_CH3_UNREADCONV 0x0001         //denotes unread CH3 reading in STATUS register
//registers
#define FDC2214_DEVICE_ID               0x7F
#define FDC2214_MUX_CONFIG              0x1B
#define FDC2214_CONFIG                  0x1A
#define FDC2214_RCOUNT_CH0              0x08
#define FDC2214_RCOUNT_CH1              0x09
#define FDC2214_RCOUNT_CH2              0x0A
#define FDC2214_RCOUNT_CH3              0x0B
#define FDC2214_OFFSET_CH0                0x0C
#define FDC2214_OFFSET_CH1              0x0D
#define FDC2214_OFFSET_CH2              0x0E
#define FDC2214_OFFSET_CH3              0x0F
#define FDC2214_SETTLECOUNT_CH0         0x10
#define FDC2214_SETTLECOUNT_CH1         0x11
#define FDC2214_SETTLECOUNT_CH2         0x12
#define FDC2214_SETTLECOUNT_CH3         0x13
#define FDC2214_CLOCK_DIVIDERS_CH0      0x14
#define FDC2214_CLOCK_DIVIDERS_CH1      0x15
#define FDC2214_CLOCK_DIVIDERS_CH2      0x16
#define FDC2214_CLOCK_DIVIDERS_CH3      0x17
#define FDC2214_STATUS                  0x18
#define FDC2214_DATA_CH0_MSB              0x00
#define FDC2214_DATA_CH0_LSB            0x01
#define FDC2214_DATA_CH1_MSB              0x02
#define FDC2214_DATA_CH1_LSB            0x03
#define FDC2214_DATA_CH2_MSB              0x04
#define FDC2214_DATA_CH2_LSB            0x05
#define FDC2214_DATA_CH3_MSB              0x06
#define FDC2214_DATA_CH3_LSB            0x07
#define FDC2214_DRIVE_CH0               0x1E
#define FDC2214_DRIVE_CH1               0x1F
#define FDC2214_DRIVE_CH2               0x20
#define FDC2214_DRIVE_CH3               0x21
// mask for 28bit data to filter out flag bits
#define FDC2214_DATA_CHx_MASK_DATA          0x0FFF
#define FDC2214_DATA_CHx_MASK_ERRAW         0x1000
#define FDC2214_DATA_CHx_MASK_ERRWD         0x2000
//------------------------------------------------
///////////////////////////////////////////////////////////////////
#define CHAN_COUNT 4 // channel number

char dev_adds = FDC2214_I2C_ADDR_0; //dev_adds = 0x54

// fdc2214 datasheet steps on page 22 followed
void write16FDC(unsigned int16 address, unsigned int16 data) {
 
  i2c_start();
  i2c_write(dev_adds);         //first, sending integrated address
  i2c_write(address & 0xff);   //secondly, sending register address
                       // (?) Masked with 0xff, to ensure that 8 bits are sent
  i2c_write(data >>8); //i2c communicates with 8 bits. But data = 16 bits.
                       //so we're shifting
  i2c_write(data);
                       //other 8 bits
  i2c_stop();
}
// fdc2214 datasheet steps on page 22 followed
unsigned int16 read16FDC(char address) {
   unsigned int16 data;
   i2c_start();
   i2c_write(dev_adds);
   i2c_write(address);
   i2c_start();
   i2c_write(dev_adds + 1);           // Set R/W bit = 1 to read bytes
   char datahigh=i2c_read(); //two pieces made from 8 bits to 16 bits
   char datalow=i2c_read(0);
   data=make16(datahigh,datalow);
   i2c_stop();
   return data;
}
///////////////////////////////////////////////////////////////////////////////
void loadSettings(char chanMask, char autoscanSeq, char deglitchValue,  int1 intOsc);

int1 FDC2214_begin(char chanMask,char autoscanSeq, char deglitchValue, int1 intOsc) {

  printf("FDC2214_begin");
  int devId = read16FDC(FDC2214_DEVICE_ID);
  //Checking the lighting of the device on the i2c line (sda, scl).
  //If the values 0x3054 and 0x3055 are displayed; connected to the correct device
  if (devId != 0x3054) {
    if (devId != 0x3055) {
      //two valid device ids for FDC2214 0x3054 and 0x3055
      return false;
    }
  }
  loadSettings(chanMask, autoscanSeq, deglitchValue, intOsc);

  return true;
}
///////////////////////////////////////////////////////////////////////////////
void loadSettings(char chanMask, char autoscanSeq, char deglitchValue, int1 intOsc) {
  //Adjusting configuration settings
  // When the FDC powers up, it enters into Sleep Mode and will wait for configuration.
  //Once the device is configured, exit Sleep Mode by setting CONFIG.
  printf("loadSettings");
  if (intOsc) {
    write16FDC(FDC2214_CONFIG, 0x1C81); //set config 0x1C81
    printf("0x1C81");
  } else {
    write16FDC(FDC2214_CONFIG, 0x1E81);  //set config 0x1E81
    printf("0x1E81");
  }
  //FDC2214 HAVE 4 CHANNEL
  //We make configuration settings for each channel.
  //If channel 1 selected, init it..
  if (chanMask & 0x01) {
    //settle count maximized, slow application
    write16FDC(FDC2214_SETTLECOUNT_CH0, 0x6400); // 0x6400
    //rcount maximized for highest accuracy
    write16FDC(FDC2214_RCOUNT_CH0, 0xFFFF); //0xFFFF
    //no offset
    write16FDC(FDC2214_OFFSET_CH0, 0x0000);
    // Set clock dividers
    write16FDC(FDC2214_CLOCK_DIVIDERS_CH0, 0x2001); //0x2001
    //set drive register
    write16FDC(FDC2214_DRIVE_CH0, 0xF800); //0xF800
  }
  // Init chan2, if selected by channel init mask
  if (chanMask & 0x02) {
    write16FDC(FDC2214_SETTLECOUNT_CH1, 0x6400);
    write16FDC(FDC2214_RCOUNT_CH1, 0xFFFF);
    write16FDC(FDC2214_OFFSET_CH1, 0x0000);
    write16FDC(FDC2214_CLOCK_DIVIDERS_CH1, 0x2001);
    write16FDC(FDC2214_DRIVE_CH1, 0xF800);
  }
  if (chanMask & 0x04) {
    write16FDC(FDC2214_SETTLECOUNT_CH2, 0x6400);
    write16FDC(FDC2214_RCOUNT_CH2, 0xFFFF);
    write16FDC(FDC2214_OFFSET_CH2, 0x0000);
    write16FDC(FDC2214_CLOCK_DIVIDERS_CH2, 0x2001);
    write16FDC(FDC2214_DRIVE_CH2, 0xF800);
  }
  if (chanMask & 0x08) {
    write16FDC(FDC2214_SETTLECOUNT_CH3, 0x6400);
    write16FDC(FDC2214_RCOUNT_CH3, 0xFFFF);
    write16FDC(FDC2214_OFFSET_CH3, 0x0000);
    write16FDC(FDC2214_CLOCK_DIVIDERS_CH3, 0x2001);
    write16FDC(FDC2214_DRIVE_CH3, 0xF800);
  }
  /////////////////////////////////////////////////////////////////////////////
  unsigned int16 muxVal = 0x0208 | ( (unsigned int16)autoscanSeq << 13) | deglitchValue;
  //(?) I have no idea what's going on here.
 
  write16FDC(FDC2214_MUX_CONFIG, muxVal);  //set mux config for channels
}

unsigned int32 getReading28(char channel) {
//    Serial.println("getReading28");
  int timeout = 100;
  unsigned int32 reading = 0;
  int status = read16FDC(FDC2214_STATUS);
  char addressMSB;
  char addressLSB;
  char bitUnreadConv;
  // Set to channel selection, we match registers with variables.
  switch (channel) {
    case 0:
      addressMSB = FDC2214_DATA_CH0_MSB;
      addressLSB = FDC2214_DATA_CH0_LSB;
      bitUnreadConv = FDC2214_CH0_UNREADCONV;
      break;
    case 1:
      addressMSB = FDC2214_DATA_CH1_MSB;
      addressLSB = FDC2214_DATA_CH1_LSB;
      bitUnreadConv = FDC2214_CH1_UNREADCONV;
      break;
    case 2:
      addressMSB = FDC2214_DATA_CH2_MSB;
      addressLSB = FDC2214_DATA_CH2_LSB;
      bitUnreadConv = FDC2214_CH2_UNREADCONV;
      break;
    case 3:
      addressMSB = FDC2214_DATA_CH3_MSB;
      addressLSB = FDC2214_DATA_CH3_LSB;
      bitUnreadConv = FDC2214_CH3_UNREADCONV;
      break;
    default: return 0;
  }
  //(?)
  while (timeout && !(status & bitUnreadConv)) {
    status = read16FDC(FDC2214_STATUS);
    timeout--;
  }
  if (timeout == 100) {
   
    reading = ((unsigned int32) read16FDC(addressMSB) & FDC2214_DATA_CHx_MASK_DATA) << 16;
    reading |= read16FDC(addressLSB);
    while (timeout && !(status & bitUnreadConv)) {
      status = read16FDC(FDC2214_STATUS);
      timeout--;
   //   PUTC(status);
    }
  }
  if (timeout) {
    //read the 28 bit result
    reading = ((unsigned int32) read16FDC(addressMSB) & FDC2214_DATA_CHx_MASK_DATA) << 16;
    reading |= read16FDC(addressLSB);
    return reading;
  } else {
    // Could not get data, chip readynes flag timeout
    return 0;
  }
}
///////////////////////////////////////////////////////////////////////////////
void main() {

  setup_oscillator(OSC_4MHZ|OSC_INTRC|OSC_PLL_ON);   
  delay_ms(10000); // this not necessary
  int1 capOk = FDC2214_begin(0xF, 0x0006, 0x5, true); //again config
//setup all four channels, autoscan with 4 channels, deglitch at 10MHz, external oscillator

  if (capOk) //we check whether it is connected
    printf("open");
  else
    printf("close");

while(true) {
  unsigned long capa[CHAN_COUNT]; // variable to store data from FDC
  for (int i = 0; i < CHAN_COUNT; i++) { // for each channel
    // ### read 28bit data
    // getReading28(reading);
    capa[i] = getReading28(i); //
    // ### Transmit data to serial in simple format readable by SerialPlot application.
    printf("%ld ",capa[i]);
    if(i==3) // printing the data we read to the bottom line   
    {
    printf("\n");
    }
    if (i < CHAN_COUNT - 1) printf(",");
    else printf("");
  }
  delay_ms(1000);
 
}}



We read from the serial port;
CCS C OUTPUT
Quote:


FDC2214_begin loadSettings 0x1C81 open
3426 ,-148 ,-5786 ,-17812
28223 ,26607 ,-8297 ,-20527
28235 ,26884 ,-8716 ,-20507
28116 ,26805 ,-8156 ,-20576
28421 ,26542 ,-8446 ,-20515
28321 ,27069 ,-7972 ,-20562
-7314 ,27396 ,-7253 ,-19059
-20984 ,26919 ,-7817 ,-21073
-32284 ,25817 ,-8841 ,-21733
-30604 ,25718 ,-8989 ,-21216
17385 ,24943 ,-9273 ,-20293
23274 ,25916 ,-8021 ,-19052
5320 ,25376 ,-8304 ,-20791
28522 ,24687 ,-8823 ,-19511
17437 ,22048 ,-7924 ,-21275
-11747 ,22397 ,-7785 ,-20986

each column represents a channel
see first line (left)
When we approach the electrode hand values are negative.
away, it gets better again. But extremely unstable
But I want it to be like this.
ARDUINO OUTPUT
Quote:


FDC2x1x test
Sensor OK
15505207, 15639900, 15257648, 15034281
15505109, 15639906, 15257629, 15034366
15504176, 15639765, 15257786, 15034380
15496631, 15639253, 15257655, 15034409
15345778, 15639432, 15257666, 15034431
15238407, 15638988, 15257743, 15034437
14955764, 15638206, 15257706, 15034025
14808308, 15638596, 15257845, 15033939
14791355, 15638333, 15257801, 15033861
15047970, 15638898, 15257308, 15034025
15388414, 15638882, 15257315, 15034124
15504363, 15639507, 15257424, 15034181


Github: https://github.com/zharijs/FDC2214
The results you see here belong to the github arduino code. The resolution value is very high and stable and no interference
I want to get an output like this
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 20, 2019 8:04 am     Reply with quote

Did you read Ttelmah's post ? You are reading an unsigned int32,
but you're putting it into an unsigned int16 array. See below in bold.
ressas wrote:

unsigned int32 getReading28(char channel) {
.
.
.
return reading;
}

unsigned long capa[CHAN_COUNT]; // variable to store data from FDC

capa[i] = getReading28(i);



Again, did you read Ttelmah's post ? In the printf below you are using
"%ld", which is for signed numbers. He told you to use "%lu".
ressas wrote:

printf("%ld ",capa[i]);
ressas



Joined: 15 Nov 2019
Posts: 135

View user's profile Send private message

PostPosted: Wed Nov 20, 2019 8:11 am     Reply with quote

thank you soo much,
data improved ELHAMDÜLİLLAH
Very Happy
Quote:

17:02:48.451 -> 14344019,14836662,14469903,14257900
17:02:48.794 -> 14323142,14836626,14471291,14261382
17:02:49.135 -> 14701915,14836605,14471031,14261227
17:02:49.438 -> 14595591,14836249,14471284,14261085
17:02:49.815 -> 14170835,14836270,14471156,14261172
17:02:50.122 -> 13968915,14835509,14470934,14257636
17:02:50.465 -> 13967938,14835581,14470969,14261248
17:02:50.774 -> 13952396,14836057,14470173,14261570
17:02:51.120 -> 13949209,14835978,14471156,14261099
17:02:51.462 -> 14504624,14835659,14470340,14260271
17:02:51.806 -> 14556380,14836284,14471325,14259846
17:02:52.117 -> 14581438,14835709,14471003,14260056
17:02:52.464 -> 14672772,14836086,14470737,14257460
17:02:52.775 -> 14698352,14836904,14471474,14261066
17:02:53.122 -> 14703193,14836960,14471021,14260438
17:02:53.466 -> 14704417,14837401,14471474,14260109



just make bold post changes Very Happy

Quote:

while(true) {
unsigned int32 capa[CHAN_COUNT]; // variable to store data from FDC
for (int i = 0; i < CHAN_COUNT; i++) { // for each channel
// ### read 28bit data
// getReading28(reading);
capa[i] = getReading28(i); //
// ### Transmit data to serial in simple format readable by SerialPlot application.
printf("%lu",capa[i]);
if(i==3) // printing the data we read to the bottom line
{
printf("\n");
}
if (i < CHAN_COUNT - 1) printf(",");
else printf("");
}
delay_ms(250);

}}
endless thanks to everyone who helped
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, 4, 5  Next
Page 1 of 5

 
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