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); } }