Skip to content

Commit d1a290e

Browse files
committed
Examples tone delay handling
1 parent 9369fbe commit d1a290e

17 files changed

+332
-263
lines changed

.github/workflows/LibraryBuild.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,14 @@ jobs:
149149
- arduino-boards-fqbn: megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal
150150
arduino-platform: megaTinyCore:megaavr@2.5.11 # The current 2.6.0 is broken see https://github.com/SpenceKonde/megaTinyCore/issues/805
151151
platform-url: http://drazzy.com/package_drazzy.com_index.json
152+
sketches-exclude: AllProtocolsOnLCD
152153
build-properties: # the flags were put in compiler.cpp.extra_flags
153154
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100
154155

155156
- arduino-boards-fqbn: megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal
156157
arduino-platform: megaTinyCore:megaavr@2.5.11
157158
platform-url: http://drazzy.com/package_drazzy.com_index.json
159+
sketches-exclude: AllProtocolsOnLCD
158160
build-properties: # the flags were put in compiler.cpp.extra_flags
159161
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100
160162

@@ -236,7 +238,7 @@ jobs:
236238

237239
- arduino-boards-fqbn: Seeeduino:samd:seeed_XIAO_m0:usbstack=arduino,debug=off,sercom4=include
238240
platform-url: https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
239-
sketches-exclude: AllProtocols
241+
sketches-exclude: AllProtocolsOnLCD
240242
build-properties: # the flags were put in compiler.cpp.extra_flags
241243
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700
242244
All: -DRAW_BUFFER_LENGTH=300

README.md

+35-31
Large diffs are not rendered by default.

examples/AllProtocols/ADCUtils.h renamed to examples/AllProtocolsOnLCD/ADCUtils.h

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define _ADC_UTILS_H
2626

2727
#if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) && (!defined(__AVR_ATmega4809__))
28+
#define ADC_UTILS_ARE_AVAILABLE
2829
#include <Arduino.h>
2930

3031
// PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz

examples/AllProtocols/ADCUtils.hpp renamed to examples/AllProtocolsOnLCD/ADCUtils.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#define _ADC_UTILS_HPP
2727

2828
#include "ADCUtils.h"
29-
#if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) && (!defined(__AVR_ATmega4809__))
29+
#if defined(ADC_UTILS_ARE_AVAILABLE)
3030

3131
#if !defined(STR_HELPER)
3232
#define STR_HELPER(x) #x

examples/AllProtocols/AllProtocols.ino renamed to examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino

+44-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
2-
* AllProtocols.cpp
2+
* AllProtocolsOnLCD.cpp
33
*
4-
* Modified ReceiveDemo.cpp with additional LCD output.
4+
* Modified ReceiveDemo.cpp with additional 1602 LCD output.
55
* If debug button is pressed (pin connected to ground) a long output is generated.
66
*
77
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
@@ -73,7 +73,7 @@
7373
* because of the long lasting serial communication.
7474
*/
7575
//#define USE_NO_LCD
76-
#define USE_SERIAL_LCD
76+
//#define USE_SERIAL_LCD
7777
#if defined(USE_SERIAL_LCD)
7878
#include "LiquidCrystal_I2C.h" // Use an up to date library version, which has the init method
7979
#elif !defined(USE_NO_LCD)
@@ -82,14 +82,12 @@
8282
#endif
8383

8484
#if defined(USE_PARALLEL_LCD)
85-
#define DEBUG_BUTTON_PIN 11
86-
#endif
87-
#if !defined(DEBUG_BUTTON_PIN)
88-
# if defined(APPLICATION_PIN)
89-
#define DEBUG_BUTTON_PIN APPLICATION_PIN // if low, print timing for each received data set
90-
# else
85+
#define DEBUG_BUTTON_PIN 11 // If low, print timing for each received data set
86+
#define AUXILIARY_DEBUG_BUTTON_PIN 12 // Is set to low to enable using of a simple connector for enabling debug
87+
#undef TONE_PIN
88+
#define TONE_PIN 9 // Pin 4 is used by LCD
89+
#else
9190
#define DEBUG_BUTTON_PIN 6
92-
# endif
9391
#endif
9492

9593
#if defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
@@ -102,8 +100,8 @@
102100
#include "ADCUtils.hpp"
103101
#define MILLIS_BETWEEN_VOLTAGE_PRINT 5000
104102
#define LCD_VOLTAGE_START_INDEX 11
105-
uint32_t volatile sMillisOfLastVoltagePrint;
106-
bool ProtocolStringOverwritesVoltage;
103+
uint32_t volatile sMillisOfLastVoltagePrint = 0;
104+
bool ProtocolStringOverwritesVoltage = false;
107105
# endif
108106
#define LCD_IR_COMMAND_START_INDEX 9
109107

@@ -113,8 +111,8 @@ bool ProtocolStringOverwritesVoltage;
113111
LiquidCrystal_I2C myLCD(0x27, LCD_COLUMNS, LCD_ROWS); // set the LCD address to 0x27 for a 16 chars and 2 line display
114112
#endif
115113
#if defined(USE_PARALLEL_LCD)
116-
LiquidCrystal myLCD(4, 5, 6, 7, 8, 9);
117-
//LiquidCrystal myLCD(7, 8, 3, 4, 5, 6);
114+
//LiquidCrystal myLCD(4, 5, 6, 7, 8, 9);
115+
LiquidCrystal myLCD(7, 8, 3, 4, 5, 6);
118116
#endif
119117

120118
void printIRResultOnLCD();
@@ -124,6 +122,10 @@ void printSpaces(uint_fast8_t aNumberOfSpacesToPrint);
124122
void setup() {
125123
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
126124
pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP);
125+
# if defined(AUXILIARY_DEBUG_BUTTON_PIN)
126+
pinMode(AUXILIARY_DEBUG_BUTTON_PIN, OUTPUT);
127+
digitalWrite(AUXILIARY_DEBUG_BUTTON_PIN, LOW); // To use a simple connector to enable debug
128+
# endif
127129
#endif
128130

129131
Serial.begin(115200);
@@ -150,6 +152,7 @@ void setup() {
150152
#endif
151153

152154
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
155+
Serial.println();
153156
Serial.print(F("Debug button pin is "));
154157
Serial.println(DEBUG_BUTTON_PIN);
155158

@@ -195,16 +198,37 @@ void loop() {
195198
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
196199
Serial.println(F("Overflow detected"));
197200
Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
201+
#if defined(USE_LCD)
202+
myLCD.setCursor(0, 0);
203+
myLCD.print(F("Overflow "));
204+
#endif
205+
198206
// see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
199207

200208
} else {
209+
// play tone
210+
auto tStartMillis = millis();
211+
IrReceiver.stop();
212+
tone(TONE_PIN, 2200);
213+
201214
// Print a short summary of received data
202215
IrReceiver.printIRResultShort(&Serial);
203216

204217
if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
205-
// We have an unknown protocol, print more info
218+
// Print more info
219+
IrReceiver.printIRSendUsage(&Serial);
206220
IrReceiver.printIRResultRawFormatted(&Serial, false);
207221
}
222+
223+
// Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame
224+
// so here we are 10 millis after end of frame. Sony20 has only a 12 ms repeat gap.
225+
while ((millis() - tStartMillis) < 5)
226+
;
227+
noTone(TONE_PIN);
228+
229+
// Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement.
230+
IrReceiver.startWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
231+
208232
#if defined(USE_LCD)
209233
printIRResultOnLCD();
210234
#endif
@@ -217,7 +241,7 @@ void loop() {
217241
IrReceiver.resume();
218242
} // if (IrReceiver.decode())
219243

220-
#if defined(USE_LCD) && defined(__AVR__) && defined(ADCSRA) && defined(ADATE)
244+
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
221245
//Periodically print VCC
222246
if (!ProtocolStringOverwritesVoltage && millis() - sMillisOfLastVoltagePrint > MILLIS_BETWEEN_VOLTAGE_PRINT) {
223247
/*
@@ -227,7 +251,8 @@ void loop() {
227251
uint16_t tVCC = getVCCVoltageMillivoltSimple();
228252
char tVoltageString[5];
229253
dtostrf(tVCC / 1000.0, 4, 2, tVoltageString);
230-
myLCD.setCursor(LCD_VOLTAGE_START_INDEX, 0);
254+
myLCD.setCursor(LCD_VOLTAGE_START_INDEX - 1, 0);
255+
myLCD.print(' ');
231256
myLCD.print(tVoltageString);
232257
myLCD.print('V');
233258
}
@@ -345,6 +370,7 @@ void printIRResultOnLCD() {
345370
#endif // defined(USE_LCD)
346371
}
347372

373+
#if defined(USE_LCD)
348374
size_t printHex(uint16_t aHexByteValue) {
349375
myLCD.print(F("0x"));
350376
size_t tPrintSize = 2;
@@ -360,3 +386,4 @@ void printSpaces(uint_fast8_t aNumberOfSpacesToPrint) {
360386
myLCD.print(' ');
361387
}
362388
}
389+
#endif

examples/ReceiveDemo/ReceiveDemo.ino

+30-16
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ void setup() {
116116
#endif
117117

118118
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
119+
Serial.println();
119120
Serial.print(F("Debug button pin is "));
120121
# if defined(APPLICATION_PIN_STRING)
121122
Serial.println(APPLICATION_PIN_STRING);
@@ -165,32 +166,45 @@ void loop() {
165166
# endif
166167

167168
} else {
168-
// Print a short summary of received data
169-
#if defined(LOCAL_DEBUG)
169+
auto tStartMillis = millis();
170+
# if !defined(ESP32)
171+
IrReceiver.stop(); // ESP32 uses another timer for tone()
172+
# endif
173+
tone(TONE_PIN, 2200);
174+
175+
// No overflow, print a short summary of received data
176+
# if defined(LOCAL_DEBUG)
170177
IrReceiver.printIRResultShort(&Serial, true);
171-
#else
178+
# else
172179
IrReceiver.printIRResultShort(&Serial, true, digitalRead(DEBUG_BUTTON_PIN) == LOW);
173-
#endif
180+
# endif
181+
// Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame
182+
// so here we are 10 millis after end of frame. Sony20 has only a 12 ms repeat gap.
183+
while ((millis() - tStartMillis) < 5)
184+
;
185+
noTone(TONE_PIN);
186+
187+
# if !defined(ESP32)
188+
// Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement.
189+
IrReceiver.startWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
190+
# endif
191+
174192
IrReceiver.printIRSendUsage(&Serial);
175-
#if defined(LOCAL_DEBUG)
193+
# if defined(LOCAL_DEBUG)
176194
IrReceiver.printIRResultRawFormatted(&Serial, true);
177-
#else
195+
# else
178196
if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
179197
// We have an unknown protocol, print more info
180198
IrReceiver.printIRResultRawFormatted(&Serial, true);
181199
}
182-
#endif
200+
# endif
183201
}
184202

185203
// tone on esp8266 works once, then it disables the successful IrReceiver.start() / timerConfigForReceive().
186-
# if !defined(ESP8266) && !defined(NRF5)
204+
# if !defined(ESP8266) && !defined(NRF5) && !defined(LOCAL_DEBUG)
187205
if ((IrReceiver.decodedIRData.protocol != SONY) && (IrReceiver.decodedIRData.protocol != PULSE_WIDTH)
188206
&& (IrReceiver.decodedIRData.protocol != PULSE_DISTANCE) && (IrReceiver.decodedIRData.protocol != UNKNOWN)
189-
&& digitalRead(DEBUG_BUTTON_PIN) != LOW
190-
#if defined(LOCAL_DEBUG)
191-
&& false // disable 8 ms tone for local debug
192-
#endif
193-
) {
207+
&& digitalRead(DEBUG_BUTTON_PIN) != LOW) {
194208
/*
195209
* If no debug mode or a valid protocol was received, play tone, wait and restore IR timer.
196210
* For SONY the tone prevents the detection of a repeat
@@ -203,14 +217,14 @@ void loop() {
203217
tone(TONE_PIN, 2200, 8);
204218
# if !defined(ESP32)
205219
delay(8);
206-
IrReceiver.start(8000); // to compensate for 8 ms stop of receiver. This enables a correct gap measurement.
220+
IrReceiver.start(8000); // Restore IR timer. 8000 to compensate for 8 ms stop of receiver. This enables a correct gap measurement.
207221
# endif
208222
}
209223
# endif
210-
#else
224+
#else // #if FLASHEND >= 0x3FFF
211225
// Print a minimal summary of received data
212226
IrReceiver.printIRResultMinimal(&Serial);
213-
#endif // FLASHEND
227+
#endif // #if FLASHEND >= 0x3FFF
214228

215229
/*
216230
* !!!Important!!! Enable receiving of the next value,

examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino

+42-33
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@
6868
/*
6969
* For callback
7070
*/
71-
volatile bool sDataJustReceived = false;
71+
#define PROCESS_IR_RESULT_IN_MAIN_LOOP
72+
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
73+
volatile bool sIRDataJustReceived = false;
74+
#endif
7275
void ReceiveCompleteCallbackHandler();
7376

7477
void setup() {
@@ -81,26 +84,46 @@ void setup() {
8184
IrReceiver.registerReceiveCompleteCallback(ReceiveCompleteCallbackHandler);
8285

8386
Serial.print(F("Ready to receive IR signals of protocols: "));
84-
printActiveIRProtocols(&Serial);
87+
printActiveIRProtocols (&Serial);
8588
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
8689
}
90+
91+
void loop() {
92+
/*
93+
* Print in loop (interrupts are enabled here) if received data is available.
94+
*/
95+
if (sIRDataJustReceived) {
96+
// Print a short summary of received data
97+
IrReceiver.printIRResultShort(&Serial);
98+
IrReceiver.printIRSendUsage(&Serial);
99+
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
100+
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
101+
/*
102+
* We have an unknown protocol here, print more info.
103+
* !!!Attention!!! This prints incorrect values, if we are late (not in this simple example :-))
104+
* and the the first mark of the next (repeat) data was yet received
105+
*/
106+
IrReceiver.printIRResultRawFormatted(&Serial, true); //
107+
}
108+
Serial.println();
109+
}
110+
}
111+
87112
/*
88113
* Callback function
89-
* This function is called in ISR (Interrupt Service Routine) context (interrupts are blocked here)
90-
* and therefore must be as short as possible (and better not use printing).
114+
* Here we know, that data is available.
115+
* This function is executed in ISR (Interrupt Service Routine) context (interrupts are blocked here).
116+
* Make it short and fast and keep in mind, that you can not use delay(), prints longer than print buffer size etc.,
117+
* because they require interrupts enabled to return.
118+
* In order to enable other interrupts you can call sei() (enable interrupt again) after evaluating/copying data.
119+
* Good practice, but somewhat more complex, is to copy relevant data and signal receiving to main loop.
91120
*/
92121
#if defined(ESP32) || defined(ESP8266)
93122
IRAM_ATTR
94123
# endif
95124
void ReceiveCompleteCallbackHandler() {
96125
IrReceiver.decode(); // fill IrReceiver.decodedIRData
97126

98-
/*
99-
* Set flag to trigger printing of results in main loop,
100-
* since printing should not be done in a callback function
101-
* running in ISR (Interrupt Service Routine) context where interrupts are disabled.
102-
*/
103-
sDataJustReceived = true;
104127
/*
105128
* Check the received data and perform actions according to the received command
106129
* Decoded result is in the IrReceiver.decodedIRData structure.
@@ -110,11 +133,18 @@ void ReceiveCompleteCallbackHandler() {
110133
* and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
111134
*/
112135
if (IrReceiver.decodedIRData.command == 0x10) {
113-
// do something
136+
// do something SHORT here
114137
} else if (IrReceiver.decodedIRData.command == 0x11) {
115-
// do something else
138+
// do something SHORT here too
116139
}
117140

141+
/*
142+
* Set flag to trigger printing of results in main loop,
143+
* since printing should not be done in a callback function
144+
* running in ISR (Interrupt Service Routine) context where interrupts are disabled.
145+
*/
146+
sIRDataJustReceived = true;
147+
118148
/*
119149
* Enable receiving of the next value.
120150
* !!!Attention!!!
@@ -125,24 +155,3 @@ void ReceiveCompleteCallbackHandler() {
125155
*/
126156
IrReceiver.resume();
127157
}
128-
129-
void loop() {
130-
/*
131-
* Print in loop (interrupts are enabled here) if received data is available.
132-
*/
133-
if (sDataJustReceived) {
134-
// Print a short summary of received data
135-
IrReceiver.printIRResultShort(&Serial);
136-
IrReceiver.printIRSendUsage(&Serial);
137-
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
138-
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
139-
/*
140-
* We have an unknown protocol here, print more info.
141-
* !!!Attention!!! This prints incorrect values, if we are late (not in this simple example :-))
142-
* and the the first mark of the next (repeat) data was yet received
143-
*/
144-
IrReceiver.printIRResultRawFormatted(&Serial, true); //
145-
}
146-
Serial.println();
147-
}
148-
}

0 commit comments

Comments
 (0)