#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
using namespace std;
#define PIN_TEMP_OUTSIDE 27
#define PIN_TEMP_INSIDE 35
#define PIN_LDR 34
#define CS_PIN 5
#define PIN_BUTTON1 26
#define PIN_BUTTON2 25
//lux
#define MIN_LUM 300
#define MAX_LUM 500
//celsius
#define MIN_TEMP 21
#define MAX_TEMP 22
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//Time for synchronizations
#define DELAY_VALUES 50
#define DELAY_DISPLAY 1000
#define DELAY_FILE 2000
unsigned long timeNow = 0;
unsigned long syncValues = 0;
unsigned long syncDisplay = 0;
unsigned long syncFile = 0;
int tempReadOutside;
int tempReadInside;
float tempCalcOutside;
float tempCalcInside;
int ldrRead;
float ldrCalc;
//AC MODE: -1 Cooling
// 0 OFF
// 1 Heating
// 2 OFF - recomendada abertura de janela
signed int ACstate = 0;
File textFile;
char *dataMessage;
char *string1;
int button1;
int button2;
int entryState = 0;
int exitState = 0;
int numPessoas = 0;
void setup() {
Serial.begin(115200);
///////////////////////////////////////////////////////////
Serial.print("Initializing SD card... ");
if (!SD.begin(CS_PIN)) {
Serial.println("Card initialization failed!");
while (true);
}
Serial.println("initialization done.");
createDir(SD, "/mydir");
listDir(SD, "/", 0);
/*Serial.println("Files in the card:");
root = SD.open("/");
printDirectory(root, 0);
Serial.println("");*/
textFile = SD.open("/mydir/data.txt");
/*if(textFile){
Serial.println("criou com sucesso");
}
else{
Serial.println("erooouuuu");
}*/
Serial.println("mydir:");
listDir(SD, "/mydir", 0);
//listDir(SD, "/", 0);
//createDir(SD, "/mydir");
//listDir(SD, "/", 0);
//removeDir(SD, "/mydir");
//listDir(SD, "/", 2);
// Example of reading file from the card:
/*File textFile = SD.open("wokwi.txt");
if (textFile) {
Serial.print("wokwi.txt: ");
while (textFile.available()) {
Serial.write(textFile.read());
}
textFile.close();
} else {
Serial.println("error opening wokwi.txt!");
}*/
/////////////////////////////////////////////////////////////////////
//Serial.println("Hello, ESP32!");
//nao e necessario definir os pins 34/35 pq sao input only
pinMode(PIN_TEMP_OUTSIDE, INPUT);
pinMode(PIN_BUTTON1, INPUT_PULLUP);
pinMode(PIN_BUTTON2, INPUT_PULLUP);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
//Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(1000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
display.display();
delay(1000);
//display.drawFastHLine(3,3,30,SSD1306_WHITE);
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0); //setcursor (,0-61) 21 caracters per line
display.print("LETS GO CHAMP");
display.display();
// Draw a single pixel in white
//display.drawPixel(10, 10, SSD1306_WHITE);
//display.display();
delay(2000); // Pause for 2 seconds
}
void loop() {
timeNow = millis();
if(timeNow - syncValues >= DELAY_VALUES){
tempReadOutside = analogRead(PIN_TEMP_OUTSIDE);
tempReadInside = analogRead(PIN_TEMP_INSIDE);
ldrRead = analogRead(PIN_LDR);
//tempCalc = 0.2406*(tempRead*tempRead) - 53.953*tempRead + 3211.2;
//tempCalc = -0.031035511787526111608 *tempRead + -97.9480752014324082348;
//tempCalc = 5*pow(10, -6) * (tempRead*tempRead) - 0.0474*tempRead + 97.317;
tempCalcOutside = 1 / (log(1 / (4095. / tempReadOutside - 1)) / 3950 + 1.0 / 298.15) - 273.15;
tempCalcInside = 1 / (log(1 / (4095. / tempReadInside - 1)) / 3950 + 1.0 / 298.15) - 273.15;
float voltage = ldrRead / 4095. * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float ldrCalc = pow(50 * 1e3 * pow(10, 0.7) / resistance, (1 / 0.7));
button1 = !digitalRead(PIN_BUTTON1);
button2 = !digitalRead(PIN_BUTTON2);
if(button1 != 0 || button2 != 0){
//Normal entry
if(button1 == 1 && button2 == 0 && entryState == 0){
entryState = 1;
//Serial.println("normal entry 1");
}
if(button1 == 1 && button2 == 1 && entryState == 1){
entryState = 2;
//Serial.println("normal entry 2");
}
if(button1 == 0 && button2 == 1 && entryState == 2){
entryState = 3;
//Serial.println("normal entry 3");
}
//Hesitant entry
if(button1 == 1 && button2 == 0 && entryState == 2){
entryState = 1;
//Serial.println("hesitant entry 1");
}
if(button1 == 1 && button2 == 1 && entryState == 3){
entryState = 2;
//Serial.println("hesitant entry 2");
}
//Normal exit
if(button1 == 0 && button2 == 1 && exitState == 0){
exitState = 1;
//Serial.println("normal exit 1");
}
if(button1 == 1 && button2 == 1 && exitState == 1){
exitState = 2;
//Serial.println("normal exit 2");
}
if(button1 == 1 && button2 == 0 && exitState == 2){
exitState = 3;
//Serial.println("normal exit 3");
}
//Hesitant exit
if(button1 == 0 && button2 == 1 && exitState == 2){
exitState = 1;
//Serial.println("hesitant exit 1");
}
if(button1 == 1 && button2 == 1 && exitState == 3){
exitState = 2;
//Serial.println("hesitant exit 2");
}
//Serial.println("A processar entrada/saida...");
}else{
if(entryState == 3)
numPessoas++;
if(exitState == 3)
numPessoas--;
entryState = 0;
exitState = 0;
//Serial.print("reset 0 - pessoas = ");
// Serial. println(numPessoas);
}
}
if(timeNow - syncDisplay >= DELAY_DISPLAY){
display.setTextColor(WHITE);
display.setCursor(0,0); //setcursor (,0-61) 21 caracters per line
display.clearDisplay();
//display.display();
display.print("\n");
display.print("Temp OUT: ");
display.print(tempCalcOutside);
display.println(" Cels");
display.print("Temp IN: ");
display.print(tempCalcInside);
display.println(" Cels");
display.print("Lum: ");
display.print(ldrCalc);
display.println(" Lux");
display.print("\n");
display.print(" Occupation: ");
display.println(numPessoas);
/*Serial.print("button1: ");
Serial.println(button1);
Serial.print("button2: ");
Serial.println(button2);
Serial.print("entrySTate: ");
Serial.println(entryState);
Serial.print("n pessoas: ");
Serial.println(numPessoas);*/
//se estiver no intervalo recomendado 21--22ºC
if(tempCalcInside >= MIN_TEMP && tempCalcInside <= MAX_TEMP){
//desliga AC
ACstate = 0;
//display.setTextColor(GREEN);
display.println("->Optimal temperature");
}
else {
//display.setTextColor(RED);
if(tempCalcInside < MIN_TEMP){//too cold
if((tempCalcOutside-tempCalcInside < 5) && (tempCalcOutside-tempCalcInside > 0)){
display.println("Temp:low, open windo");
ACstate = 2;
}
else {
display.println("Temp:low, AC heating");
ACstate = 1;
}
}
if(tempCalcInside > MAX_TEMP){//too hot
//se diferença for MAX 5 GRAUS CELSIUS / se TempInside > TempOutside / se TempOutside < 25
if((tempCalcInside-tempCalcOutside < 5) && (tempCalcInside-tempCalcOutside > 0) && (tempCalcOutside < 25)){//open window
display.println("Temp:high, open windo");
ACstate = 2;
}
else{
display.println("Temp:high, AC cooling");
ACstate = -1; //cooling
}
}
}
//display.print("\n");
if(ldrCalc >= MIN_LUM && ldrCalc <= MAX_LUM){
//display.setTextColor(GREEN);
display.println("->Optimal lighting");
}
else {
//display.setTextColor(RED);
if(ldrCalc < MIN_LUM){//abaixo
display.println("Light:low, brightening");
}
if(ldrCalc > MAX_LUM){//acima
display.println("Light:high, dimming");
}
}
display.display();
}
if(timeNow - syncFile >= DELAY_FILE){
appendFile(SD, "/data.txt", "\n->Temp OUT: ");
appendFile(SD, "/data.txt", tempCalcOutside);
appendFile(SD, "/data.txt", " Temp IN: ");
appendFile(SD, "/data.txt", tempCalcInside);
appendFile(SD, "/data.txt", " Luminosidade: ");
appendFile(SD, "/data.txt", ldrCalc);
appendFile(SD, "/data.txt", "\nOcupacao: ");
appendFile(SD, "/data.txt", numPessoas);
appendFile(SD, "/data.txt", " Estado A/C: ");
if(ACstate == -1)
appendFile(SD, "/data.txt", "On - Cooling");
if(ACstate == 0)
appendFile(SD, "/data.txt", "Off");
if (ACstate == 1)
appendFile(SD, "/data.txt", "On - Heating");
if (ACstate == 2)
appendFile(SD, "/data.txt", "Off - Open window");
}
//appendFile(SD, "/data.txt", tempCalcInside);
//appendFile(SD, "/data.txt", "\n");
//writeFile(SD, "/data.txt", dataMessage);
//readFile(SD, "/data.txt");
//display.print("\n\n");
/*if (textFile) {
Serial.print("Writing to data.txt... ");
while (textFile.available()) {
textFile.print("Temperature outside: ");
textFile.println(tempCalcOutside);
textFile.print("Temp inside: ");
textFile.println(tempCalcInside);
textFile.print("Luminosity: ");
textFile.println(ldrCalc);
}
//textFile.close();
} else {
Serial.println("error opening data.txt!");
}*/
}
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
//Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
//Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
//Serial.print(" DIR : ");
//Serial.println(file.name());
if(levels){
listDir(fs, file.name(), levels -1);
}
} else {
//Serial.print(" FILE: ");
//Serial.print(file.name());
//Serial.print(" SIZE: ");
//Serial.println(file.size());
}
file = root.openNextFile();
}
}
void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
Serial.write(file.read());
}
file.close();
}
void appendFile(fs::FS &fs, const char * path, const char * message){
//Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
file.print(message);
/*if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}*/
file.close();
}
void appendFile(fs::FS &fs, const char * path, float var){
//Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
file.print(var);
/*if(file.print(var)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}*/
file.close();
}
void appendFile(fs::FS &fs, const char * path, int var){
//Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
file.print(var);
/*if(file.print(var)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}*/
file.close();
}
void intToString(int num, char* str) {
int i = 0;
if(num == 0) {
str[i++] = '0';
str[i] = '\0';
return;
}
while(num != 0) {
int rem = num % 10;
str[i++] = (char) (rem + '0');
num /= 10;
}
str[i] = '\0';
int len = i - 1;
for(int j = 0; j < i/2; j++) {
char tmp = str[j];
str[j] = str[len-j];
str[len-j] = tmp;
}
}