├── .gitattributes ├── README.md ├── hw_timer.h ├── ESP8266_MQTT_Dimmer.ino └── hw_timer.c /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP8266_MQTT_Dimmer 2 | This is the code for the project ESP8266 based AC Dimmer made using Generic ESP8266 Module and some other basic components. 3 | In this project I have used Ubidots MQTT server for wireless communication. 4 | 5 | You can have a look over the full tutorial video to know more about this project 6 | https://youtu.be/X3PXI-QLK9s 7 | 8 | Credits 9 | The original code for ESP8266 based dimmer was written by Nasir Malik. I have just edited the code to make it work with Ubidots 10 | MQTT server. 11 | 12 | You can use the original code from Nasir Malik. Here is the link 13 | https://github.com/nassir-malik/IOT-AC-Light-Dimmer-With-Alexa/tree/master/Part%20%23%201/robodyn_dimmer 14 | -------------------------------------------------------------------------------- /hw_timer.h: -------------------------------------------------------------------------------- 1 | #ifndef HW_TIMER_H 2 | #define HW_TIMER_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define US_TO_RTC_TIMER_TICKS(t) \ 9 | ((t) ? \ 10 | (((t) > 0x35A) ? \ 11 | (((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \ 12 | (((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \ 13 | 0) 14 | 15 | #define FRC1_ENABLE_TIMER BIT7 16 | #define FRC1_AUTO_LOAD BIT6 17 | 18 | //TIMER PREDIVED MODE 19 | typedef enum { 20 | DIVDED_BY_1 = 0, //timer clock 21 | DIVDED_BY_16 = 4, //divided by 16 22 | DIVDED_BY_256 = 8, //divided by 256 23 | } TIMER_PREDIVED_MODE; 24 | 25 | typedef enum { //timer interrupt mode 26 | TM_LEVEL_INT = 1, // level interrupt 27 | TM_EDGE_INT = 0, //edge interrupt 28 | } TIMER_INT_MODE; 29 | 30 | typedef enum { 31 | FRC1_SOURCE = 0, 32 | NMI_SOURCE = 1, 33 | } FRC1_TIMER_SOURCE_TYPE; 34 | 35 | 36 | void hw_timer_arm(u32 val); 37 | void hw_timer_set_func(void (* user_hw_timer_cb_set)(void)); 38 | void hw_timer_init(FRC1_TIMER_SOURCE_TYPE source_type, u8 req); 39 | //void ICACHE_RAM_ATTR blink_gpio(void); 40 | //volatile bool state; 41 | 42 | 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* HW_TIMER_H */ 49 | -------------------------------------------------------------------------------- /ESP8266_MQTT_Dimmer.ino: -------------------------------------------------------------------------------- 1 | #include "hw_timer.h" 2 | #include "UbidotsESPMQTT.h" 3 | #include 4 | const byte zcPin = 0; 5 | const byte pwmPin = 2; 6 | // String temp; 7 | byte fade = 1; 8 | byte state = 1; 9 | byte tarBrightness = 255; 10 | byte curBrightness = 0; 11 | byte zcState = 0; // 0 = ready; 1 = processing; 12 | 13 | void zcDetectISR(); 14 | void dimTimerISR(); 15 | 16 | 17 | #define WIFINAME "SSID" //Your SSID 18 | #define WIFIPASS "PASS" // Your Wifi Pass 19 | #define TOKEN "YOUR_TOKEN_NUMBER" // Your Ubidots TOKEN 20 | 21 | 22 | Ubidots client(TOKEN); 23 | 24 | 25 | /**************************************** 26 | Auxiliar Functions 27 | ****************************************/ 28 | void callback(char* topic, byte* payload, unsigned int length) { 29 | digitalWrite(1, LOW); 30 | //Serial.print("Message arrived ["); 31 | //Serial.print(topic); 32 | //Serial.print("] "); 33 | 34 | for (int i = 0; i < length; i++) { 35 | //Serial.print((char)payload[i]); 36 | // temp = temp + payload[i 37 | //Serial.println(); 38 | // //Serial.println(temp); 39 | int mytopic = atoi(topic); 40 | payload[length] = '\0'; 41 | int mymsg = atoi ((const char*)payload); 42 | 43 | int val = mymsg; 44 | if (val > 0) { 45 | tarBrightness = val; 46 | //Serial.println(tarBrightness); 47 | digitalWrite(1, LOW); 48 | } 49 | // temp = ""; 50 | } 51 | } 52 | 53 | 54 | void setup() { 55 | 56 | //Serial.begin(115200); 57 | client.ubidotsSetBroker("business.api.ubidots.com"); // Sets the broker properly for the business account 58 | client.setDebug(false); // Pass a true or false bool value to activate debug messages 59 | //Serial.begin(115200); 60 | client.wifiConnection(WIFINAME, WIFIPASS); 61 | client.begin(callback); 62 | client.ubidotsSubscribe("esp-01", "bulb"); //Insert the dataSource and Variable's Labels 63 | 64 | pinMode(1, OUTPUT); 65 | digitalWrite(1, HIGH); 66 | pinMode(zcPin, INPUT_PULLUP); 67 | pinMode(pwmPin, OUTPUT); 68 | attachInterrupt(zcPin, zcDetectISR, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection 69 | hw_timer_init(NMI_SOURCE, 0); 70 | hw_timer_set_func(dimTimerISR); 71 | //client.ubidotsSubscribe("esp32", "relay1"); //Insert the dataSource and Variable's Labels 72 | } 73 | 74 | 75 | 76 | void loop() { 77 | 78 | if (!client.connected()) { 79 | client.reconnect(); 80 | client.ubidotsSubscribe("esp-01", "bulb"); //Insert the dataSource and Variable's Labels 81 | } 82 | client.loop(); 83 | } 84 | 85 | 86 | void dimTimerISR() { 87 | if (fade == 1) { 88 | if (curBrightness > tarBrightness || (state == 0 && curBrightness > 0)) { 89 | --curBrightness; 90 | } 91 | else if (curBrightness < tarBrightness && state == 1 && curBrightness < 255) { 92 | ++curBrightness; 93 | } 94 | } 95 | else { 96 | if (state == 1) { 97 | curBrightness = tarBrightness; 98 | } 99 | else { 100 | curBrightness = 0; 101 | } 102 | } 103 | 104 | if (curBrightness == 0) { 105 | state = 0; 106 | digitalWrite(pwmPin, 0); 107 | } 108 | else if (curBrightness == 255) { 109 | state = 1; 110 | digitalWrite(pwmPin, 1); 111 | } 112 | else { 113 | digitalWrite(pwmPin, 1); 114 | } 115 | 116 | zcState = 0; 117 | } 118 | 119 | void zcDetectISR() { 120 | if (zcState == 0) { 121 | zcState = 1; 122 | 123 | if (curBrightness < 255 && curBrightness > 0) { 124 | digitalWrite(pwmPin, 0); 125 | 126 | int dimDelay = 30 * (255 - curBrightness) + 400;//400 127 | hw_timer_arm(dimDelay); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /hw_timer.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Copyright 2013-2014 Espressif Systems (Wuxi) 3 | * 4 | * FileName: hw_timer.c 5 | * 6 | * Description: hw_timer driver 7 | * 8 | * Modification history: 9 | * 2014/5/1, v1.0 create this file. 10 | *******************************************************************************/ 11 | //#include "c-types.h" 12 | typedef __SIZE_TYPE__ size_t; 13 | #include "ets_sys.h" 14 | #include "os_type.h" 15 | #include "osapi.h" 16 | #include "hw_timer.h" 17 | 18 | 19 | /****************************************************************************** 20 | * FunctionName : hw_timer_arm 21 | * Description : set a trigger timer delay for this timer. 22 | * Parameters : uint32 val : 23 | in autoload mode 24 | 50 ~ 0x7fffff; for FRC1 source. 25 | 100 ~ 0x7fffff; for NMI source. 26 | in non autoload mode: 27 | 10 ~ 0x7fffff; 28 | * Returns : NONE 29 | *******************************************************************************/ 30 | void hw_timer_arm(u32 val) 31 | { 32 | RTC_REG_WRITE(FRC1_LOAD_ADDRESS, US_TO_RTC_TIMER_TICKS(val)); 33 | } 34 | 35 | static void (* user_hw_timer_cb)(void) = NULL; 36 | /****************************************************************************** 37 | * FunctionName : hw_timer_set_func 38 | * Description : set the func, when trigger timer is up. 39 | * Parameters : void (* user_hw_timer_cb_set)(void): 40 | timer callback function, 41 | * Returns : NONE 42 | *******************************************************************************/ 43 | void hw_timer_set_func(void (* user_hw_timer_cb_set)(void)) 44 | { 45 | user_hw_timer_cb = user_hw_timer_cb_set; 46 | } 47 | 48 | static void hw_timer_isr_cb(void) 49 | { 50 | if (user_hw_timer_cb != NULL) { 51 | (*(user_hw_timer_cb))(); 52 | } 53 | } 54 | 55 | /****************************************************************************** 56 | * FunctionName : hw_timer_init 57 | * Description : initilize the hardware isr timer 58 | * Parameters : 59 | FRC1_TIMER_SOURCE_TYPE source_type: 60 | FRC1_SOURCE, timer use frc1 isr as isr source. 61 | NMI_SOURCE, timer use nmi isr as isr source. 62 | u8 req: 63 | 0, not autoload, 64 | 1, autoload mode, 65 | * Returns : NONE 66 | *******************************************************************************/ 67 | void ICACHE_FLASH_ATTR hw_timer_init(FRC1_TIMER_SOURCE_TYPE source_type, u8 req) 68 | { 69 | if (req == 1) { 70 | RTC_REG_WRITE(FRC1_CTRL_ADDRESS, 71 | FRC1_AUTO_LOAD | DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT); 72 | } else { 73 | RTC_REG_WRITE(FRC1_CTRL_ADDRESS, 74 | DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT); 75 | } 76 | 77 | if (source_type == NMI_SOURCE) { 78 | ETS_FRC_TIMER1_NMI_INTR_ATTACH(hw_timer_isr_cb); 79 | } else { 80 | ETS_FRC_TIMER1_INTR_ATTACH(hw_timer_isr_cb, NULL); 81 | } 82 | 83 | TM1_EDGE_INT_ENABLE(); 84 | ETS_FRC1_INTR_ENABLE(); 85 | } 86 | 87 | //-------------------------------Test Code Below-------------------------------------- 88 | #if 0 89 | void hw_test_timer_cb(void) 90 | { 91 | static uint16 j = 0; 92 | j++; 93 | 94 | if ((WDEV_NOW() - tick_now2) >= 1000000) { 95 | static u32 idx = 1; 96 | tick_now2 = WDEV_NOW(); 97 | os_printf("b%u:%d\n", idx++, j); 98 | j = 0; 99 | } 100 | 101 | //hw_timer_arm(50); 102 | } 103 | 104 | void ICACHE_FLASH_ATTR user_init(void) 105 | { 106 | hw_timer_init(FRC1_SOURCE, 1); 107 | hw_timer_set_func(hw_test_timer_cb); 108 | hw_timer_arm(100); 109 | } 110 | #endif 111 | /* 112 | NOTE: 113 | 1 if use nmi source, for autoload timer , the timer setting val can't be less than 100. 114 | 2 if use nmi source, this timer has highest priority, can interrupt other isr. 115 | 3 if use frc1 source, this timer can't interrupt other isr. 116 | 117 | */ 118 | --------------------------------------------------------------------------------