Post your best Lua script examples here

User avatar
By Donquixote2u
#48027 Sparkfun have an example in Arduino IDE, but shuttling between their sample sketch and the HMC5883L datasheet they include on the page just confused me, particularly when trying to relate the lua i2c commands back to the Arduino ones.

For example the datasheet talks about sending 0x3c/ox3d to set read and write modes, but I can't see that in the Arduino code

Then when I get past that, the lua for converting two 8-bit registers to a signed integer are also causing me a bit of head-scratching.

please tell me you've been there, done it all!
User avatar
By Donquixote2u
#48142 OK< well for anyone else trying to do this, I'll post the results of my diagnostic efforts below; The i2c read/write routines I used almost unchanged from this post of Sanchos for the pcf8591 adc - thank you Sancho, particularly since I will also be using that very device alongside the compass at a later stage!

I understand the compass needs some calibration for location, but I'll skip that for now.

The HMC5883L datasheet was hellish confusing, but what worked was just setting the mode to continuous read, a delay while the moded activated, and then reading all 6 registers (in auto-increment mode) at once. Hope this helps anyone trying to tame this beast. The code just reads the data registers every 10 secs, displaying hex and integer values.

Code: Select all    --  read from reg_addr content of dev_addr
    function read_reg(dev_addr, reg_addr)
      i2c.start(id)
      i2c.address(id, dev_addr ,i2c.TRANSMITTER)
      i2c.write(id,reg_addr)
      i2c.stop(id)
      i2c.start(id)
      i2c.address(id, dev_addr,i2c.RECEIVER)
      c=i2c.read(id,6)
      i2c.stop(id)
      return c
    end
-- write value into device dev_addr, register reg_addr
    function write_reg(dev_addr, reg_addr, reg_val)
      i2c.start(id)
      i2c.address(id, dev_addr, i2c.TRANSMITTER)
      i2c.write(id, reg_addr)
      i2c.write(id, reg_val)
      i2c.stop(id)
    end
    -- convert 2 hex bytes to 16 bit signed int
    function reg2int(reg1, reg2)
    num=bit.lshift(reg1,8)+reg2
    if num>2047 then num=num-65536 end
    return num       
    end

function read_compass()
-- get contents of all 6 data registers
result = read_reg(device, 0x03)
-- show contents in hex, convert to signed 16-bit integers
print("read:")
for i=1,6,1 do print(string.format("%02X",string.byte(result,i))) end
x=reg2int(string.byte(result, 1),string.byte(result, 2))
z=reg2int(string.byte(result, 3),string.byte(result, 4))
y=reg2int(string.byte(result, 5),string.byte(result, 6))
print("heading:"..x..";"..z..";"..y)
-- reread data every  10 secs
tmr.alarm( 1 , 10000 , 0 , read_compass )
end

--  start here
    device=0x1E --HMC5883L
    id=0    -- bus
    sda=1   -- i2c data
    scl=3   -- i2c clock
   
-- initialize i2c, set gpio0 as sda, gpio4 as scl
    i2c.setup(id,sda,scl,i2c.SLOW)
-- set mode register to 00 = continuous update   
    write_reg(device,0x02,0x00)
--  wait 100ms before trying to read compass (min 67ms)
tmr.alarm( 1 , 100, 0 , read_compass )
User avatar
By Donquixote2u
#48926
devsaurus wrote:For your info: there's a related Pull Request for a native module pending at https://github.com/nodemcu/nodemcu-firmware/pull/1253.


Thanks for that info; I see the hmc5883l module option has popped up in the online build, too.

At the moment it just reads the x/z/y axis readings from the device; What would be really good would be for someone to add the options that exist in the Arduino IDE side to convert to compass headings in radians or degrees; I note that this uses the atan2 math function not present in the normal build options, though.

I did manage to convert those axis readings to compass bearings sufficient for my purposes (N/NE/E ..etc) but it is clunky code with quite few if..else.. comparisons, so some slick functions would be nice.But hey, it works, somewhat.