This project is based on a previous project I did last year ( https://mculabs.blogspot.com/2018/10/a-mqtt-demo-using-esp-01-esp8266.html ) , but has benn improved a lot. The most significant change is this time a dedicated mobile App is created, so we can have a decent App that suites the needs. Then this time we have 2 devices connected to the MQTT server simultaneously, the 2 devices are subscribed to different topics on the MQTT server. Of course it is possible to combine these 2 into 1 and save a ESP-01 module.
The smart plug uses a ESP-01-RELAY module and a AC/DC |
The IR transmitter circuit is simple |
What is tricky is the IR transmitter, to simulate the work of a TV remote controller, the ESP8266 must generate a 38kHz carrier and then modulate it in order to send proper commands. Using software to generate a 38kHz wave is going to waste too much resources, fortunately the ESP8266 has a built-in I2S port, which can be configured to work at 38kHz, bad news is this I2S port has been removed from the official documents, I have to spend days on searching the internet and Espressif's SDKs to find a proper demo code which shows how to configure the I2S. Turns out, there is an API function named sdk_rom_i2c_writeReg_Mask() , which is dedicated to I2S configuration, but I couldn't find any documentation about it, if you knows about it, I would appreciate it very much if you can leave a comment below.
I would like to share the 38kHz carrier generation code here, if you are also doing a similar project, I hope this can help you. It is written in C++ but is easy to be understand and therefore adopt to any other languages.
//*********************************************************
//**** This code is by Jian Jiao, mculabs.blogspot.com ****
//*********************************************************
#include <espressif/esp_common.h>
#include "esp_carrier.h"
#define DR_REG_I2S_BASE (0x60000e00)
#define I2SCONF (DR_REG_I2S_BASE + 0x0008)
extern "C" void sdk_rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id,
uint32_t reg_add, uint32_t Msb, uint32_t Lsb, uint32_t indata);
ESP_CARRIER_GEN::ESP_CARRIER_GEN()
{
sdk_rom_i2c_writeReg_Mask(0x67, 4, 4, 7, 7, 1);
// this is a undocumented API, copied from Espressif example code.
// The supposed use for this API is to enable I2S CLK source
// rom_i2c_writeReg_Mask( i2c_bbpll,
// i2c_bbpll_hostid,
// i2c_bbpll_en_audio_clock_out,
// i2c_bbpll_en_audio_clock_out_msb,
// i2c_bbpll_en_audio_clock_out_lsb,
// 1);
WRITE_PERI_REG(I2SCONF, (READ_PERI_REG(I2SCONF) & 0xF0000FFF) | (0x3e << 22) | (0x02 << 16) | (0x01 << 12));
// set I2CCONF register. This set the I2S WS output frequency to 38kHz
// bit 22~27 : I2S_BCK_DIV_NUM
// bit 16~21 : I2S_CLKM_DIV_NUM
// bit 12 : FIFO access mode, 1=SLC DMA, 0=software direct, default=1
WRITE_PERI_REG(I2SCONF, (READ_PERI_REG(I2SCONF) & 0xFFFFFDFF) | (0x01 << 8)); // for output on I2SO_WS
// WRITE_PERI_REG(I2SCONF, (READ_PERI_REG(I2SCONF) & 0xFFFFFDFF) | (0x02 << 8)); // for output on I2SI_WS
// I2S rx start
}
void ESP_CARRIER_GEN::carrier_on(void)
{
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_I2SI_WS); // MTMS pin as WS output
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS); // GPIO_2 pin as WS output
}
void ESP_CARRIER_GEN::carrier_off(void)
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2); // GPIO_2 pin as GPIO
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, 1 << 2); // enable output
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << 2); // output 0
}
The mobile app is written in C++ in Embarcadero's C++ Builder, I'm very glad they have made this great product available free for personal users. It saves me tremendous time to learn a new language in order to create a mobile phone App.
The UI of the App is still ugly and needs improvements, but for now I won't spend more time on it and just move on to my next project.
The ESP8266 part of the project was developed in the open source FreeRTOS SDK esp-open-rtos, and it's using FreeRTOS and C++.
Here is the demo video of this project.