As the title says... Chat on...

User avatar
By grhhm
#40489 Hi,

I am trying to read the HTU21D via i2c bus. No success meanwhile.
I have tried:
- 2 different HTU21D module models: One model from Adafruit and other model GY-21.
- 2 separated units of each model to exclude broken module.
- Pull up resistors adding and removal for SCL and SDA.
- This example that claimed as working.

The voltage supply and hook up is correct. Other modules (bmp085 and tsl2561) are working fine with the same setup.
There is not ACK on address 0x40 to the HTU21D (i2c.address returns false).
An attempt to set the HTU21D to receive/transmit mode (i2c.write returns 0 no matter what).

What could be a problem?
Any hint is appreciated.
User avatar
By DrG
#40491
grhhm wrote:Hi,

I am trying to read the HTU21D via i2c bus. No success meanwhile.
I have tried:
- 2 different HTU21D module models: One model from Adafruit and other model GY-21.
- 2 separated units of each model to exclude broken module.
- Pull up resistors adding and removal for SCL and SDA.
- This example that claimed as working.

The voltage supply and hook up is correct. Other modules (bmp085 and tsl2561) are working fine with the same setup.
There is not ACK on address 0x40 to the HTU21D (i2c.address returns false).
An attempt to set the HTU21D to receive/transmit mode (i2c.write returns 0 no matter what).

What could be a problem?
Any hint is appreciated.


I have used this chip successfully and posted about it here viewtopic.php?f=11&t=6854&p=36831&hilit=sensor+board#p35199 It is with the Arduino IDE not LUA, but maybe and can be of some help. -DrG
User avatar
By grhhm
#40494 DrG, thanks for sharing!
I tried to increase wait time of measurement to 95 ms as in your example.
Still negative result.
Seems the HTU21D just doesn't react to commands: the read data is always fully asserted bytes (255).
User avatar
By jankop
#40496 Hi grhhm,
I have not any problem with HTU21D. I like it, it is very good. Here is functional example for you.

Code: Select all--     thingspeak.com client with sensor HTU21 (SHT21,Si7021) and BMP180 (BMP85)
--    Tested with Lua NodeMCU 0.9.6 (nodemcu_float_0.9.6-dev_20150704.bin)
--    Minimal period for data send to api.thingspeak.com is 15s
--
   DEBUGPRINT = true -- true: enable debugg print, false: disable debugg print
--****************************************************************
   WRITEKEY="yourAPIkey" -- set your thingspeak.com key
--****************************************************************
   alt=188 -- set correction for your altitude location in meters
--****************************************************************
   ssid="yourSSID"    -- your router SSID
    pass="yourPasw"   -- your router passwo
--****************************************************************
   prs=60  -- period reading and sending sensors *s*
   sda=4   -- GPIO2 connect to SDA BMP180 and HTU21
   scl=3   -- GPIO0 connect to SCL BMP180 and HTU21
   h1=0    -- humidity HTU21
   t1=0    -- temperature HTU21
   p2=0    -- pressure BMP180
   t2=0    -- temperature BMP180
   wifi.setmode(wifi.STATION)
   wifi.sta.config(ssid,pass,1)

function debugprint(...)
   if DEBUGPRINT then
      print(...)
   end
end
--load HTU module for read sensor
function ReadHTU21()
    htu21=require("htu21")
   htu21.init(sda,scl)
   t1=string.format("%.1f",tostring(htu21.getTemperature()/100))
   h1=string.format("%.1f",tostring(htu21.getHumidity()/100))
   debugprint("Temperature: "..t1.." deg C")-- can be disabled
   debugprint("Humidity:    "..h1.." %")    -- can be disabled
   htu21=nil
   package.loaded["htu21"]=nil
end
--load BMP module for read sensor
function ReadBMP180()
   bmp180 = require("bmp180")
   bmp180.init(sda, scl)
   bmp180.read(oss)
   t2= string.format("%.1f",tostring(bmp180.getTemperature()/10))
   p2= string.format("%.1f",tostring(bmp180.getPressure()/((1-alt/44330)^5.255)/100))
   debugprint("Temperature: "..t2.." deg C")-- can be disabled
   debugprint("Pressure   : "..p2.." hPa")  -- can be disabled
   bmp180 = nil
   package.loaded["bmp180"]=nil
end
-- send data to https://api.thingspeak.com
function SendTS()
conn = net.createConnection(net.TCP, 0)
conn:connect(80,'api.thingspeak.com')   -- This row is good, but only for newer firmware
--conn:connect(80,'184.106.153.149')    -- This is worse, but it also works well with the older firmware.
conn:on("connection",
   function(conn) debugprint("Connection!")
   conn:send('GET /update?key='..WRITEKEY..
   '&headers=false'..
   '&field1='..h1..
   '&field2='..t1..
   '&field3='..p2..
   '&field4='..t2..
   ' HTTP/1.1\r\n'..
   'Host: api.thingspeak.com\r\nAccept: */*\r\nUser-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n\r\n')
   end)
conn:on("sent",
   function(conn)
   debugprint("Sent!")
      if DEBUGPRINT == false
      then
      conn:close()
      end
   end)
conn:on("receive",
   function(conn, payload)
   debugprint("Receive!")
   debugprint(payload)
   conn:close()
   end)
conn:on("disconnection",
   function(conn)
   debugprint("Disconnection!")
   end)
end

-- first reading sensors
  ReadBMP180()
  ReadHTU21()
  SendTS()
-- Periodic reading of the sensor
tmr.alarm(0,prs*1000,1,
 function()
 if wifi.sta.getip()==nil
   then
   print("IP refresh")
   print("!!!!!!!!!!!!!!")
   node.restart()
   end
  ReadBMP180()
  ReadHTU21()
  SendTS()
end)

Code: Select all-- ***************************************************************************
-- BMP180 module for ESP8266 with nodeMCU
-- BMP085 compatible but not tested
--
-- Written by Javier Yanez
--
-- MIT license, http://opensource.org/licenses/MIT
-- ***************************************************************************

local moduleName = ...
local M = {}
_G[moduleName] = M

local ADDR = 0x77 --BMP180 address
local REG_CALIBRATION = 0xAA
local REG_CONTROL = 0xF4
local REG_RESULT = 0xF6

local COMMAND_TEMPERATURE = 0x2E
local COMMAND_PRESSURE = {0x34, 0x74, 0xB4, 0xF4}

-- calibration coefficients
local AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD

-- temperature and pressure
local t,p

local init = false

-- i2c interface ID
local id = 0

-- 16-bit  two's complement
-- value: 16-bit integer
local function twoCompl(value)
 if value > 32767 then value = -(65535 - value + 1)
 end
 return value
end

-- read data register
-- reg_addr: address of the register in BMP180
-- lenght: bytes to read
local function read_reg(reg_addr, length)
  i2c.start(id)
  i2c.address(id, ADDR, i2c.TRANSMITTER)
  i2c.write(id, reg_addr)
  i2c.stop(id)
  i2c.start(id)
  i2c.address(id, ADDR,i2c.RECEIVER)
  c = i2c.read(id, length)
  i2c.stop(id)
  return c
end

-- write data register
-- reg_addr: address of the register in BMP180
-- reg_val: value to write to the register
local function write_reg(reg_addr, reg_val)
  i2c.start(id)
  i2c.address(id, ADDR, i2c.TRANSMITTER)
  i2c.write(id, reg_addr)
  i2c.write(id, reg_val)
  i2c.stop(id)
end

-- initialize module
-- sda: SDA pin
-- scl SCL pin
function M.init(sda, scl)
  i2c.setup(id, sda, scl, i2c.SLOW)
  local calibration = read_reg(REG_CALIBRATION, 22)

  AC1 = twoCompl(string.byte(calibration, 1) * 256 + string.byte(calibration, 2))
  AC2 = twoCompl(string.byte(calibration, 3) * 256 + string.byte(calibration, 4))
  AC3 = twoCompl(string.byte(calibration, 5) * 256 + string.byte(calibration, 6))
  AC4 = string.byte(calibration, 7) * 256 + string.byte(calibration, 8)
  AC5 = string.byte(calibration, 9) * 256 + string.byte(calibration, 10)
  AC6 = string.byte(calibration, 11) * 256 + string.byte(calibration, 12)
  B1 = twoCompl(string.byte(calibration, 13) * 256 + string.byte(calibration, 14))
  B2 = twoCompl(string.byte(calibration, 15) * 256 + string.byte(calibration, 16))
  MB = twoCompl(string.byte(calibration, 17) * 256 + string.byte(calibration, 18))
  MC = twoCompl(string.byte(calibration, 19) * 256 + string.byte(calibration, 20))
  MD = twoCompl(string.byte(calibration, 21) * 256 + string.byte(calibration, 22))

  init = true
end

-- read temperature from BMP180
local function read_temp()
  write_reg(REG_CONTROL, COMMAND_TEMPERATURE)
  tmr.delay(5000)
  local dataT = read_reg(REG_RESULT, 2)
  UT = string.byte(dataT, 1) * 256 + string.byte(dataT, 2)
  local X1 = (UT - AC6) * AC5 / 32768
  local X2 = MC * 2048 / (X1 + MD)
  B5 = X1 + X2
  t = (B5 + 8) / 16
  return(t)
end

-- read pressure from BMP180
-- must be read after read temperature
local function read_pressure(oss)
  write_reg(REG_CONTROL, COMMAND_PRESSURE[oss + 1]);
  tmr.delay(30000);
  local dataP = read_reg(0xF6, 3)
  local UP = string.byte(dataP, 1) * 65536 + string.byte(dataP, 2) * 256 + string.byte(dataP, 1)
  UP = UP / 2 ^ (8 - oss)
  local B6 = B5 - 4000
  local X1 = B2 * (B6 * B6 / 4096) / 2048
  local X2 = AC2 * B6 / 2048
  local X3 = X1 + X2
  local B3 = ((AC1 * 4 + X3) * 2 ^ oss + 2) / 4
  X1 = AC3 * B6 / 8192
  X2 = (B1 * (B6 * B6 / 4096)) / 65536
  X3 = (X1 + X2 + 2) / 4
  local B4 = AC4 * (X3 + 32768) / 32768
  local B7 = (UP - B3) * (50000/2 ^ oss)
  p = (B7 / B4) * 2
  X1 = (p / 256) * (p / 256)
  X1 = (X1 * 3038) / 65536
  X2 = (-7357 * p) / 65536
  p = p +(X1 + X2 + 3791) / 16
  return (p)
end

-- read temperature and pressure from BMP180
-- oss: oversampling setting. 0-3
function M.read(oss)
  if (oss == nil) then
     oss = 0
  end
  if (not init) then
     print("init() must be called before read.")
  else 
     read_temp()
     read_pressure(oss)
  end
end;

-- get temperature
function M.getTemperature()
  return t
end

-- get pressure
function M.getPressure()
  return p
end

return M

Code: Select all-- ***************************************************************************
-- HTU21D I2C module for ESP8266 with NodeMCU
-- pavel.janko@fancon.cz
-- MIT license, http://opensource.org/licenses/MIT
-- ***************************************************************************

local moduleName = ...
local M = {}
_G[moduleName] = M

local id = 0
local addr = 0x40 --HTU21 I2C address
local check, sda, scl, r
local HUMIDITY = 0xE5
local TEMPERATURE = 0xE3
local WRITE_REGISTER = 0xE6
local READ_REGISTER = 0xE7
local SOFT_RESET = 0xFE

function M.init(d, l)
  if (d~=nil)and(l~=nil)and(d>=0)and(d<=11)and(l>=0)and(l<=11)and(d~=l)then
    sda = d
    scl = l
  else
    print("I2C config failed!") return nil
  end
    i2c.setup(id, sda, scl, i2c.SLOW)
end

local function writeReg(DATA)
  i2c.start(id)
  i2c.address(id, addr, i2c.TRANSMITTER)
  i2c.write(id, WRITE_REGISTER)
  i2c.write(id, DATA)
  i2c.stop(id)
  return
end

local function readReg()
  i2c.start(id)
  i2c.address(id, addr, i2c.TRANSMITTER)
  i2c.write(id, READ_REGISTER)
  i2c.start(id)
  i2c.address(id, addr, i2c.RECEIVER)
  r = i2c.read(id,1)
  i2c.stop(id)
  return string.byte(r,1)
end

local function softRst()
  i2c.start(id)
  i2c.address(id, addr, i2c.TRANSMITTER)
  i2c.write(id, SOFT_RESET)
  i2c.stop(id)
  return
end

local function readTemp()
  i2c.start(id)
  i2c.address(id, addr, i2c.TRANSMITTER)
  i2c.write(id, TEMPERATURE)
  i2c.start(id)
  i2c.address(id, addr, i2c.RECEIVER)
  tmr.delay(50000) --wait for measurment
  r = i2c.read(id,3)
  i2c.stop(id)
return (bit.band((bit.lshift(string.byte(r,1),8)+string.byte(r,2)),0xfffc)*17572)/65536-4685
end

local function readHumi()
  i2c.start(id)
  i2c.address(id, addr, i2c.TRANSMITTER)
  i2c.write(id, HUMIDITY)
  i2c.start(id)
  i2c.address(id, addr, i2c.RECEIVER)
  tmr.delay(50000) --wait for measurment
  r = i2c.read(id,3)
  i2c.stop(id)
return (bit.band((bit.lshift(string.byte(r,1),8)+string.byte(r,2)),0xfffc)*12500)/65536-600
end

function M.getHumidity()
   return readHumi()
end

function M.getTemperature()
   return readTemp()
end

function M.getRegister()
    return readReg()
end

function M.getBatteryEnd()
   return bit.isset(readReg(),6)
end

function M.getHeaterStat()
   return bit.isset(readReg(),2)
end

function M.setHeaterOn()
   writeReg(bit.bor(readReg(),0x04))
   return readReg()
end

function M.setHeaterOff()
   writeReg(bit.band(readReg(),0xFB))
   return readReg()
end

function M.softReset()
   softRst()
   return readReg()
end




return M


https://thingspeak.com/channels/52907

and here is output from sensors.