AMS ENS210

I would like to thank Jesse Casman and Craig Oda from the Learn IoT Community for providing me with the Renesas IoT Fast Prototyping Kit. These guys have a great site going that focuses on IoT and Sensors and you really should take a look if you are interested in either sensors or IoT.

The IoT Fast Prototyping Kit comes with several PMOD sensors (PMOD is a particular way of wiring a connector, like an Ardunio Shield, see Digilent’s Website for more information). One of these sensors is the AMS Renesas Sensor Board which includes the following sensors:

  1. AMS iAQ-Core Indoor Air Quality Sensor
  2. AMS ENS210 Humidity and Temperature Sensor
  3. AMS AS3935 Lightning Sensor
  4. AMS TMD3782 Proximity Sensor

Today we will be working with the AMS ENS210 Relative Humidity and Temperature Sensor. The ENS210 is a temperature and humidity sensor with average accuracy.

This is a follow on article for the AMS Renesas Sensor Board. Please see AMS Renesas Sensor Board – SSP Configuration article for instructions on configuring your DK-S7G2.

The temperature sensor functions from -40C to 100C with a 0.3C accuracy from 0C to 70C and 0.5C from -40C to 0C and 0.5C from 70C to 100C.

AMS played a little bit of specmanship however. The stated accuracy is within 3σ, which in fairness is 99.73% of all sensors. However, it is much more typical to give the guaranteed absolute worst a sensor can perform (at least when you need high accuracy).

ENS210Temp.png

The relative humidity functions from 0% to 100% with an accuracy of 3.5% RH at 25C and from 20% RH to 80% RH (again with 3 sigma). From 0% to 20% and 80% to 100%, the accuracy drops to 5% RH. No information is given about temperatures other than 25C (this is typical – and frustrating!).

ENS210Humi.png

The ENS210 is an I2C device and is configured for an address of 0x43. There are various control registers as well as read only registers to get the sensor values.

ENS210Registers.png

The header file contains a structure definition to hold the sensor outputs as well as function prototypes to read and write registers.

#ifndef ENS210_H_
#define ENS210_H_

typedef struct _ENS210Data
{
    float Temperature;
    float Humidity;
} ENS210Data;

ssp_err_t ENS210Initialize(void);
ssp_err_t ENS210Open(i2c_master_instance_t * const i2c, uint8_t address);
ssp_err_t ENS210ChipId(i2c_master_instance_t * const i2c, uint8_t address, uint16_t * const chipId);
ssp_err_t ENS210UniqueId(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const uniqueId);
ssp_err_t ENS210UpdateSensors(i2c_master_instance_t * const i2c, uint8_t address, ENS210Data * const data);
ssp_err_t ENS210SetSystemControl(i2c_master_instance_t * const i2c, uint8_t address, uint8_t systemControl);
ssp_err_t ENS210GetSystemControl(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const systemControl);
ssp_err_t ENS210GetSystemStatus(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const systemStatus);
ssp_err_t ENS210SetSensorRunMode(i2c_master_instance_t * const i2c, uint8_t address, uint8_t const sensorRunMode);
ssp_err_t ENS210GetSensorRunMode(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const sensorRunMode);
ssp_err_t ENS210SetSensorStart(i2c_master_instance_t * const i2c, uint8_t address, uint8_t const sensorStart);
ssp_err_t ENS210GetSensorStart(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const sensorStart);
ssp_err_t ENS210SetSensorStop(i2c_master_instance_t * const i2c, uint8_t address, uint8_t const sensorStop);
ssp_err_t ENS210GetSensorStop(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const sensorStop);
ssp_err_t ENS210GetSensorStatus(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const sensorStatus);

#endif /* ENS210_H_ */

Each function takes an I2C instance (a reference to the I2C driver you configured in the SSP), the device address (0x43 in this case), and a reference to control/return data if necessary.

The majority of the function implementation are simple calls to I2CReadRegister and I2CWriteRegister. The two that are different are the ENS210Open function and ENS210UpdateSensors.

/*
 * ENS210.c
 *
 *  Created on: Dec 6, 2016
 *      Author: lycan
 */

#include "hal_data.h"
#include "ENS210.h"
#include "I2C.h"
#include "Timer.h"
#include 

/* Constant Structure to hold the addresses for the various registers */
const struct
{
    uint8_t PART_ID;
    uint8_t UID;
    uint8_t SYS_CTRL;
    uint8_t SYS_STAT;
    uint8_t SENS_RUN;
    uint8_t SENS_START;
    uint8_t SENS_STOP;
    uint8_t SENS_STAT;
    uint8_t T_VAL;
    uint8_t H_VAL;
} ENS210RegisterAddresses =
{ 0x00, // PART_ID
  0x04, // UID
  0x10, // SYS_CTRL
  0x11, // SYS_STAT
  0x21, // SENS_RUN
  0x22, // SENS_START
  0x23, // SENS_STOP
  0x24, // SENS_STAT
  0x30, // T_VAL
  0x33  // H_VAL
        };

ssp_err_t ENS210Initialize(void)
{
    return SSP_SUCCESS;
}

ssp_err_t ENS210Open(i2c_master_instance_t * const i2c, uint8_t address)
{
    ssp_err_t error;

    // Disable Low Power Mode
    error = ENS210SetSystemControl (i2c, address, 0x00);
    if (error != SSP_SUCCESS)
        return error;

    // Wait for sensor to be active
    uint8_t status = 0;
    while ((status & 0x01) == 0)
    {
        error = ENS210GetSystemStatus (i2c, address, &status);
        if (error != SSP_SUCCESS)
            return error;
        printf (".");
        TimerSleepMs (50);
    }

    // Enable Continuous Measurements
    error = ENS210SetSensorRunMode (i2c, address, 0x03);
    if (error != SSP_SUCCESS)
        return error;

    // Start R & H Measurements
    error = ENS210SetSensorStart (i2c, address, 0x03);
    if (error != SSP_SUCCESS)
        return error;

    return SSP_SUCCESS;
}

ssp_err_t ENS210SetSystemControl(i2c_master_instance_t * const i2c, uint8_t address, uint8_t const systemControl)
{
    return I2CWriteRegister (i2c, address, ENS210RegisterAddresses.SYS_CTRL, systemControl, false);
}

ssp_err_t ENS210GetSystemControl(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const systemControl)
{
    return I2CReadRegister (i2c, address, ENS210RegisterAddresses.SYS_CTRL, systemControl, 1, false);
}

ssp_err_t ENS210GetSystemStatus(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const systemStatus)
{
    return I2CReadRegister (i2c, address, ENS210RegisterAddresses.SYS_STAT, systemStatus, 1, false);
}

ssp_err_t ENS210SetSensorRunMode(i2c_master_instance_t * const i2c, uint8_t address, uint8_t const sensorRunMode)
{
    return I2CWriteRegister (i2c, address, ENS210RegisterAddresses.SENS_RUN, *((uint8_t *) &sensorRunMode), false);
}

ssp_err_t ENS210GetSensorRunMode(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const sensorRunMode)
{
    return I2CReadRegister (i2c, address, ENS210RegisterAddresses.SENS_RUN, sensorRunMode, 1, false);
}

ssp_err_t ENS210SetSensorStart(i2c_master_instance_t * const i2c, uint8_t address, uint8_t const sensorStart)
{
    return I2CWriteRegister (i2c, address, ENS210RegisterAddresses.SENS_START, *((uint8_t *) &sensorStart), false);
}
ssp_err_t ENS210GetSensorStart(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const sensorStart)
{
    return I2CReadRegister (i2c, address, ENS210RegisterAddresses.SENS_START, sensorStart, 1, false);
}

ssp_err_t ENS210SetSensorStop(i2c_master_instance_t * const i2c, uint8_t address, uint8_t const sensorStop)
{
    return I2CWriteRegister (i2c, address, ENS210RegisterAddresses.SENS_STOP, *((uint8_t *) &sensorStop), false);
}

ssp_err_t ENS210GetSensorStop(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const sensorStop)
{
    return I2CReadRegister (i2c, address, ENS210RegisterAddresses.SENS_STOP, sensorStop, 1, false);
}

ssp_err_t ENS210GetSensorStatus(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const sensorStatus)
{
    return I2CReadRegister (i2c, address, ENS210RegisterAddresses.SENS_STOP, sensorStatus, 1, false);
}

ssp_err_t ENS210ChipId(i2c_master_instance_t * const i2c, uint8_t address, uint16_t * const chipId)
{
    return I2CReadRegister (i2c, address, ENS210RegisterAddresses.PART_ID, (uint8_t *) chipId, 2, false);
}

ssp_err_t ENS210UniqueId(i2c_master_instance_t * const i2c, uint8_t address, uint8_t * const uniqueId)
{
    return I2CReadRegister (i2c, address, ENS210RegisterAddresses.UID, uniqueId, 8, false);
}

ssp_err_t ENS210UpdateSensors(i2c_master_instance_t * const i2c, uint8_t address, ENS210Data * const data)
{
    ssp_err_t error;

    uint8_t buffer[6] =
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
    uint16_t rawTemp;
    uint16_t rawHumi;

    error = I2CReadRegister(i2c, address, ENS210RegisterAddresses.T_VAL, buffer, 6, false);
    if (error != SSP_SUCCESS)
        return error;

    // Cast Data
    rawTemp = (uint16_t) ((buffer[1] << 8) | buffer[2]);
    rawHumi = (uint16_t) ((buffer[4] << 8) | buffer[5]);
    
    data->Temperature = (float) ((rawTemp / 64.0) - 273.15);
    data->Humidity = (float) ((rawHumi / 512.0));

    return SSP_SUCCESS;
}

The ENS210Open function disables low power mode, continuously checks the status register until low power mode is disabled, then enables continuous measurement and finally starts the temperature and relative humidity measurements.

The ENS210UpdateSensors reads the six bytes starting from the temperature register. Since the humidity register follows right after the temperature register, we can continue reading and get both values at the same time.

Once we have the raw ADC values, we convert them into degrees C and %RH. Each sensor value has 3 bytes, but the upper byte is the CRC data. We only need the lower two bytes.

First, we shift the raw data into variables. Then we convert each to the correct values.

There is not a stand alone project for the AMS ENS210. Instead, a single project that has all four sensors on the AMS Renesas Sensor Board has been created on GitHub at https://github.com/lycannon/ajwrs/tree/master/amsRenesasSensorBoard.

 

Advertisements

One thought on “AMS ENS210

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s