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!
Part 4 of the MPRSx8 + ESPEasy Tutorial - After having all the bits & pieces in place, ESPEasy Formware properly uploaded and configured, now is time for the Domoticz setup and testing the Control interface!
Part 3 of the MPRSx8 + ESPEasy Tutorial - This time we will take a deeper look on the ESPEasy Firmware configuration and preparing the MPRSx8 Board for Domoticz integration:
Part 2 of the series, ESPEasy Firmware Upload tutorial using a simple standard USB-to-Serial Adapter:
The story behind: Somebody was asking if is really possible to upload firmware with a simple USB to serial adapter, as the ones that are available all over the place. As you can see from the above step-by-step tutorial it is possible and is working very smooth. You are loosing the autoreset and autoupload capabilities of the USBProg board, but as long as you are doing rarely the firmware upload is not so bad. On the other hand, if you want to use it with Arduino IDE or anything else that means frequent upload then I think you will start looking after that functions sooner or later, I think more sooner than later :)
The install process is pretty straight forward so I will not insist to much on it:
1. Install Domoticz 2. Install CURL 3. Save LUA script in Domoticz \scripts\lua folder 4.
Check that you don't have any Firewall/AV/Whatever program blocking the
Network IN/OUT traffic for the needed programs and Ports !
For the used version of CURL for Windows installed I was forced to change a bit the sintax, nothing fancy, just see below:
UPDATE !! If you are using Domoticz under Windows, please take a look also at the PART3
Part 2 of the ESPEasy Series. This time we will go further and complete a full ESP8266 / Domoticz Dimmer setup on a RPi2 Board using the MPDMv4 Universal AC Dimmer Board.
commandArray = {} DomDevice = 'MPDMv4_Dimmer'; IP = '192.168.1.169'; PIN = "5"; if devicechanged[DomDevice] then if(devicechanged[DomDevice]=='Off') then print ("OFF dimm = "..uservariables['dimm']); CalcValue = 890; else if(devicechanged[DomDevice]=='On') then DomValue = uservariables['dimm']; print ("ON dimm = "..uservariables['dimm']); CalcValue = DomValue; else print("Other"); DomValue = otherdevices_svalues[DomDevice]; CalcValue = 900-(DomValue*9); commandArray['Variable:dimm'] = tostring(CalcValue); print ("dimm Level = "..uservariables['dimm']); end end runcommand = "curl 'http://" .. IP .. "/control?cmd=PWM," ..PIN.. "," .. CalcValue .. "'"; os.execute(runcommand); print("PWM calculated value= "..CalcValue); end return commandArray
You need to save it in your Domoticz folder under "/scripts/lua/" subfolder as "script_device_MPDMv4_Dimmer.lua"
If followed step-by-step setup as done in the Youtube Video Tutorial above and all OK, you should end up with a working MPDMv4 AC Dimmer interface as below:
In Part 3 you can find details about changes that need to be done for a Domoticz for Windows installation.
Happy Breadboarding!!
ESP Easy Series, Part 1: Firmware upload and MPDMv4 driver simple test
The ESP Easy firmware can be used to turn the ESP module into an easy
to use multifunction sensor device for Home Automation solutions, been easy to integrate it in setups based on Domoticz, OpenHUB, etc.
The configuration process of the ESP Easy is entirely web based, so once you've got
the firmware loaded, you don't need any other tool besides a common web
browser.
First thing that I want to mention, as I found that a lot of people
sometime forget about this simple one: You DAC/ADC/PWM, etc Input/Output
is as good as your Power Supply/Voltage regulator!! If you have a crap
power supply/regulator output with bad filtering & stuff, don't expect
miracles happening!
It is working OK as long as you don't have any blocking process running
on the ESP8266 that can badly interrupt your PWM signal (1/2 second and
more). With a bit of attention to some details and also for not to
complicated lighting setup scenarios is working very nice.
I will do also a more complicated setup example Youtube Video showing you the MPDMv4 AC Dimmer working OK driven directly by
ESP8266 PWM pin, connected as a daughter board on the MPRSx8 Home Automation board.
From Domoticz you can drive thru ESPEasy the MPRSx8 8ON/OFF AC Relays
AND MPDMv4 AC Dimmer channel without any problems at all!
MPDMv4 AC Dimmer board has a first order filter on the VCNT input so can handle even noisy PWM and decent level of duty cycle skipping/derating.
2.Dedicated PWM IC.
I have used with a lot of success the PCA9685, working very smooth and has no
problem related with ESP8266 workload process, etc. You can find more
about a PCA9685 Board here. Probably the best solution for multiple AC Dimmer boards (upto 16 per each PCA9685 Extension Board).
3. Digital driver using a dedicated DAC IC.
VCNT input voltage driven from a MCP4726 12 bit DAC output is working very smooth and has no problem related
with ESP8266 workload process, etc, same as with PCA9685.
As been a 12 Bit DAC it's giving you
very fine VCNT control. I have designed also a Dimmer board with
integrated DAC and digital control, but that's another story.
For any new orders/requests please feel free to use as usual: tech at esp8266-projects.com. MPDMv4 Boards are also available on Tindie: AC MAINS Dimmer - MPDMv4
WARNING!! You will play with LIVE MAINS!! Deadly zone!!
If you don't
have any experience and are not qualified for working with MAINS power I
will not encourage you to play arround!. The
author take no responsibility for any injury or
death resulting, directly or indirectly, from your inability to
appreciate the hazards of household mains voltages.
The circuit diagrams are as accurately as possible, but are offered with no
guarantees whatsoever.
There is no guarantee that this design meets any Rules which may be in
force in your country so please check before your local
rules/regulations.
One of the main problem that people has been complained about was the fact that a simple MAINS Power Dimmer/Switch unit like the basic one presented last year is using sometime too much resources from a already overloaded application MCU/processor:
MPDMv3 - MAINS Dimmer/Switch with Phase detection
One of the scenarios, directly related with ESP8266 is about the limited timers capabilities that you have. For example, if you want to implement a proper web server to directly serve your webpages from ESP8266 you are automatically using one timer. If you want to start using the second one for your ZCD processing ...well...it's becoming very tricky. Very.
Don't uderstand me wrong, a bigger, better MCU can do it probably very well,
but even then if you have the chance to free some resources easily, do
it!. And I really cannot see a ESP8266 acting as a App MCU (webserver,
data logger, MQTT client, etc, etc) and doing reliable also other demanding
functions as Processing Zero Crossing Detection.
SOLUTION?
I can see only one, and it is a lesson learned many years ago: keep your real-time processing functions away from your Application MCU/Processor. To do that we just need to move the ZCD processing function from the ESP8266/whatever MCU you want to the MPDM Driver itself:
MPDMv4 - MAINS Phase detection and ZCD processing
What means that? means that in this new configuration our ESP8266 will be free from any type of real-time ZCD processing that is related with the MAINS Dimming process, you just need to send to the MPDMv4 driver a voltage (Vcontrol) in a pre-established range (0-3V for example) that will correspond with different desired Dimming levels.
What we have obtained? A UNIVERSAL MAINS Power Dimmer driver that can be used with any MCU you might want or even no MCU at all. You can dimm it even with a simple Potentiometer at input, no programming, no code, no nothing!!
Legend:
PURPLE - Phase detector output
BLUE - Reversed phase signal (normalised)
Yellow - Triac Driver CMD signal (PWM)
Vcontrol = 0, CMD Duty cycle=6%
Vcontrol = 2V, CMD Duty=50%
Vcontrol = 2.8V, CMD Duty=96%
How can be done that? Easy. Use PWM or a DAC, your choice. For ESP8266 I will recommend you to use a DAC, like the MCP4726 or, why not , the MCP4728, for a full 4 Channel MAINS Dimmers solution. PWM in case of the ESP8266..let's say that is has some limitations that you will discover very soon that you don't like :)
The mains advantages of using DAC?
Notable:
1. Very low to zero overhead on the App MCU
2. High precision (DAC from above are 12 bit!! - 4096 levels of dimming!!)
3. You can use the "set-and-forget" technique using DAC internal nonvolatile memory (EEPROM) and have the same level on the next power-off/on cycle.
IMPLEMENTATION
SCHEMATICS
As the only functional difference between the previous MPDMv3 MAINS Dimmer and the new MPDMv4 is the presence of the ZCD function onboard, basically, without some small bits and pieces around like the MOV protection circuit, you can see it exactly as it is: a MPDMv3 with a ZCD circuit onboard:
MPDMv3 - Phase detection and Triac control
Zero crossing detector circuit
MPDMv4 PCB:
MPDMv4 PCB
As you can see from the above picture, it was carefully designed with proper MAINS isolation from the rest of the driver, you can see even the extra isolation slots done for a even bigger Creepage distance.
And because I know this terms still creates some confusion, short definitions below:
CLEARANCE is the shortest distance in air between two conductive parts. CREEPAGE distance means the shortest distance along the surface of a solid insulating material between two conductive parts.
A creepage distance cannot be less than the associated clearance so that
the shortest creepage distance possible is equal to the required
clearance. However, there is no physical relationship, other than this
dimensional limitation, between the minimum clearance in air and the
minimum acceptable creepage distance.
And the new, freshly baked result:
MPDMv4 - MAINS Power Dimmer/Switch with Phase detection and ZCD Processing
Next time we will move on to the Software side, to see what is going on with our Webserver interface & stuff.
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
Had a lot fun fun with them, looks a nice and stable solution so I'm thinking to use them as Display for one of my future projects.
Meanwhile I was also playing with ESP8266 CBDBv2 EVO and Arduino IDE and because it looks like the latest 1.6.4 version it's becoming more stable and usable than previous releases I will give it a try for MAX7219 Driver implementation.
I still consider ESP8266 + NodeMCU LUA interpreter as the best environment for Learning/Drivers Developpment or even small projects, offering you a great flexibility that a Interpreter can give you but it's obviously that for bigger projects you need something else, so let's give Arduino IDE a try.
What we will need:
CBDBv2 EVO Board ( or any other ESP8266 Board with the same capabilities you may like )
USB adapter (take a look on Part 1 for details about the USB Adapter)
For programming and uploading the driver and the software we will use the Arduino IDE.
I will not insist to much on the Arduino IDE install process, it is a quite trivial process. If anybody wants more details about please feel free to ask.
MAX 7219 - 8 digit display driver connections
Wire MAX7219 ESP8266
Green +5Vcc Blue GND GND Yellow DIN 13 White CS 12 Orange CLK 14
MAX7219 Driver Implementation
For details about MAX Timing Diagram, Registers, Initialisation, etc please take a look at the detailed description from the previous MAX7219 article.
1. Init
int INTENSITYMIN = 0; // minimum brightness, valid range [0,15] int INTENSITYMAX = 1; // maximum brightness, valid range [0,15]
int DIN_PIN = 13; // data in pin int CS_PIN = 12; // load (CS) pin int CLK_PIN = 14; // clock pin int dly = 50; // delay in us int adc=0; // read ADC int spr=32; // number of readings int offset=5; // input offset
4. Convert anf Print float value in xxxx.xxx format
void print_LED(float fVal, int w, int p) { int d = 1; int ch = 1; int n = 0; int nr_size = 0; char charVal[11]; //temporarily holds data from vals String stringVal = ""; //data on buff is copied to this string
//dtostrf(fVal, w, p, charVal); //4 is mininum width, 3 is precision; //NOT WORKING FOR Values SMALLER THAT 0.01 !! // stringVal = charVal; // created a new function below for converting properly a pozitive xxxx.xxx float to string
stringVal=ftos(fVal,3);
int strl = stringVal.length()-1; for (int i=0;i<strl+1;i++) { charVal[i]=stringVal[i]; }
Serial.print("Length: ");Serial.println(strl); //display string Serial.println(stringVal); //convert charVal[] to LED Display string for(int i=0;i<strl+1;i++) { if ((charVal[i] == '.') && (d==1)) { stringVal=charVal[i]; n = 0; n = (n * 10) + (charVal[i-1] - 48); setRegistry(strl-i+1, 128+n); d = 0; } else { stringVal=charVal[i]; Serial.print("d: ");Serial.print(d); //display string Serial.print(" - Increment: ");Serial.print(i); //display string Serial.print(" - INT: ");Serial.println(charVal[i]); //display string n=0; n = (n * 10) + (charVal[i] - 48); int pos = i; if (d==0) { pos = i-1; } setRegistry(strl-pos,n); } } }
5. Convert float value to a string String ftos(float fVal, int prec) { int mlt=10; String snr; String dp; int iprt,dprt;
iprt = int(fVal);
// Round fVal for proper prec printing - correctly so that print(1.999, 2) prints as "2.00" double rnd = 0.5; for(uint8_t i = 0; i < prec; ++i) rnd /= 10.0; mlt *= 100; fVal += rnd;
// Check and count "0"'s proper after ZERO (0.00xx) number display dprt = 1000*(fVal-iprt); if (dprt < 10) { dp = "00" + String(dprt); }else if (dprt < 100) { dp = "0" + String(dprt); }else {dp = dprt;}
WARNING!! You will play with LIVE MAINS!! Deadly zone!!
If you don't
have any experience and are not qualified for working with MAINS power I
will not encourage you to play arround!. The
author take no responsibility for any injury or
death resulting, directly or indirectly, from your inability to
appreciate the hazards of household mains voltages.
The circuit diagrams are as accurately as possible, but are offered with no
guarantees whatsoever.
There is no guarantee that this design meets any Rules which may be in force in your country so please check before your local rules/regulations.
For any new requests please feel free to use as usual: tech at esp8266-projects.com. If
you want to order MAINS POwer Dimmer/Switch bare PCBs only,
you can also do it directly at Dirty PCBs, our preferred PCB House:
MAINS Power Dimmer / Switch Module - MPDMv3 - Connections
CBDB Evolution DevBoard
Because I don't like to have flying MAINS wires on my workdesk I have created a temporary separate MPDMv3 Module Box, containing all the MAINS part of the story :).
Isolated MAINS unit - keep your fingers away from the Deadly zone !
Remember, Safety First! And also more relaxing knowing that is no Russian Roulette wire game on progress on my table. Shit happens all the time, but at least let's try to reduce the chances to hit badly the fan too often :)
Live Testing on progress
In the Box above is enough space for all the parts going inside, including ESP8266 module, power supply, Dimmer Module, Choke, etc, but at this stage I find it easier to connect them together like that.
MPDMv3 Web Server Software
For programming CBDBv2 Board and uploading the driver and the software we will continue to use the LuaUploader as before. 1. Define used GPIO pin:
outpin=7 -- Select Triac Command pin - GPIO13 gpio.mode(outpin,gpio.OUTPUT) gpio.write(outpin,gpio.LOW) -- Triac OFF inpin=6 -- Zero crossing detector input - GPIO12 gpio.mode(inpin,gpio.INT,gpio.PULLUP) -- attach interrupt to ZCD
2. Zero Cross Detector function and Triac command
For a more detailed explanation how Zero cross detection circuit works please take a look at the previous MPDMv3 article.
function zero_cross() dt = 76*dim --print("Zero cross detected!") stat = "ON" tmr.delay(dt) -- Firing delay time calculated above gpio.write(outpin,gpio.HIGH) -- Triac ON - Zero cross detected tmr.delay(100) -- Triac ON - Propagation time gpio.write(outpin,gpio.LOW) -- Triac OFF - let's be sure it's OFF before next cycle :) tmr.wdclr() return stat end
3. WEB Server
srv=net.createServer(net.TCP) srv:listen(80,function(conn) conn:on("receive", function(conn,payload) --debugging output only -- print(payload) if (string.find(payload, "GET / HTTP/1.1") ~= nil) then --print("GET received") sendPage(conn) else swstat={string.find(payload,"cmd=")} --If POST value exist, set power switch status if swstat[2]~=nil then --print("Command received: " .. payload) PwrSW(swstat,payload) sendPage(conn) end end end) conn:on("sent", function(conn) conn:close() conn = nil -- clear and allow the garbage collector to free the memory --print("Connection closed")
CSS file created for this example is just for fancy decorations. If you don't like it you can very easy change the style attributes or add local ones.
5.Check received Dimmer value and update status
function PwrSW(swstat,payload) gpio.mode(outpin,gpio.OUTPUT) newstat=string.sub(payload,swstat[2]+1,#payload) status = tonumber(newstat) print("Dimmer Value:" .. status) end
4. Main code
status = 60 -- around 50% - choose your desired start value. newstat = 60 outpin=7 -- Select Triac Command pin - GPIO13 gpio.mode(outpin,gpio.OUTPUT) gpio.write(outpin,gpio.LOW) -- Triac OFF inpin=6 -- Zero crossing detector input - GPIO12 gpio.mode(inpin,gpio.INT,gpio.PULLUP) -- attach interrupt to ZCD
gpio.trig(inpin,"up",zero_cross) -- ZCD interrupt attached - trigger on falling edge print(wifi.sta.getip()) -- print our new MPDMv3 WebServer IP
For testing, just save the code on ESP as 'dimserver.lua', restart ESP and run: dofile("dimserver.lua") -- Start the Dimmer Listening WebServer =wifi.sta.getip() -- find the IP Address where your Web Server will be
Open your favorite Web browser and type your new MPDMv3 Web Server IP address. If all ok, should look something like below :
MPDMv3 Web Interface
If you want the MPDMv3 software to start automatically when your CBDB module
starts or reboots, then you neet to create and add some lines in your
'init.lua' file: dofile("dimserver.lua") -- Start automatically the Dimmer Listening WebServer
Save the code on ESP as 'init.lua', restart ESP. It should reboot and restart automatically the program.
A short video presentation, testing the Web Interface: