How to program Alert Interrupt for SHT3x sensors

Hello, I want to create interrupt from AL pin on SHT31 specifically but couldn't find enough resources for the most popular libraries. It is above my level to write registry level code from datasheet.

Can you please provide me the code for Temp and Hum level interrupts in "ClosedCube SHT31D" or RobTillaart's SHT31 library? If not possible then can you provide the registry level code if it isn't too much to ask? Also can you put explanations to each line?

Thank you.

Edit: I am using Arduino pro mini 3.3V 8Mhz version

what Arduino are you using?
have a look at sht31-temperature-humidity-sensor-arduino-tutorial and attachinterrupt

I've edited the question, the link you've sent only briefly touches the alert topic :frowning:

alert requires the sht31 to be in Periodic Data Acquisition Mode
the following code tests the high alert temperature set and clear
Note to use this code the file Docements>Arduino>libraries>Adafruit_SHT31_Library>Adafruit_SHT31.h
requires line 66 editing to comment out the private keyword, e.g

    //private:

this gives the code below access to the private members of class Adafruit_SHT31

// SHT31 - read and set high alert temperature set and clear and test

// see https://sensirion.com/products/catalog/SHT31-DIS-B/
// datasheet and alert mode application note

// to use this code the file Docements>Arduino>libraries>Adafruit_SHT31_Library>Adafruit_SHT31.h
//    requires line 66 editing to comment out the private keyword, e.g
//  //private:
//  this gives the code below access to the private members of class Adafruit_SHT31

#include <Arduino.h>
#include <Wire.h>
#include "Adafruit_SHT31.h"

// parameters for test
#define alertPin 2                        // sht31 alert pin
float highAlertTemperatureSet = 29.0f;    // high alert set
float highAlertTemperatureClear = 26.0f;  // high alert cleared

Adafruit_SHT31 sht31 = Adafruit_SHT31();

// alert interrupt ISR - set alertFlag on change of state
volatile int alertFlag = 0;
void alertISR(void) {
  alertFlag = 1;  // set alert indicator
}

void setup() {
  Serial.begin(115200);
  if (!sht31.begin(0x44)) {  // Set to 0x45 for alternate I2C address
    Serial.println("Couldn't find SHT31");
    while (1) delay(1);
  }
  Serial.println("\n\nsht31 alert limit tests");
  sht31.reset();
  float HighAlertLimitSetTemperature = 0, HighAlertLimitClearTemperature = 0, LowAlertLimitSetTemperature = 0,
        HighAlertLimitSetHumidity = 0, HighAlertLimitClearHumidity = 0, LowAlertLimitSetHumidity = 0;
  // check high and low alert temperatures - should be +60 and -10
  readHighAlertLimitSet(HighAlertLimitSetTemperature, HighAlertLimitSetHumidity);
  Serial.print("high alert limit set temperature (should be 60.00) = ");
  Serial.print(HighAlertLimitSetTemperature);
  Serial.print("  humidity (should be 80.00) = ");
  Serial.println(HighAlertLimitSetHumidity);
  readHighAlertLimitClear(HighAlertLimitClearTemperature, HighAlertLimitClearHumidity);
  Serial.print("high alert limit clear temperature (should be 58.00) = ");
  Serial.print(HighAlertLimitClearTemperature);
  Serial.print("  humidity (should be 79.00) = ");
  Serial.println(HighAlertLimitClearHumidity);
  readLowAlertLimitSet(LowAlertLimitSetTemperature, LowAlertLimitSetHumidity);
  Serial.print("low alert limit set(should be -10.00) = ");
  Serial.print(LowAlertLimitSetTemperature);
  Serial.print("  humidity (should be 22.00) = ");
  Serial.println(LowAlertLimitSetHumidity);

  // set the high temperature alert set and clear
  writeHighAlertLimitSet(highAlertTemperatureSet);  // set high alert temperature level and check it
  readHighAlertLimitSet(HighAlertLimitSetTemperature, HighAlertLimitSetHumidity);
  Serial.print("\nnew high alert limit set temperature  = ");
  Serial.print(highAlertTemperatureSet = HighAlertLimitSetTemperature);
  Serial.print("  humidity  ");
  Serial.println(HighAlertLimitSetHumidity);
  writeHighAlertLimitClear(highAlertTemperatureClear);
  readHighAlertLimitClear(HighAlertLimitClearTemperature, HighAlertLimitClearHumidity);
  Serial.print("new high alert limit clear temperature = ");
  Serial.print(highAlertTemperatureClear = HighAlertLimitClearTemperature);
  Serial.print("  humidity  = ");
  Serial.println(HighAlertLimitClearHumidity);
  uint16_t status = sht31.readStatus();
  Serial.print("status ");
  Serial.println(status, HEX);
  clearStatusRegister();                                               // clear status bits
  setPeriodicDataAcquisitionMode();                                    // set Periodic Data Acquisition Mode
  attachInterrupt(digitalPinToInterrupt(alertPin), alertISR, CHANGE);  // set up interrupt
}

// loop reading temperature and humidity and check for alerts
void loop() {
  uint16_t status = sht31.readStatus();  // read status bits
  Serial.print("status ");
  Serial.print(status, HEX);  // read temperature and humidity
  float temperature, humidity;
  readTempHum(temperature, humidity);
  if (!isnan(temperature)) {  // check if 'is not a number'
    Serial.print("  Temp *C = ");
    Serial.print(temperature);
    Serial.print("\t\t");
  } else {
    Serial.println("Failed to read temperature");
  }
  if (!isnan(humidity)) {  // check if 'is not a number'
    Serial.print("Hum. % = ");
    Serial.println(humidity);
  } else {
    Serial.println("Failed to read humidity");
  }
  // delay checking alertFlag
  long timer = millis();
  bool printedAlert = 0;
  while (millis() - timer < 3000) {
    if (alertFlag) {  // if alert occured
      alertFlag = 0;
      if (!printedAlert) {  // if not already printed
        printedAlert = 1;
        Serial.print("******* alert !! *******  status ");
        status = sht31.readStatus();
        Serial.print(status, HEX);
        Serial.print(" alert pin state  = ");
        int alertPinState = digitalRead(alertPin);
        Serial.println(alertPinState);
        if (alertPinState)
          Serial.println("   *** high temperature alert set !  **** ");
        else
          Serial.println("   *** high temperature alert cleared !  **** ");
        clearStatusRegister();
      }
    }
  }
}

// set up setPeriodic Data Acquisition Mode for alerts
void setPeriodicDataAcquisitionMode(void) {
  sht31.writeCommand(0x2126);  // set repeatability mode
  delay(20);
}

void clearStatusRegister(void) {
  sht31.writeCommand(0x3041);  // clear status register
  delay(20);
}

// read high alert set limit
bool readHighAlertLimitSet(float &temp, float &humidity) {
  Serial.println("reading high alert limit set ");
  uint8_t readbuffer[3] = { 0 };
  sht31.writeCommand(0xE11F);  // read high alert set
  delay(20);
  sht31.i2c_dev->read(readbuffer, sizeof(readbuffer));
  if (readbuffer[2] != crc8(readbuffer, 2)) {
    Serial.println("CRC error!");
    return false;
  }
  Serial.print("readHigAlertLimitSet 0x");
  Serial.print(readbuffer[0], HEX);
  Serial.print(readbuffer[1], HEX);
  Serial.println(readbuffer[2], HEX);
  // temperature convert 9 bit value to 16bit value
  int32_t stemp = ((int32_t)(((uint32_t)((readbuffer[0] & 0x01) << 8)) | readbuffer[1])) << 7;
  // convert from 16bit value
  stemp = 100.0f * ((stemp * 175.0f) / 65535.0f - 45.0f);
  temp = (float)stemp / 100.0f;
  // humidity convert 7 bit value to 16 bit value
  uint32_t shum = (uint32_t)((uint32_t)(readbuffer[0] & 0xFE) << 8);
  humidity = (shum * 100.0f) / 65535.0f;
  return true;
}

// read high alert clear limit
bool readHighAlertLimitClear(float &temp, float &humidity) {
  Serial.print("reading high alert limit clear ");
  uint8_t readbuffer[3] = { 0 };
  sht31.writeCommand(0xE114);  // read high alert set
  delay(20);
  sht31.i2c_dev->read(readbuffer, sizeof(readbuffer));
  if (readbuffer[2] != crc8(readbuffer, 2)) {
    Serial.println("CRC error!");
    return false;
  }
  Serial.print(" 0x");
  Serial.print(readbuffer[0], HEX);
  Serial.print(readbuffer[1], HEX);
  Serial.println(readbuffer[2], HEX);
  // temperature convert 9 bit value to 16bit value
  int32_t stemp = ((int32_t)(((uint32_t)((readbuffer[0] & 0x01) << 8)) | readbuffer[1])) << 7;
  // convert from 16bit value
  stemp = 100.0f * ((stemp * 175.0f) / 65535.0f - 45.0f);
  temp = (float)stemp / 100.0f;
  uint32_t shum = (uint32_t)((uint32_t)(readbuffer[0] & 0xFE) << 8);
  humidity = (shum * 100.0f) / 65535.0f;
  return true;
}

// write high alert set temperature
void writeHighAlertLimitSet(float temp) {
  Serial.print("write high alert limit set ");
  Serial.println(temp);
  // calculate 9 bit value for temperature
  int32_t stemp = (temp + 45.0f) * 65535.0f / 175.0f;
  stemp = stemp >> 7;
  //Serial.print("setHighAlertLimit 0x");
  //Serial.println(stemp,HEX);
  // buffer to set high alert - command is 0x611D
  uint8_t writebuffer[5] = { 0x61, 0x1D, ((stemp >> 8) & 0x01) | 0xCC, stemp & 0xff, 0 };
  writebuffer[4] = crc8(writebuffer + 2, 2);
  //Serial.print(writebuffer[2], HEX);
  //Serial.print(writebuffer[3], HEX);
  //Serial.println(writebuffer[4], HEX);
  sht31.i2c_dev->write(writebuffer, sizeof(writebuffer));  // write updated value
  delay(20);
  sht31.writeCommand(0x2126);  // set repeatability
  delay(20);
}


// write high alert clear temperature
void writeHighAlertLimitClear(float temp) {
  Serial.print("write high alert limit clear ");
  Serial.println(temp);
  // calculate 9 bit value for temperature
  int32_t stemp = (temp + 45.0f) * 65535.0f / 175.0f;
  stemp = stemp >> 7;
  //Serial.print("setHighAlertLimit 0x");
  //Serial.println(stemp,HEX);
  // buffer to set high alert - command is 0x611D
  uint8_t writebuffer[5] = { 0x61, 0x16, ((stemp >> 8) & 0x01) | 0xc8, stemp & 0xff, 0 };
  writebuffer[4] = crc8(writebuffer + 2, 2);
  //Serial.print(writebuffer[2], HEX);
  //Serial.print(writebuffer[3], HEX);
  //Serial.println(writebuffer[4], HEX);
  sht31.i2c_dev->write(writebuffer, sizeof(writebuffer));  // write updated value
  delay(20);
  sht31.writeCommand(0x2126);  // set repeatability
  delay(20);
}

// read low alert set temperature
bool readLowAlertLimitSet(float &temp, float &humidity) {
  Serial.println("reading low alert limit set ");
  uint8_t readbuffer[3] = { 0 };
  sht31.writeCommand(0xE102);  // read low alert set
  delay(20);
  sht31.i2c_dev->read(readbuffer, sizeof(readbuffer));
  if (readbuffer[2] != crc8(readbuffer, 2)) {
    Serial.println("CRC error!");
    return false;
  }
  Serial.print("readLowAlertLimitSet 0x");
  Serial.print(readbuffer[0], HEX);
  Serial.print(readbuffer[1], HEX);
  Serial.println(readbuffer[2], HEX);
  // temperature convert 9 bit value to 16bit value
  int32_t stemp = ((int32_t)(((uint32_t)((readbuffer[0] & 0x01) << 8)) | readbuffer[1])) << 7;
  // temperature convert from 16bit value
  stemp = 100.0f * ((stemp * 175.0f) / 65535.0f - 45.0f);
  temp = (float)stemp / 100.0f;
  // humidity convert 7 bit value to 16 bit value
  uint32_t shum = (uint32_t)((uint32_t)(readbuffer[0] & 0xFE) << 8);
  humidity = (shum * 100.0f) / 65535.0f;
  return true;
}

static uint8_t crc8(const uint8_t *data, int len) {
  /*
   *
   * CRC-8 formula from page 14 of SHT spec pdf
   *
   * Test data 0xBE, 0xEF should yield 0x92
   *
   * Initialization data 0xFF
   * Polynomial 0x31 (x8 + x5 +x4 +1)
   * Final XOR 0x00
   */

  const uint8_t POLYNOMIAL(0x31);
  uint8_t crc(0xFF);

  for (int j = len; j; --j) {
    crc ^= *data++;

    for (int i = 8; i; --i) {
      crc = (crc & 0x80) ? (crc << 1) ^ POLYNOMIAL : (crc << 1);
    }
  }
  return crc;
}

// read data in Periodic Data Acquisition Mode
bool readTempHum(float &temp, float &humidity) {
  uint8_t readbuffer[6];
  sht31.writeCommand(0xE000);  // Fetch Data command
  delay(20);
  sht31.i2c_dev->read(readbuffer, sizeof(readbuffer));
  if (readbuffer[2] != crc8(readbuffer, 2) || readbuffer[5] != crc8(readbuffer + 3, 2))
    return false;
  int32_t stemp = (int32_t)(((uint32_t)readbuffer[0] << 8) | readbuffer[1]);
  // simplified (65536 instead of 65535) integer version of:
  // temp = (stemp * 175.0f) / 65535.0f - 45.0f;
  stemp = ((4375 * stemp) >> 14) - 4500;
  temp = (float)stemp / 100.0f;
  uint32_t shum = ((uint32_t)readbuffer[3] << 8) | readbuffer[4];
  // simplified (65536 instead of 65535) integer version of:
  // humidity = (shum * 100.0f) / 65535.0f;
  shum = (625 * shum) >> 12;
  humidity = (float)shum / 100.0f;
  return true;
}

serial monitor output as temperature varies above set and below clear limits

sht31 limit tests
reading high alert limit set 
readHigAlertLimitSet 0xCCD822
high alert limit set temperature (should be 60.00) = 28.82  humidity (should be 80.00) = 79.69
reading high alert limit clear  0xC8CF75
high alert limit clear temperature (should be 58.00) = 25.75  humidity (should be 79.00) = 78.13
reading low alert limit set 
readLowAlertLimitSet 0x3466AD
low alert limit set(should be -10.00) = -10.13  humidity (should be 22.00) = 20.31
write high alert limit set 29.00
reading high alert limit set 
readHigAlertLimitSet 0xCCD822

new high alert limit set temperature  = 28.82  humidity  79.69
write high alert limit clear 26.00
reading high alert limit clear  0xC8CF75
new high alert limit clear temperature = 25.75  humidity  = 78.13
status 60
status 60  Temp *C = 23.84		Hum. % = 50.36
status E0  Temp *C = 23.84		Hum. % = 50.27
status E0  Temp *C = 23.83		Hum. % = 50.29
status E0  Temp *C = 23.80		Hum. % = 50.29
status E0  Temp *C = 23.80		Hum. % = 50.09
status E0  Temp *C = 26.93		Hum. % = 53.67
status E0  Temp *C = 28.74		Hum. % = 76.61
******* alert !! *******  status 8C60 alert pin state  = 1
   *** high temperature alert set !  **** 
status 8CE0  Temp *C = 28.74		Hum. % = 87.06
status 8CE0  Temp *C = 27.46		Hum. % = 85.21
status 84E0  Temp *C = 26.90		Hum. % = 73.39
status 84E0  Temp *C = 26.59		Hum. % = 60.77
status 84E0  Temp *C = 26.31		Hum. % = 53.30
status 84E0  Temp *C = 26.04		Hum. % = 49.52
status 84E0  Temp *C = 25.81		Hum. % = 47.74
******* alert !! *******  status A0 alert pin state  = 0
   *** high temperature alert cleared !  **** 
status E0  Temp *C = 25.63		Hum. % = 46.94
status E0  Temp *C = 25.51		Hum. % = 46.70
status E0  Temp *C = 25.30		Hum. % = 46.75
status E0  Temp *C = 25.16		Hum. % = 46.84
status E0  Temp *C = 24.72		Hum. % = 47.80
status E0  Temp *C = 24.68		Hum. % = 48.08
status E0  Temp *C = 24.57		Hum. % = 48.13
status E0  Temp *C = 24.55		Hum. % = 48.23
status E0  Temp *C = 29.59		Hum. % = 60.79
******* alert !! *******  status 8460 alert pin state  = 1
   *** high temperature alert set !  **** 
status 8CE0  Temp *C = 30.81		Hum. % = 80.16
status 84E0  Temp *C = 29.03		Hum. % = 75.95
status 84E0  Temp *C = 28.32		Hum. % = 62.32
status 84E0  Temp *C = 27.81		Hum. % = 51.87
status 8520  Temp *C = 27.23		Hum. % = 46.15
status 84E0  Temp *C = 26.89		Hum. % = 44.74
status 84E0  Temp *C = 26.59		Hum. % = 44.32
status 84E0  Temp *C = 26.41		Hum. % = 44.44
status 84E0  Temp *C = 26.20		Hum. % = 44.54
status 84E0  Temp *C = 25.95		Hum. % = 44.84
status 84E0  Temp *C = 25.83		Hum. % = 45.16
******* alert !! *******  status A0 alert pin state  = 0
   *** high temperature alert cleared !  **** 
status E0  Temp *C = 25.69		Hum. % = 45.53
status E0  Temp *C = 25.57		Hum. % = 45.76
status E0  Temp *C = 25.44		Hum. % = 46.05

oscilloscope odisplaying state of SHT31 alert pin output
image

it is probably simpler to use the standard sht31 libraries and test the limits say every tenth of a second in an timer interrupt routine, e.g. along the lines of

volatile int alertFlag = 0;
ISR(TIMER1_COMPA_vect) {
    if(sht31.readTemperature() > highAlertTemperatureSet)
       alertFlag = 1;  // set alert indicator
}

void loop(void) {
  .........
    if(alertFlag)
          Serial.println("high temperature alert set !");
}

ser what Arduino are you using?

a UNO R3

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.