Re: Aw: IR-blasting 455 kHz with the new upstream kernel modules gpio-ir-tx and pwm-ir-tx
[email protected] Mon, 3 Jun 2019 20:51:56 +0200
| Newsgroups | gmane.comp.hardware.lirc |
|---|---|
| Message-ID | <trinity-4bf5c50c-122e-4f72-9559-33e1ea475f08-1559587916568@msvc-mesg-gmx122> |
Am 03.06.19 um 12:14 schrieb Bengt Martensson > On 5/31/19 1:17 PM, [email protected] wrote: > > >> My appliance (a heater) stopped responding reliably to sent IR signals after upgrading the Raspberry Pi 3 to raspbian 4.19.42. I tried both new kernel modules: gpio-ir-tx and pwm-ir-tx (new kernel modules from upstream for software and hardware Pulse Width Modulation PWM). Very occasionally, maybe once in a hundred, the heater picks the IR signal up. Prior to the upgrade, the system worked nicely; as the IR signal has a high carrier frequency (455 kHz) I had used a lirc-rpi module that I had modified for hardware PWM. I measured the signal at the GPIO pin with a picoscope and noted that the carrier frequency was a bit too high when using pwm-ir-tx (around 475 - 480 kHz) and much too low when using gpio-ir-tx. > >> > ... > > Investigating the above 455 kHz issue further: > > - for testing purposes: lirc and the pwm-ir-tx module reliably blasts to a DVD player using the default carrier frequency (38 kHz). > > - a hardcoded c program using pigpio (thus avoiding all of lirc and the pwm-ir-tx module) works nicely at 455 kHz (accuracy also confirmed using picoscope). > > > > I conclude that indeed pwm-ir-tx or its dependencies are not accurate enough for 455 kHz blasting, at least not for my heater (other appliances might be less picky). I will let the author of pwm-ir-tx know. > > Hallo Andreas, > > thank you very much for sharing your experiences. Some thoughts (sorry > if these are not immediately useful): > > Some years ago (pretty many really), some thought (B&O obviously) that > 455 kHz would be a big deal, since it would allow to transfer data over > IR with a higher data rate. This appears to completely have died out. > For example, Vishay has no demodulating IR receivers in their program > since around 10 years. (See > http://www.vishay.com/whatsnew/doc/ff_FastFacts_CounterfeitTSOP7000_Dec72018.pdf > for the discontinued TSOP7000.) So I am a bit surprised that you have > found such a thingy. Can you give some more details? Can you see if you > can identify the IR receiver? > > > I conclude that indeed pwm-ir-tx or its dependencies are not accurate > enough for 455 kHz blasting, at least not for my heater (other > appliances might be less picky). I will let the author of pwm-ir-tx know. > > Was it modulation frequency or the timing of the bursts that were not > accurate? > > Generally speaking, I am a bit allergic to the idea of using a > non-realtime general-purpose multi-user OS like Linux for generating the > precise timing required to send IR signals. (This is more-or-less the > Lirc concept, at least with simple hardware.) Using "intelligent" > sending hardware (or you may prefer to call it a slave processor) is the > obvious alternative. Maybe this: > https://www.watterott.com/en/RPi-UNO-HAT would be an idea?? (Somewhere I > have heard that an Arduino Uno/Nano (Atmel328p) CAN generate 455kHz in > PWM, but I have not tried it myself.) > > Please keep us posted. > > Greetz, > > Bengt Hi Bengt, all The radiator is from Zehnder (https://www.zehnder-systems.ch/de/produkte-und-systeme/design-heizkoerper/zehnder-yucca), also the electrical heater (IRVAR 900 Heizpatrone) that is inserted into the radiator. The actual receiver within the IRVAR 900 is likely from a third party and used also in other devices; at least that was given as reason when Zehnder declined (years ago) to provide me IR details. My workaround, a hard-coded c program (copied below), is very accurate (it loses only 0-3 microseconds for the entire IR signal and 455 kHz carrier by pwm) and reliably switches the heater. I am very happy with using the RPi3 for this; no need for an Arduino or so. Issue with pwm-ir-tx: The frequency is a bit too high; Sean has meanwhile identified the error in the source code (drivers/pwm/pwm-bcm2835.c): a rounding error at low periods (= high frequencies) and submitted a patch. Only now, after your mail, I also checked the durations; and indeed, also inaccurate, notably the pulses that should be 30 microseconds. Thus, I do not know whether frequency or pulse/space lengths or both are responsible for the malfunctioning. Best regards, Andreas Appendix: my workaround using pigpio, not lirc > #include <pigpio.h> > #include <unistd.h> > #include <stdio.h> > #include <errno.h> > > // compile: gcc -Wall -pthread -o pigpio_pwm pigpio_pwm.c -lpigpio -lrt > > > int main() { > > const unsigned int gpiopin = 18; > const unsigned int pulse = 30; > #define SpaceN 19 > const unsigned int zero = 650; > const unsigned int one = 830; > const unsigned int spaces[ SpaceN ] = > {1000, // lead > one, zero, one, one, one, zero, zero, zero, // constant IR signal prefix > // one, one, one, one, one, one, one, one, // encoded key (KEY_8) > zero, zero, zero, zero, one, one, zero, one, // encoded key (KEY_0) > 470, // tail > 100}; // reasonably >0 to measure success > > // *** startup > // some calculations > uint32_t durationCalc = SpaceN * pulse; > for ( int s = 0; s < SpaceN; ++s ) durationCalc += spaces[s]; > // lower nice to get priority > errno = 0; > nice(-50); > if (errno != 0) return -2; // failed to increase priority > // initialize library > int result = gpioInitialise(); > if ( result < 0 ) return -1; // pigpio initialisation failed > // gpioTick must not be close to wrapping > if ( gpioTick() > (0xFFFFFFFF - (2 * durationCalc)) ) usleep( 2 * durationCalc ); > > // *** send the IR signal > uint32_t startPulse; > uint32_t startSpace; > int s = 0; > int notDone = (1==1); > gpioHardwarePWM( gpiopin, 455000, 0 ); > // this is the section sensitive to timing > uint32_t start = gpioTick(); > startPulse = gpioTick(); > while (notDone) { > // a pulse > gpioHardwarePWM( gpiopin, 455000, 500000 ); > startPulse += pulse; > do startSpace = gpioTick(); > while (startPulse > startSpace); > // a space (spaces are relatively long, thus we have time for housekeeping) > gpioHardwarePWM( gpiopin, 455000, 0 ); > startSpace += spaces[s]; > ++s; > notDone = (s < SpaceN); > do startPulse = gpioTick(); > while (startSpace > startPulse); > } > uint32_t end = gpioTick(); > > // *** cleanup > // close library > gpioTerminate(); > // measure success (as interrupts could have led to a prolonged pulse or space) > uint32_t durationEff = end > start ? end - start : 0xFFFFFFFF - end + start; > // checking for a delay >3 us off per period (better check for an absolute value?) > int exitvalue = (durationEff > durationCalc + 3 * 2 * SpaceN) ? 2 : 0; > // report > fprintf(stderr, "Summary of sent IR signal\n"); > fprintf(stderr, "- start at %u us\n", start); > fprintf(stderr, " end at %u us\n", end); > fprintf(stderr, "- duration %u us (should be %u us; delta %u us)\n", durationEff, durationCalc, durationEff - durationCalc); > fprintf(stderr, "- exit code %d (0 - success, >0 - should repeat, <0 - failure)\n", exitvalue); > > return exitvalue; }