Reading a Sensirion SGP30 sensor with nRF52840 via I2C/TWI

After working with arduino's and microprocessors like the ESP8266 and ESP32, I recently started toying around with a nRF52840 dev kit.
After going through some tutorials, I wanted to see if I can get a SGP30 air quality sensor to work (https://www.mouser.com/datasheet/2/682/Sensirion_Gas_Sensors_Datasheet_SGP30-2320451.pdf) 

I have visual studio running with the nRF connect integration / SDK. I used the following sketch to scan for I2C devices:

/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
 */

#include <zephyr.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <drivers/i2c.h>
#include <device.h>

#define TEST_BUF_SIZE 128

void main(void)
{
	printk("The I2C scanner started\n");
    const struct device *i2c_dev;
	int error;

    i2c_dev = device_get_binding("I2C_1");
    if (!i2c_dev) {
        printk("Binding failed.");
        return;
    }

	/* Demonstration of runtime configuration */
    i2c_configure(i2c_dev, I2C_SPEED_SET(I2C_SPEED_STANDARD));
    printk("Value of NRF_TWIM2->PSEL.SCL : %d \n",NRF_TWIM1->PSEL.SCL);
	printk("Value of NRF_TWIM2->PSEL.SDA : %d \n",NRF_TWIM1->PSEL.SDA);
	printk("Value of NRF_TWIM2->FREQUENCY: %d \n",NRF_TWIM1->FREQUENCY);
	printk("26738688 -> 100k\n");

    for (uint8_t i = 4; i <= 0x7F; i++) {
		struct i2c_msg msgs[1];
		uint8_t dst = 1;

		msgs[0].buf = &dst;
		msgs[0].len = 1U;
		msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
		
		// printk("Testing %2x", i);

		error = i2c_transfer(i2c_dev, &msgs[0], 1, i);
		if (error == 0) {
			printk("0x%2x FOUND\n", i);
		}
		else {
			// printk("error %d \n", error);
		}
		
	}
}

Which worked, the SGP30 was found on address 0x58.

With the nRF connect SDK, a driver is supplied for the SGP40, but unfortunately not for the SGP30. 

I found a github repository from Sensirion where they have some code for Nordic nRF series: https://github.com/Sensirion/embedded-common/tree/master/i2c/sample-implementations/Nordic_nRF5_series , however, I am not sure how I should use it. I also found the NRF40 drivers that are included with the SDK, and thought that I might be able to replace it with the code from their repository, but it doesn't look like the SGP40 driver code at all.

So now I am a bit lost where I should go from here, any ideas?

  • Hi,

    With the nRF connect SDK, a driver is supplied for the SGP40, but unfortunately not for the SGP30. 

    Are the sensors very different? It should not be that much work to copy and modify the existing driver to work with a similar device. Look at the SGP40 driver implementation in Zephyr and compare the commands/features with the datasheet of the SGP30 sensor and make the necessary changes.

    I found a github repository from Sensirion where they have some code for Nordic nRF series: https://github.com/Sensirion/embedded-common/tree/master/i2c/sample-implementations/Nordic_nRF5_series , however, I am not sure how I should use it.

    It looks like this is using driver APIs from nRF5 SDK and not from nRF Connect SDK. It may be possible to use this driver with nRF Connect SDK, but you will need to rewrite the HAL layer by using the I2C API from Zephyr (or nrfx_twim). How to actually use that driver is a question you need to direct to Sensirion.

    Best regards,
    Jørgen

  • Thanks, I looked into the SGP40 driver files an think I can use them as a base to build driver files for the SGP30, using the SGP30 data sheets. 

    I am however running into a problem with the SGP40 sample. I believe I was able to compile it earlier on without any modifications, but when I now try to compile it, it gets stuck at these lines:

    #if !DT_HAS_COMPAT_STATUS_OKAY(sensirion_sgp40)
    #error "No sensirion,sgp40 compatible node found in the device tree"
    #endif
    I have the SGP40 drivers enabled in kconfig, but am not sure what I should do to add the SGP40 to the device tree.
    I also have tried to add this to the overlay file:
    &i2c1 {
        sgp40@59 {
            compatible = "sensirion,sgp40";
            reg = <0x59>;
            label = "sensirion_sgp40";
        };
    };
    
    Bu to no avail.
    I'm probably overlooking something simple, but I just don't know what it is. I first would like to be able to compile the SGP40 sample before starting on the SGP30
  • ah, it seems I did not.

    I now changed my overlay file to:

    &i2c1 {
    sgp30@58 {
    compatible = "sensirion,sgp30";
    reg = ;
    label = "sensirion_sgp30";
    status = "okay";
    };
    };

    I does give me some red remarks (Only i2c nodes accepted in /soc/peripheral@50000000/i2c@9000/.), but it does now go past the "No sensirion,sgp30 compatible node found in the device tree" it seems.

    I do now however get stuck at the compiler not finding the sgp30.h file.


    In the main.c file, I replaced

    #include <drivers/sensor/sgp40.h>

    with

    #include <drivers/sensor/sgp30.h>

    But when I try to compile the code, I get: 


    c:\Users\Erik\zigbee\test1\sgp30test1\src\main.c:12:10: fatal error: drivers/sensor/sgp30.h: No such file or directory

    I even tired manually copieng the sgp30.h and sgp30.c files to C:\Users\Erik\zigbee\test1\sgp30test1\src\drivers\sensor, but I stil get the same error.


    Maybe I should explain a bit more what I did. I started with the files that where located in C:\Users\Erik\ncs\v1.8.0\zephyr\drivers\sensor\sgp40 and copied them to C:\Users\Erik\ncs\v1.8.0\zephyr\drivers\sensor\sgp30

    I then changed the 4 files in the directory to match the sgp30 datasheet where possible.
    I now have the following files in that dir:

    - CMakeList.txt
    - Kconfig
    - sgp30.h
    - sgp30.c

    I then added the following line to C:\Users\Erik\ncs\v1.8.0\zephyr\drivers\sensor\CMakeLists.txt

    add_subdirectory_ifdef(CONFIG_SGP30 sgp30)

    and the following line to C:\Users\Erik\ncs\v1.8.0\zephyr\drivers\sensor\Kconfig

    source "drivers/sensor/sgp30/Kconfig"

    I then created the sample application for the sgp40/sht40 that is included in the SDK in visual studio code, added the sgp30 to the KConfig (and removed the SGP40)

    I simplified the code to make it as minimal as possible.

    There's probably some step I'm missing in the process, but I just can't figure out what it is. Any ideas?

  • Hi,

    I followed your instructions, but I do not get the same error. I get a similar error, through:

    C:/ncs/v1.8.0/zephyr/drivers/sensor/sgp30/sgp30.c:17:10: fatal error: drivers/sensor/sgp30.h: No such file or directory
       17 | #include <drivers/sensor/sgp30.h>
          |          ^~~~~~~~~~~~~~~~~~~~~~~~
    compilation terminated.

    This could be resolved by duplicating sgp40.h to sgp30.h in C:\ncs\v1.8.0\zephyr\include\drivers\sensor\. I'm not sure if this is the issue in your case, as it is complaining about the include from main.c. I assume you did a pristine build/removed the build directory before building, after making the changes?

    Best regards,
    Jørgen

Related