-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.ino
217 lines (190 loc) · 5.08 KB
/
client.ino
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#include <Arduino.h>
#include <LiquidCrystal.h>
#include "./include/SerialConstant.hpp"
#include "./include/Datatypes.hpp"
#define REDRAW_INTERVAL 600000
#define TEMP_UPDATE_INTERVAL 100
#define TEMP_AVERAGE_COUNT 100
#define TEMP_SENSOR_CALIB_VALUE 0.437528f
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
class StateKeeper {
public:
byte buf[SerialConstant::Size::SERIALBUF] = {0x00};
byte state = SerialConstant::State::IDLE;
byte next = SerialConstant::State::IDLE;
byte bIndex = 0x00;
struct Timekeep_S {
u64 redraw = 0,
tempRead = 0,
curr = 0;
} timekeep;
struct Temperature_S {
f32 reading = 0.0f;
u16 divisor = 0;
cf32 adjust = TEMP_SENSOR_CALIB_VALUE;
} temp;
void resetBuf(){
for(u16 i = 0; i < SerialConstant::Size::SERIALBUF; i++) this->buf[i] = 0x00;
this->bIndex = 0x00;
this->state = SerialConstant::State::IDLE;
}
} s;
// Resets the device
void (*resetDevice)(void) = 0;
// Blanks num blocks starting at col, row and returns the cursor to col, row
void lBlank(byte col, byte row, byte num){
lcd.setCursor(col,row);
if(col + num > 15) num = 15 - col;
for(byte i = 0; i<num; ++i)
lcd.write(" ");
lcd.setCursor(col,row);
}
// Draws some basic elements
void drawBaseElements(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("C");
lcd.setCursor(6, 0);
lcd.print("R");
}
// Date&Time handler for serial data
// Needs s.buf[0] = HOURS
// [1] = MINS
// [2] = DAY
// [3] = MONTH
void handleDateTime(){
// ==== HOURS ==== //
byte temp = s.buf[0];
// Blank time display
lBlank(0,1,5);
// If hours < 10, add preceding zero
if(temp<10)
lcd.print(0);
lcd.print(temp);
// Add separator
lcd.print(":");
// ==== MINS ==== //
// Cursor should already be after the separator
temp = s.buf[1];
// If mins < 10, add preceding zero
if(temp<10)
lcd.print(0);
lcd.print(temp);
// ==== DAY ==== //
temp = s.buf[2];
lcd.setCursor(6, 1);
// If day < 10, add preceding zero
if(temp<10)
lcd.print("0");
lcd.print(temp);
lcd.print(".");
// ==== MONTH ==== //
// Cursor should already be after the separator
temp = s.buf[3];
// If month < 10, add preceding zero
if(temp<10)
lcd.print("0");
lcd.print(temp);
}
// CPU Utilization handler for serial data
// Needs s.buf[0] = CPU%
void handleCPUtil(){
// Blank CPU% Range
lBlank(2, 0, 4);
// Write CPU%
lcd.print(s.buf[0]);
lcd.print("%");
}
// RAM Utilization handler for serial data
// Needs s.buf[0] = RAM%
void handleRAMUtil(){
// Blank RAM% Range
lBlank(8,0,4);
// Write RAM%
lcd.print(s.buf[0]);
lcd.print("%");
}
void setup(){
Serial.begin(9600);
delay(1000);
lcd.begin(16,2);
delay(1000);
drawBaseElements();
// Temperature sensor
pinMode(A0,INPUT);
}
void loop(){
// Redrau UI every REDRAW_INTERVAL secs
s.timekeep.curr = millis();
if(s.timekeep.curr - s.timekeep.redraw > REDRAW_INTERVAL){
s.timekeep.redraw = s.timekeep.curr;
drawBaseElements();
}
if(Serial.available() > 0){
// If at DATA_START, don't read next byte / if done, 1 byte gets skipped
// If next is HALT, preserve it for the switch
if(s.next != SerialConstant::Flag::DATA_START && s.next != SerialConstant::State::HALT)
s.next = Serial.read();
switch(s.next){
case SerialConstant::Flag::DATA_START:
// Don't mess up the state if next byte isn't available yet
if(Serial.available() > 0)
s.next = s.state = Serial.read();
break;;
case SerialConstant::Flag::DATA_END:
// If END of DataPacket found, find the appropriate handler for the data
switch(s.state){
case SerialConstant::Data::DATETIME:
handleDateTime(); break;;
case SerialConstant::Data::CPUTIL:
handleCPUtil(); break;;
case SerialConstant::Data::RAMUTIL:
handleRAMUtil(); break;;
}
s.resetBuf();
break;;
case SerialConstant::State::HALT:
// Reset the device via software (send HALT byte)
resetDevice();
break;;
default: {
// If not at IDLE push back the next serial byte in the array
if(s.state != SerialConstant::State::IDLE){
// Overflow detection
if(s.bIndex > SerialConstant::Size::SERIALBUF - 1 ){
s.bIndex = 0;
// Reset if overflown
s.next = SerialConstant::State::HALT;
}
s.buf[s.bIndex++] = s.next;
}
}
}
}
if(s.timekeep.curr - s.timekeep.tempRead > TEMP_UPDATE_INTERVAL){
s.timekeep.tempRead = s.timekeep.curr;
f32 temp = analogRead(A0);
if ( temp > 0 && temp < 140 )
s.temp.reading += temp;
else {
// if we don't read a valid temp, report immediately that the sersor is kaputt
// Blank TEMP Range
lBlank(12,1,4);
// Write Na
lcd.print("N/A");
}
if (s.temp.divisor++ >= TEMP_AVERAGE_COUNT){
// Blank TEMP Range
lBlank(12,1,4);
f32 temp = s.temp.reading * s.temp.adjust / s.temp.divisor;
// Round to 1st digit after floating point
temp = floor(temp*10.0f + 0.5f) / 10.0f;
// Print temp
lcd.print(temp);
// Reset Counter
s.temp.divisor = 0;
// Reset temperatureReading
s.temp.reading = 0;
}
}
}