nRF52DK with BME280 Sensor

Hi All,

I have been trying to get the BME280 to work with the nRF52 Development Kit using the Zephyr Framework,

I can't seem to get the firmware to pick-up the BME280 sensor, although I have define the correct I2C address, below is the code Main.c code and the bme.c and the bme.h as well as my prj.conf and the overlay file.

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <stddef.h>
#include <stdio.h>
#include <sys/printk.h>
#include <sys/util.h>
#include <zephyr/types.h>
#include "bme280.h"
#include <logging/log.h>

#define ADV_PARAM \
BT_LE_ADV_PARAM(0, BT_GAP_ADV_SLOW_INT_MIN, \
BT_GAP_ADV_SLOW_INT_MAX, NULL)

static struct bt_data ad[] = {
		BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
		BT_DATA_BYTES(
		BT_DATA_MANUFACTURER_DATA, 0xff, 0xff, /* Test company ID */
		0x00, 0x00, /* Temperature, int16, little-endian */
		0x00, 0x00, /* Pressure - 50000, uint16, little-endian */
		0x00, 0x00) /* Humidity, uint16, little-endian */
		};


void update_ad_bme280(const struct device *dev) {

	int16_t temperature;
	uint16_t pressure, humidity;
	bme280_fetch_sample(dev);
	temperature = bme280_get_temperature(dev);
	memcpy(&(ad[1].data[2]), &temperature, 2);
	pressure = bme280_get_pressure(dev);
	memcpy(&(ad[1].data[4]), &pressure, 2);
	humidity = bme280_get_humidity(dev);
	memcpy(&(ad[1].data[6]), &humidity, 2);

}

void main(void) {

	int err;
	printk("Starting firmware...\n");
	// Initialize BME280
	const struct device *bme280 = bme280_get_device();

		if (bme280 == NULL) {
		return;
		}

		// Initialize the Bluetooth subsystem
		err = bt_enable(NULL);

		if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
			return;
		}

		printk("Bluetooth initialized\n");
		// Start advertising sensor values
		update_ad_bme280(bme280);
		err = bt_le_adv_start(ADV_PARAM, ad, ARRAY_SIZE(ad), NULL, 0);

		if (err) {
			printk("Advertising failed to start (err %d)\n", err);
			return;
		}

			while (1) {

		k_sleep(K_MSEC(980));
		// Update advertised sensor values
		update_ad_bme280(bme280);
		err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), NULL, 0);
		
		if (err) {
			printk("Advertising update failed (err %d)\n", err);
			return;
		}
	}
}

Here is the bme.c code

#include <device.h>
#include <devicetree.h>
#include <drivers/sensor.h>
#include <sys/printk.h>
#include <zephyr/types.h>

/*
 * Get a device structure from a devicetree node with compatible
 * "bosch,bme280". (If there are multiple, just pick one.)
 */
const struct device *bme280_get_device(void) {
  const struct device *dev = DEVICE_DT_GET_ANY(bosch_bme280);

  if (dev == NULL) {
    /* No such node, or the node does not have status "okay". */
    printk("\nError: no device found.\n");
    return NULL;
  }

  if (!device_is_ready(dev)) {
    printk("\nError: Device \"%s\" is not ready; "
           "check the driver initialization logs for errors.\n",
           dev->name);
    return NULL;
  }

  printk("Found device \"%s\", getting sensor data\n", dev->name);
  return dev;
}

void bme280_fetch_sample(const struct device *dev) {
  sensor_sample_fetch(dev);
}

int16_t bme280_get_temperature(const struct device *dev) {
  struct sensor_value temperature;

  sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temperature);
  return (int16_t)(temperature.val1 * 100 + temperature.val2 / 10000);
}

uint16_t bme280_get_pressure(const struct device *dev) {
  struct sensor_value pressure;
  uint32_t p; // Pressure without offset

  sensor_channel_get(dev, SENSOR_CHAN_PRESS, &pressure);
  p = (uint32_t)(pressure.val1 * 1000 + pressure.val2 / 10000);
  return (uint16_t)(p - 50000);
}

uint16_t bme280_get_humidity(const struct device *dev) {
  struct sensor_value humidity;

  sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity);
  return (uint16_t)(humidity.val1 * 100 + humidity.val2 / 10000);
}

here is the bme.h code

#ifndef BME280_H_
#define BME280_H_

const struct device *bme280_get_device(void);
void bme280_fetch_sample(const struct device *dev);
int16_t bme280_get_temperature(const struct device *dev);
uint16_t bme280_get_pressure(const struct device *dev);
uint16_t bme280_get_humidity(const struct device *dev);

#endif /* BME280_H_ */

here is the overlay file

 &i2c0 {
  status = "okay";
  sda-pin = <26>;
  scl-pin = <27>;
  bme280@77 {
    compatible = "bosch,bme280";
    reg = <0x77>;
    label = "BME280_I2C";
  };
};
  &uart0 {
    current-speed = <115200>;
    status = "okay";
    tx-pin = <6>;
    rx-pin = <8>;
};

here is the prj.conf

CONFIG_BT=y
# Enable BME280 sensor
CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_BME280=y

#CONFIG_BT_DEVICE_NAME="GAVO_IV"
CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=y
CONFIG_SERIAL=y
CONFIG_UART_CONSOLE=y
CONFIG_LOG=y

and the cmake:

cmake_minimum_required(VERSION 3.13.1)
#include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})

project(ZEPHYR_BME280)

FILE(GLOB app_sources ../src/*.c*)
target_sources(app PRIVATE ${app_sources})
#target_sources(app PRIVATE src/bme280.c src/main.c)

message(STATUS "Current source directory: ${CMAKE_CURRENT_SOURCE_DIR}")

Any help would be greatly appreciated!

Parents
  • Hi,

    There is a sample for the BME280 Sensor that you can refer to. You need to adjust the board configuration for your board though, as I see you have done.

    I don't see any error in the CMake log snippet, but from your text I get the feeling this fails at run-time? Can you elaborate?

    Note that if the problem is run-time, a quite common issue with I2C is that the internal pull resistors in the nRF are quite weak, so you should add external pull-up resistors (typically 4.7 k).

  • Hi Einar, my apologies for the delay, I tried the sample and same as my previous code, this is what I see in TeraTerm

    *** Booting Zephyr OS build zephyr-v20701  ***


    Error: no device found.

    Both the code above the Zephyr sample code as well.

    I will try a 4K7 resistor but I am using the nRF52DK, surely there are Pins that I can use that have strong pull ups for the I2C?

    I am also using Platform IO and below is my .ini file

    [env:nrf52_dk]
    platform = nordicnrf52
    board = nrf52_dk
    framework = zephyr
    board_build.mcu = nrf52832
  • Hi,

    Which nRF Connect SDK version are you using? If you are using >= 2.0.0, then pinctrl is in use, and you need to configure the pins differently. You can refer to zephyr/boards/arm/bl654_sensor_board/bl654_sensor_board.dts for an exmaple. This part is relevant:

    &i2c0 {
    	compatible = "nordic,nrf-twi";
    	status = "okay";
    
    	pinctrl-0 = <&i2c0_default>;
    	pinctrl-1 = <&i2c0_sleep>;
    	pinctrl-names = "default", "sleep";
    	bme280@76 {
    		compatible = "bosch,bme280";
    		status = "okay";
    		reg = <0x76>;
    	};
    };

    And for the pinctrl part where the i2c0 pins are defined, you can refer to zephyr/boards/arm/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi:

    	i2c0_default: i2c0_default {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 26)>,
    				<NRF_PSEL(TWIM_SCL, 0, 27)>;
    		};
    	};
    
    	i2c0_sleep: i2c0_sleep {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 26)>,
    				<NRF_PSEL(TWIM_SCL, 0, 27)>;
    			low-power-enable;
    		};
    	};

    gavo said:

    I will try a 4K7 resistor but I am using the nRF52DK, surely there are Pins that I can use that have strong pull ups for the I2C?

    The internal pull resistors are typically strong enough for 100 kHz, but if you want to use a higher frequency, external pull resistors make sense.

    gavo said:
    I am also using Platform IO and below is my .ini file

    I have no experience with platform IO unfortunately, so I cannot say if there is any problem with that part. Generally though, I would recomend using nRF Connect SDK for VS Code, which is the only IDE we support

  • Hi Einar,

    I saw this in the Zephyr.dts file in the project

    I changed it to 0x26 and 0x27 but it made no difference.

    I also tried your suggestion about but it still shows no device connected

  • My New overlay file below:

     &i2c0 {
      compatible = "nordic,nrf-twim";
      status = "okay";
      sda-pin = <26>;
      scl-pin = <27>;
         bme280@77 {
        compatible = "bosch,bme280";
        reg = <0x77>;
        label = "BME280_I2C";
         };
     
      // Other properties like clock-frequency can also be set here
    };


      &uart0 {
        current-speed = <115200>;
        status = "okay";
        tx-pin = <6>;
        rx-pin = <8>;
    };


    and I made changes to the Zephyr Projects.dts files to this below and it still did not work...

    i2c0: arduino_i2c: i2c@40003000 {
                #address-cells = < 0x1 >;
                #size-cells = < 0x0 >;
                reg = < 0x40003000 0x1000 >;
                clock-frequency = < 0x186a0 >;
                interrupts = < 0x3 0x1 >;
                status = "okay";
                label = "I2C_0";
                compatible = "nordic,nrf-twi";
                sda-pin = < 0x26 >;
                scl-pin = < 0x27 >;
            };
  • Hi,

    I am not aware of a Projects.dts file, but your overlay file looks outdated. Which nRF Connect SDK version are you using? As mentionned, pin control is used in version 2.0.0 and higher, so you should refer to the samples mentionned (or other examples of I2C in the SDK). There is also a good introduction in Lesson 6 – Serial communication (I2C) in the nRF Connect SDK Fundamentals course.

Reply Children
  • Hi Einar,

    I believe it would be 2.7.1? as shown below what my Platform IO Generates:

    PLATFORM: Nordic nRF52 (10.2.0) > Nordic nRF52-DK     
    HARDWARE: NRF52832 64MHz, 64KB RAM, 512KB Flash       
    DEBUG: Current (jlink) On-board (cmsis-dap, jlink) External (blackmagic, stlink)
    PACKAGES:
     - framework-zephyr @ 2.20701.220422 (2.7.1)
     - tool-bossac-nordicnrf52 @ 1.10901.201022 (1.9.1)   
     - tool-cmake @ 3.21.3
     - tool-dtc @ 1.4.7
     - tool-jlink @ 1.77001.0 (7.70.1)
     - tool-ninja @ 1.9.0
     - tool-openocd @ 3.1200.0 (12.0)
     - tool-sreccat @ 1.164.0 (1.64)
     - toolchain-gccarmnoneeabi @ 1.80201.181220 (8.2.1) 

    Regards,

    Gavin

  • Hi Gavin,

    The latest nRF Connect SDK version is 2.5.1. If you are using plain zephyr I am not able to support that. If you want to do product development for the nRF devices I strongly recomend you use the nRF Connect SDK (and the development tools we support, though that is not as essential).

    For using vanilla zephyr you can get support form the Zephyr community 

Related