ESP8266 Projects Blog
Home of CBDB / MPDMv4 /SmartMon Development boards (ESP-12/ESP-07).
Guidelines and ESP8266 programming examples using LUA, Eclipse and Arduino IDE, ESP Basic and many more!
In the process of choosing of some Light Sensors for one of the new projects that will involve the nEXT EVO Board and also the MPDMv4 Mains Dimmer somebody suggested to give a try also to the ROHM BH1750FVI Sensor.
As you can see on the picture above, on the tiny board, you have the BH1750FVI Sensor, a LDO regulator some filtering caps and pull-up resistors and that's it!
BH1750FVI Module - Bottom
The bottom side is bringing us more good news, the Module interface connector is fully compatible with the nEXT EVO Bus!
BH1750FVI Overview
BH1750FVI is an digital Ambient Light Sensor IC for I2C bus interface. This IC is the mostly used to obtain the ambient light data for adjusting LCD and Keypad backlight power of Mobile phone. This is great as we are looking forward to use it for Automatic light adjustment using the MPDMv4 AC Dimmer board :)
Features
I2C bus Interface ( f / s Mode Support )
Spectral responsibility is approximately human eye response
Illuminance to Digital Converter
Wide range and High resolution. ( 1 - 65535 lx )
Low Current by power down function
50Hz / 60Hz Light noise reject-function
1.8V Logic input interface
Native 3.3V Device
No need any external parts
Light source dependency is little. ( ex. Incandescent Lamp. Fluorescent Lamp. Halogen Lamp. White LED. Sun Light )
It is possible to select 2 type of I2C slave-address.
Adjustable measurement result for influence of optical window ( It is possible to detect min. 0.11 lx, max. 100000 lx by using this function. )
Small measurement variation (+/- 20%)
The influence of infrared is very small.
Internal Diagram
BH1750FVI - Internal Diagram
PD - Photo diode with approximately human eye response.
AMP - Integration-OPAMP for converting from PD current to Voltage.
ADC - AD converter for obtainment Digital 16bit data.
Logic + I2C Interface :
- Ambient Light Calculation and I2C BUS Interface. It is including below register.
- Data Register - This is for registration of Ambient Light Data. Initial Value is
"0000_0000_0000_0000".
- Measurement Time Register - This is for registration of measurement time. Initial Value
is "0100_0101".
OSC - Internal Oscillator ( typ. 320kHz ). It is CLK for internal logic.
BH1750FVI Module from above. Can be ordered in packs of ONE, FIVE or even TEN from the corresponding links. My 10 one was backordered but received it quite quickly.
For programming and uploading the driver and the software we will continue to use the LuaUploader as before.
Connection with the ESP8266 nEXT EVO Board is very easy, as MPU6050 GY-521 Module connector
is fully compatible with the nEXT Bus connector. Depending on how to you
choose you socket type, you can install it on TOP or Bottom of the ESP8266 nEXT EVO Board :
BH1750FVI Module directly connected to the ESP8266 nEXT EVO Board
BH1750FVI Driver implementation
1. Init I2C bus/interface
Standard I2C Bus Initialisation function:
function init_I2C() i2c.setup(bus, sda, scl, i2c.SLOW) end
2. WRITE Function - Set BH1750FVI Register config
From BH1750FVI Datasheet :
No active state : pwr_down 0x00
Wating for measurment command : pwr_on=0x01
Reset data register value - not accepted in POWER_DOWN mode : reset=0x07
Continuous modes, no pwr down:
Start measurement at 1lx resolution. Measurement time is approx 120ms:
hi_res_m1=0x10
Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
hi_res_m2=0x11
Start measurement at 4lx resolution. Measurement time is approx 16ms.
lo_res_m1=0x13
Device is automatically set to Power Down after measurement:
Start measurement at 1lx resolution. Measurement time is approx 120ms.
hi_res_m3=0x20
Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
hi_res_m4=0x21
Start measurement at 1lx resolution. Measurement time is approx 120ms.
lo_res_m2=0x23
function setcfg(cfg) i2c.start(id) i2c.address(id, dev_addr ,i2c.TRANSMITTER) i2c.write(id,cfg) i2c.stop(id) end
Somebody sent to me a nice & tiny temperature/humidity sensor breakout board based on the Si7021 IC:
Si7021 Module - Top View
On the Top side we have Si7021 Sensor only.
Si7021 Module - Bottom View
Bottom Side, a 3.3V LDO and a Voltage level shifting circuit that probably makes it 5V tolerant on I2C bus. We will use it at 3.3V so nothing to worry about.
DESCRIPTION
The Si7021 I2C Humidity and Temperature Sensor is a monolithic CMOS IC integrating humidity and temperature sensor elements, an analog-to-digital converter, signal processing, calibration data, and an I2C Interface.
The patented use of industry-standard, low-K polymeric dielectrics for sensing humidity enables the construction of low-power, monolithic CMOS Sensor ICs with low drift and hysteresis, and excellent long term stability.
The humidity and temperature sensors are factory-calibrated and the calibration data is stored in the on-chip non-volatile memory. This ensures that the sensors are fully interchangeable, with no recalibration or software changes required.
The Si7021 offers an accurate, low-power, factory-calibrated digital solution ideal for measuring humidity, dew-point, and temperature, in applications ranging from HVAC/R and asset tracking to industrial and consumer platforms.
Si7021 - Block Diagram
Nice. Looks more or less like SHT21 from Sensirion. And we will see that it is quite compatible (at least on the temp/humidity reading procedure side) with small differences for the rest of registers.
For programming and uploading the driver and the software we will continue to use the LuaUploader as before.
Connection with ESP8266 nEXT EVO Board is pretty straight-forward as the module is fully pin-to-pin compatible with the availavble nEXT Bus connector.
Si7021 Board connected with ESP8266 nEXT EVO DevBoard - TOP view
Si7021 Board connected with ESP8266 nEXT EVO DevBoard - 45 deg view
Software implementation
The Si7021 communicates with the host controller over a digital I2C interface. The 7-bit base slave address is 0x40
Master I2C devices communicate with the Si7021 using a command structure. The commands are listed below in the I2C command table. Commands other than those documented below are undefined and should not be sent to the device.
I2C Command Table
Issuing a Measurement Command The measurement commands instruct the Si7021 to perform one of two possible measurements: Relative Humidity or Temperature.
The procedure to issue any one of these commands is identical. While the measurement is in progress, the option of either clock stretching (Hold Master Mode) or Not Acknowledging read requests (No Hold Master Mode) is available to indicate to the master that the measurement is in progress. The chosen command code determines which mode is used.
Optionally, a checksum byte can be returned from the slave for use in checking for transmission errors. The checksum byte will follow the least significant measurement byte if it is acknowledged by the master. The checksum byte is not returned if the master “not acknowledges” the least significant measurement byte. The checksum byte is calculated using a CRC generator polynomial of x^8+ x^5 + x^4 + 1, with an initialization of 0x00.
The checksum byte is optional after initiating an RH or temperature measurement with commands 0xE5, 0xF5,0xE3, and 0xF3. It is required for reading the electronic ID with commands 0xFA 0x0F and 0xFC 0xC9.
For all other commands, the checksum byte is not supported.
1. Init I2C bus/interface
Standard I2C Bus Initialisation function:
function init_I2C() i2c.setup(bus, sda, scl, i2c.SLOW) end
2. Write Si7021 Register Function
write_Si_Reg = function (dev_addr, set) i2c.start(0x0) i2c.address(0x0, dev_addr ,i2c.TRANSMITTER) i2c.write(0x0,set) i2c.stop(0x0) tmr.delay(5000) end
3. Read Si7021 Register Function
read_Si_Reg = function (dev_addr) i2c.start(0x0) i2c.address(0x0, dev_addr,i2c.RECEIVER) tmr.delay(5000) c = i2c.read(0x0,2) i2c.stop(0x0)
rval = (bit.lshift(string.byte(c, 1), 8) + string.byte(c, 2)) status = bit.band(rval,3) --save status bits rval = bit.band(rval,65532) --clear status bits return rval, status end
4. Measuring Relative Humidity
Once a relative humidity measurement has been made, the results of the measurement may be converted to percent relative humidity by using the following expression:
hum = -6.0+125.0/65536.0*rval
A humidity measurement will always return XXXXXX10 in the LSB field -> Status bit = 1 -> marking a Humidity measurement data.
function read_hum() write_Si_Reg(dev_addr, RHumidityHoldCmd) tmr.delay(10000) read_Si_Reg(dev_addr) hum = -6.0+125.0/65536.0*rval print("\nStatus : "..status) print("Humidity : "..string.format("%.2f",hum).."%") end
5. Measuring Temperature
Each time a relative humidity measurement is made a temperature measurement is also made for the purposes of temperature compensation of the relative humidity measurement. If the temperature value is required, it can be read using command 0xE0; this avoids having to perform a second temperature measurement. The measure temperature commands 0xE3 and 0xF3 will perform a temperature measurement and return the measurement value, command 0xE0 does not perform a measurement but returns the temperature value measured during the relative humidity measurement. The checksum output is not available with the 0xE0 command.
The results of the temperature measurement may be converted to temperature in degrees Celsius (°C) using the following expression:
temp = -46.85+175.72/65536.0*rval
A temperature measurement will always return XXXXXX00 in the LSB field - Status bit = 0 -> marking a Temperature measurement data.
function read_temp() write_Si_Reg(dev_addr, TempHoldCmd) read_Si_Reg(dev_addr) temp = -46.85+175.72/65536.0*rval print("Status : "..status) print("Temperature : "..string.format("%.2f",temp).."C") end
As been working to a ESP DHT22 sensors array for a Environment data logging system I was thinking that it would be nice to have also a direct reading panel for the data. And because just received in my mailbox few days ago a KN-WS400 Weather station to be used for another project I said why do not to take a deeper look and see if we can use it also as a realtime data view panel for our DHT22 sensors.
As you can see from the picture below, it has a big and nice looking display (not the best quality or contrast in town but, hey, it's just a 40USD unit, nothing fancy):
KN-WS400 Weather station
It has only temperature and humidity capabilities, but for our project is more than enough:).
What is interesting about KN-WS400 is the fact that it can receive temperature and humidity data also from another 3 external sensors (but delivered in the box with only one!).
You can setup and choose between 3 different channels, each one allocated for a separate remote sensor unit.
Remote sensor
Reading remote temperature data on Channel 1
Channel setup is done very simple, choose your desired free channel from your remote sensor unit and reset the corresponding channel on the Weather station by pressing more than 10 sec the channel button.
External sensor CHannel setup and C/F scale option buttons
So far so good. The idea is to try to use another 2 ESP DHT22 sensor units to send the temperature and humidity data directly to WS400 Weather station on the available channels. Or, why not, to replace them all 3 with the WIFI Web enabled ESP DHT22 smarter ones :)
To do this, first of all we need to take a look at the transmission frequency to know what kind of receiver/transmitter to use with our ESP DHT22 Modules.
As is written on the back of the unit, the KN-WS400 Weather station use for remote sensors communication the standard 433Mhz frequency, same as probably most of the zillions different types of cheap weather stations available around.
So now, as we know the frequency, next we need to see if we can have any luck in decoding the communication protocol.
I will not insist to much on the wiring setup as it is a very simple one, just connect your simple 433mhz Receiver module to your Power supply Vcc , GND and the Data pin to your used Oscilloscope channel probe.
As soon as it is connected and you start changing the channel on the KN-WS400 sensor module by pressing the CH button from the back of the unit, you will see a data burst on your Oscilloscope. See also Youtube video from above.
Data burst received on 433Mhz from KN-WS400 remote sensor
As you can see from the captured data above, it looks like the unit is transmitting the data in 6 separate data bursts. Actually, when zoomed in we can see that is sending the same data 6 times.
At a deeper look at the received data stream we can see that:
Each transmission consists of 6 repetitions of the same data.
They are separated by a long sync signal ("preamble") that’s about 4.5ms (3.8ms low + 0.7ms high)
We can suppose the bit patterns (they might be inverted sometime 1<->0 but is not the case of this sensor) as:
- Logic 1 (or 0) is about 2.6ms -> 1.9ms low + 0.7ms high
- Logic 0 (or 1) is about 1.7ms -> 1.0ms low + 0.7ms high
"Preamble" measurement
Logic "1" Measuremnt
Logic "0" measurement
Based on the assumptions from above, let's try to "transcribe" the signal from the above: PRE10101011100100010000010111110011010100000PRExxxxPRExxx4PRE
Before even thinking to try to decode the data we need to be able to identify where reside each data value in the stream. For this taskthat can become quite complicated or impossible some time, you can start using a very simple technique: just change only one variable at a time, in very small increments if possible and look after changes.
The easiest one to do, is the Channel setup, as we have on the back of the sensor unit a switch for it.
Press the channel button and change Channel to 1,2 and 3.
Capture and take a look at the received data :
Now you can clearly see that the channel data (CH) is encoded on 2 bits in the 3rd column. Not bad at all. You know why? because despite the fact that you cannot find 2 Weather stations with the same exact data format they are quite similar and any existing information can help you a lot in the reduction of the complexity of the decoding process.
Let's make another assumption based on the info that we already have from other existing models, that the first 2 bits from column 3 to be the battery status ones. Usually they are coded in this way.
Powering the sensor unit from an external lab PSU and reducing gradually the voltage until under normal working one the data obtained looks:
Nice. So, until now, we have identified the Battery status and Channel ID. Let's go further.
For temperature and humidity a common found coding technique is as follows:
Humidity is stored as low/high order nibbles. So you need to take
the first 4 bits and tack them on the end of the next 4 bits. 11010101 becomes
01011101.
Temperature is transmitted as 12 bits in 3x nibbles ranging from low to
high nibbles. A fixed offset of 900 is applied to the temperature value so 0
degrees F = 900 and each degree F change is 10 decimal. Then the obtained value is divided by 10. And converted to degC. Confusing and painful stuff to find in a data stream.
Sounds complicated? Why are temperature and humidity data coded like that? My personal opinion is that some specifications were created for the first designed one and now as these cheap weather stations has become such a mass product everybody is copying more or less the same design :)
If somebody really knows the true reason for such a coding, I will more than happy to know. Might be some good reasons behind that I'm missing.
Let's see what's happening in our case. And before anything else, let's use the same technique, keeping all the data the same and change slowly Temperature only part:
Only few things remained "undecoded" but believe me after capturing hundreds and hundreds of data streams it looks like de ID remains stable, same with the mysterious "1111" between Temperature and Humidity and the "0" from the end.
As it looks like there is no fancy Checksum algorithm involved or any special data stream identifier I think we can move further and design your own ESP DHT22 Module transmission program for direct data upload. And as you can see in the above Youtube video it was a success.
As soon as I cleaned it a little bit, the Part 2 will follow, with the full code description.
PS: I really hope that after reading this article the guys from Konig or who are doing the coding for this product will let it as it is because it has becoming the most desired cheap Wireless Weather Station around, believe me, they are selling like hotcakes :). Thank you Konig for such a nice surprise for all of us!
And to be clear: I am NOT afiliated in any way with Konig and the unit was not received from Konig. But if they want to thank me for opening a new market for their products I will not say no. lol.