-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIrPowerOn.ino
377 lines (318 loc) · 8.3 KB
/
IrPowerOn.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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
//Written by Carl Frank Otto III
//Version 0.0.2-03202021-0208p
#include <EEPROM.h>
//SEEED IR library
#include <IRLibRecvPCI.h>
#include <IRLibSendBase.h>
#include <IRLib_HashRaw.h>
//IR Code storage (RAM)
#define MAX_STORE_SIZE 255
uint16_t storedCodes[MAX_STORE_SIZE];
uint8_t storedCodesLength = 0;
//IR pins/settings
#define IR_RX_PIN 2
#define IR_TX_PIN 3 //Doesn't set in lib
#define IR_FREQ 36
//Need some play in the timings because of jitter
//freq / 1.3 == microseconds per cycle
//Last number is the allowance percent, 1.5 == 50%, so about 34 microseconds
#define ALLOWED_JITTER ((IR_FREQ / 1.3) * 1.5)
//Number of accepted codes needed to save
#define goodCodesNeeded 5
IRrecvPCI myReceiver(IR_RX_PIN);
IRsendRaw mySender;
// --- CONSTANTS / DEFINES ---
//GPIO
#define ledPin LED_BUILTIN
#define programButtonPin 4
//Modes
#define MODE_NORMAL 0
#define MODE_SEND_CODE 1
#define MODE_CODE_SENT 2
#define MODE_PROGRAM 10
#define MODE_PROGRAM_COMPLETE 11
//Blink Rates
#define intervalProgram 100
#define intervalNormal 990
#define interbalpButton 500
//Send intervals
#define sendDelay 15000
#define sendRepeats 0
#define sendRepeatDelay 50
// --- GLOBAL VARS ---
//Mode
int currentMode = MODE_NORMAL;
//Code verification
int sameCodeCount = 0;
//LED blink millis
unsigned long previousMillisLED = 0;
bool ledOn = false;
//Send repeat millis
unsigned long previousMillisSend = 0;
//Send repeat millis
unsigned long prevpButtonMillis = 0;
//Count number of times code sent
int codeSentCount = 0;
//Previous button state
int prevpButtonState = LOW;
void writeUnsignedIntIntoEEPROM(int address, uint16_t number)
{
EEPROM.write(address, number >> 8);
EEPROM.write(address + 1, number & 0xFF);
}
uint16_t readUnsignedIntFromEEPROM(int address)
{
return (EEPROM.read(address) << 8) + EEPROM.read(address + 1);
}
void setup()
{
//Save current button state so we can detect a change
pinMode(ledPin, OUTPUT);
pinMode(programButtonPin, INPUT_PULLUP);
digitalWrite(ledPin, LOW);
ledOn = false;
//Solves double-reset oddness, and lets input pullup stabilize.
delay(500);
prevpButtonState = digitalRead(programButtonPin);
//Setup serial, and IR send
Serial.begin(115200);
Serial.println("");
Serial.println("Starting...");
int i;
for (i = 0; i < MAX_STORE_SIZE; i++)
{
storedCodes[i] = 0;
}
//Setup IR send pin
Serial.print(F("Ready to send IR signals at pin "));
Serial.println(IR_RX_PIN);
//READ EEPROM
storedCodesLength = EEPROM.read(0);
if (storedCodesLength > 0)
{
Serial.print("EEPROM read len: ");
Serial.println(storedCodesLength);
for (i = 0; i <= storedCodesLength; i++)
{
storedCodes[i] = readUnsignedIntFromEEPROM((i+1) * 2);
Serial.print(storedCodes[i]);
Serial.print(", ");
if (i % 20 == 0)
{
Serial.println("");
}
}
Serial.println("END");
goNormalMode();
return;
}
goProgramMode();
}
void clearTemp()
{
sameCodeCount = 0;
codeSentCount = 0;
previousMillisLED = 0;
previousMillisSend = 0;
prevpButtonMillis = 0;
ledOn = false;
digitalWrite(ledPin, LOW);
}
void goProgramMode()
{
currentMode = MODE_PROGRAM;
clearTemp();
Serial.println("Entering program mode.");
myReceiver.enableIRIn(); // Start the receiver
Serial.print("Ready to receive IR signals on pin ");
Serial.println(IR_RX_PIN);
}
void goNormalMode()
{
currentMode = MODE_NORMAL;
clearTemp();
//Clear status LED.
digitalWrite(ledPin, LOW);
ledOn = false;
Serial.println("Entering normal mode.");
//Get data from EEPROM HERE
Serial.print("Sending IR code in ");
Serial.print(sendDelay / 1000);
Serial.println(" seconds!");
}
void goCompleteMode()
{
currentMode = MODE_PROGRAM_COMPLETE;
clearTemp();
//Clear status LED.
digitalWrite(ledPin, LOW);
ledOn = false;
Serial.println("Entering program-complete mode.");
}
void goSendMode()
{
currentMode = MODE_SEND_CODE;
clearTemp();
}
void goSendComplete()
{
currentMode = MODE_CODE_SENT;
clearTemp();
Serial.println("IR code send complete, sleeping...");
//Clear status LED.
digitalWrite(ledPin, LOW);
ledOn = false;
}
void loop()
{
int curpButtonState = digitalRead(programButtonPin);
//Check for program button state changes
if (currentMode != MODE_PROGRAM && curpButtonState != prevpButtonState)
{
//Update state
prevpButtonState = curpButtonState;
unsigned long currentMillis = millis();
//Check last time we triggered program mode
if (currentMillis - prevpButtonMillis >= interbalpButton)
{
prevpButtonMillis = currentMillis;
goProgramMode();
}
}
if (currentMode == MODE_PROGRAM)
{
//Check if it is time to blink status LED, to indicate program mode.
unsigned long currentMillis = millis();
if (currentMillis - previousMillisLED >= intervalProgram)
{
previousMillisLED = currentMillis;
//Blink LED
if (ledOn)
{
ledOn = false;
digitalWrite(ledPin, LOW);
}
else
{
ledOn = true;
digitalWrite(ledPin, HIGH);
}
}
if (myReceiver.getResults())
{
//Check if code is really short, and probably a repeat code... or if it is too long to store.
if (recvGlobal.recvLength > 4 && recvGlobal.recvLength < MAX_STORE_SIZE)
{
storedCodesLength = recvGlobal.recvLength;
Serial.println("");
Serial.print("Length: ");
Serial.print(recvGlobal.recvLength);
if (sameCodeCount == 0)
{
Serial.println(" , Data:");
}
else
{
Serial.println(" , Diff:");
}
bool codeBad = false;
int i;
for (i = 1; i < storedCodesLength; i++)
{
if (sameCodeCount == 0)
{
storedCodes[i] = recvGlobal.recvBuffer[i];
Serial.print(storedCodes[i]);
Serial.print(", ");
}
else
{
//If the codes are reasonably close ( jitter ), consider them the same
uint64_t diff = abs((int64_t)storedCodes[i] - (int64_t)recvGlobal.recvBuffer[i]);
if (diff < ALLOWED_JITTER)
{
Serial.print((uint32_t)diff);
Serial.print(", ");
}
else
{
Serial.print("BAD, ");
codeBad = true;
}
}
if (i % 20 == 0)
{
Serial.println("");
}
}
Serial.println("END.");
if (!codeBad)
{
sameCodeCount++;
if (sameCodeCount > goodCodesNeeded)
{
Serial.println("Codes appear good, saving to EEPROM!");
int i;
EEPROM.write(0, storedCodesLength);
for (i = 0; i <= storedCodesLength; i++)
{
writeUnsignedIntIntoEEPROM((i+1) * 2, storedCodes[i]);
}
goNormalMode();
}
}
else
{
Serial.println("Code didn't match!!! Starting over!");
sameCodeCount = 0;
}
}
else
{
Serial.println("Code is invalid, or a repeat code... skipping.");
}
//This should get skipped once code is verified as good.
myReceiver.enableIRIn();
}
}
else if (currentMode == MODE_NORMAL)
{
//Check if it is time to blink status LED, to indicate count down
unsigned long currentMillis = millis();
if (currentMillis - previousMillisLED >= intervalNormal)
{
previousMillisLED = currentMillis;
digitalWrite(ledPin, HIGH);
delay(10);
ledOn = false;
digitalWrite(ledPin, LOW);
}
//Check if it is time to send IR code.
currentMillis = millis();
if (currentMillis - previousMillisSend >= sendDelay)
{
previousMillisSend = currentMillis;
goSendMode();
}
}
else if (currentMode == MODE_SEND_CODE)
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillisSend >= sendRepeatDelay)
{
previousMillisSend = currentMillis;
//SEND IR CODE
mySender.send(storedCodes, storedCodesLength, IR_FREQ);
Serial.println("Sending IR Code...");
codeSentCount++;
}
if (codeSentCount >= sendRepeats)
{
goSendComplete();
}
}
else if (currentMode == MODE_CODE_SENT)
{
//Nothing to do but look for program button, sleep
}
}