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?

Parents Reply Children
  • 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