add si7021 module (#1921)
* add si7021 module * add settings function for resolution and heater
This commit is contained in:
parent
3e24b1c75b
commit
8668239640
|
@ -53,6 +53,7 @@
|
|||
//#define LUA_USE_MODULES_RTCFIFO
|
||||
//#define LUA_USE_MODULES_RTCMEM
|
||||
//#define LUA_USE_MODULES_RTCTIME
|
||||
//#define LUA_USE_MODULES_SI7021
|
||||
//#define LUA_USE_MODULES_SIGMA_DELTA
|
||||
//#define LUA_USE_MODULES_SJSON
|
||||
//#define LUA_USE_MODULES_SNTP
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
//***************************************************************************
|
||||
// Si7021 module for ESP8266 with nodeMCU
|
||||
// fetchbot @github
|
||||
// MIT license, http://opensource.org/licenses/MIT
|
||||
//***************************************************************************
|
||||
|
||||
#include "module.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "osapi.h"
|
||||
|
||||
//***************************************************************************
|
||||
// I2C ADDRESS DEFINITON
|
||||
//***************************************************************************
|
||||
|
||||
#define SI7021_I2C_ADDRESS (0x40)
|
||||
|
||||
//***************************************************************************
|
||||
// COMMAND DEFINITON
|
||||
//***************************************************************************
|
||||
|
||||
#define SI7021_CMD_MEASURE_RH_HOLD (0xE5)
|
||||
#define SI7021_CMD_MEASURE_RH_NOHOLD (0xF5)
|
||||
#define SI7021_CMD_MEASURE_TEMP_HOLD (0xE3)
|
||||
#define SI7021_CMD_MEASURE_TEMP_NOHOLD (0xF3)
|
||||
#define SI7021_CMD_READ_PREV_TEMP (0xE0)
|
||||
#define SI7021_CMD_RESET (0xFE)
|
||||
#define SI7021_CMD_WRITE_RHT_REG (0xE6)
|
||||
#define SI7021_CMD_READ_RHT_REG (0xE7)
|
||||
#define SI7021_CMD_WRITE_HEATER_REG (0x51)
|
||||
#define SI7021_CMD_READ_HEATER_REG (0x11)
|
||||
#define SI7021_CMD_ID1 (0xFA0F)
|
||||
#define SI7021_CMD_ID2 (0xFCC9)
|
||||
#define SI7021_CMD_FIRM_REV (0x84B8)
|
||||
|
||||
//***************************************************************************
|
||||
// REGISTER DEFINITON
|
||||
//***************************************************************************
|
||||
|
||||
#define SI7021_RH12_TEMP14 (0x00)
|
||||
#define SI7021_RH08_TEMP12 (0x01)
|
||||
#define SI7021_RH10_TEMP13 (0x80)
|
||||
#define SI7021_RH11_TEMP11 (0x81)
|
||||
#define SI7021_HEATER_ENABLE (0x04)
|
||||
#define SI7021_HEATER_DISABLE (0x00)
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
static const uint32_t si7021_i2c_id = 0;
|
||||
static uint8_t si7021_i2c_addr = SI7021_I2C_ADDRESS;
|
||||
static uint8_t si7021_res = 0x00;
|
||||
static uint8_t si7021_config = 0x3A;
|
||||
static uint8_t si7021_heater = 0x00;
|
||||
static uint8_t si7021_heater_setting = 0x00;
|
||||
|
||||
static uint8_t write_byte(uint8_t reg) {
|
||||
platform_i2c_send_start(si7021_i2c_id);
|
||||
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
|
||||
platform_i2c_send_byte(si7021_i2c_id, reg);
|
||||
platform_i2c_send_stop(si7021_i2c_id);
|
||||
}
|
||||
|
||||
static uint8_t write_reg(uint8_t reg, uint8_t data) {
|
||||
platform_i2c_send_start(si7021_i2c_id);
|
||||
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
|
||||
platform_i2c_send_byte(si7021_i2c_id, reg);
|
||||
platform_i2c_send_byte(si7021_i2c_id, data);
|
||||
platform_i2c_send_stop(si7021_i2c_id);
|
||||
}
|
||||
|
||||
static uint8_t read_reg(uint8_t reg, uint8_t *buf, uint8_t size) {
|
||||
platform_i2c_send_start(si7021_i2c_id);
|
||||
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
|
||||
platform_i2c_send_byte(si7021_i2c_id, reg);
|
||||
platform_i2c_send_stop(si7021_i2c_id);
|
||||
platform_i2c_send_start(si7021_i2c_id);
|
||||
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_RECEIVER);
|
||||
os_delay_us(25000);
|
||||
while (size-- > 0)
|
||||
*buf++ = platform_i2c_recv_byte(si7021_i2c_id, size > 0);
|
||||
platform_i2c_send_stop(si7021_i2c_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t read_serial(uint16_t reg, uint8_t *buf, uint8_t size) {
|
||||
platform_i2c_send_start(si7021_i2c_id);
|
||||
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER);
|
||||
platform_i2c_send_byte(si7021_i2c_id, (uint8_t)(reg >> 8));
|
||||
platform_i2c_send_byte(si7021_i2c_id, (uint8_t)(reg & 0xFF));
|
||||
// platform_i2c_send_stop(si7021_i2c_id);
|
||||
platform_i2c_send_start(si7021_i2c_id);
|
||||
platform_i2c_send_address(si7021_i2c_id, si7021_i2c_addr, PLATFORM_I2C_DIRECTION_RECEIVER);
|
||||
while (size-- > 0)
|
||||
*buf++ = platform_i2c_recv_byte(si7021_i2c_id, size > 0);
|
||||
platform_i2c_send_stop(si7021_i2c_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// CRC8
|
||||
uint8_t si7021_crc8(uint8_t crc, uint8_t *buf, uint8_t size) {
|
||||
while (size--) {
|
||||
crc ^= *buf++;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (crc & 0x80) {
|
||||
crc = (crc << 1) ^ 0x31;
|
||||
} else crc <<= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
static int si7021_lua_setup(lua_State* L) {
|
||||
|
||||
write_byte(SI7021_CMD_RESET);
|
||||
os_delay_us(50000);
|
||||
|
||||
// check for device on i2c bus
|
||||
uint8_t buf_r[1];
|
||||
read_reg(SI7021_CMD_READ_RHT_REG, buf_r, 1);
|
||||
if (buf_r[0] != 0x3A)
|
||||
return luaL_error(L, "found no device");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Change sensor settings and returns them
|
||||
// Lua: res, vdds, heater[, heater_set] = si7021.settings(RESOLUTION[,HEATER,HEATER_SETTING])
|
||||
static int si7021_lua_setting(lua_State* L) {
|
||||
|
||||
// check variable
|
||||
if (!lua_isnumber(L, 1)) {
|
||||
return luaL_error(L, "wrong arg range");
|
||||
}
|
||||
|
||||
si7021_res = luaL_checkinteger(L, 1);
|
||||
if (!((si7021_res == SI7021_RH12_TEMP14) || (si7021_res == SI7021_RH08_TEMP12) || (si7021_res == SI7021_RH10_TEMP13) || (si7021_res == SI7021_RH11_TEMP11))) {
|
||||
return luaL_error(L, "Invalid argument: resolution");
|
||||
}
|
||||
|
||||
si7021_config = (si7021_res | 0x3A);
|
||||
write_reg(SI7021_CMD_WRITE_RHT_REG,si7021_config);
|
||||
|
||||
// Parse optional parameters
|
||||
if (lua_isnumber(L, 2)) {
|
||||
|
||||
if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3)) {
|
||||
return luaL_error(L, "wrong arg range");
|
||||
}
|
||||
|
||||
si7021_heater = luaL_checkinteger(L, 2);
|
||||
if (!((si7021_heater == SI7021_HEATER_ENABLE) || (si7021_heater == SI7021_HEATER_DISABLE))) {
|
||||
return luaL_error(L, "Invalid argument: heater");
|
||||
}
|
||||
|
||||
si7021_heater_setting = luaL_checkinteger(L, 3);
|
||||
if ((si7021_heater_setting < 0x00) || (si7021_heater_setting > 0x0F)) {
|
||||
return luaL_error(L, "Invalid argument: heater_setting");
|
||||
}
|
||||
|
||||
si7021_config = (si7021_res | si7021_heater | 0x3A);
|
||||
write_reg(SI7021_CMD_WRITE_RHT_REG,si7021_config);
|
||||
write_reg(SI7021_CMD_WRITE_HEATER_REG,(si7021_heater_setting & 0x0F));
|
||||
}
|
||||
|
||||
uint8_t buf_c[1];
|
||||
uint8_t buf_h[1];
|
||||
read_reg(SI7021_CMD_READ_RHT_REG, buf_c, 1);
|
||||
read_reg(SI7021_CMD_READ_HEATER_REG, buf_h, 1);
|
||||
|
||||
lua_pushinteger(L, ((buf_c[0] >> 6) + (buf_c[0] & 0x01)));
|
||||
lua_pushinteger(L, ((buf_c[0] >> 6) & 0x01));
|
||||
lua_pushinteger(L, ((buf_c[0] >> 2) & 0x01));
|
||||
lua_pushinteger(L, (buf_h[0] & 0x0F));
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Reads sensor values from device and returns them
|
||||
// Lua: hum, temp, humdec, tempdec = si7021.read()
|
||||
static int si7021_lua_read(lua_State* L) {
|
||||
|
||||
uint8_t buf_h[3]; // first two byte data, third byte crc
|
||||
read_reg(SI7021_CMD_MEASURE_RH_HOLD, buf_h, 3);
|
||||
if (buf_h[2] != si7021_crc8(0, buf_h, 2)) //crc check
|
||||
return luaL_error(L, "crc error");
|
||||
double hum = (uint16_t)((buf_h[0] << 8) | buf_h[1]);
|
||||
hum = ((hum * 125) / 65536 - 6);
|
||||
int humdec = (int)((hum - (int)hum) * 1000);
|
||||
|
||||
uint8_t buf_t[2]; // two byte data, no crc on combined temp measurement
|
||||
read_reg(SI7021_CMD_READ_PREV_TEMP, buf_t, 2);
|
||||
double temp = (uint16_t)((buf_t[0] << 8) | buf_t[1]);
|
||||
temp = ((temp * 175.72) / 65536 - 46.85);
|
||||
int tempdec = (int)((temp - (int)temp) * 1000);
|
||||
|
||||
lua_pushnumber(L, hum);
|
||||
lua_pushnumber(L, temp);
|
||||
lua_pushinteger(L, humdec);
|
||||
lua_pushinteger(L, tempdec);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Reads electronic serial number from device and returns them
|
||||
// Lua: serial = si7021.serial()
|
||||
static int si7021_lua_serial(lua_State* L) {
|
||||
|
||||
uint32_t serial_a;
|
||||
uint8_t crc = 0;
|
||||
uint8_t buf_s_1[8]; // every second byte contains crc
|
||||
read_serial(SI7021_CMD_ID1, buf_s_1, 8);
|
||||
for(uint8_t i = 0; i <= 6; i+=2) {
|
||||
crc = si7021_crc8(crc, buf_s_1+i, 1);
|
||||
if (buf_s_1[i+1] != crc)
|
||||
return luaL_error(L, "crc error");
|
||||
serial_a = (serial_a << 8) + buf_s_1[i];
|
||||
}
|
||||
|
||||
uint32_t serial_b;
|
||||
crc = 0;
|
||||
uint8_t buf_s_2[6]; // every third byte contains crc
|
||||
read_serial(SI7021_CMD_ID2, buf_s_2, 6);
|
||||
for(uint8_t i = 0; i <=3; i+=3) {
|
||||
crc = si7021_crc8(crc, buf_s_2+i, 2);
|
||||
if (buf_s_2[i+2] != crc)
|
||||
return luaL_error(L, "crc error");
|
||||
serial_b = (serial_b << 16) + (buf_s_2[i] << 8) + buf_s_2[i+1];
|
||||
}
|
||||
|
||||
lua_pushinteger(L, serial_a);
|
||||
lua_pushinteger(L, serial_b);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Reads electronic firmware revision from device and returns them
|
||||
// Lua: firmware = si7021.firmware()
|
||||
static int si7021_lua_firmware(lua_State* L) {
|
||||
|
||||
uint8_t firmware;
|
||||
uint8_t buf_f[1];
|
||||
read_serial(SI7021_CMD_FIRM_REV, buf_f, 1);
|
||||
firmware = buf_f[0];
|
||||
|
||||
lua_pushinteger(L, firmware);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const LUA_REG_TYPE si7021_map[] = {
|
||||
{ LSTRKEY( "setup" ), LFUNCVAL(si7021_lua_setup) },
|
||||
{ LSTRKEY( "setting" ), LFUNCVAL(si7021_lua_setting) },
|
||||
{ LSTRKEY( "read" ), LFUNCVAL(si7021_lua_read) },
|
||||
{ LSTRKEY( "serial" ), LFUNCVAL(si7021_lua_serial) },
|
||||
{ LSTRKEY( "firmware" ), LFUNCVAL(si7021_lua_firmware) },
|
||||
{ LSTRKEY( "RH12_TEMP14" ), LNUMVAL(SI7021_RH12_TEMP14) },
|
||||
{ LSTRKEY( "RH08_TEMP12" ), LNUMVAL(SI7021_RH08_TEMP12) },
|
||||
{ LSTRKEY( "RH10_TEMP13" ), LNUMVAL(SI7021_RH10_TEMP13) },
|
||||
{ LSTRKEY( "RH11_TEMP11" ), LNUMVAL(SI7021_RH11_TEMP11) },
|
||||
{ LSTRKEY( "HEATER_ENABLE" ), LNUMVAL(SI7021_HEATER_ENABLE) },
|
||||
{ LSTRKEY( "HEATER_DISABLE" ), LNUMVAL(SI7021_HEATER_DISABLE) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
NODEMCU_MODULE(SI7021, "si7021", si7021_map, NULL);
|
|
@ -0,0 +1,152 @@
|
|||
# Si7021 Module
|
||||
| Since | Origin / Contributor | Maintainer | Source |
|
||||
| :----- | :-------------------- | :---------- | :------ |
|
||||
| 2017-04-19 | [fetchbot](https://github.com/fetchbot) | [fetchbot](https://github.com/fetchbot) | [si7021.c](../../../app/modules/si7021.c)|
|
||||
|
||||
This module provides access to the Si7021 humidity and temperature sensor.
|
||||
|
||||
## si7021.firmware()
|
||||
Read the internal firmware revision of the Si7021 sensor.
|
||||
|
||||
#### Syntax
|
||||
`si7021.firmware()`
|
||||
|
||||
#### Parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
`fwrev` Firmware version
|
||||
* `0xFF` Firmware version 1.0
|
||||
* `0x20` Firmware version 2.0
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
local sda, scl = 6, 5
|
||||
i2c.setup(0, sda, scl, i2c.SLOW) -- call i2c.setup() only once
|
||||
si7021.setup()
|
||||
|
||||
fwrev = si7021.firmware()
|
||||
print(string.format("FW: %X\r\n", fwrev))
|
||||
```
|
||||
|
||||
## si7021.setting()
|
||||
Settings for the sensors configuration register to adjust measurement resolution, on-chip heater and read the supply voltage status.
|
||||
|
||||
#### Syntax
|
||||
`si7021.setting(RESOLUTION[, HEATER, HEATER_SETTING])`
|
||||
|
||||
#### Parameters
|
||||
- `RESOLUTION`
|
||||
* `si7021.RH12_TEMP14` Relative Humidity 12 bit - Temperature 14 bit (default)
|
||||
* `si7021.RH08_TEMP12` Relative Humidity 8 bit - Temperature 12 bit
|
||||
* `si7021.RH10_TEMP13` Relative Humidity 10 bit - Temperature 13 bit
|
||||
* `si7021.RH11_TEMP11` Relative Humidity 11 bit - Temperature 11 bit
|
||||
- `HEATER` optional
|
||||
* `si7021.HEATER_ENABLE` On-chip Heater Enable
|
||||
* `si7021.HEATER_DISABLE` On-chip Heater Disable (default)
|
||||
- `HEATER_SETTING` optional
|
||||
* `0x00` - `0x0F` 3.09 mA - 94.20 mA
|
||||
|
||||
#### Returns
|
||||
- `resolution`
|
||||
* `0` Relative Humidity 12 bit - Temperature 14 bit
|
||||
* `1` Relative Humidity 8 bit - Temperature 12 bit
|
||||
* `2` Relative Humidity 10 bit - Temperature 13 bit
|
||||
* `3` Relative Humidity 11 bit - Temperature 11 bit
|
||||
- `vdds`
|
||||
* `0` VDD OK (1.9V - 3.6V)
|
||||
* `1` VDD LOW (1.8V - 1.9V)
|
||||
- `heater`
|
||||
* `0` Disabled
|
||||
* `1` Enabled
|
||||
- `heater_setting`
|
||||
* `0` - `15`
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
local id, sda, scl = 0, 6, 5
|
||||
i2c.setup(id, sda, scl, i2c.SLOW) -- call i2c.setup() only once
|
||||
si7021.setup()
|
||||
|
||||
res, vdds, heater, heater_set = si7021.setting(si7021.RH12_TEMP14)
|
||||
res, vdds, heater, heater_set = si7021.setting(si7021.RH12_TEMP14, si7021.HEATER_ENABLE, 0x01)
|
||||
```
|
||||
|
||||
## si7021.setup()
|
||||
Initializes the device on fixed I²C device address (0x40).
|
||||
|
||||
#### Syntax
|
||||
`si7021.setup()`
|
||||
|
||||
#### Parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
local sda, scl = 6, 5
|
||||
i2c.setup(0, sda, scl, i2c.SLOW) -- call i2c.setup() only once
|
||||
si7021.setup()
|
||||
```
|
||||
|
||||
## si7021.read()
|
||||
|
||||
#### Syntax
|
||||
`si7021.read()`
|
||||
|
||||
#### Parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
- `hum` humidity (see note below)
|
||||
- `temp` temperature (see note below)
|
||||
- `hum_dec` humidity decimal
|
||||
- `temp_dec` temperature decimal
|
||||
|
||||
!!! note
|
||||
|
||||
If using float firmware then `hum` and `temp` are floating point numbers. On an integer firmware, the final values have to be concatenated from `hum` and `hum_dec` / `temp` and `temp_dec`.
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
local sda, scl = 6, 5
|
||||
i2c.setup(0, sda, scl, i2c.SLOW) -- call i2c.setup() only once
|
||||
si7021.setup()
|
||||
|
||||
hum, temp, hum_dec, temp_dec = si7021.read()
|
||||
|
||||
-- Integer firmware using this example
|
||||
print(string.format("Humidity:\t\t%d.%03d\nTemperature:\t%d.%03d\n", hum, hum_dec, temp, temp_dec))
|
||||
|
||||
-- Float firmware using this example
|
||||
print("Humidity: "..hum.."\n".."Temperature: "..temp)
|
||||
```
|
||||
|
||||
## si7021.serial()
|
||||
Read the individualized 64-bit electronic serial number of the Si7021 sensor.
|
||||
|
||||
#### Syntax
|
||||
`si7021.serial()`
|
||||
|
||||
#### Parameters
|
||||
none
|
||||
|
||||
#### Returns
|
||||
- `sna` 32-bit serial number part a
|
||||
- `snb` 32-bit serial number part b, upper byte contains the device identification
|
||||
* `0x00` or `0xFF` engineering samples
|
||||
* `0x0D` `13` Si7013
|
||||
* `0x14` `20` Si7020
|
||||
* `0x15` `21` Si7021
|
||||
|
||||
#### Example
|
||||
```lua
|
||||
local sda, scl = 6, 5
|
||||
i2c.setup(0, sda, scl, i2c.SLOW) -- call i2c.setup() only once
|
||||
si7021.setup()
|
||||
|
||||
sna, snb = si7021.serial()
|
||||
print(string.format("SN:\t\t%X%X\nDevice:\tSi70%d", sna, snb, bit.rshift(snb,24)))
|
||||
```
|
|
@ -72,6 +72,7 @@ pages:
|
|||
- 'rtcfifo': 'en/modules/rtcfifo.md'
|
||||
- 'rtcmem': 'en/modules/rtcmem.md'
|
||||
- 'rtctime': 'en/modules/rtctime.md'
|
||||
- 'si7021' : 'en/modules/si7021'
|
||||
- 'sigma delta': 'en/modules/sigma-delta.md'
|
||||
- 'sjson': 'en/modules/sjson.md'
|
||||
- 'sntp': 'en/modules/sntp.md'
|
||||
|
|
Loading…
Reference in New Issue