|
|
View previous topic :: View next topic |
Author |
Message |
ressas
Joined: 15 Nov 2019 Posts: 135
|
Need help for i2c communication with FDC2214 |
Posted: Tue Nov 19, 2019 12:39 am |
|
|
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: 9229 Location: Greensville,Ontario
|
|
Posted: Tue Nov 19, 2019 5:38 am |
|
|
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: 19520
|
|
Posted: Tue Nov 19, 2019 2:08 pm |
|
|
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
|
|
Posted: Tue Nov 19, 2019 3:01 pm |
|
|
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
|
|
Posted: Tue Nov 19, 2019 3:12 pm |
|
|
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: 9229 Location: Greensville,Ontario
|
|
Posted: Tue Nov 19, 2019 3:30 pm |
|
|
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
|
|
Posted: Tue Nov 19, 2019 5:24 pm |
|
|
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: 9229 Location: Greensville,Ontario
|
|
Posted: Tue Nov 19, 2019 6:45 pm |
|
|
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
|
|
Posted: Tue Nov 19, 2019 8:36 pm |
|
|
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
|
|
Posted: Wed Nov 20, 2019 4:17 am |
|
|
Thank you both for your help. 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? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Nov 20, 2019 5:28 am |
|
|
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: 19520
|
|
Posted: Wed Nov 20, 2019 7:08 am |
|
|
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
|
|
Posted: Wed Nov 20, 2019 7:46 am |
|
|
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
|
|
Posted: Wed Nov 20, 2019 8:04 am |
|
|
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
|
|
Posted: Wed Nov 20, 2019 8:11 am |
|
|
thank you soo much,
data improved ELHAMDÜLİLLAH
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
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 |
|
|
|
|
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
|