I'm pretty new to embedded development/electronics and I'm trying to interface with a I2C pressure sensor, but I can't seem to communicate with it. I'm using nrf52840dk board and nrf Connect sdk / toolchain v2.7.0.
At first, I just connected the sensor directly to the i2c0 pins. Clock (SCL) on P0.27 and data (SDA) on P0.26. I also connected the sensor's GND/VDD wires to the boards GND/VDD inputs. Finally, the sensor has two modes (sleep and awake). there is a "PD" wire that is supposed to "wake up" the sensor when it's LOW, so I connected it to P1.10.
So it looks like this:
nrf52840 sensor -------- ------ P0.27 SCL P0.26 SDA P1.10 PD GND GND VDD VDD
I tried to communicate with the sensor using i2c device but it always errors out when using the `i2c_write_read_dt` function.
I then proceeded to learn a bit more about i2c and realized that the SDA/SCL lines need to be pulled up with an external resistor to VDD. Is that correct? Is it possible to do it in software? If not, what resistor values should I use?
Also, does the GPIO pin p1.10 need to use an external resistor as well? (see code below)
Thanks
For reference, here is my code so far:
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1000
// read-only
// main data channel registers, signed number
#define PRESSURE_SENSOR_PDATA_23_16_REG 0x06
#define PRESSURE_SENSOR_PDATA_15_8_REG 0x07
#define PRESSURE_SENSOR_PDATA_7_0_REG 0x08
/* Get the node identifier of the sensor */
#define I2C_NODE DT_NODELABEL(pressure_sensor)
#if !DT_NODE_EXISTS(DT_NODELABEL(pressure_sensor_wake))
#error "Overlay for power output node not properly defined."
#endif
static const struct gpio_dt_spec pressure_sensor_wake =
GPIO_DT_SPEC_GET_OR(DT_NODELABEL(pressure_sensor_wake), gpios, {0});
/* Retrieve the API-specific device structure and make sure that the device is ready to use */
static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C_NODE);
int main(void)
{
int ret;
if (!gpio_is_ready_dt(&pressure_sensor_wake)) {
printk("The pressure sensor wake pin GPIO port is not ready.\n");
return -1;
}
printk("Initializing pin with active level.\n");
ret = gpio_pin_configure_dt(&pressure_sensor_wake, GPIO_OUTPUT_ACTIVE);
if (ret != 0) {
printk("error");
printf("Configuring GPIO pin failed: %d\n", ret);
return -1;
}
ret = device_is_ready(dev_i2c.bus);
if (!ret) {
printk("error");
printf("I2C bus %s is not ready!\n",dev_i2c.bus->name);
return -1;
}
ret = i2c_configure(dev_i2c.bus, I2C_SPEED_SET(I2C_SPEED_FAST));
if (ret != 0) {
printf("I2C configuration failed!\n",dev_i2c.bus->name);
return -1;
}
while (1) {
/* Read the data from the sensor */
uint8_t pdata_regs_data[3]= {0};
uint8_t pdata_regs[3] ={PRESSURE_SENSOR_PDATA_23_16_REG, PRESSURE_SENSOR_PDATA_15_8_REG, PRESSURE_SENSOR_PDATA_7_0_REG};
ret = i2c_write_read_dt(&dev_i2c,&pdata_regs[0],1,&pdata_regs_data[0],1);
if(ret != 0){
printf("Failed to write/read I2C device address %x at Reg. %x \n", dev_i2c.addr, pdata_regs[0]);
}
ret = i2c_write_read_dt(&dev_i2c,&pdata_regs[1],1,&pdata_regs_data[1],1);
if(ret != 0){
printf("Failed to write/read I2C device address %x at Reg. %x \n", dev_i2c.addr, pdata_regs[1]);
}
ret = i2c_write_read_dt(&dev_i2c,&pdata_regs[2],1,&pdata_regs_data[2],1);
if(ret != 0){
printf("Failed to write/read I2C device address %x at Reg. %x \n", dev_i2c.addr, pdata_regs[2]);
}
// Print reading to console
printf("PDATA_23_16: %x\n", pdata_regs_data[0]);
printf("PDATA_15_8: %x\n", pdata_regs_data[1]);
printf("PDATA_7_0: %x\n", pdata_regs_data[2]);
k_msleep(SLEEP_TIME_MS);
}
}