bengtmartensson / infrared4arduino Goto Github PK
View Code? Open in Web Editor NEWAn object oriented infrared library for the Arduino
Home Page: http://www.harctoolbox.org/Infrared4Arduino.html
License: GNU General Public License v2.0
An object oriented infrared library for the Arduino
Home Page: http://www.harctoolbox.org/Infrared4Arduino.html
License: GNU General Public License v2.0
Rationale is found in this IRremote issue and links therein.
This should be a class, called for example IrReceiverInterrupt
, inheriting from IrReceiver
.
Have not got this to work yet, possibly something silly. Anyone who can help?
The restriction is due to the default selection of frequency_t. Pretty unnecessary, really.
This is bengtmartensson/AGirs#5 moved to this project.
This has a very low usability/effort ratio. Probably cannot be done with 16MHz hardware. Neither can our favorite sensors like TSMP58000 be used, since they end at 60kHz.
Somehow (I have no theoretical explanation) IrWidgetAggragating seems to produce too short marks (bengtmartensson/IrScrutinizer#97) Adding a MARK_EXCESS should be a work-around. See also See bengtmartensson/AGirs#17.
For the implementation, move the class variable markExcess and its accessor functions from IrReceiver to the parent class IrReader, and rewrite getDuration(unsigned int) in class IrWidget.
Unfortunately, #1 is delayed. Instead, some widely used protocol (roughly the ones implemented in IRremote) should be manually implemented. Rendering only.
Currently, extra protocols go into the branch 'protocols
.
Hey, first I wanted to say thanks for this library. It definitely looks like it has taken a lot of work, and I'm super appreciative of people who put in the work and share it with the community.
So, on to the help bit. I'm trying to take an NEC IR signal:
Address: 9D62
Command: 28
Inverted Command: D7
And send it along as an output to a device, but nothing I seem to do actually seems to work. Code I used was a modified version of your example Nec1 Renderer
#include <Nec1Renderer.h>
#include <IrSenderPwm.h>
const IrSignal *irSignal;
void setup() {
Serial.begin(115200);
irSignal = Nec1Renderer::newIrSignal(0x9D62, 0x28, 0xD7);
}
void loop() {
irSignal->dump(Serial, true);
IrSenderPwm::getInstance(true)->sendIrSignal(*irSignal, 38);
delay(10000);
}
Now, I'll go ahead and state, I'm not at all familiar with IR or the NEC protocol. I'm sort of stumbling around trying to make this work, so if there is anything I can do to get some more information and/or help, feel free to let me know and I'll do whatever.
With all that stated, any help you may be able to offer would be greatly appreciated.
The different boards should not define their own IrReceiverSampler::enable
etc. Instead IrReceiverSampler::enable
could call something like Board::enableSampler
with Board
a class encapsulating the board dependencies.
Get rid of as much of the macro madness as possible!
Currently, when using uint16_t as microseconds_t, ending spaces are limited to that data type. This is not enough for many use cases.
Requirement on a solution is that it does not depend on microseconds_t being uint16_t,
Branch ExtraEndingGap. millisec-edning
Probably the IrSignal::intro/repeat/ending etc should be referenced, or pointed-to instead of copied. Dispose stategy unclear, cf. IrSignal::~IrSignal.
Cf. #14 & #15. The latter makes Pronto::mkSequence slightly unpleasant: generates a dynamic object that neither will be completely disposed by its destructor, nor does it consist of "borrowed" data (that is what toBeFreed = false is intended for).
These functions (which all "real professionals" hate :-)) do some constant computations at each invocation. These intermediate results can be kept as local variables in calling classes. Portability must not be sacrificed.
Possible usable libraries:
Branch: speedup
.
Example sketch. envision a switch connected, and a (general) IrSignal, preferrably in PROGMEM. When the switch is depressed, send first intro (if present), then, as long as the switch is depressed, keep sending the repeat. When button released send ending sequence (if present).
IrSignal (const microseconds_t *intro, size_t lengthIntro, const microseconds_t *repeat, size_t lengthRepeat, frequency_t frequency=defaultFrequency, boolean toBeFreed=false)
declared but not implemented. Workaround: use
IrSignal (const microseconds_t *intro, size_t lengthIntro, const microseconds_t *repeat, size_t lengthRepeat, const microseconds_t *ending, size_t lengthEnding, frequency_t frequency=defaultFrequency, boolean toBeFreed=false)
The idea is to define the enums PinStatus and PinMode unless they are defined already. The present solution brings in hardware dependencies where it does not belong, and it sometimes breaks with unknown boards (#53).
Problem might lie with ~/.arduino15/packages/arduino/hardware/megaavr/1.8.6/cores/arduino/api/Common.h which defines these enums.
Task is to find a clean solution.
Old, but still hot...
Cf. Arduino IDE 1.5: Library specification.
These are Arduino.h, IrTimerDefs.h, boarddefs.h
.
Using an IrReader and the new plotter from the arduino serial console.
See https://github.com/arduino/Arduino/blob/master/build/shared/ArduinoSerialPlotterProtocol.md
... like the other Girses. Nonconfigurable.
Since the project is to remain an Arduino project, this is "support" and not "migrate to". Basically create an platformio.ini
.
I create a small sketch which sends the same frame repeatedly using 3 different libs: IRremote, IRLib2 and Infrared4Arduino. On another board (both boards are Arduino Nano), IRrecvDumpV2 is dumping the frames received to the serial console. With device ID 0x00
and command 0xe0
(0b1110'0000
), I correctly receive the frame 0x00ffe01f
with both IRremove and IRLib2.
With Infrared4Arduino, the receiver reports 0x00ff07f8
(cmd 0b0000'0111
, bits backwards). I tried other commands, e.g. 0b1110'0001
, receiving 0b100000111
. The reversal is also the case for device ID when its bits are not symmetric (like 0x01
is received as 0x80
).
What is going on here? Is my sender's crystal perhaps running at negative frequency, reversing time sense?
The sending-side sketch is here as gist: https://gist.github.com/eudoxos/f2c1439adb56ac0b01f7dc523a6d8978
PS a working function to make "correct" signal for me is like this:
#define REVBITS __builtin_avr_insert_bits(0x01234567,b,0)
IrSignal* makeSig(uint8_t devId, uint8_t cmd){
union{ uint16_t data; byte b[2]; };
frame.b[0]=REVBITS(cmd);
frame.b[1]=REVBITS(0xff-cmd);
return Nec1Renderer::newIrSignal(REVBITS(devId),cmd2.data);
}
Subclasses: IrSenderPwmHard (corresponds to current IrSenderPwm) and IrSenderPwmSoft (abstract class, having subclasses IrSenderPwmSoftDelay, IrSenderPwmSpinWait. #24).
IrSignalNonMod -> IrSenderNonMod.
It is not the focus of this project to support as much different hardware as possible. Therefore, include the timer wizardry from another source, preferably IRremote (IRremoteInt.h), preferably with no or little modifications, instead of maintaining an own file (now IRLibTimer.h). Since it has a more active user base, there is reason to believe that IRremote in the future will be more "vivid" than IRLib.
This way, support for new hardware in IRremote can be directly imported in this project. Cf #5.
Using microseconds_t = uint16_t, when a duration > 65535, the correct result modulu 65536 is delivered. Fix; deliver 65535 in this case.
Also cf. #10.
Clarify what happens when IrWidget sees a non-modulated signal. What exactly does f=20000 mean? Suggest a way for capuring/reading of such signals.
This is bengtmartensson/AGirs#4, moved
Class IrSenderSpinwait. inheriting from IrSender. Multiple instantiations allowed, since no timer (explicitly) involved. Cf. Arduino-IRremote/Arduino-IRremote#437
In my possession:
for example, maintain the second, generate the first with an xslt script.
Should be possible to construct an IrSequence from data residing in PROGMEM, preferably without internally copying the data to RAM.
There should be a static IrSignal *Pronto::parse(const __FlashStringHelper *str)
allowing to say Pronto::parse(F("0000 006c 0022 ....."))
.
Pack the sendRaw function of the oppo_raw example into (e.g.) a factory method
static IrSequence IrSequence::readFlash(const microseconds_t /* In PROGMEM*/ , size_t)
Implement the well-known hack ("F2") for Panasonic DVD/Bluray player for turning DVD code free as a sketch using the present library. Requires the Panasonic protocol, cf #28.
Likely a bug in the SAMD platform (String?), since the code runs on other platforms.
Possibly rewrite the Tokenizer without String? Check available libraries.
"boolean" is an abomination. Cf arduino/Arduino#4673
Static function
const char* Pronto::toProntoHex(const IrSignal& irSIgnal)
and/or String.
Hi Sir,
I try to use ProntoReadDump sample.
I found it is hard to receive the IR signal.
I uncomment "receiver->dump(Serial)".
There is output. However, it seems not completed. So that, it can't decode to Pronto format.
Is there any one has this issue?
Please advise. Thanks.
Output Ex.
18:54:35.526 -> +3350 -1850 +350 -500 +400 -1400 +350 -500 +350 -500 +400 -500 +350 -500 +350 -500 +350 -550 +350 -500 +350 -500 +400 -500 +300 -550 +350 -500 +400 -1350 +400 -500 +350 -550 +350 -450 +400 -500 +350 -500 +350 -500 +400 -500 +350 -500 +350 -500 +400 -1400 +350 -500 +350 -550 +300 -500 +400 -500 +400 -450 +350 -500 +400 -500 +350 -500 +350 -500 +400 -500 +350 -1400 +400 -1350 +400 -500 +350 -500 +350 -500 +400 -500 +350 -500 +350 -550 +350 -1400 +350 -1400 +350 -500 +400 -500 +350 -500 +350 -1400 +350 -65535 +3350 -1850 +400 -500 +350 -1450 +350 -450 +350 -550 +350 -500 +400 -450 +350 -550 +350 -500 +350 -500 +400 -500 +350 -500 +350 -500 +400 -500 +350 -1400 +350 -500 +350 -500 +400 -500 +350 -500 +350 -500 +400 -500 +350 -500 +400 -450 +350 -550 +350 -1450 +300 -550 +350 -500 +350 -500 +400 -450 +400 -500 +350 -500 +350 -500 +350 -550 +350 -500 +350 -500 +400 -1400 +350 -1400 +350 -500 +350 -500 +400 -500 +350 -550 +300 -500 +350 -550 +350 -1400 +400 -1400 +300 -550 +350 -500
Current code has the problems:
Probable solution: Just make endTimeout a normal class field of type milliseconds_t, and use that.
Boards:
Replace C style casts by static_cast, NULL -> nullptr,...
MicroGirs is a minimal Girs server directly on top of IRremote (see my PR) or Infrared4Arduino, that can be used directly by IrScrutinizer and Lirc. Task is to port the IRremote PR.
Use case: for example, using IrSenderNonMod to emulate the output of a demodulating receiver; these are (almost?) always active low.
Possible implementation:
private:
bool inverting;
public:
IrSenderNonMod(pin_t pin, bool inverting_ = false) : ... inverting(inverting_) { ... }
Alternative: derived class IrSenderNonModInvert
. (Boolean arguments are considered evil these days ;-).)
When attempting to update an irSignal with new codes by calling Pronto::parse(...) again it leads to memory leak. even when attempting to delete irSignal before parse call issue persists.
Console output:
start 1517
After irSignal Assignment: 1324
IrSenderPwm::getInstance(true)->sendIrSignal 1319
IrSenderPwm::getInstance(true)->sendIrSignal 1319
IrSenderPwm::getInstance(true)->sendIrSignal 1319
after delete: 1319
After irSignal Assignment: 1292
after delete: 1319
After irSignal Assignment: 1283
after delete: 1310
After irSignal Assignment: 1236
after delete: 1310
After irSignal Assignment: 1236
after delete: 1310
After irSignal Assignment: 1209
after delete: 1310
After irSignal Assignment: 1209
after delete: 1310
After irSignal Assignment: 1191
after delete: 1218
After irSignal Assignment: 1144
after delete: 1218
After irSignal Assignment: 1144
after delete: 1218
After irSignal Assignment: 1117
after delete: 1218
After irSignal Assignment: 1117
after delete: 1218
steve
code:
// Sends a signal in Pronto format
#include <IrSenderPwm.h>
#include <Pronto.h>
IrSignal *irSignal;
static const uint16_t power[] = {0x0000, 0x006D, 0x0012, 0x0012, 0x0008, 0x0022, 0x0008, 0x0041, 0x0008, 0x001D, 0x0008, 0x006A, 0x0008, 0x0032, 0x0008, 0x0032, 0x0008, 0x002C, 0x0008, 0x0065, 0x0008, 0x020C, 0x0008, 0x0022, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x006A, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x0BEF, 0x0008, 0x0022, 0x0008, 0x0041, 0x0008, 0x001D, 0x0008, 0x006A, 0x0008, 0x0032, 0x0008, 0x0032, 0x0008, 0x002C, 0x0008, 0x0065, 0x0008, 0x020C, 0x0008, 0x0022, 0x0008, 0x0046, 0x0008, 0x0046, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x006A, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x0BEF};
static const uint16_t guide[] = {0x0000, 0x006C, 0x0012, 0x0012, 0x0008, 0x0023, 0x0008, 0x0043, 0x0008, 0x001D, 0x0008, 0x006E, 0x0008, 0x0033, 0x0008, 0x0033, 0x0008, 0x002D, 0x0008, 0x0068, 0x0008, 0x01F3, 0x0008, 0x0023, 0x0008, 0x003D, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x0028, 0x0008, 0x0043, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x0C45, 0x0008, 0x0023, 0x0008, 0x0043, 0x0008, 0x001D, 0x0008, 0x006E, 0x0008, 0x0033, 0x0008, 0x0033, 0x0008, 0x002D, 0x0008, 0x0068, 0x0008, 0x01F3, 0x0008, 0x0023, 0x0008, 0x0068, 0x0008, 0x0048, 0x0008, 0x001D, 0x0008, 0x0028, 0x0008, 0x0043, 0x0008, 0x001D, 0x0008, 0x001D, 0x0008, 0x0C45};
void setup() {
Serial.begin(250000);
Serial.print("start ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
IrSenderPwm::getInstance(true)->sendIrSignal(*irSignal);
Serial.print("IrSenderPwm::getInstance(true)->sendIrSignal ");
Serial.println(freeRam());
Serial.print("IrSenderPwm::getInstance(true)->sendIrSignal ");
Serial.println(freeRam());
Serial.print("IrSenderPwm::getInstance(true)->sendIrSignal ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
irSignal=Pronto::parse(power,sizeof(power)/sizeof(power[0]));
Serial.print("After irSignal Assignment: ");
Serial.println(freeRam());
delete irSignal;
Serial.print("after delete: ");
Serial.println(freeRam());
Serial.println("steve");
}
void loop() {
}
int freeRam() {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
Michael Dreher's code is, in his own words, "optimized for efficiency, not readability". So it is effectively very hard to understand and to maintain. Also see #4 (which has never been solved, really).
Main reason for this is to port it to new processors and architectures.
branches refactor-capture, refactor-widget , see also PM by @mparthey /pull/7
powerful, cheap, small,...
The esp8266 is a sub-3-EUR module with built-in WLAN and MCU. It can be used to send and receive IR codes over WLAN.
Using an I2C 16 button keyboard. Must handle intro/repeat/ending correctly by held-down buttons (see OneButtonRemote).
Should be easy to combine with IrScrutinizer generated Arduino code. Handle PROGMEM.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.