vsergeev / lua-periphery

A Lua library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
MIT License
182 stars 38 forks source link

i2c:transfer causes error "error object is not a string", pcall fails to capture #32

Closed drauschenbach closed 4 weeks ago

drauschenbach commented 4 weeks ago

I'm trying to figure out how to use the I2C error reporting in a pcall.

My test script attempts to perform the equivalent of:

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- 1a -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --              
-- find_components.lua
local I2C = require('periphery').I2C

local device = '/dev/i2c-1'

io.stderr:write('     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n')
for i = 0, 127, 16 do
  for j = 0, 15 do
    io.stderr:write(string.format('%02x: ', i))
    local addr = i + j
    local i2c = I2C(device, addr)
    local message = { 0, flags = I2C.I2C_M_RD }
    local _, err = pcall(i2c:transfer(addr, { message }))
    if err.code ~= nil then
      io.stderr:write('-- ')
    else
      io.stderr:write(string.format('%02x ', addr))
    end
  end
  io.stderr:write('\n')
end
$ lua find_components.lua
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: lua: (error object is not a string)

System Info

Raspberry Pi 5.

$ lua -v
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio

$ dpkg --print-architecture
arm64

$ cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
drauschenbach commented 4 weeks ago

My mistake, I was using the pcall incorrectly. This works:

local I2C = require('periphery').I2C

local device = '/dev/i2c-1'

function find_components(device)
  io.stderr:write('     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n')
  for i = 0, 127, 16 do
    io.stderr:write(string.format('%02x: ', i))
    for j = 0, 15 do
      local addr = i + j
      if addr < 0x03 or addr > 0x77 then
        io.stderr:write('   ')
      else
        local i2c = I2C(device, addr)
        local message = { 0, flags = I2C.I2C_M_RD }
        local ok = pcall(I2C.transfer, i2c, addr, { message })
        if ok then
          io.stderr:write(string.format('%02x ', addr))
        else
          io.stderr:write('-- ')
        end
      end
    end
    io.stderr:write('\n')
  end
end

find_components(device)