From 2a944026c5196d771078b71d408e350067584f64 Mon Sep 17 00:00:00 2001 From: Pawel Jasinski Date: Wed, 7 Feb 2018 21:29:17 +0100 Subject: [PATCH] introduced sign into read and startread (#2246) in float build, uV and sign are included in mV in int build, uV and mV are absolute, sign is -1, 0, 1 added rounding of uV values added optional test function --- app/modules/ads1115.c | 84 ++++++++++++++++++++++++++------------ docs/en/modules/ads1115.md | 38 ++++++++++------- 2 files changed, 81 insertions(+), 41 deletions(-) diff --git a/app/modules/ads1115.c b/app/modules/ads1115.c index e814e430..1814c811 100644 --- a/app/modules/ads1115.c +++ b/app/modules/ads1115.c @@ -105,6 +105,8 @@ #define ADS1115_DEFAULT_CONFIG_REG (0x8583) // Config register value after reset +// #define ADS1115_INCLUDE_TEST_FUNCTION + //*************************************************************************** static const uint8_t ads1115_i2c_id = 0; @@ -155,7 +157,8 @@ static uint16_t read_reg(uint8_t ads_addr, uint8_t reg) { } // convert ADC value to voltage corresponding to PGA settings -static double get_volt(uint16_t gain, uint16_t value) { +// returned voltage is in milivolts +static double get_mvolt(uint16_t gain, uint16_t value) { double volt = 0; @@ -394,7 +397,7 @@ static int ads1115_lua_setting(lua_State *L) { } // Read the conversion register from the ADC device -// Lua: ads1115.device:startread(function(volt, voltdec, adc) print(volt,voltdec,adc) end) +// 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); @@ -455,46 +458,70 @@ static int ads1115_lua_startread(lua_State *L) { 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 ads1115_conversion = read_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_CONVERSION); - double ads1115_volt = get_volt(ads_ctrl->gain, ads1115_conversion); - int ads1115_voltdec = (int)((ads1115_volt - (int)ads1115_volt) * 1000); - ads1115_voltdec = ads1115_voltdec > 0 ? ads1115_voltdec : 0 - ads1115_voltdec; - + 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; - - lua_pushnumber(L, ads1115_volt); - lua_pushinteger(L, ads1115_voltdec); - lua_pushinteger(L, ads1115_conversion); - - lua_call(L, 3, 0); + read_common(ads_ctrl, raw, L); + lua_call(L, 4, 0); } // Read the conversion register from the ADC device -// Lua: volt,voltdec,adc = ads1115.device:read() +// 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 ads1115_conversion = read_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_CONVERSION); - double ads1115_volt = get_volt(ads_ctrl->gain, ads1115_conversion); - int ads1115_voltdec = (int)((ads1115_volt - (int)ads1115_volt) * 1000); - ads1115_voltdec = ads1115_voltdec > 0 ? ads1115_voltdec : 0 - ads1115_voltdec; - - lua_pushnumber(L, ads1115_volt); - lua_pushinteger(L, ads1115_voltdec); - lua_pushinteger(L, ads1115_conversion); - - return 3; + 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) { @@ -557,6 +584,9 @@ static const LUA_REG_TYPE ads1115_instance_map[] = { { LSTRKEY( "setting" ), LFUNCVAL(ads1115_lua_setting) }, { LSTRKEY( "startread" ), LFUNCVAL(ads1115_lua_startread) }, { LSTRKEY( "read" ), LFUNCVAL(ads1115_lua_read) }, +#ifdef ADS1115_INCLUDE_TEST_FUNCTION + { LSTRKEY( "test_volt_conversion" ), LFUNCVAL(test_volt_conversion)}, +#endif { LSTRKEY( "__index" ), LROVAL(ads1115_instance_map) }, { LSTRKEY( "__gc" ), LFUNCVAL(ads1115_lua_delete) }, { LNILKEY, LNILVAL } diff --git a/docs/en/modules/ads1115.md b/docs/en/modules/ads1115.md index 265cb8ea..9ae4e120 100644 --- a/docs/en/modules/ads1115.md +++ b/docs/en/modules/ads1115.md @@ -92,19 +92,20 @@ ads1115.reset() Gets the result stored in the register of a previously issued conversion, e.g. in continuous mode or with a conversion ready interrupt. #### Syntax -`volt, volt_dec, adc = device:read()` +`volt, volt_dec, raw, sign = device:read()` #### Parameters none #### Returns - `volt` voltage in mV (see note below) -- `volt_dec` voltage decimal (see note below) -- `adc` raw adc value +- `volt_dec` voltage decimal in uV (see note below) +- `adc` raw adc register value +- `sign` sign of the result (see note below) !!! note - If using float firmware then `volt` is a floating point number. On an integer firmware, the final value has to be concatenated from `volt` and `volt_dec`. Both values `volt` and `volt_dec` contains sign. + If using float firmware then `volt` is a floating point number, `volt_dec` and `sign` are nil. On an integer firmware, the final value has to be concatenated from `volt`, `volt_dec` and `sign`. On integer firmware `volt` and `volt_dec` are always positive, sign can be `-1`, `0`, `1`. #### Example ```lua @@ -116,23 +117,32 @@ adc1 = ads1115.ads1115(id, ads1115.ADDR_GND) -- continuous mode adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_128SPS, ads1115.SINGLE_0, ads1115.CONTINUOUS) -- read adc result with read() -volt, volt_dec, adc = ads1:read() -print(volt, volt_dec, adc) +volt, volt_dec, adc, sign = ads1:read() +print(volt, volt_dec, adc, sign) -- comparator adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_128SPS, ads1115.SINGLE_0, ads1115.CONTINUOUS, ads1115.COMP_1CONV, 1000, 2000) local function comparator(level, when) -- read adc result with read() when threshold reached gpio.trig(alert_pin) - volt, volt_dec, adc = ads1:read() - print(volt, volt_dec, adc) + volt, volt_dec, adc, sign = ads1:read() + print(volt, volt_dec, adc, sign) end gpio.mode(alert_pin, gpio.INT) gpio.trig(alert_pin, "both", comparator) -- read adc result with read() -volt, volt_dec, adc = ads1115:read() -print(volt, volt_dec, adc) +volt, volt_dec, adc, sign = ads1115:read() +print(volt, volt_dec, adc, sing) + +-- format value in int build +if sign then + -- int build + print(string.format("%s%d.%03d mV", sign >= 0 and "+" or "-", volt, volt_dec)) +else + -- float build + -- just use V as it is +end ``` @@ -218,7 +228,7 @@ Starts the ADC reading for single-shot mode and after the conversion is done it #### Parameters - `CALLBACK` callback function which will be invoked after the adc conversion is done - * `function(volt, volt_dec, adc) end` + * `function(volt, volt_dec, adc, sign) end` #### Returns - `nil` @@ -233,14 +243,14 @@ adc1 = ads1115.ads1115(id, ads1115.ADDR_VDD) -- single shot adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_128SPS, ads1115.SINGLE_0, ads1115.SINGLE_SHOT) -- start adc conversion and get result in callback after conversion is ready -adc1:startread(function(volt, volt_dec, adc) print(volt, volt_dec, adc) end) +adc1:startread(function(volt, volt_dec, adc, sign) print(volt, volt_dec, adc, sign) end) -- conversion ready adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_128SPS, ads1115.SINGLE_0, ads1115.SINGLE_SHOT, ads1115.CONV_RDY_1) local function conversion_ready(level, when) gpio.trig(alert_pin) - volt, volt_dec, adc = adc1:read() - print(volt, volt_dec, adc) + volt, volt_dec, adc, sign = adc1:read() + print(volt, volt_dec, adc, sign) end gpio.mode(alert_pin, gpio.INT) gpio.trig(alert_pin, "down", conversion_ready)