//*************************************************************************** // 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" #include "c_stdlib.h" //*************************************************************************** // CHIP //*************************************************************************** #define ADS1115_ADS1015 ( 15) #define ADS1115_ADS1115 (115) //*************************************************************************** // I2C ADDRESS DEFINITON //*************************************************************************** #define ADS1115_I2C_ADDR_GND (0x48) #define ADS1115_I2C_ADDR_VDD (0x49) #define ADS1115_I2C_ADDR_SDA (0x4A) #define ADS1115_I2C_ADDR_SCL (0x4B) #define IS_I2C_ADDR_VALID(addr) (((addr) & 0xFC) == 0x48) //*************************************************************************** // POINTER REGISTER //*************************************************************************** #define ADS1115_POINTER_MASK (0x03) #define ADS1115_POINTER_CONVERSION (0x00) #define ADS1115_POINTER_CONFIG (0x01) #define ADS1115_POINTER_THRESH_LOW (0x02) #define ADS1115_POINTER_THRESH_HI (0x03) //*************************************************************************** // CONFIG REGISTER //*************************************************************************** #define ADS1115_OS_MASK (0x8000) #define ADS1115_OS_NON (0x0000) #define ADS1115_OS_SINGLE (0x8000) // Write: Set to start a single-conversion #define ADS1115_OS_BUSY (0x0000) // Read: Bit = 0 when conversion is in progress #define ADS1115_OS_NOTBUSY (0x8000) // Read: Bit = 1 when device is not performing a conversion #define ADS1115_MUX_MASK (0x7000) #define ADS1115_MUX_DIFF_0_1 (0x0000) // Differential P = AIN0, N = AIN1 (default) #define ADS1115_MUX_DIFF_0_3 (0x1000) // Differential P = AIN0, N = AIN3 #define ADS1115_MUX_DIFF_1_3 (0x2000) // Differential P = AIN1, N = AIN3 #define ADS1115_MUX_DIFF_2_3 (0x3000) // Differential P = AIN2, N = AIN3 #define ADS1115_MUX_SINGLE_0 (0x4000) // Single-ended AIN0 #define ADS1115_MUX_SINGLE_1 (0x5000) // Single-ended AIN1 #define ADS1115_MUX_SINGLE_2 (0x6000) // Single-ended AIN2 #define ADS1115_MUX_SINGLE_3 (0x7000) // Single-ended AIN3 #define IS_CHANNEL_VALID(channel) (((channel) & 0x8FFF) == 0) #define ADS1115_PGA_MASK (0x0E00) #define ADS1115_PGA_6_144V (0x0000) // +/-6.144V range = Gain 2/3 #define ADS1115_PGA_4_096V (0x0200) // +/-4.096V range = Gain 1 #define ADS1115_PGA_2_048V (0x0400) // +/-2.048V range = Gain 2 (default) #define ADS1115_PGA_1_024V (0x0600) // +/-1.024V range = Gain 4 #define ADS1115_PGA_0_512V (0x0800) // +/-0.512V range = Gain 8 #define ADS1115_PGA_0_256V (0x0A00) // +/-0.256V range = Gain 16 #define ADS1115_MODE_MASK (0x0100) #define ADS1115_MODE_CONTIN (0x0000) // Continuous conversion mode #define ADS1115_MODE_SINGLE (0x0100) // Power-down single-shot mode (default) #define ADS1115_DR_MASK (0x00E0) #define ADS1115_DR_8SPS ( 8) #define ADS1115_DR_16SPS ( 16) #define ADS1115_DR_32SPS ( 32) #define ADS1115_DR_64SPS ( 64) #define ADS1115_DR_128SPS ( 128) #define ADS1115_DR_250SPS ( 250) #define ADS1115_DR_475SPS ( 475) #define ADS1115_DR_490SPS ( 490) #define ADS1115_DR_860SPS ( 860) #define ADS1115_DR_920SPS ( 920) #define ADS1115_DR_1600SPS (1600) #define ADS1115_DR_2400SPS (2400) #define ADS1115_DR_3300SPS (3300) #define ADS1115_CMODE_MASK (0x0010) #define ADS1115_CMODE_TRAD (0x0000) // Traditional comparator with hysteresis (default) #define ADS1115_CMODE_WINDOW (0x0010) // Window comparator #define ADS1115_CPOL_MASK (0x0008) #define ADS1115_CPOL_ACTVLOW (0x0000) // ALERT/RDY pin is low when active (default) #define ADS1115_CPOL_ACTVHI (0x0008) // ALERT/RDY pin is high when active #define ADS1115_CLAT_MASK (0x0004) // Determines if ALERT/RDY pin latches once asserted #define ADS1115_CLAT_NONLAT (0x0000) // Non-latching comparator (default) #define ADS1115_CLAT_LATCH (0x0004) // Latching comparator #define ADS1115_CQUE_MASK (0x0003) #define ADS1115_CQUE_1CONV (0x0000) // Assert ALERT/RDY after one conversions #define ADS1115_CQUE_2CONV (0x0001) // Assert ALERT/RDY after two conversions #define ADS1115_CQUE_4CONV (0x0002) // Assert ALERT/RDY after four conversions #define ADS1115_CQUE_NONE (0x0003) // Disable the comparator and put ALERT/RDY in high state (default) #define ADS1115_DEFAULT_CONFIG_REG (0x8583) // Config register value after reset // #define ADS1115_INCLUDE_TEST_FUNCTION //*************************************************************************** static const uint8_t ads1115_i2c_id = 0; static const uint8_t general_i2c_addr = 0x00; static const uint8_t ads1115_i2c_reset = 0x06; static const char metatable_name[] = "ads1115.device"; static const char unexpected_value[] = "unexpected value"; typedef struct { uint8_t i2c_addr; uint8_t chip_id; uint16_t gain; uint16_t samples_value; // sample per second uint16_t samples; // register value uint16_t comp; uint16_t mode; uint16_t threshold_low; uint16_t threshold_hi; uint16_t config; int timer_ref; os_timer_t timer; } ads_ctrl_ud_t; static int ads1115_lua_readoutdone(void * param); static int ads1115_lua_register(lua_State *L, uint8_t chip_id); static uint8_t write_reg(uint8_t ads_addr, uint8_t reg, uint16_t config) { platform_i2c_send_start(ads1115_i2c_id); platform_i2c_send_address(ads1115_i2c_id, ads_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER); platform_i2c_send_byte(ads1115_i2c_id, reg); platform_i2c_send_byte(ads1115_i2c_id, (uint8_t)(config >> 8)); platform_i2c_send_byte(ads1115_i2c_id, (uint8_t)(config & 0xFF)); platform_i2c_send_stop(ads1115_i2c_id); } static uint16_t read_reg(uint8_t ads_addr, uint8_t reg) { platform_i2c_send_start(ads1115_i2c_id); platform_i2c_send_address(ads1115_i2c_id, ads_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER); platform_i2c_send_byte(ads1115_i2c_id, reg); platform_i2c_send_stop(ads1115_i2c_id); platform_i2c_send_start(ads1115_i2c_id); platform_i2c_send_address(ads1115_i2c_id, ads_addr, PLATFORM_I2C_DIRECTION_RECEIVER); uint16_t buf = (platform_i2c_recv_byte(ads1115_i2c_id, 1) << 8); buf += platform_i2c_recv_byte(ads1115_i2c_id, 0); platform_i2c_send_stop(ads1115_i2c_id); return buf; } // convert ADC value to voltage corresponding to PGA settings // returned voltage is in milivolts static double get_mvolt(uint16_t gain, uint16_t value) { double volt = 0; switch (gain) { case (ADS1115_PGA_6_144V): volt = (int16_t)value * 0.1875; break; case (ADS1115_PGA_4_096V): volt = (int16_t)value * 0.125; break; case (ADS1115_PGA_2_048V): volt = (int16_t)value * 0.0625; break; case (ADS1115_PGA_1_024V): volt = (int16_t)value * 0.03125; break; case (ADS1115_PGA_0_512V): volt = (int16_t)value * 0.015625; break; case (ADS1115_PGA_0_256V): volt = (int16_t)value * 0.0078125; break; } return volt; } // validates and convert threshold in volt to ADC value corresponding to PGA settings // returns true if valid static uint8_t get_value(uint16_t gain, uint16_t channel, int16_t *volt) { switch (gain) { case (ADS1115_PGA_6_144V): if ((*volt >= 6144) || (*volt < -6144) || ((*volt < 0) && (channel >> 14))) return 0; *volt = *volt / 0.1875; break; case (ADS1115_PGA_4_096V): if ((*volt >= 4096) || (*volt < -4096) || ((*volt < 0) && (channel >> 14))) return 0; *volt = *volt / 0.125; break; case (ADS1115_PGA_2_048V): if ((*volt >= 2048) || (*volt < -2048) || ((*volt < 0) && (channel >> 14))) return 0; *volt = *volt / 0.0625; break; case (ADS1115_PGA_1_024V): if ((*volt >= 1024) || (*volt < -1024) || ((*volt < 0) && (channel >> 14))) return 0; *volt = *volt / 0.03125; break; case (ADS1115_PGA_0_512V): if ((*volt >= 512) || (*volt < -512) || ((*volt < 0) && (channel >> 14))) return 0; *volt = *volt / 0.015625; break; case (ADS1115_PGA_0_256V): if ((*volt >= 256) || (*volt < -256) || ((*volt < 0) && (channel >> 14))) return 0; *volt = *volt / 0.0078125; break; } return 1; } // Reset of all devices // Lua: ads1115.reset() static int ads1115_lua_reset(lua_State *L) { platform_i2c_send_start(ads1115_i2c_id); platform_i2c_send_address(ads1115_i2c_id, general_i2c_addr, PLATFORM_I2C_DIRECTION_TRANSMITTER); platform_i2c_send_byte(ads1115_i2c_id, ads1115_i2c_reset); platform_i2c_send_stop(ads1115_i2c_id); return 0; } // Register an ADS device // Lua: ads1115.ADS1115(I2C_ID, ADDRESS) static int ads1115_lua_register_1115(lua_State *L) { return ads1115_lua_register(L, ADS1115_ADS1115); } static int ads1115_lua_register_1015(lua_State *L) { return ads1115_lua_register(L, ADS1115_ADS1015); } static int ads1115_lua_register(lua_State *L, uint8_t chip_id) { uint8_t i2c_id = luaL_checkinteger(L, 1); luaL_argcheck(L, 0 == i2c_id, 1, "i2c_id must be 0"); uint8_t i2c_addr = luaL_checkinteger(L, 2); luaL_argcheck(L, IS_I2C_ADDR_VALID(i2c_addr), 2, unexpected_value); uint16_t config_read = read_reg(i2c_addr, ADS1115_POINTER_CONFIG); if (config_read == 0xFFFF) { return luaL_error(L, "found no device"); } if (config_read != ADS1115_DEFAULT_CONFIG_REG) { return luaL_error(L, "unexpected config value (%p) please reset device before calling this function", config_read); } ads_ctrl_ud_t *ads_ctrl = (ads_ctrl_ud_t *)lua_newuserdata(L, sizeof(ads_ctrl_ud_t)); if (NULL == ads_ctrl) { return luaL_error(L, "ads1115 malloc: out of memory"); } luaL_getmetatable(L, metatable_name); lua_setmetatable(L, -2); ads_ctrl->chip_id = chip_id; ads_ctrl->i2c_addr = i2c_addr; ads_ctrl->gain = ADS1115_PGA_6_144V; ads_ctrl->samples = ADS1115_DR_128SPS; ads_ctrl->samples_value = chip_id == ADS1115_ADS1115 ? 128 : 1600; ads_ctrl->comp = ADS1115_CQUE_NONE; ads_ctrl->mode = ADS1115_MODE_SINGLE; ads_ctrl->threshold_low = 0x8000; ads_ctrl->threshold_hi = 0x7FFF; ads_ctrl->config = ADS1115_DEFAULT_CONFIG_REG; ads_ctrl->timer_ref = LUA_NOREF; return 1; } // Change the ADC device settings // Lua: ads1115.device:settings(GAIN,SAMPLES,CHANNEL,MODE[,CONVERSION_RDY][,COMPARATOR,THRESHOLD_LOW,THRESHOLD_HI[,COMP_MODE]) static int ads1115_lua_setting(lua_State *L) { int argc = lua_gettop(L); if (argc != 5 && argc != 6 && argc != 8 && argc != 9) { // user data counts luaL_error(L, "invalid number of arguments to 'setting'"); } ads_ctrl_ud_t *ads_ctrl = luaL_checkudata(L, 1, metatable_name); // gain uint16_t gain = luaL_checkinteger(L, 2); luaL_argcheck(L, (gain == ADS1115_PGA_6_144V) || (gain == ADS1115_PGA_4_096V) || (gain == ADS1115_PGA_2_048V) || (gain == ADS1115_PGA_1_024V) || (gain == ADS1115_PGA_0_512V) || (gain == ADS1115_PGA_0_256V), 2, unexpected_value); ads_ctrl->gain = gain; // samples uint16_t samples_value = luaL_checkinteger(L, 3); uint16_t samples = 0; if (ads_ctrl->chip_id == ADS1115_ADS1115) { switch(samples_value) { case ADS1115_DR_8SPS: samples = 0; break; case ADS1115_DR_16SPS: samples = 0x20; break; case ADS1115_DR_32SPS: samples = 0x40; break; case ADS1115_DR_64SPS: samples = 0x60; break; case ADS1115_DR_128SPS: // default samples = 0x80; break; case ADS1115_DR_250SPS: samples = 0xA0; break; case ADS1115_DR_475SPS: samples = 0xC0; break; case ADS1115_DR_860SPS: samples = 0xE0; break; default: luaL_argerror(L, 3, unexpected_value); } } else { // ADS1115_ADS1015 switch(samples_value) { case ADS1115_DR_128SPS: samples = 0; break; case ADS1115_DR_250SPS: samples = 0x20; break; case ADS1115_DR_490SPS: samples = 0x40; break; case ADS1115_DR_920SPS: samples = 0x60; break; case ADS1115_DR_1600SPS: // default samples = 0x80; break; case ADS1115_DR_2400SPS: samples = 0xA0; break; case ADS1115_DR_3300SPS: samples = 0xC0; break; default: luaL_argerror(L, 3, unexpected_value); } } ads_ctrl->samples = samples; ads_ctrl->samples_value = samples_value; // channel uint16_t channel = luaL_checkinteger(L, 4); luaL_argcheck(L, IS_CHANNEL_VALID(channel), 4, unexpected_value); // mode uint16_t mode = luaL_checkinteger(L, 5); luaL_argcheck(L, (mode == ADS1115_MODE_SINGLE) || (mode == ADS1115_MODE_CONTIN), 5, unexpected_value); ads_ctrl->mode = mode; uint16_t os = mode == ADS1115_MODE_SINGLE ? ADS1115_OS_SINGLE : ADS1115_OS_NON; uint16_t comp = ADS1115_CQUE_NONE; // Parse optional parameters if (argc > 5) { // comparator or conversion count comp = luaL_checkinteger(L, 6); luaL_argcheck(L, (comp == ADS1115_CQUE_1CONV) || (comp == ADS1115_CQUE_2CONV) || (comp == ADS1115_CQUE_4CONV), 6, unexpected_value); uint16_t threshold_low = 0x7FFF; uint16_t threshold_hi = 0x8000; if (argc > 6) { // comparator thresholds threshold_low = luaL_checkinteger(L, 7); threshold_hi = luaL_checkinteger(L, 8); luaL_argcheck(L, (int16_t)threshold_low <= (int16_t)threshold_hi, 7, "threshold_low > threshold_hi"); luaL_argcheck(L, get_value(gain, channel, &threshold_low), 7, unexpected_value); luaL_argcheck(L, get_value(gain, channel, &threshold_hi), 8, unexpected_value); } ads_ctrl->threshold_low = threshold_low; ads_ctrl->threshold_hi = threshold_hi; NODE_DBG("ads1115 low: %04x\n", threshold_low); NODE_DBG("ads1115 hi : %04x\n", threshold_hi); write_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_THRESH_LOW, threshold_low); write_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_THRESH_HI, threshold_hi); } ads_ctrl->comp = comp; uint16_t comparator_mode = ADS1115_CMODE_TRAD; if (argc == 9) { comparator_mode = luaL_checkinteger(L, 9); luaL_argcheck(L, (comparator_mode == ADS1115_CMODE_WINDOW) || (comparator_mode == ADS1115_CMODE_TRAD), 9, unexpected_value); } uint16_t config = (os | channel | gain | mode | samples | comparator_mode | ADS1115_CPOL_ACTVLOW | ADS1115_CLAT_NONLAT | comp); ads_ctrl->config = config; NODE_DBG("ads1115 config: %04x\n", ads_ctrl->config); write_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_CONFIG, config); return 0; } // Read the conversion register from the ADC device // Lua: ads1115.device:startread(function(volt, voltdec, adc, sign) print(volt,voltdec,adc,sign) end) static int ads1115_lua_startread(lua_State *L) { ads_ctrl_ud_t *ads_ctrl = luaL_checkudata(L, 1, metatable_name); if (((ads_ctrl->comp == ADS1115_CQUE_1CONV) || (ads_ctrl->comp == ADS1115_CQUE_2CONV) || (ads_ctrl->comp == ADS1115_CQUE_4CONV)) && (ads_ctrl->threshold_low == 0x7FFF) && (ads_ctrl->threshold_hi == 0x8000)) { // conversion ready mode if (ads_ctrl->mode == ADS1115_MODE_SINGLE) { NODE_DBG("ads1115 trigger config: %04x", ads_ctrl->config); write_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_CONFIG, ads_ctrl->config); } return 0; } luaL_argcheck(L, (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION), 2, "Must be function"); lua_pushvalue(L, 2); ads_ctrl->timer_ref = luaL_ref(L, LUA_REGISTRYINDEX); if (ads_ctrl->mode == ADS1115_MODE_SINGLE) { write_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_CONFIG, ads_ctrl->config); } // Start a timer to wait until ADC conversion is done os_timer_disarm(&ads_ctrl->timer); os_timer_setfn(&ads_ctrl->timer, (os_timer_func_t *)ads1115_lua_readoutdone, (void *)ads_ctrl); int msec = 1; // ADS1115_DR_1600SPS, ADS1115_DR_2400SPS, ADS1115_DR_3300SPS switch (ads_ctrl->samples_value) { case ADS1115_DR_8SPS: msec = 150; break; case ADS1115_DR_16SPS: msec = 75; break; case ADS1115_DR_32SPS: msec = 35; break; case ADS1115_DR_64SPS: msec = 20; break; case ADS1115_DR_128SPS: msec = 10; break; case ADS1115_DR_250SPS: msec = 5; break; case ADS1115_DR_475SPS: case ADS1115_DR_490SPS: msec = 3; break; case ADS1115_DR_860SPS: case ADS1115_DR_920SPS: msec = 2; } os_timer_arm(&ads_ctrl->timer, msec, 0); return 0; } static void read_common(ads_ctrl_ud_t * ads_ctrl, uint16_t raw, lua_State *L) { double mvolt = get_mvolt(ads_ctrl->gain, raw); #ifdef LUA_NUMBER_INTEGRAL int sign; if (mvolt == 0) { sign = 0; } else if (mvolt > 0) { sign = 1; } else { sign = -1; } int uvolt; if (sign >= 0) { uvolt = (int)((mvolt - (int)mvolt) * 1000 + 0.5); } else { uvolt = -(int)((mvolt - (int)mvolt) * 1000 - 0.5); mvolt = -mvolt; } lua_pushnumber(L, mvolt); lua_pushinteger(L, uvolt); lua_pushinteger(L, raw); lua_pushinteger(L, sign); #else lua_pushnumber(L, mvolt); lua_pushnil(L); lua_pushinteger(L, raw); lua_pushnil(L); #endif } // adc conversion timer callback static int ads1115_lua_readoutdone(void * param) { ads_ctrl_ud_t * ads_ctrl = (ads_ctrl_ud_t *)param; uint16_t raw = read_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_CONVERSION); lua_State *L = lua_getstate(); os_timer_disarm(&ads_ctrl->timer); lua_rawgeti(L, LUA_REGISTRYINDEX, ads_ctrl->timer_ref); luaL_unref(L, LUA_REGISTRYINDEX, ads_ctrl->timer_ref); ads_ctrl->timer_ref = LUA_NOREF; read_common(ads_ctrl, raw, L); lua_call(L, 4, 0); } // Read the conversion register from the ADC device // Lua: volt,voltdec,adc,sign = ads1115.device:read() static int ads1115_lua_read(lua_State *L) { ads_ctrl_ud_t *ads_ctrl = luaL_checkudata(L, 1, metatable_name); uint16_t raw = read_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_CONVERSION); read_common(ads_ctrl, raw, L); return 4; } #ifdef ADS1115_INCLUDE_TEST_FUNCTION // this function simulates conversion using raw value provided as argument // Lua: volt,volt_dec,adc,sign = ads1115.test_volt_conversion(-1) static int test_volt_conversion(lua_State *L) { ads_ctrl_ud_t *ads_ctrl = luaL_checkudata(L, 1, metatable_name); uint16_t raw = luaL_checkinteger(L, 2); read_common(ads_ctrl, raw, L); return 4; } #endif static int ads1115_lua_delete(lua_State *L) { ads_ctrl_ud_t *ads_ctrl = luaL_checkudata(L, 1, metatable_name); if (ads_ctrl->timer_ref != LUA_NOREF) { os_timer_disarm(&ads_ctrl->timer); luaL_unref(L, LUA_REGISTRYINDEX, ads_ctrl->timer_ref); } return 0; } LROT_BEGIN(ads1115) LROT_FUNCENTRY( ads1115, ads1115_lua_register_1115 ) LROT_FUNCENTRY( ads1015, ads1115_lua_register_1015 ) LROT_FUNCENTRY( reset, ads1115_lua_reset ) LROT_NUMENTRY( ADDR_GND, ADS1115_I2C_ADDR_GND ) LROT_NUMENTRY( ADDR_VDD, ADS1115_I2C_ADDR_VDD ) LROT_NUMENTRY( ADDR_SDA, ADS1115_I2C_ADDR_SDA ) LROT_NUMENTRY( ADDR_SCL, ADS1115_I2C_ADDR_SCL ) LROT_NUMENTRY( SINGLE_SHOT, ADS1115_MODE_SINGLE ) LROT_NUMENTRY( CONTINUOUS, ADS1115_MODE_CONTIN ) LROT_NUMENTRY( DIFF_0_1, ADS1115_MUX_DIFF_0_1 ) LROT_NUMENTRY( DIFF_0_3, ADS1115_MUX_DIFF_0_3 ) LROT_NUMENTRY( DIFF_1_3, ADS1115_MUX_DIFF_1_3 ) LROT_NUMENTRY( DIFF_2_3, ADS1115_MUX_DIFF_2_3 ) LROT_NUMENTRY( SINGLE_0, ADS1115_MUX_SINGLE_0 ) LROT_NUMENTRY( SINGLE_1, ADS1115_MUX_SINGLE_1 ) LROT_NUMENTRY( SINGLE_2, ADS1115_MUX_SINGLE_2 ) LROT_NUMENTRY( SINGLE_3, ADS1115_MUX_SINGLE_3 ) LROT_NUMENTRY( GAIN_6_144V, ADS1115_PGA_6_144V ) LROT_NUMENTRY( GAIN_4_096V, ADS1115_PGA_4_096V ) LROT_NUMENTRY( GAIN_2_048V, ADS1115_PGA_2_048V ) LROT_NUMENTRY( GAIN_1_024V, ADS1115_PGA_1_024V ) LROT_NUMENTRY( GAIN_0_512V, ADS1115_PGA_0_512V ) LROT_NUMENTRY( GAIN_0_256V, ADS1115_PGA_0_256V ) LROT_NUMENTRY( DR_8SPS, ADS1115_DR_8SPS ) LROT_NUMENTRY( DR_16SPS, ADS1115_DR_16SPS ) LROT_NUMENTRY( DR_32SPS, ADS1115_DR_32SPS ) LROT_NUMENTRY( DR_64SPS, ADS1115_DR_64SPS ) LROT_NUMENTRY( DR_128SPS, ADS1115_DR_128SPS ) LROT_NUMENTRY( DR_250SPS, ADS1115_DR_250SPS ) LROT_NUMENTRY( DR_475SPS, ADS1115_DR_475SPS ) LROT_NUMENTRY( DR_490SPS, ADS1115_DR_490SPS ) LROT_NUMENTRY( DR_860SPS, ADS1115_DR_860SPS ) LROT_NUMENTRY( DR_920SPS, ADS1115_DR_920SPS ) LROT_NUMENTRY( DR_1600SPS, ADS1115_DR_1600SPS ) LROT_NUMENTRY( DR_2400SPS, ADS1115_DR_2400SPS ) LROT_NUMENTRY( DR_3300SPS, ADS1115_DR_3300SPS ) LROT_NUMENTRY( CONV_RDY_1, ADS1115_CQUE_1CONV ) LROT_NUMENTRY( CONV_RDY_2, ADS1115_CQUE_2CONV ) LROT_NUMENTRY( CONV_RDY_4, ADS1115_CQUE_4CONV ) LROT_NUMENTRY( COMP_1CONV, ADS1115_CQUE_1CONV ) LROT_NUMENTRY( COMP_2CONV, ADS1115_CQUE_2CONV ) LROT_NUMENTRY( COMP_4CONV, ADS1115_CQUE_4CONV ) LROT_NUMENTRY( CMODE_TRAD, ADS1115_CMODE_TRAD ) LROT_NUMENTRY( CMODE_WINDOW, ADS1115_CMODE_WINDOW ) LROT_END(ads1115, NULL, 0 ) LROT_BEGIN(ads1115_instance) LROT_FUNCENTRY( setting, ads1115_lua_setting ) LROT_FUNCENTRY( startread, ads1115_lua_startread ) LROT_FUNCENTRY( read, ads1115_lua_read ) #ifdef ADS1115_INCLUDE_TEST_FUNCTION LROT_FUNCENTRY( test_volt_conversion, test_volt_conversion ) #endif LROT_TABENTRY( __index, ads1115_instance ) LROT_FUNCENTRY( __gc, ads1115_lua_delete ) LROT_END(ads1115_instance, ads1115_instance, LROT_MASK_GC_INDEX ) int luaopen_ads1115(lua_State *L) { luaL_rometatable(L, metatable_name, LROT_TABLEREF(ads1115_instance)); return 0; } NODEMCU_MODULE(ADS1115, "ads1115", ads1115, luaopen_ads1115);