-
Notifications
You must be signed in to change notification settings - Fork 0
/
lightMeter.ino
234 lines (182 loc) · 8.26 KB
/
lightMeter.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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
An example analogue meter using a ST7735 TFT LCD screen
This example uses the hardware SPI only
Needs Font 2 (also Font 4 if using large scale label)
Updated by Bodmer for variable meter size
*/
// SET THE PINS FOR THE LIGHT SENSORS.
#define PhotoTransistor 36
#define ALS_PT19 15
// Define meter size
#define M_SIZE 1.000
#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define TFT_GREY 0x5AEB
#define TFT_ORANGE 0xFD20 /* 255, 165, 0 */
float ltx = 0; // Saved x coord of bottom of needle
uint16_t osx = M_SIZE*120, osy = M_SIZE*120; // Saved x & y coords
uint32_t updateTime = 0; // time for next update
int old_analog = -999; // Value last displayed
int value[6] = {0, 0, 0, 0, 0, 0};
int old_value[6] = { -1, -1, -1, -1, -1, -1};
int d = 0;
// ANALOG READ THE LIGHT SENSORS.
int phtrAnalogValue = 0;
int alsAnalogValue = 0;
// CONVERT THE ANALOG READ TO A VOLTAGE.
float phtrVoltage = 0.0;
float alsVoltage = 0.0;
void setup(void) {
Serial.begin(9600); // For debug
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
// ANALOG READ THE LIGHT SENSORS.
phtrAnalogValue = analogRead(PhotoTransistor);
alsAnalogValue = analogRead(ALS_PT19);
// CONVERT THE ANALOG READ TO A VOLTAGE.
phtrVoltage = (3.3 / 4095.0) * phtrAnalogValue;
alsVoltage = (3.3 / 4095.0) * alsAnalogValue;
analogMeter(); // Draw analogue meter
updateTime = millis(); // Next update time
}
void loop() {
if (updateTime <= millis()) {
updateTime = millis() + 35; // Update meter every 35 milliseconds
// ANALOG READ THE LIGHT SENSORS.
phtrAnalogValue = analogRead(PhotoTransistor);
alsAnalogValue = analogRead(ALS_PT19);
// CONVERT THE ANALOG READ TO A VOLTAGE.
phtrVoltage = (3.3 / 4059.0) * phtrAnalogValue;
alsVoltage = (3.3 / 4059.0) * alsAnalogValue;
plotNeedle((phtrAnalogValue / 40.95), 0); // It takes between 2 and 14ms to replot the needle with zero delay
//Serial.println(millis()-tt);
} // END IF
}
// #########################################################################
// Draw the analogue meter on the screen
// #########################################################################
void analogMeter()
{
// Meter outline
tft.fillRect(0, 0, M_SIZE*239, M_SIZE*131, TFT_GREY);
tft.fillRect(1, M_SIZE*3, M_SIZE*234, M_SIZE*125, TFT_WHITE);
tft.setTextColor(TFT_BLACK); // Text colour
// Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing)
for (int i = -50; i < 51; i += 5) {
// Long scale tick length
int tl = 15;
// Coodinates of tick to draw
float sx = cos((i - 90) * 0.0174532925);
float sy = sin((i - 90) * 0.0174532925);
uint16_t x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120;
uint16_t y0 = sy * (M_SIZE*100 + tl) + M_SIZE*150;
uint16_t x1 = sx * M_SIZE*100 + M_SIZE*120;
uint16_t y1 = sy * M_SIZE*100 + M_SIZE*150;
// Coordinates of next tick for zone fill
float sx2 = cos((i + 5 - 90) * 0.0174532925);
float sy2 = sin((i + 5 - 90) * 0.0174532925);
int x2 = sx2 * (M_SIZE*100 + tl) + M_SIZE*120;
int y2 = sy2 * (M_SIZE*100 + tl) + M_SIZE*150;
int x3 = sx2 * M_SIZE*100 + M_SIZE*120;
int y3 = sy2 * M_SIZE*100 + M_SIZE*150;
// Yellow zone limits
if (i >= -50 && i < 0) {
tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_YELLOW);
tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_YELLOW);
} // END IF
// Green zone limits
if (i >= 0 && i < 25) {
tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_GREEN);
tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_GREEN);
} // END IF
// Orange zone limits
if (i >= 25 && i < 50) {
tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_ORANGE);
tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_ORANGE);
} // END IF
// Short scale tick length
if (i % 25 != 0) tl = 8;
// Recalculate coords incase tick lenght changed
x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120;
y0 = sy * (M_SIZE*100 + tl) + M_SIZE*150;
x1 = sx * M_SIZE*100 + M_SIZE*120;
y1 = sy * M_SIZE*100 + M_SIZE*150;
// Draw tick
tft.drawLine(x0, y0, x1, y1, TFT_BLACK);
// Check if labels should be drawn, with position tweaks
if (i % 25 == 0) {
// Calculate label positions
x0 = sx * (M_SIZE*100 + tl + 10) + M_SIZE*120;
y0 = sy * (M_SIZE*100 + tl + 10) + M_SIZE*150;
switch (i / 25) {
case -2: tft.drawCentreString("0%", x0+4, y0-4, 1); break;
case -1: tft.drawCentreString("25%", x0+2, y0, 1); break;
case 0: tft.drawCentreString("50%", x0, y0, 1); break;
case 1: tft.drawCentreString("75%", x0, y0, 1); break;
case 2: tft.drawCentreString("100%", x0-2, y0-4, 1); break;
} // END SWITCH
} // END IF
// Now draw the arc of the scale
sx = cos((i + 5 - 90) * 0.0174532925);
sy = sin((i + 5 - 90) * 0.0174532925);
x0 = sx * M_SIZE*100 + M_SIZE*120;
y0 = sy * M_SIZE*100 + M_SIZE*150;
// Draw scale arc, don't draw the last part
if (i < 50) tft.drawLine(x0, y0, x1, y1, TFT_BLACK);
} // END FOR
tft.drawString(String(phtrVoltage, 1)+"V", M_SIZE*(3 + 230 - 40), M_SIZE*(119 - 20), 2); // Units at bottom right
tft.drawCentreString("LIGHT", M_SIZE*120, M_SIZE*75, 2); // Comment out to avoid font 4
tft.drawRect(1, M_SIZE*3, M_SIZE*236, M_SIZE*126, TFT_BLACK); // Draw bezel line
plotNeedle(0, 0); // Put meter needle at 0
} // END analogMeter()
// #########################################################################
// Update needle position
// This function is blocking while needle moves, time depends on ms_delay
// 10ms minimises needle flicker if text is drawn within needle sweep area
// Smaller values OK if text not in sweep area, zero for instant movement but
// does not look realistic... (note: 100 increments for full scale deflection)
// #########################################################################
void plotNeedle(int value, byte ms_delay)
{
tft.setTextColor(TFT_BLACK, TFT_WHITE);
char buf[8]; dtostrf(phtrAnalogValue, 4, 0, buf);
tft.drawRightString(buf, 35, M_SIZE*(119 - 20), 2);
// ADD VOLTS HERE I GUESS
tft.drawString(String(phtrVoltage, 1)+"V", M_SIZE*(3 + 230 - 40), M_SIZE*(119 - 20), 2); // Units at bottom right
if (value < -10) value = -10; // Limit value to emulate needle end stops
if (value > 110) value = 110;
// Move the needle until new value reached
while (!(value == old_analog)) {
if (old_analog < value) old_analog++;
else old_analog--;
if (ms_delay == 0) old_analog = value; // Update immediately if delay is 0
float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle
// Calculate tip of needle coords
float sx = cos(sdeg * 0.0174532925);
float sy = sin(sdeg * 0.0174532925);
// Calculate x delta of needle start (does not start at pivot point)
float tx = tan((sdeg + 90) * 0.0174532925);
// Erase old needle image
tft.drawLine(M_SIZE*(120 + 24 * ltx) - 1, M_SIZE*(150 - 24), osx - 1, osy, TFT_WHITE);
tft.drawLine(M_SIZE*(120 + 24 * ltx), M_SIZE*(150 - 24), osx, osy, TFT_WHITE);
tft.drawLine(M_SIZE*(120 + 24 * ltx) + 1, M_SIZE*(150 - 24), osx + 1, osy, TFT_WHITE);
// Re-plot text under needle
tft.setTextColor(TFT_BLACK, TFT_WHITE);
tft.drawCentreString("LIGHT", M_SIZE*120, M_SIZE*75, 2); // // Comment out to avoid font 4
// Store new needle end coords for next erase
ltx = tx;
osx = M_SIZE*(sx * 98 + 120);
osy = M_SIZE*(sy * 98 + 150);
// Draw the needle in the new postion, magenta makes needle a bit bolder
// draws 3 lines to thicken needle
tft.drawLine(M_SIZE*(120 + 24 * ltx) - 1, M_SIZE*(150 - 24), osx - 1, osy, TFT_RED);
tft.drawLine(M_SIZE*(120 + 24 * ltx), M_SIZE*(150 - 24), osx, osy, TFT_MAGENTA);
tft.drawLine(M_SIZE*(120 + 24 * ltx) + 1, M_SIZE*(150 - 24), osx + 1, osy, TFT_RED);
// Slow needle down slightly as it approaches new postion
if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5;
// Wait before next update
delay(ms_delay);
} // END WHILE
} // END plotNeedle()