ソースを参照

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
Pawel Jasinski 6 年 前
コミット
2a944026c5
2 ファイル変更80 行追加40 行削除
  1. 56 26
      app/modules/ads1115.c
  2. 24 14
      docs/en/modules/ads1115.md

+ 56 - 26
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,45 +458,69 @@ 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 raw = read_reg(ads_ctrl->i2c_addr, ADS1115_POINTER_CONVERSION);
+    read_common(ads_ctrl, raw, L);
+    return 4;
+}
 
-    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;
+#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);
@@ -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                                            }

+ 24 - 14
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)