-
Notifications
You must be signed in to change notification settings - Fork 1
/
thermostat.c
157 lines (134 loc) · 3.93 KB
/
thermostat.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
* HTTP server example.
*
* This sample code is in the public domain.
*/
#include <espressif/esp_common.h>
#include <esp8266.h>
#include <esp/uart.h>
#include <string.h>
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include <ssid_config.h>
#include <httpd/httpd.h>
#include <ds18b20/ds18b20.h>
#include <math.h>
enum {
SSI_TEMPERATURE,
SSI_THERMOSTAT_STATE,
SSI_ERROR_COUNT
};
typedef enum {
Cooling,
Heating
} ThermostatState;
#define RELAY_GPIO 12
#define SENSOR_GPIO 14
#define LOOP_DELAY_MS 250
volatile int error_count = 0;
volatile float temperature = NAN;
volatile ThermostatState ts = Cooling;
int32_t ssi_handler(int32_t iIndex, char *pcInsert, int32_t iInsertLen)
{
switch (iIndex) {
case SSI_TEMPERATURE:
snprintf(pcInsert, iInsertLen, "%.2f", temperature);
break;
case SSI_ERROR_COUNT:
snprintf(pcInsert, iInsertLen, "%d", error_count);
break;
case SSI_THERMOSTAT_STATE:
snprintf(pcInsert, iInsertLen, ts == Heating ? "Heating" : "Cooling");
break;
default:
snprintf(pcInsert, iInsertLen, "N/A");
break;
}
/* Tell the server how many characters to insert */
return strlen(pcInsert);
}
char *gpio_cgi_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{
return "/index.ssi";
}
void httpd_task(void *pvParameters)
{
tCGI pCGIs[] = {
{"/gpio", (tCGIHandler) gpio_cgi_handler},
};
const char *pcConfigSSITags[] = {
"temp", // SSI_TEMPERATURE
"stat", // SSI_THERMOSTAT_STATE
"err" // SSI_ERROR_COUNT
};
/* register handlers and start the server */
http_set_cgi_handlers(pCGIs, sizeof (pCGIs) / sizeof (pCGIs[0]));
http_set_ssi_handler((tSSIHandler) ssi_handler, pcConfigSSITags,
sizeof (pcConfigSSITags) / sizeof (pcConfigSSITags[0]));
httpd_init();
for (;;);
}
void measure_task(void *pvParameters)
{
ds18b20_addr_t addr = 0x83031701A30CFF28ULL;
while (1) {
temperature = ds18b20_measure_and_read(SENSOR_GPIO, addr);
if (isnan(temperature)) {
error_count++;
} else {
error_count = 0;
}
vTaskDelay(LOOP_DELAY_MS / portTICK_PERIOD_MS);
}
}
void setThermostatState(ThermostatState state) {
ts = state;
gpio_write(RELAY_GPIO, state == Heating);
}
void thermostat_task(void *pvParameters) {
gpio_enable(RELAY_GPIO, GPIO_OUTPUT);
gpio_write(RELAY_GPIO, false);
while (1) {
if (error_count > 10) {
setThermostatState(Cooling);
} else if (!isnan(temperature)) {
switch (ts) {
case Cooling:
if (temperature < 60.0) {
setThermostatState(Heating);
} else {
setThermostatState(Cooling);
}
break;
case Heating:
if (temperature > 80.0) {
setThermostatState(Cooling);
}
break;
default:
setThermostatState(Cooling);
break;
}
}
vTaskDelay(LOOP_DELAY_MS / portTICK_PERIOD_MS);
}
}
void user_init(void)
{
uart_set_baud(0, 115200);
printf("SDK version:%s\n", sdk_system_get_sdk_version());
struct sdk_station_config config = {
.ssid = WIFI_SSID,
.password = WIFI_PASS,
};
/* required to call wifi_set_opmode before station_set_config */
sdk_wifi_set_opmode(STATION_MODE);
sdk_wifi_station_set_config(&config);
sdk_wifi_station_set_auto_connect(true);
sdk_wifi_station_connect();
/* initialize tasks */
xTaskCreate(&httpd_task, "HTTP Daemon", 256, NULL, 2, NULL);
xTaskCreate(&measure_task, "Measurement", 256, NULL, 3, NULL);
xTaskCreate(&thermostat_task, "Thermostat", 256, NULL, 4, NULL);
}