This is an old revision of the document!
Student: Andrei-Alexandru Ulmamei
Master: ACES II
Git repository: https://gitlab.upb.ro/aulmamei/iot-project
Demo link: To be added
This goal of this project is to create a temperature monitoring and control system, intended to be used in a server room, that consists of a Web Application, a microcontroller that communicates with the Web App, a sensor for monitoring temperature and an IR transmitter, used for controlling an air conditioning unit.
The hardware components needed for the project are:
The following electric schematic represents the project’s hardware.
The schematic was realized using KiCad (https://www.kicad.org/).
The code is composed of 4 elements: the embedded software, written in Arduino IDE for the ESP32 board, the Web Component, which was written in HTML and Javascript for the frontend functionality, the Firebase Realtime Database configuration and the Grafana dashboard configuration.
Embedded software
The code is written in Arduino IDE, which controls both the hardware components and the communication to the database. The code is divided into the following sections:
The temperature is read from the sensor and printed on the display every two seconds:
if(millis() - writePrevDisplay > writeDisplayTimer || writePrevDisplay == 0) { writePrevDisplay = millis(); writeTempToDisplay(dht.readTemperature()); }
The temperature is written to the database. This is done by using a JSON that contains the timestamp (in epoch form) and the temperature, which is logged to the Realtime database each minute.
if (Firebase.ready() && (millis() - sendDataPrevMillis > timerDelay || sendDataPrevMillis == 0)){ sendDataPrevMillis = millis(); //Get current timestamp timestamp = getTime(); Serial.print ("time: "); Serial.println (timestamp); parentPath= databasePath + "/" + String(timestamp); json.set(tempPath.c_str(), String(dht.readTemperature())); json.set(timePath, String(timestamp)); Serial.printf("Set json... %s\n", Firebase.RTDB.setJSON(&fbdo, parentPath.c_str(), &json) ? "ok" : fbdo.errorReason().c_str()); }
In the control section, control data (information about the state of the A/C unit, about which temperature should be set, about which fan speed should be set) is read from the database, and accordingly the needed IR command is sent. In this section, the previous A/C state is saved, so that commands will be sent to the A/C unit only in case of a change.
if(millis() - prevDataQuery > dataQueryTimer || prevDataQuery == 0) { prevDataQuery = millis(); String ac_status_path = controlPath + ac_status; String ac_temp_path = controlPath + ac_temp; String fan_speed_path = controlPath + fan_speed; int ac_status_val, ac_temp_val, fan_speed_val; bool s = Firebase.RTDB.getInt(&fbdo, ac_status_path.c_str(), &ac_status_val); s = Firebase.RTDB.getInt(&fbdo, ac_temp_path.c_str(), &ac_temp_val); s = Firebase.RTDB.getInt(&fbdo, fan_speed_path.c_str(), &fan_speed_val); if(prev_ac_temp == ac_temp_val && prev_ac_status == ac_status_val && prev_fan_speed == fan_speed_val) { } else { sendIRCmd(ac_status_val, ac_temp_val, fan_speed_val); } prev_ac_temp = ac_temp_val; prev_ac_status = ac_status_val; prev_fan_speed = fan_speed_val; }
For the embedded part, the remote control of the A/C unit was reverse engineered to get the set temperature commands, or set fan speed commands. The commands format is a 16 bit value, where the most significant 8 bits are the temperature setting and the least significant bits were the fan speed. The A/C can be turned on by using any temperature/fan speed command. The turn off command is done by sending 0x7DE command.
#define IR_ADDR 0xB24D #define OFF_CMD 0x7DE #define DEG_17_CMD 0x00 #define DEG_18_CMD 0x08 #define DEG_19_CMD 0x0C #define DEG_20_CMD 0x04 #define DEG_21_CMD 0x06 #define DEG_22_CMD 0x0E #define DEG_23_CMD 0x0A #define DEG_24_CMD 0x02 #define DEG_25_CMD 0x03 #define FAN_1_CMD 0xF9 #define FAN_2_CMD 0xFA #define FAN_3_CMD 0xFC #define FAN_AUTO_CMD 0xFD
Web Application
Database configuration
Grafana Dashboard