Improving mark function
This commit is contained in:
parent
02ee78376f
commit
0cfbbcf4c4
|
@ -162,13 +162,11 @@ We are open to suggestions for adding support to new boards, however we highly r
|
|||
# Timer and pin usage
|
||||
The receiver sample interval is generated by a timer. On many boards this must be a hardware timer, on some a software timer is available and used.<br/>
|
||||
Every pin can be used for receiving.<br/>
|
||||
The send PWM signal is by default generated by software. **Therefore every pin can be used for sending**.
|
||||
The send PWM signal is by default generated by software. **Therefore every pin can be used for sending**. The PWM pulse length is guaranteed to be constant by using `delayMicroseconds()`. Take care not to generate interrupts during sending with software generated PWM, otherwise you will get jitter in the generated PWM. E.g. wait for a former `Serial.print()` statement to be finished by `Serial.flush()`. Since the Arduino `micros()` function has a resolution of 4 us at 16 MHz, we always see a small jitter in the signal, which seems to be OK for the receivers.
|
||||
|
||||
| Software generated PWM showing discontinuities in the Arduino core micros() function | Zoom into the discontinuity. The space is once too short but compensated at the next one |
|
||||
| Software generated PWM showing small jitter because of the limited resolution of 4 us of the Arduino core `micros()` function for an ATmega328 | Detail (ATmega328 generated) showing 33% Duty cycle |
|
||||
|-|-|
|
||||
| ![Software PWM](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software.png) | ![Software PWM detail](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software_zoom.png) |
|
||||
| Software generated PWM (ATmega328) with 33% Duty cycle | |
|
||||
| ![Software PWM detail](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software_detail.png) | |
|
||||
| ![Software PWM](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software_jitter.png) | ![Software PWM detail](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software_detail.png) |
|
||||
|
||||
## Hardware-PWM signal generation for sending
|
||||
If you define `SEND_PWM_BY_TIMER`, the send PWM signal is generated by a hardware timer. The same timer as for the receiver is used.
|
||||
|
|
|
@ -17,6 +17,7 @@ The latest version may not be released!
|
|||
- Added ATtiny88 support.
|
||||
- Use LED_BUILTIN instead of FEEDBACK_LED FeedbackLEDPin is 0.
|
||||
- Use F_CPU instead of SYSCLOCK.
|
||||
- Removed SENDPIN_ON and SENDPIN_OFF macros.
|
||||
|
||||
## 3.0.2
|
||||
- Bug fix for USE_OLD_DECODE.
|
||||
|
|
|
@ -58,7 +58,7 @@ void setup() {
|
|||
Serial.print(F("Ready to send IR signals at pin "));
|
||||
Serial.println(IR_SEND_PIN);
|
||||
|
||||
#if defined(USE_SOFT_SEND_PWM) && !defined(ESP32) // for esp32 we use PWM generation by hw_timer_t for each pin
|
||||
#if defined(USE_SOFT_SEND_PWM) && !defined(ESP32) // for esp32 we use PWM generation by hw_timer_t for each pin
|
||||
/*
|
||||
* Print internal signal generation info
|
||||
*/
|
||||
|
@ -100,10 +100,12 @@ void loop() {
|
|||
Serial.flush();
|
||||
|
||||
Serial.println(F("Send NEC with 8 bit address"));
|
||||
Serial.flush();
|
||||
IrSender.sendNEC(sAddress & 0xFF, sCommand, sRepeats);
|
||||
delay(DELAY_AFTER_SEND); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
|
||||
|
||||
Serial.println(F("Send NEC with 16 bit address"));
|
||||
Serial.flush();
|
||||
IrSender.sendNEC(sAddress, sCommand, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
|
@ -113,6 +115,7 @@ void loop() {
|
|||
* Send constant values only once in this demo
|
||||
*/
|
||||
Serial.println(F("Sending NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats"));
|
||||
Serial.flush();
|
||||
IrSender.sendPronto(F("0000 006D 0022 0000 015E 00AB " /* Pronto header + start bit */
|
||||
"0017 0015 0017 0015 0017 0017 0015 0017 0017 0015 0017 0015 0017 0015 0017 003F " /* Lower address byte */
|
||||
"0017 003F 0017 003E 0017 003F 0015 003F 0017 003E 0017 003F 0017 003E 0017 0015 " /* Upper address byte (inverted at 8 bit mode) */
|
||||
|
@ -127,6 +130,7 @@ void loop() {
|
|||
Serial.println(
|
||||
F(
|
||||
"Send NEC with 16 bit address 0x0102 and command 0x34 with NECRaw(0xCC340102) which results in a parity error, since 34 == ~CB and not C0"));
|
||||
Serial.flush();
|
||||
IrSender.sendNECRaw(0xC0340102, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
|
@ -136,52 +140,64 @@ void loop() {
|
|||
* Example:
|
||||
* 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3
|
||||
*/
|
||||
Serial.flush();
|
||||
Serial.println(F("Send NEC with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first"));
|
||||
IrSender.sendNECMSB(0x40802CD3, 32, false);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
}
|
||||
|
||||
Serial.println(F("Send Apple"));
|
||||
Serial.flush();
|
||||
IrSender.sendApple(sAddress & 0xFF, sCommand, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send Panasonic"));
|
||||
Serial.flush();
|
||||
IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send Kaseikyo with 0x4711 as Vendor ID"));
|
||||
Serial.flush();
|
||||
IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, sRepeats, 0x4711);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send Denon"));
|
||||
Serial.flush();
|
||||
IrSender.sendDenon(sAddress & 0x1F, sCommand, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send Denon/Sharp variant"));
|
||||
Serial.flush();
|
||||
IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits"));
|
||||
Serial.flush();
|
||||
IrSender.sendSony(sAddress & 0x1F, sCommand & 0x7F, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send Sony/SIRCS with 7 command and 8 address bits"));
|
||||
Serial.flush();
|
||||
IrSender.sendSony(sAddress & 0xFF, sCommand, sRepeats, SIRCS_15_PROTOCOL);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits"));
|
||||
Serial.flush();
|
||||
IrSender.sendSony(sAddress & 0x1FFF, sCommand & 0x7F, sRepeats, SIRCS_20_PROTOCOL);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send RC5"));
|
||||
Serial.flush();
|
||||
IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, sRepeats, true); // 5 address, 6 command bits
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send RC5X with 7.th MSB of command set"));
|
||||
Serial.flush();
|
||||
IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, true); // 5 address, 7 command bits
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
Serial.println(F("Send RC6"));
|
||||
Serial.flush();
|
||||
IrSender.sendRC6(sAddress, sCommand, sRepeats, true);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
|
@ -204,17 +220,20 @@ void loop() {
|
|||
IRSendData.protocol = JVC; // switch protocol
|
||||
Serial.print(F("Send "));
|
||||
Serial.println(getProtocolString(IRSendData.protocol));
|
||||
Serial.flush();
|
||||
IrSender.write(&IRSendData, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
IRSendData.protocol = LG;
|
||||
Serial.print(F("Send "));
|
||||
Serial.println(getProtocolString(IRSendData.protocol));
|
||||
Serial.flush();
|
||||
IrSender.write(&IRSendData, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
IRSendData.protocol = BOSEWAVE;
|
||||
Serial.println(F("Send Bosewave with no address and 8 command bits"));
|
||||
Serial.flush();
|
||||
IrSender.write(&IRSendData, sRepeats);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
|
@ -222,6 +241,7 @@ void loop() {
|
|||
* LEGO is difficult to receive because of its short marks and spaces
|
||||
*/
|
||||
Serial.println(F("Send Lego with 2 channel and with 4 command bits"));
|
||||
Serial.flush();
|
||||
IrSender.sendLegoPowerFunctions(sAddress, sCommand, LEGO_MODE_COMBO, true);
|
||||
delay(DELAY_AFTER_SEND);
|
||||
|
||||
|
@ -248,6 +268,5 @@ void loop() {
|
|||
sRepeats = 4;
|
||||
}
|
||||
|
||||
|
||||
delay(DELAY_AFTER_LOOP); // additional delay at the end of each loop
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ void ACSendCode(uint16_t aCommand) {
|
|||
Serial.print(aCommand, HEX);
|
||||
Serial.print(F(" | "));
|
||||
Serial.println(aCommand, BIN);
|
||||
Serial.flush();
|
||||
IrSender.sendLG((uint8_t) 0x88, aCommand, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ void loop() {
|
|||
* The values are NOT multiple of 50, but are taken from the NEC timing definitions
|
||||
*/
|
||||
Serial.println(F("Send NEC 8 bit address 0xFB04, 0x08 with exact timing (16 bit array format)"));
|
||||
Serial.flush();
|
||||
|
||||
const uint16_t irSignal[] = { 9000, 4500, 560, 560, 560, 560, 560, 1690, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560,
|
||||
1690, 560, 1690, 560, 560, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 560, 560, 560, 560, 560, 560,
|
||||
|
@ -106,11 +107,13 @@ void loop() {
|
|||
* Note the approach used to automatically calculate the size of the array.
|
||||
*/
|
||||
Serial.println(F("Send NEC 16 bit address 0xFB0C, 0x18 with (50 us) tick resolution timing (8 bit array format) "));
|
||||
Serial.flush();
|
||||
IrSender.sendRaw_P(irSignalP, sizeof(irSignalP) / sizeof(irSignalP[0]), NEC_KHZ);
|
||||
|
||||
delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
|
||||
|
||||
Serial.println(F("Send NEC 16 bit address 0x0102, 8 bit data 0x34 with generated timing"));
|
||||
Serial.flush();
|
||||
IrSender.sendNEC(0x0102, 0x34, true, 0);
|
||||
|
||||
delay(3000);
|
||||
|
|
|
@ -64,6 +64,7 @@ void loop() {
|
|||
Serial.println();
|
||||
|
||||
Serial.println(F("Send NEC with 16 bit address"));
|
||||
Serial.flush();
|
||||
|
||||
// Results for the first loop to: Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 (32 bits)
|
||||
IrSender.sendNEC(sAddress, sCommand, sRepeats);
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 24 KiB |
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
|
@ -31,6 +31,7 @@
|
|||
*/
|
||||
|
||||
#include "IRremoteInt.h"
|
||||
//#include "digitalWriteFast.h"
|
||||
|
||||
__attribute((error("Version > 3.0.1"))) void UsageError(const char *details);
|
||||
|
||||
|
@ -360,36 +361,27 @@ void IRsend::mark(unsigned int aMarkMicros) {
|
|||
#if defined(USE_SOFT_SEND_PWM) && !defined(ESP32) // for esp32 we use PWM generation by hw_timer_t for each pin
|
||||
unsigned long start = micros();
|
||||
unsigned long nextPeriodEnding = start;
|
||||
while (micros() - start < aMarkMicros) {
|
||||
unsigned long tMicros;
|
||||
do {
|
||||
// digitalToggleFast(IR_TIMING_TEST_PIN);
|
||||
// Output the PWM pulse
|
||||
noInterrupts(); // do not let interrupts extend the short on period
|
||||
# ifdef SENDPIN_ON
|
||||
SENDPIN_ON(sendPin);
|
||||
# else
|
||||
digitalWrite(sendPin, HIGH);
|
||||
# endif
|
||||
digitalWrite(sendPin, HIGH); // 4.3 us from do{ to pin setting
|
||||
delayMicroseconds(periodOnTimeMicros); // this is normally implemented by a blocking wait
|
||||
|
||||
// Output the PWM pause
|
||||
# ifdef SENDPIN_OFF
|
||||
SENDPIN_OFF(sendPin);
|
||||
# else
|
||||
digitalWrite(sendPin, LOW);
|
||||
# endif
|
||||
interrupts(); // Enable interrupts -to keep micros correct- for the longer off period 3.4 us until receive ISR is active (for 7 us + pop's)
|
||||
nextPeriodEnding += periodTimeMicros;
|
||||
while (micros() < nextPeriodEnding){
|
||||
;
|
||||
}
|
||||
}
|
||||
do {
|
||||
tMicros = micros(); // we have only 4 us resolution for and AVR @16MHz
|
||||
// digitalToggleFast(IR_TIMING_TEST_PIN); // 3.0 us per call @16MHz
|
||||
} while (tMicros < nextPeriodEnding); // 3.4 us @16MHz
|
||||
} while (tMicros - start < aMarkMicros);
|
||||
|
||||
#else
|
||||
# if defined(USE_NO_SEND_PWM)
|
||||
# ifdef SENDPIN_OFF
|
||||
SENDPIN_OFF(sendPin);
|
||||
# else
|
||||
digitalWrite(sendPin, LOW); // Set output to active low.
|
||||
# endif
|
||||
|
||||
# else
|
||||
TIMER_ENABLE_SEND_PWM; // Enable pin 3 PWM output
|
||||
|
@ -408,11 +400,7 @@ void IRsend::mark(unsigned int aMarkMicros) {
|
|||
*/
|
||||
void IRsend::ledOff() {
|
||||
#if defined(USE_SOFT_SEND_PWM) && !defined(ESP32) // for esp32 we use PWM generation by hw_timer_t for each pin
|
||||
# ifdef SENDPIN_OFF
|
||||
SENDPIN_OFF(sendPin);
|
||||
# else
|
||||
digitalWrite(sendPin, LOW);
|
||||
# endif
|
||||
#elif defined(USE_NO_SEND_PWM)
|
||||
digitalWrite(sendPin, HIGH); // Set output to inactive high.
|
||||
#else
|
||||
|
|
|
@ -164,7 +164,7 @@
|
|||
|
||||
/**
|
||||
* If USE_SOFT_SEND_PWM, this amount is subtracted from the on-time of the pulses.
|
||||
* It should be the time used for SENDPIN_OFF(sendPin) and the call to delayMicros()
|
||||
* It should be the time used for digitalWrite(sendPin, LOW) and the call to delayMicros()
|
||||
* Measured value for Nano @16MHz is around 3000, for Bluepill @72MHz is around 700, for Zero 3600
|
||||
*/
|
||||
#ifndef PULSE_CORRECTION_NANOS
|
||||
|
|
|
@ -474,7 +474,7 @@ public:
|
|||
uint8_t sendPin;
|
||||
|
||||
unsigned int periodTimeMicros;
|
||||
unsigned int periodOnTimeMicros;
|
||||
unsigned int periodOnTimeMicros; // compensated with PULSE_CORRECTION_NANOS for duration of digitalWrite.
|
||||
|
||||
void customDelayMicroseconds(unsigned long aMicroseconds);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue