Hello, I have a little problem .I boug FDC1004QEVM board and everthing works well with original SW: Sensing solution EVM GUI , but when i decided to move from QEVM to STM32F103C8 (bluepill) meassuring stopped working and i dont know why.
Here is my code:
#include <Wire.h>
#define FDC1004_ADDRESS 0x50 // Adresa FDC1004
#define I2C_SPEED 50000 // I2C rychlost (50 kHz)
// Registry FDC1004
#define MEAS1_CONFIG_REG 0x08 // Konfigurační registr pro MEAS1
#define FDC_CONFIG_REG 0x0C // Globální registr pro spuštění měření
#define DATA_MSB_REG 0x00 // Výsledek MEAS1 (MSB)
#define DATA_LSB_REG 0x01 // Výsledek MEAS1 (LSB)
// Převodní konstanta z datasheetu (~0.00024414 pF/LSB)
// Může se mírně lišit podle konfigurace a přesného výkladu, ale toto je typická hodnota.
#define FDC1004_PF_PER_COUNT 0.00024414f
void setup() {
Serial1.begin(9600);
Wire.begin();
Wire.setClock(I2C_SPEED);
Serial1.println("Diagnostika FDC1004...");
// 1) Test I2C sběrnice
testI2CBus();
// 2) Pokus o čtení "Device ID" (0xFF) - FDC1004 nemá oficiální ID registr,
// ale necháváme jako diagnostiku.
readDeviceID();
// 3) Nastavení MEAS1 (CIN1, single-ended, CAPDAC=0)
configureMeasurement(1);
// Hotovo, přejdeme do hlavní smyčky
}
void loop() {
// 1) Spuštění jednorázového měření v MEAS1
startMeasurement();
// 2) Vyčkáme na dokončení měření - min. 15 ms pro 100 S/s
delay(20);
// 3) Čtení výsledků měření (surové i přepočtené)
int16_t rawData = readRawCapacitance();
float capacitancePf = rawData * FDC1004_PF_PER_COUNT;
// 4) Výpis výsledku
Serial1.print("Raw data (CIN1) = ");
Serial1.print(rawData);
Serial1.print(" => Kapacita: ");
Serial1.print(capacitancePf, 4);
Serial1.println(" pF");
delay(1000);
}
/**
* Ověření komunikace s FDC1004 na adrese 0x50
*/
void testI2CBus() {
Serial1.println("Testuji I2C sběrnici...");
Wire.beginTransmission(FDC1004_ADDRESS);
byte error = Wire.endTransmission();
if (error == 0) {
Serial1.println("Zařízení na adrese 0x50 odpovídá.");
} else {
Serial1.print("Chyba komunikace s adresou 0x50: ");
Serial1.println(error);
diagnoseI2CError(error);
}
}
/**
* Pokus o čtení neoficiálního registru 0xFF pro Device ID
* (FDC1004 oficiálně tento registr nemá, může vracet 0 nebo jinou hodnotu)
*/
void readDeviceID() {
Serial1.println("Čtu (neoficiální) Device ID na 0xFF...");
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(0xFF); // Čtení z neexistujícího registru, pro test
if (Wire.endTransmission() != 0) {
Serial1.println("Chyba při zápisu na registr 0xFF.");
return;
}
Wire.requestFrom(FDC1004_ADDRESS, 2);
if (Wire.available() == 2) {
byte msb = Wire.read();
byte lsb = Wire.read();
uint16_t deviceID = (msb << 8) | lsb;
Serial1.print("Device ID (0xFF): 0x");
Serial1.println(deviceID, HEX);
} else {
Serial1.println("Chyba při čtení registru 0xFF.");
}
}
/**
* Nastaví MEAS1 (0x08) pro single-ended měření na zvoleném kanálu (CIN1–CIN4) s CAPDAC=0.
* channel = 1 => CIN1, 2 => CIN2, 3 => CIN3, 4 => CIN4
*
* Ve 16bit registru:
* [15:13] = 0 => single-ended
* [12:10] = channel-1 => 0 (CIN1), 1 (CIN2), 2 (CIN3), 3 (CIN4)
* [9:5] = CAPDAC = 0
* [4:0] = 0
*/
void configureMeasurement(uint8_t channel) {
Serial1.print("Konfiguruji MEAS1 pro CIN");
Serial1.println(channel);
uint16_t configValue = ((channel - 1) << 10); // např. channel=1 => 0<<10 => CIN1
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(MEAS1_CONFIG_REG); // 0x08 (MEAS1)
Wire.write(configValue >> 8); // MSB
Wire.write(configValue & 0xFF); // LSB
Wire.endTransmission();
}
/**
* Spustí jednorázové měření na MEAS1 s datovou rychlostí 100 S/s.
*
* FDC Configuration (0x0C), 16 bitů:
* [14] = 0 => single measurement
* [13:10] = 0b1000 => 8 => 100 S/s
* [7:4] = 0b0001 => povolený slot MEAS1
* => 0x2010
*/
void startMeasurement() {
// 0x2010 = single shot, 100S/s, MEAS1 enabled
uint16_t configValue = 0x2010;
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(FDC_CONFIG_REG); // 0x0C
Wire.write(configValue >> 8); // MSB
Wire.write(configValue & 0xFF); // LSB
Wire.endTransmission();
}
/**
* Přečte surová 16bit data z registrů 0x00 (MSB) a 0x01 (LSB) pro MEAS1.
* Vrací signed 16bit (two's complement). Převod na pF probíhá vynásobením FDC1004_PF_PER_COUNT.
*/
int16_t readRawCapacitance() {
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(DATA_MSB_REG); // 0x00
Wire.endTransmission();
Wire.requestFrom((int)FDC1004_ADDRESS, 2);
if (Wire.available() >= 2) {
int16_t rawData = (Wire.read() << 8);
rawData |= Wire.read();
return rawData;
} else {
Serial1.println("Chyba při čtení kapacity.");
return 0;
}
}
/**
* Pomocná funkce pro diagnostiku chyb I2C
*/
void diagnoseI2CError(byte error) {
switch (error) {
case 0:
Serial1.println("Žádná chyba.");
break;
case 1:
Serial1.println("Přetížení I2C (data nebyla doručena).");
break;
case 2:
Serial1.println("Přijetí NACK po odeslání adresy.");
break;
case 3:
Serial1.println("Přijetí NACK po odeslání dat.");
break;
case 4:
Serial1.println("Jiná chyba.");
break;
default:
Serial1.println("Neznámá chyba.");
break;
}
}
COM7 Output with ENG translate - what is happening :
07:32:08.933 -> Diagnostika FDC1004... - Diagnosing
07:32:08.933 -> Testuji I2C sběrnici... - Testing I2C
07:32:08.980 -> Zařízení na adrese 0x50 odpovídá. - Device at adress 0x50 response (FDC1004)
07:32:08.980 -> Čtu (neoficiální) Device ID na 0xFF... - Reading of 0xFF (device id)
07:32:09.033 -> Device ID (0xFF): 0x1004 - Correct device ID
07:32:09.080 -> Konfiguruji MEAS1 pro CIN1 - Configurating MEAS1 for CIN1 measuring
07:32:09.134 -> Raw data (CIN1) = 0 => Kapacita: 0.0000 pF
07:32:10.136 -> Raw data (CIN1) = 0 => Kapacita: 0.0000 pF
07:32:11.139 -> Raw data (CIN1) = 0 => Kapacita: 0.0000 pF
07:32:12.188 -> Raw data (CIN1) = 0 => Kapacita: 0.0000 pF
07:32:13.191 -> Raw data (CIN1) = 0 => Kapacita: 0.0000 pF
The problem is that i got 0 RAW data and of course the cappacitance too. No matter i do.
What i tried:
Added pull ups between SDA a SCL (4.7Kohm)
Connected ground between FDC and STM32
Added C (220pF) between GND and CIN1
A lot of variants of codes.
Can you please help me. I am trying this liquid cappacitive sensing thing few weeks, but i cant move above this phase of 0 outputs.
Without providing a datasheet of this device you are loading a lot of research work on the shoulders of your potential helpers.
I'm pretty sure that you agree and will follow the way how to solve your problem mimimum 200 minutes faster.
This requires to invest 20 minutes of your precious time to read how to speedup solving your problems.
Directly after registering you got presented informations how to speed up solving your problem.
You should really read it.
As an experiment what will be the output of the AI deepseek R1, I pasted your initial post 1 : 1
as the prompt into deepseek
Here is the answer from deepseek:
START of deepseek answer
It looks like you've done a lot of the right things already, but let's go through a systematic approach to debug the issue. Here are some steps and considerations:
1. Verify I2C Communication
Pull-up Resistors: Ensure that you have the correct pull-up resistors (typically 4.7kΩ) on both SDA and SCL lines.
I2C Address: Double-check that the I2C address (0x50) is correct and that there are no other devices on the bus with conflicting addresses.
I2C Speed: Ensure that the I2C speed (50 kHz) is appropriate for your setup. Sometimes, lowering the speed can help with communication issues.
2. Check Power Supply
Ensure that the FDC1004 is receiving the correct voltage (3.3V or 5V, depending on your setup).
Verify that the ground connections between the FDC1004 and the STM32 are solid.
3. Configuration Registers
MEAS1 Configuration: Ensure that the MEAS1 configuration register is set correctly. You are setting it to single-ended mode on CIN1 with CAPDAC=0, which should be correct.
FDC Configuration: Ensure that the FDC configuration register is set correctly to start the measurement.
4. Measurement Timing
Ensure that you are waiting long enough for the measurement to complete. The datasheet specifies a minimum conversion time, which you should respect.
5. Debugging Steps
Read Configuration Registers: After writing to the configuration registers, read them back to ensure they have been set correctly.
Check for Errors: Add error checking after each I2C operation to ensure that the communication is successful.
6. Code Review and Adjustments
Read Configuration Registers: Add a function to read back the configuration registers to verify they are set correctly.
Error Checking: Add more robust error checking after each I2C operation.
Here is an updated version of your code with additional debugging steps:
#include <Wire.h>
#define FDC1004_ADDRESS 0x50 // Adresa FDC1004
#define I2C_SPEED 50000 // I2C rychlost (50 kHz)
// Registry FDC1004
#define MEAS1_CONFIG_REG 0x08 // Konfigurační registr pro MEAS1
#define FDC_CONFIG_REG 0x0C // Globální registr pro spuštění měření
#define DATA_MSB_REG 0x00 // Výsledek MEAS1 (MSB)
#define DATA_LSB_REG 0x01 // Výsledek MEAS1 (LSB)
// Převodní konstanta z datasheetu (~0.00024414 pF/LSB)
#define FDC1004_PF_PER_COUNT 0.00024414f
void setup() {
Serial1.begin(9600);
Wire.begin();
Wire.setClock(I2C_SPEED);
Serial1.println("Diagnostika FDC1004...");
// 1) Test I2C sběrnice
testI2CBus();
// 2) Pokus o čtení "Device ID" (0xFF) - FDC1004 nemá oficiální ID registr,
// ale necháváme jako diagnostiku.
readDeviceID();
// 3) Nastavení MEAS1 (CIN1, single-ended, CAPDAC=0)
configureMeasurement(1);
// 4) Read back configuration registers to verify
readConfigurationRegisters();
// Hotovo, přejdeme do hlavní smyčky
}
void loop() {
// 1) Spuštění jednorázového měření v MEAS1
startMeasurement();
// 2) Vyčkáme na dokončení měření - min. 15 ms pro 100 S/s
delay(20);
// 3) Čtení výsledků měření (surové i přepočtené)
int16_t rawData = readRawCapacitance();
float capacitancePf = rawData * FDC1004_PF_PER_COUNT;
// 4) Výpis výsledku
Serial1.print("Raw data (CIN1) = ");
Serial1.print(rawData);
Serial1.print(" => Kapacita: ");
Serial1.print(capacitancePf, 4);
Serial1.println(" pF");
delay(1000);
}
void testI2CBus() {
Serial1.println("Testuji I2C sběrnici...");
Wire.beginTransmission(FDC1004_ADDRESS);
byte error = Wire.endTransmission();
if (error == 0) {
Serial1.println("Zařízení na adrese 0x50 odpovídá.");
} else {
Serial1.print("Chyba komunikace s adresou 0x50: ");
Serial1.println(error);
diagnoseI2CError(error);
}
}
void readDeviceID() {
Serial1.println("Čtu (neoficiální) Device ID na 0xFF...");
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(0xFF); // Čtení z neexistujícího registru, pro test
if (Wire.endTransmission() != 0) {
Serial1.println("Chyba při zápisu na registr 0xFF.");
return;
}
Wire.requestFrom(FDC1004_ADDRESS, 2);
if (Wire.available() == 2) {
byte msb = Wire.read();
byte lsb = Wire.read();
uint16_t deviceID = (msb << 8) | lsb;
Serial1.print("Device ID (0xFF): 0x");
Serial1.println(deviceID, HEX);
} else {
Serial1.println("Chyba při čtení registru 0xFF.");
}
}
void configureMeasurement(uint8_t channel) {
Serial1.print("Konfiguruji MEAS1 pro CIN");
Serial1.println(channel);
uint16_t configValue = ((channel - 1) << 10); // např. channel=1 => 0<<10 => CIN1
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(MEAS1_CONFIG_REG); // 0x08 (MEAS1)
Wire.write(configValue >> 8); // MSB
Wire.write(configValue & 0xFF); // LSB
byte error = Wire.endTransmission();
if (error != 0) {
Serial1.print("Chyba při konfiguraci MEAS1: ");
Serial1.println(error);
}
}
void startMeasurement() {
// 0x2010 = single shot, 100S/s, MEAS1 enabled
uint16_t configValue = 0x2010;
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(FDC_CONFIG_REG); // 0x0C
Wire.write(configValue >> 8); // MSB
Wire.write(configValue & 0xFF); // LSB
byte error = Wire.endTransmission();
if (error != 0) {
Serial1.print("Chyba při spuštění měření: ");
Serial1.println(error);
}
}
int16_t readRawCapacitance() {
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(DATA_MSB_REG); // 0x00
byte error = Wire.endTransmission();
if (error != 0) {
Serial1.print("Chyba při zahájení čtení kapacity: ");
Serial1.println(error);
return 0;
}
Wire.requestFrom((int)FDC1004_ADDRESS, 2);
if (Wire.available() >= 2) {
int16_t rawData = (Wire.read() << 8);
rawData |= Wire.read();
return rawData;
} else {
Serial1.println("Chyba při čtení kapacity.");
return 0;
}
}
void readConfigurationRegisters() {
Serial1.println("Čtu konfigurační registry...");
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(MEAS1_CONFIG_REG);
if (Wire.endTransmission() != 0) {
Serial1.println("Chyba při zápisu na registr MEAS1_CONFIG_REG.");
return;
}
Wire.requestFrom(FDC1004_ADDRESS, 2);
if (Wire.available() == 2) {
uint16_t configValue = (Wire.read() << 8) | Wire.read();
Serial1.print("MEAS1_CONFIG_REG: 0x");
Serial1.println(configValue, HEX);
} else {
Serial1.println("Chyba při čtení MEAS1_CONFIG_REG.");
}
Wire.beginTransmission(FDC1004_ADDRESS);
Wire.write(FDC_CONFIG_REG);
if (Wire.endTransmission() != 0) {
Serial1.println("Chyba při zápisu na registr FDC_CONFIG_REG.");
return;
}
Wire.requestFrom(FDC1004_ADDRESS, 2);
if (Wire.available() == 2) {
uint16_t configValue = (Wire.read() << 8) | Wire.read();
Serial1.print("FDC_CONFIG_REG: 0x");
Serial1.println(configValue, HEX);
} else {
Serial1.println("Chyba při čtení FDC_CONFIG_REG.");
}
}
void diagnoseI2CError(byte error) {
switch (error) {
case 0:
Serial1.println("Žádná chyba.");
break;
case 1:
Serial1.println("Přetížení I2C (data nebyla doručena).");
break;
case 2:
Serial1.println("Přijetí NACK po odeslání adresy.");
break;
case 3:
Serial1.println("Přijetí NACK po odeslání dat.");
break;
case 4:
Serial1.println("Jiná chyba.");
break;
default:
Serial1.println("Neznámá chyba.");
break;
}
}
Additional Tips:
Oscilloscope: If you have access to an oscilloscope, check the I2C signals to ensure they are clean and correctly timed.
Logic Analyzer: A logic analyzer can help you capture and analyze the I2C communication in detail.
Datasheet: Always refer to the FDC1004 datasheet for detailed register descriptions and timing requirements.
By following these steps and adding the additional debugging code, you should be able to identify where the issue lies and get your measurements working correctly.
END of deepseek-answer
It will be very interesting to see if the code compiles and if you are able to identify what is going wrong.
Thanks for your answer, the problem actually was in that i made mistake in putting BITS for MEAS4 instead for MEAS1 and i changed configValue to 0x0480 instead of 0x2010 . And now the CIN1 is meassuring properly. Weeks lost by this little mistake.
Hi @ungertech . May I ask whether the FDC1004 QEVM you’re using includes a built-in proximity sensor, or are you using a custom electrode setup?
I’m currently working on a non-conductive liquid sensing project using the FDC1004 paired with an STM32 microcontroller. However, I'm facing difficulties establishing a proper connection between the STM32 and the FDC1004. I've tried several code implementations and configurations, but so far I haven't been able to get a reliable response from the sensor. Any insights or suggestions you could share would be greatly appreciated.