Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADS1115 adc1:setting #2753

Closed
ZOZOliv opened this issue May 10, 2019 · 12 comments
Closed

ADS1115 adc1:setting #2753

ZOZOliv opened this issue May 10, 2019 · 12 comments

Comments

@ZOZOliv
Copy link

ZOZOliv commented May 10, 2019

Expected behavior

I try to read the value of the channel 0 from the ADS1115, i use the code provided on the documentation

Actual behavior

I got an error :
test.lua:5: attempt to index global 'adc1' (a userdata value)
stack traceback:
test.lua:5: in main chunk
[C]: in function 'dofile'
stdin:1: in main chunk

I think it's a problem on the syntax with 'adc1'

Test code

Provide a Minimal, Complete, and Verifiable example which will reproduce the problem.

id, sda, scl = 0, 2, 1
i2c.setup(id, sda, scl, i2c.SLOW)
ads1115.reset()
adc1 = ads1115.ads1115(id, ads1115.ADDR_GND)
adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_8SPS, ads1115.SINGLE_0, ads1115.SINGLE_SHOT)
adc1:startread(
    function(volt, volt_dec, adc, sign)
        print("getChannel...")
        print("volt: " + volt + ", volt_dec: " + volt_dec + ", adc: " + adc + ", sign: " + sign)
    end
)

NodeMCU version

I use the dev branch

Hardware

I use an esp8266-12

@KT819GM
Copy link

KT819GM commented May 11, 2019

Can confirm. Issue does not exist on master branch.

@ZOZOliv
Copy link
Author

ZOZOliv commented May 11, 2019

Thanks i try on master branch, its works
I make some correction on my previous code

id, sda, scl = 0, 2, 1
i2c.setup(id, sda, scl, i2c.SLOW)
ads1115.reset()
adc1 = ads1115.ads1115(id, ads1115.ADDR_GND)
adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_8SPS, ads1115.SINGLE_0, ads1115.SINGLE_SHOT)
adc1:startread(
    function(volt, volt_dec, adc, sign)
        print("getChannel...")
        if volt ~= nil then
            print("volt: " .. volt)
        end
        if volt_dec ~= nil then
            print("volt_dec: " .. volt_dec)
        end
        if adc ~= nil then
            print("adc: " .. adc)
        end
        if sign ~= nil then
            print("sign: " .. sign)
        end
    end
)

@KT819GM
Copy link

KT819GM commented May 29, 2019

Anyone from dev's could take a quick look into this issue please? Commit 5f43a41 still have same issue as author stated on the first topic. On master branch I'm struggling to avoid restart when ADS1115 is disconnected unexpectedly (constantly reading all 4 inputs inside function), thinking to try dev branch as have no more ideas left.
Thank you!

@galjonsfigur
Copy link
Member

After comparing results with xtensa-lx106-elf-gcc -E I found the problem. In https://github.com/nodemcu/nodemcu-firmware/blob/dev/app/modules/ads1115.c#L588 instead of:
LROT_TABENTRY( "__index", ads1115_instance )
should be
LROT_TABENTRY( __index, ads1115_instance )

I don't have ADS1115 but I think this should solve the issue. I will try to find other similar bugs and send PR.

galjonsfigur added a commit to galjonsfigur/nodemcu-firmware that referenced this issue May 31, 2019
@KT819GM
Copy link

KT819GM commented May 31, 2019

Thank you, just now had possibility to try it. Fix is working, I can read ADS1115 after modifying ads1115.c with
LROT_TABENTRY( __index, ads1115_instance )
p.s. there are mistake in documentation example where adc1 becames ads1.

@KT819GM
Copy link

KT819GM commented May 31, 2019

Forgot to add - tested on both i2c introduced with third SDK. Using 400kHz:

node.setcpufreq(node.CPU160MHZ)
i2c0 = {
id = 0,
sda = 1,
scl = 2,
speed = i2c.FAST
}
-- initialize i2c bus 0
i2c0.speed = i2c.setup(i2c0.id, i2c0.sda, i2c0.scl, i2c0.speed)
i2c.start(0)
ads1115.reset()
node.setcpufreq(node.CPU160MHZ) -- to support FASTPLUS speed
adc1 = ads1115.ads1115(0, ads1115.ADDR_GND)
adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_128SPS, ads1115.SINGLE_0, ads1115.CONTINUOUS)
-- give delay time for MUX to switch
tmr.create():alarm(10, tmr.ALARM_SINGLE, function()
volt, volt_dec, adc, sign = adc1:read()
print(volt, volt_dec, adc, sign)
end)

p.s. sorry, have no idea, how to properly format code on github comments.

@galjonsfigur
Copy link
Member

p.s. there are mistake in documentation example where adc1 becames ads1.

I will try to add this to the PR. Thanks for info!

galjonsfigur added a commit to galjonsfigur/nodemcu-firmware that referenced this issue May 31, 2019
@KT819GM
Copy link

KT819GM commented May 31, 2019

I will use opportunity to ask one more question, because I still have my problem with ads1115 in a dev version, and I'm 100% sure it's because of my incompetence.
I'm reading ads1115 values by that function (I have stripped it, any missing var's are declared, function is working):

function Main.Start()
    local adsvars = {}
    local adsSetup = {16384, 20480, 24576, 28672}
    tmr.create():alarm(Cfg.Main_dataCollectInterval,tmr.ALARM_AUTO,function()
        t:read_temp(readout, pin)
            Main.data[Main.currIndex] = adc.read(0) ads1115.reset() Main.ads_read(adsSetup[Main.currIndex])
            adsvars[Main.currIndex] = adsval
            Main.currIndex = Main.currIndex + 1
            if Main.currIndex == Cfg.Main_samplesToCollect then
                Main.medium = Main.getMedian(Main.data, Cfg.Main_samplesToCollect) Main.currIndex = 1
                if adsvars[1] and adsvars[2] and adsvars[3] and adsvars[4] ~=nil and Cfg.cloudEnable then
                    Main.sendCollectedDataToMqtt(''..string.format("%.1f",Main.medium)..';'..string.format("%.1f",adsvars[2])..';'..string.format("%.1f",adsvars[3])..';'..string.format("%.1f",adsvars[4])..';'..string.format("%.1f",adsvars[1])..";"..string.format("%.1f",temp1)..';'..wifi.sta.getrssi()..';'..node.heap())
                end
        end
    end)
end

function Main.ads_read(reg)
    local adc1 = ads1115.ads1115(0, ads1115.ADDR_GND)
    adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_16SPS, reg, ads1115.SINGLE_SHOT)
    tmr.create():alarm(30, tmr.ALARM_SINGLE, function(t_ads) adc1:startread(function(volt) adsval = volt ads1115.reset() return adsval end) ;t_ads:unregister() end)
end

Values are readed every 2.5 seconds and after 10 seconds are sent to mqtt. Problem is - I don't know how to isolate error when ads is disconnected (I have EMC noisy environment), because after disconnection error like:
ads_test2.lua:4: found no device stack traceback: [C]: in function 'ads1115' ads_test2.lua:4: in main chunk [C]: in function 'dofile' stdin:1: in main chunk
is thrown into main function.

Question is - how can I silently ignore disconnection error?

p.s. I know, that question like this usually p**s off dev's, but please remember, that you can silently ignore it or even remove it. Any help would be appreciated, even paid.

Thank you

@galjonsfigur
Copy link
Member

galjonsfigur commented May 31, 2019

You can use pcall for ads_read function - I think it should do the trick.

@KT819GM
Copy link

KT819GM commented Jun 1, 2019

Thank you for answer. Looked at pcall again and still have no juice, error is always returned, no difference which part of function (or whole of it) I will cover into pcall. And because of how I've constructed my main function, I'm always getting restart at the same moment when ads1115 is disconnected. Question again:
On ads1115.c we have:
if (config_read == 0xFFFF) { return luaL_error(L, "found no device"); }
What could I put instead of it, for function to return -1(or any string) in case of config_read == 0xFFFF without triggering return luaL_error
That would solve my particular problem as I could use simple if ... else to check result from ads_read function.
Thank you!

@galjonsfigur
Copy link
Member

You could change this to return 0; instead of luaL_error and check if returning argument is nil but it's a really bad idea because it does not really solve the problem. I've tested pcall approach and it works just fine. Example code:

id, sda, scl = 0, 2, 1

function read()
  i2c.setup(id, sda, scl, i2c.SLOW)
  ads1115.reset()
  adc1 = ads1115.ads1115(id, ads1115.ADDR_GND)
  adc1:setting(ads1115.GAIN_6_144V, ads1115.DR_8SPS, ads1115.SINGLE_0, ads1115.SINGLE_SHOT)
  adc1:startread(
    function(volt, volt_dec, adc, sign)
      print("getChannel...")
      if volt ~= nil then
        print("volt: " .. volt)
      end
      if volt_dec ~= nil then
        print("volt_dec: " .. volt_dec)
      end
      if adc ~= nil then
        print("adc: " .. adc)
      end
      if sign ~= nil then
        print("sign: " .. sign)
      end
    end)
end

if pcall(read) then
  print("Success")
else
  print("Fail")
end

You just have to check the pcall result and even if luaL_error is raised, pcall will just return false as 1st argument.

@marcelstoer
Copy link
Member

@galjonsfigur thanks for digging into this. With #2742 @TerryE changed some 90 files. I expect that we'll find more such glitches - not because Terry doesn't work diligently but simply because it's nearly impossible to get everything right with such a far-reaching change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants