Bruno M. schrieb:> Funktioniert es bei dir denn normal?
Wie gesagt: Ich kann momentan mangels HW nicht testen.
Was funktioniert denn nicht? Wird gar nichts mehr auf dem UART
ausgegeben oder fehlt lediglich der Protokollname? Wenn letzteres, muss
in irmpconfig.h lediglich
IRMP_PROTOCOL_NAMES
auf 1 gesetzt werden.
was bis jetzt läuft,
LED Stripe-steuerung mit WS2812
IRMP
Nokia 5110 LCD
I2C Tastatur mit PCF8574a
RTC DS1307 (die gegen die bessere DS3231 getauscht werden soll)
Frank M. schrieb:> Wofür zum Teufel brauchst Du 200µs? Zeig mal, was Du da alles machst.
gerne,
1
ISR(COMPA_VECT)// Timer1 output compare A interrupt service routine, called every 1/15000 sec
2
{
3
uint8_tii;
4
5
#ifdef IRQ_TEST
6
PORT_QUITT_LED|=(1<<QUITT_LED);
7
#endif
8
9
(void)irmp_ISR();// call irmp ISR
10
11
#ifdef IRQ_TEST
12
PORT_QUITT_LED&=~(1<<QUITT_LED);
13
#endif
14
15
if(teiler)
16
teiler--;
17
else
18
{
19
20
#ifdef IRQ_TEST
21
PORT_CRTL_LED|=(1<<CRTL_LED);
22
#endif
23
24
teiler=150;count++;
25
if(lcd_time_update)
26
lcd_time_update--;
27
else
28
lcd_time_update=33;
29
30
if(warte_ms)
31
warte_ms--;
32
33
if(count==1)
34
PORT_POW_LED|=(1<<POW_LED);
35
else
36
{
37
if(count==21)
38
PORT_POW_LED&=~(1<<POW_LED);
39
if(count==100)
40
{count=0;
41
#ifdef RTCTEST
42
sek_offset++;
43
#endif
44
}
45
}
46
47
#ifndef IRQ_TEST
48
if(quitt_count)
49
{PORT_QUITT_LED|=(1<<QUITT_LED);quitt_count--;
50
}
51
else
52
PORT_QUITT_LED&=~(1<<QUITT_LED);
53
#endif
54
55
if(_i2c_key)
56
{if(!_i2c_busy)
57
{_i2c_busy=1;
58
if(_i2c_key=='A')
59
{if(!i2c_start(PCF8574A_0+I2C_READ))//; // set device address and write mode
Joachim B. schrieb:> Frank M. schrieb:>> Wofür zum Teufel brauchst Du 200µs? Zeig mal, was Du da alles machst.>> gerne,
Die Zeit wird hier wohl in i2c_start() bzw. in i2c_stop() verbraten.
Diese Funktionen benutzen wahrscheinlich Warteschleifen.
So etwas gehört nicht in eine ISR. Das ist ein No Go. Low-Level-IO ist
in Ordnung, aber nicht so etwas.
Was machst Du überhaupt noch in der Hauptschleife? Warten und sonst nix?
Frank M. schrieb:> Die Zeit wird hier wohl in i2c_start() bzw. in i2c_stop() verbraten.> Diese Funktionen benutzen wahrscheinlich Warteschleifen.
mag sein, ist aber für mich OK weil ich da die I2C Tastatur entprelle
(nach Dannegger), ich mag diese Methode weil mir da nie ein Tastendruck
entgeht und sie sauber arbeitet.
> So etwas gehört nicht in eine ISR. Das ist ein No Go. Low-Level-IO ist> in Ordnung, aber nicht so etwas.
ohne Kommentar.
> Was machst Du überhaupt noch in der Hauptschleife? Warten und sonst nix?
genug was eben noch so anfällt, auf IR reagieren, je nach Taste was tun,
die LED Stripe Programme abarbeiten, das LCD mit der Uhrzeit
aktualisieren, ab und an Statusmeldungen an serial print übergeben.
Zusatz:
Eigentlich ist die Lösung ganz einfach:
Einlesen und Setzen von ii machst Du in der Hauptschleife (wenn ein
Zähler abgelaufen ist), das PeDa-Entprellen von ii machst Du im Timer.
> Was funktioniert denn nicht? Wird gar nichts mehr auf dem UART> ausgegeben oder fehlt lediglich der Protokollname?
Wie gesagt, das Loggen funktioniert problemlos, aber vom Protokoll kommt
gar nichts.
> Wenn letzteres, muss> in irmpconfig.h lediglich>> IRMP_PROTOCOL_NAMES>> auf 1 gesetzt werden.
Das habe ich natürlich gemacht!
Bruno M. schrieb:> Wie gesagt, das Loggen funktioniert problemlos, aber vom Protokoll kommt> gar nichts.
Auch wenn das Logging abgeschaltet ist? Nicht, dass Du vor lauter Bäumen
(sprich Einsen und Nullen) den Wald im Terminal-Programm nicht mehr zu
sehen bekommst ;-)
Ehrlich gesagt: Ich bin ratlos, warum das nicht funktionieren soll. Muss
ich selber testen. Vielleicht schaffe ich es heute abend.
Gruß,
Frank
> Wenn diese jetzt plötzlich auch nicht mehr funktioniert, dann machst Du> aber was falsch und nicht ich ;-)
Das Problem scheint tatsächlich bei mir zu liegen. Ich habe den Fehler
zwar noch nicht gefunden, aber ich bin dran.
Das Problem hat sich erledigt. Die Batterie meiner Fernbedienung war zu
schwach und hat das Signal offensichtlich nicht ordentlich übertragen.
Die Ursprungsversion funktioniert also wieder. Jetzt werde ich noch die
neuee testen.
Bruno M. schrieb:> Das Problem hat sich erledigt. Die Batterie meiner Fernbedienung war zu> schwach und hat das Signal offensichtlich nicht ordentlich übertragen.
Tipp: Immer zwei ausprobieren ;-)
> Tipp: Immer zwei ausprobieren ;-)
Ja, hinterher ist man immer schlauer.
Mit der neuen Version komme ich aber trotzdem nicht ganz klar, u.z. wird
der Protokollname nicht richtig angezeigt
protocol: 0x05 YO address: 0x2002 command: 0x90A0 flags:
0x00<\r><\n>
oder
protocol: 0x02 /?.???,?+?*?)?(?'?&?%?$?#?"?!?? address: 0xEB14
command: 0x0012 flags: 0x00<\r><\n>
Bruno M. schrieb:> protocol: 0x05 YO address: 0x2002 command: 0x90A0 flags:> 0x00<\r><\n>
Du hast jetzt auch die irmp.c-Version, wo
1
staticconstcharproto_unknown[]PROGMEM="UNKNOWN";
2
usw.(vielePROGMEM-Zeilen)
drinsteht?
EDIT:
Ah, ich weiß schon, wo der Fehler steckt. Nicht nur die Array-Inhalte,
sondern auch das Array selbst ist im Flash. Ich muss also 2x
dereferenzieren. Irre Sache.
Ich melde mich gleich nochmal.
Frank M. schrieb:
> Du hast jetzt auch die irmp.c-Version, wostatic const char> proto_unknown[] PROGMEM = "UNKNOWN";> usw. (viele PROGMEM-Zeilen)>> drinsteht?
Ja genau die habe ich und wenn ich an 3 Stellen (irmp.c, irmp.h und
main.c) den alten Stand herstelle, dann funktioniert es wieder.
Frank M. schrieb:> Ah, ich weiß schon, wo der Fehler steckt. Nicht nur die Array-Inhalte,> sondern auch das Array selbst ist im Flash. Ich muss also 2x> dereferenzieren. Irre Sache.
Du musst jetzt mal für mich testen.
Ersetze bitte in main.c:
Frank M. schrieb:
> Du musst jetzt mal für mich testen.
Hat sich nichts geändert.
Es kommt auch eine Warnung:
uninitialized variable 'irmp_protocol_names' put into program memory
area [-Wuninitialized] irmp.h
Frank M. schrieb:> Zusatz:>> Eigentlich ist die Lösung ganz einfach:
oder noch einfacher
ich weiss das deine IRQ keine 4µs dauert !
ich weiss das meine lange Ausführung 200µs dauert und nur alle 10ms
stattfindet.
ich setze ein Flag wenn ich im langen 200µs Teil bin und erlaube dann
mit sei(); wieder IRQ, und da deine IRQ nur 4µs dauern -um was meine
200µs verlängert werden- die aber nur alle 10ms stattfinden und am Ende
der langen IRQ-Ausführung lösche ich das Flag wieder und mache cli() ->
damit habe ich kein Problem.
voila, es kommen nun wieder alle IRMP IRQ durch für 4µs, der lange Teil
wird umgangen solange das Flag long_irq gesetzt ist und wird erst wieder
ausgeführt wenn long_irq auf 0 gesetzt ist am Ende vom long IRQ
klappt prima !
Die Idee mit Timer2 schied aus weil der für die Arduino PWM genutzt
wird.
Hi,
Bin heute Morgen leider nicht mehr dazu gekommen das Ganze richtig zu
recherchieren und wollte da nicht voreilig Falschaussagen treffen. Die
vorgeschlagenen Linker-Optionen kamen mir nämlich ein wenig spanisch
vor.
Frank M. schrieb:> Wenn Du einen neueren avr-gcc hast (z.B. 4.7.2), kannst Du einiges> herausholen durch folgende Flags:>> Compiler:>> -Os # hast Du wahrscheinlich schon> -flto> -ffunction-sections> -fdata-sections
Das geht soweit in Ordnung bzw. macht Sinn.
> Linker:> -Os # ja, beim Linker!
Das ist nicht dokumentiert. Die Manpage sagt dazu folgendes:
> -O level> If level is a numeric values greater than zero ld optimizes the output.
Auf gut deutsch: Nur nummerische Werte sind erlaubt. Keine Ahnung was s
bewirkt, wahrscheinlich gar nichts, siehe unten.
> -flto> -ffunction-sections> -fdata-sections
Diese Optionen gibt es laut Manpage des Linkers (avr-ld) nicht.
> -Wl,--gc-sections
Die eigentliche Option hier wäre aber nur gc-sections. Mit dem
vorangestelltem "-Wl," reichst du die Option nur zum Linker durch, falls
du diesen nicht explizit aufrufst, sondern "avr-gcc" direkt benutzt.
All dies lässt mich zu der Vermutung kommen, dass du hier etwas
durcheinander gebracht hast und es dir nur durch Glück (bzw. Pech) nicht
aufgefallen ist. Kann es sein, dass du die Optionen nicht zum Linker
weiter reichst (weil du kein "-Wl," vorangestellt hast), sondern diese
direkt vom Compiler ausgewertet werden. Dadurch kommt es zu keinen
Fehlermeldungen, bringt halt nur auch nichts ;).
Frank M. schrieb:> SVN ist eine Versionsverwaltung. ;-)
Das ich SVN für einen Krampf halte, weißt du ja von der Wordclock
Diskussion schon. Aber ja, SVN ist eine Versionsverwaltung und besser
als keine. Die Aussage bezog ich aber gar nicht auf dich, sondern auf
Bruno M., der ja sagte, dass er den vorherigen Zustand nicht wieder
herstellen kann.
Joachim B. schrieb:> noch jemand einen Einwand ?
Ja, ich halte das auch für eine schlechte Idee. Prinzipiell möglich,
aber man muss ÜBERVORSICHTIG sein. Die Lösung wäre es, wie schon
gesagt, keine I2C Transfers innerhalb der ISR zu initiieren und auf die
Antwort zu warten. Teil der I2C Spezifikation ist übrigens auch das sog.
Clock Stretching, d.h. das zeitliche Verhalten ist absolut
unvorhersagbar und hat nichts in der ISR verloren.
Frank M. schrieb:> Nicht nur die Array-Inhalte,> sondern auch das Array selbst ist im Flash. Ich muss also 2x> dereferenzieren. Irre Sache.
Ja, und das wird ziemlich schnell ziemlich unleserlich, zumindest
besonders intuitiv ist es nicht.
Frank M. schrieb:> PGM_P p = (PGM_P) pgm_read_word> (irmp_protocol_names[irmp_data.protocol]);
Fehlt da nicht noch ein "&" samt passender Klammerung innerhalb von
pgm_read_word()? Also in etwa so:
1
PGM_P p = (PGM_P) pgm_read_word (&(irmp_protocol_names[irmp_data.protocol]));
Du willst das was sich hinter "irmp_protocol_names[irmp_data.protocol]"
verbirgt ja als Adresse an pgm_read_word() übergeben und selbst wieder
als Adresse interpretieren (daher pgm_read_word() und der Cast zu
(PGM_P)). So jedenfalls habe ich das kürzlich bei einem ähnlichem
Problem bei meinen Umbaumaßnahmen am Wordclock Projekt gelöst, siehe [1]
und [2]. Das hatte ich auch getestet und es hat funktioniert. Kann das
aber leider gerade auch nicht verifizieren, müsste mich aber gerade
schon ganz stark irren.
Mit freundlichen Grüßen,
Karol Babioch
[1]:
https://github.com/Wordclock/firmware/blob/feat/log/src/uart_protocol.c#L1094
[2]:
https://github.com/Wordclock/firmware/blob/feat/log/src/uart_protocol.c#L1121
Karol Babioch schrieb:> Joachim B. schrieb:>> noch jemand einen Einwand ?>> Ja, ich halte das auch für eine schlechte Idee. Prinzipiell möglich,> aber man muss ÜBERVORSICHTIG sein. Die Lösung wäre es, wie schon> gesagt, keine I2C Transfers innerhalb der ISR zu initiieren und auf die> Antwort zu warten. Teil der I2C Spezifikation ist übrigens auch das sog.> Clock Stretching, d.h. das zeitliche Verhalten ist absolut> unvorhersagbar und hat nichts in der ISR verloren.
danke ist klar, aber nach über 4 Jahren mit meiner "I2C Tastatur" ist
mir da nie was aufgefallen. Ich halte den PCF8574 nicht für so komplex
das er Clock Stretching betreibt. Sein Verhalten war bis jetzt korrekt
oder sagen wir überschaubar, von daher glaube ich kann ich in meiner
Anwendung das so lassen. Selbst wenn er Clock Stretching betreiben würde
glaube ich nicht das er seine default 100kHz -> 10µs pro bit Zugriff auf
1ms verlängert was dann kritisch werden würde.
Ich glaube fest ohne weitere Hinweise das es für "meine" I2C Tastatur
unkritisch bleibt. Weitere Anwendungen für I2C in einer ISR dafür fallen
mir eh nicht ein.
Bruno M. schrieb:> Hat sich nichts geändert.
Hm, komisch. Das sollte eigentlich die Lösung sein. Dann werde ich das
heute abend mal selbst testen.
> Es kommt auch eine Warnung:> uninitialized variable 'irmp_protocol_names' put into program memory> area [-Wuninitialized] irmp.h
Die bekomme ich nicht. Irgendwas ist bei Dir nicht konsistent. Du hast
nun wieder alle Dateien aus dem SVN + Korrektur der 2 Zeilen?
Dann teste bitte mal Karols Vorschlag:
Hi Karol,
Karol Babioch schrieb:>> Linker:>> -Os # ja, beim Linker!>> Das ist nicht dokumentiert. Die Manpage sagt dazu folgendes:
Es ist mir egal, was die Manpage dazu sagt. ;-)
Die Optionen sind von mir (und anderen!) einzeln und in Gruppen
durchgetestet. Nur in dieser Kombination bekommt man ein optimales
Ergebnis.
Erst mit dem Linker-Flag -Os funktioniert die flto-Optimierung, d.h. der
gcc behandelt externe Funktionen wie static Funktionen. Bildlich
gesprochen zieht er den kompletten Source in einen Quelltext und kann
viel besser optimieren, nämlich z.B. quelltext-übergreifend inlinen.
Real passiert natürlich etwas anderes: Es wird alles in eine
Zwischensprache (GIMPLE) übersetzt, welche dann in der zweiten Stufe
nochmals optimiert wird. Dazu muss der Linker(!) den Compiler nochmals
aufrufen und ihm (dem Compiler!) das -Os als Optimierungsflag mitgeben.
Siehe dazu auch folgenden Thread, wo das Thema ausführlichst behandelt
wird:
Beitrag ""Include-Libs" - Teufelswerk?"> Diese Optionen gibt es laut Manpage des Linkers (avr-ld) nicht.>>> -Wl,--gc-sections
Ich kann nichts dafür, dass die Manpage nicht stimmt, s.o. ;-)
> Die eigentliche Option hier wäre aber nur gc-sections. Mit dem> vorangestelltem "-Wl," reichst du die Option nur zum Linker durch, falls> du diesen nicht explizit aufrufst, sondern "avr-gcc" direkt benutzt.
Siehe oben:
Der Linker muss den Compiler aufrufen und ihm die Compiler-Flags
nochmals unterjubeln.
> All dies lässt mich zu der Vermutung kommen, dass du hier etwas> durcheinander gebracht hast [...]
Nein, habe ich nicht. Der Witz ist, dass bei -flto der Linker den
Compiler für einen 2. Optimierungslauf aufruft. Deshalb muss dem Linker
die notwendigen Compilerflags mitgegeben werden.
> [irmp_protocol_names]...> Ja, und das wird ziemlich schnell ziemlich unleserlich, zumindest> besonders intuitiv ist es nicht.
Das liegt daran, dass zum einen die Strings im Flash liegen:
1
staticconstcharproto_unknown[]PROGMEM="UNKNOWN";
2
staticconstcharproto_sircs[]PROGMEM="SIRCS";
3
staticconstcharproto_nec[]PROGMEM="NEC";
4
...
... und zum anderen das Array selbst:
1
constchar*const
2
irmp_protocol_names[IRMP_N_PROTOCOLS+1]PROGMEM=
3
{
4
proto_unknown,
5
proto_sircs,
6
...
> Fehlt da nicht noch ein "&" samt passender Klammerung innerhalb von> pgm_read_word()? Also in etwa so:>>
1
> PGM_P p = (PGM_P) pgm_read_word
2
> (&(irmp_protocol_names[irmp_data.protocol]));
3
>
Ja, könnte durchaus sein. Ich habe mir da gestern zu wenig Gedanken
drüber gemacht und einfach eine 2. Dereferenzierung eingebaut. Denn wir
haben ja hier eine geschachtelte Situation. Habe ich so noch nie
verwendet. Aber nur so wird der RAM-Verbrauch minimal.
Gruß,
Frank
Joachim B. schrieb:> Ich halte den PCF8574 nicht für so komplex> das er Clock Stretching betreibt.
Das ist überhaupt kein komplexes Feature. Spreche das Teil einfach mal
mit mehr als 100 kHz an und sehe was passiert.
Joachim B. schrieb:> Sein Verhalten war bis jetzt korrekt> oder sagen wir überschaubar,
Du verlässt dich damit halt implizit auf die von dir gemachte Erfahrung,
dass das Teil schnell genug antwortet. Selbst wenn das Ding selbst keine
Probleme macht, könnte jeder zusätzliche Teilnehmer am Bus deine Annahme
auf den Kopf stellen. Das Debuggen wird dann nicht einfacher ...
Keine Ahnung in welchem Kontext du das Ganze entwickelst, aber sofern
die Möglichkeit besteht, dass in einigen Monaten/Jahren jemand anderes
bzw. (wieder du) daran weiterentwickelt, so machst du demjenigen nur das
Leben schwer, wenn du da irgendwelche untypischen Dinge vollführst.
Zumindest solltest du das GUT dokumentieren.
Letztendlich musst das natürlich du alleine entscheiden, du scheinst
dich aber ganz schön vehement zu sträuben und sowieso an deiner Meinung
fest zu halten. Insofern hättest du dir die Frage auch sparen können ;).
Mit freundlichen Grüßen,
Karol Babioch
Frank M. schrieb:
> Dann teste bitte mal Karols Vorschlag:> PGM_P p = (PGM_P) pgm_read_word> (&(irmp_protocol_names[irmp_data.protocol]));
Ergebnis:
protocol: 0x05 KASEIKYO address: 0x2002 command: 0x90A0 flags:
0x00<\r><\n>
das sieht doch gut aus. Die Warnung ist aber geblieben.
Jetzt ergibt sich daraus aber noch eine Frage. Ich hatte das Programm so
umgeschrieben, daß ich es auch auf LCD ausgeben kann. In der
Vorgängerversion ging das auch gut.
Was muß ich aber jetzt für den Programmnamen hinter lcd_string eingeben?
Bruno M. schrieb:> protocol: 0x05 KASEIKYO address: 0x2002 command: 0x90A0 flags:> 0x00<\r><\n>>> das sieht doch gut aus. Die Warnung ist aber geblieben.
Prima, freut mich. Ich werde die korrigierte Version gleich ins SVN
einchecken. Zu der Warnung kann ich leider nichts sagen, denn ich
erhalte sie nicht. Wird da irgendwo eine Zeilennummer ausgegeben? Oder
kannst Du per Copy&Paste den genauen Wortlaut hier reinstellen?
Bruno M. schrieb:> Jetzt ergibt sich daraus aber noch eine Frage. Ich hatte das Programm so> umgeschrieben, daß ich es auch auf LCD ausgeben kann. In der> Vorgängerversion ging das auch gut.>> Was muß ich aber jetzt für den Programmnamen hinter lcd_string eingeben?
Ich weiß leider nicht, welche LCD-Lib Du nutzt. Aber ich vermute stark,
dass es neben lcd_string() auch eine Funktion lcd_string_P() gibt.
Probiers aus.
Frank M. schrieb:> Bruno M. schrieb:>> Jetzt ergibt sich daraus aber noch eine Frage. Ich hatte das Programm so>> umgeschrieben, daß ich es auch auf LCD ausgeben kann. In der>> Vorgängerversion ging das auch gut.>>>> Was muß ich aber jetzt für den Programmnamen hinter lcd_string eingeben?>> Ich weiß leider nicht, welche LCD-Lib Du nutzt. Aber ich vermute stark,> dass es neben lcd_string() auch eine Funktion lcd_string_P() gibt.> Probiers aus.
Alternativ kannst du den String auch mit strcpy_P bzw. strncpy_P in den
SRAM kopieren und dann wie gewohnt an deine LCD-Ausgaberoutine
übergeben.
Mit freundlichen Grüßen,
Karol Babioch
Karol Babioch schrieb:> Alternativ kannst du den String auch mit strcpy_P bzw. strncpy_P in den> SRAM kopieren und dann wie gewohnt an deine LCD-Ausgaberoutine> übergeben.
Wie???
Du willst die mit viel Aufwand gesparten Bytes im RAM jetzt wieder zum
Fenster hinauswerfen?!? ;-)
Dann doch lieber eine lcd_string_P-Funktion schreiben, die analog zum
uart_puts_P arbeitet.
Aber wie gesagt: Ich vermute stark, dass es die Funktion lcd_string_P()
bereits schon gibt.
Frank M. schrieb:
> Ich weiß leider nicht, welche LCD-Lib Du nutzt. Aber ich vermute stark,> dass es neben lcd_string() auch eine Funktion lcd_string_P() gibt.> Probiers aus.
Ich hatte die lib aus dem Tutorial, die enthält kein lcd_string_P(). Ich
habe sie mir aber jetzt aus der lib von Peter Fleury kopiert und das
funktioniert.
Karol Babioch schrieb:
> Alternativ kannst du den String auch mit strcpy_P bzw. strncpy_P in den> SRAM kopieren und dann wie gewohnt an deine LCD-Ausgaberoutine> übergeben.
Ich habe das mit
Frank M. schrieb:
> Zu der Warnung kann ich leider nichts sagen, denn ich> erhalte sie nicht. Wird da irgendwo eine Zeilennummer ausgegeben? Oder> kannst Du per Copy&Paste den genauen Wortlaut hier reinstellen?
Warning 4 uninitialized variable 'irmp_protocol_names' put into
program memory area [-Wuninitialized] irmp.h 132 41
das ist die komplette Warnung, nur mein Dateipfad fehlt.
Bruno M. schrieb:> Geht auch, aber dann warnt der Compiler wegen char und const> char.
Was genau wird beanstandet? Im Notfall castest du den Pointer halt
passend :).
Mit freundlichen Grüßen,
Karol Babioch
Bruno M. schrieb:> Ich hatte die lib aus dem Tutorial, die enthält kein lcd_string_P(). Ich> habe sie mir aber jetzt aus der lib von Peter Fleury kopiert und das> funktioniert.
Prima. Diese Lösung solltest Du so beibehalten.
> Ich habe das mit>>
1
strcpy_P(p,(PGM_P)pgm_read_word
2
>(&(irmp_protocol_names[irmp_data.protocol])));
3
>lcd_string(p);
>>> probiert. Geht auch, aber dann warnt der Compiler wegen char und const> char.
Nicht nur das. p ist nur ein Pointer und stellt keinerlei RAM durch
Reservierung zur Verfügung. Das heisst: Du schreibst Dir mit strcpy_P()
irgendwo unkontrolliert in den Speicher. Ein Crash ist damit
vorprogrammiert.
Wenn, dann musst Du p definieren als:
char p[32]; // 32: max. mögliche Länge des Strings + 1
Nur dann hast Du auch Speicher für die Copy-Funktion reserviert. Kostet
Dich aber auch 32 Bytes. Und genau da wollten wir doch eigentlich
sparen ;-)
Frank M. schrieb:> Du willst die mit viel Aufwand gesparten Bytes im RAM jetzt wieder zum> Fenster hinauswerfen?!? ;-)Frank M. schrieb:> Wenn, dann musst Du p definieren als:>> char p[32]; // 32: max. mögliche Länge des Strings + 1>> Nur dann hast Du auch Speicher für die Copy-Funktion reserviert. Kostet> Dich aber auch 32 Bytes. Und genau da wollten wir doch eigentlich> sparen ;-)
Sind ja jetzt keine globalen Variablen mehr und können daher in den
Speicherbereich eines Stackframes kopiert werden.
Ist ja auch nur eine Alternative gewesen, wenn entsprechende *_P()
Funktionen zur Verfügung stehen. Interessant in diesem Zusammenhang ist
ggf. auch das "__flash" Attribut, siehe [1]. Würde das aber gerne mal in
Aktion sehen (bei einem größeren Projekt) bevor ich meine Quellen
migriere und mir unnötig Arbeit mache.
Mit freundlichen Grüßen,
Karol Babioch
[1]: Beitrag "avr-gcc progmem immer noch?"
Karol Babioch schrieb:> Joachim B. schrieb:>> Ich halte den PCF8574 nicht für so komplex>> das er Clock Stretching betreibt.>> Das ist überhaupt kein komplexes Feature. Spreche das Teil einfach mal> mit mehr als 100 kHz an und sehe was passiert.
das Datenblatt weisst den nicht als 400kHz Typen aus, also warum sollte
ich sowas machen ?
> Du verlässt dich damit halt implizit auf die von dir gemachte Erfahrung,> dass das Teil schnell genug antwortet. Selbst wenn das Ding selbst keine> Probleme macht, könnte jeder zusätzliche Teilnehmer am Bus deine Annahme> auf den Kopf stellen. Das Debuggen wird dann nicht einfacher ...
OK das Argument lasse ich gelten, da ich aber bis jetzt den Takt auf
100kHz habe und ich noch keinen unter 100kHz entdecken konnte weiss ich
nicht ob dieser Einwand nicht ein wenig konstruiert wirkt, ich gebe zu
viele verschiedene I2C Bausteine habe ich noch nicht angesteuert.
> Keine Ahnung in welchem Kontext du das Ganze entwickelst
nur für mich
> die Möglichkeit besteht, dass in einigen Monaten/Jahren jemand anderes
bin ich tot und dann geht es in den Elektronikschrott
> Zumindest solltest du das GUT dokumentieren.
meine berufliche Erfahrung, Unterlagen verschwinden als erstes !
(zumindest privat habe ich noch meine Quellprogramme dokumentiert aus
den 80er bis 90er Jahren)
> Letztendlich musst das natürlich du alleine entscheiden, du scheinst> dich aber ganz schön vehement zu sträuben und sowieso an deiner Meinung> fest zu halten.
ich sträube mich normalerweise nicht, aber je weiter ich komme umso mehr
tun sich Fragen auf.
Entweder ich schaffe es irgendwann alle Fragen perfekt zu beantworten,
dann habe ich nichts geschaffen
(der Spezialist weiss immer mehr von immer weniger bis er bald alles von
nichts weiss)
oder ich muss mich damit abfinden das es läuft aber Risiken der
Fehlfunktion überbleiben
Es soll eine Spielerei oder word clock werden ! kein Feuermelder oder
Entrauchungsanlage, auch keine Lasersteuerung.
Trotzdem danke für jeden Hinweis den ich bei Neugier auch mal selber
folgen kann.
Karol Babioch schrieb:> Interessant in diesem Zusammenhang ist> ggf. auch das "__flash" Attribut, siehe [1].
Ich kenne diesen Thread, habe ja schließlich auch was dort dazu
geschrieben ;-)
Aber eigentlich wird dem Programmierer mittels __flash nur etwas
Schreibarbeit abgenommen. Das vom Compiler erzeugte Programm ist
identisch zur PROGMEM-Variante. Ich würde kurzfristig IRMP und andere
meiner Programme nicht darauf umstellen wollen, da ich darauf bedacht
bin, dass andere Leute immer noch ältere Compiler verwenden können. Zum
Beispiel ist AVRStudio4 mit avr-gcc 4.3.3 aus WinAVR-2010-01-20 immer
noch sehr verbreitet.
> Würde das aber gerne mal in> Aktion sehen (bei einem größeren Projekt) bevor ich meine Quellen> migriere und mir unnötig Arbeit mache.
Das mit der Schreibweise __flash funktioniert tadellos. Es sieht
natürlich im Quelltext schöner aus. Wenn es Dir nur um eigene Programme
geht, die nur Du kompilierst, kannst Du das bedenkenlos umstellen.
gruß,
Frank
Bruno M. schrieb:> Frank M. schrieb:>>> Dann teste bitte mal Karols Vorschlag:>> PGM_P p = (PGM_P) pgm_read_word>> (&(irmp_protocol_names[irmp_data.protocol]));
sind diese Änderungen schon im svn ?
ich hatte gerade mal nur irmp.c und irmp.h probiert aber gleich
Fehlermeldungen bekommen bezüglich IRMP port und bit
die Namen im flash hätte ich auch schon gerne genutzt
im Moment habe ich
irmp.c
* $Id: irmp.c,v 1.145 2014/02/20 14:55:17 fm Exp $
irmp.h
* $Id: irmp.h,v 1.84 2014/02/19 12:57:36 fm Exp $
mein Code läuft nur die Namen erzeuge ich so, etwas umständlich halt
#ifdef IRMP_SUPPORT_NEC_PROTOCOL
case IRMP_NEC_PROTOCOL: Serial.print(F("IR: "));
Serial.print(F("NEC")); Serial.print(F(", Address: "));
Serial.print(irmp_data.address); Serial.print(F(", Command: "));
Serial.println(irmp_data.command);
schöner wäre statt
Serial.print(F("NEC"));
direkt aus dem flash
Serial.print(irmp_protocol_names[IRMP_NEC_PROTOCOL]);
lg jar
Joachim B. schrieb:> sind diese Änderungen schon im svn ?
Ja, schon seit kurz vor Mittag.
> im Moment habe ich>> irmp.c> * $Id: irmp.c,v 1.145 2014/02/20 14:55:17 fm Exp $> irmp.h> * $Id: irmp.h,v 1.84 2014/02/19 12:57:36 fm Exp $http://www.mikrocontroller.net/svnbrowser/irmp/
zeigt was anderes. Du hast da die Version vom Februar aus dem
Zip-Archiv.
> #ifdef IRMP_SUPPORT_NEC_PROTOCOL> case IRMP_NEC_PROTOCOL: Serial.print(F("IR: "));> Serial.print(F("NEC")); Serial.print(F(", Address: "));> Serial.print(irmp_data.address); Serial.print(F(", Command: "));> Serial.println(irmp_data.command);
Viel zu umständlich. Das Array irmp_protocol_names gibt es schon seit
ein paar Jahren.
> Serial.print(irmp_protocol_names[IRMP_NEC_PROTOCOL]);
Du musst wegen der doppelten Referenzierung des Arrays im Flash
denselben Trick anwenden wie heute morgen diskutiert.
Frank M. schrieb:> Ja, schon seit kurz vor Mittag.
wo ?
mit diesem habe ich Fehler bekommen (heute um diese Zeit aus dem gnu
tarball ausgepackt)
* $Id: irmp.c,v 1.164 2014/09/15 12:36:28 fm Exp $
der 15 sagt mir war nicht von heute Mittag
deswegen wieder zurückgegangen
> zeigt was anderes. Du hast da die Version vom Februar aus dem> Zip-Archiv.
war wohl misverständlich
> Viel zu umständlich. Das Array irmp_protocol_names gibt es schon seit> ein paar Jahren.
ich weiss, hatte ich im studio 4 schon genutzt, aber irgendwas funzte am
arduino nicht (weswegen ich diesen umständlichen Weg ging, nicht aus jux
und dollerei) und nun einen neuen Versuch starte
Joachim B. schrieb:> der 15 sagt mir war nicht von heute Mittag
Das war vorgestern.
Wir reden hier seit 2 Tagen über das Beispiel-main.c und nicht über
irmp.c - noch nicht gemerkt?
Ich habe mir eben die Arbeit gemacht, Dir einen Link auf das SVN zu
posten.
Hier nochmal:
http://www.mikrocontroller.net/svnbrowser/irmp/
Da siehst Du direkt, von wann welche Datei ist.
Das erste, was Du dann fragst, ist: "Wo?".
Ich bitte Dich, etwas aufmerksamer bei der Sache zu bleiben. Sonst komme
ich mir irgendwie verarscht vor.
Frank M. schrieb:> Ich bitte Dich, etwas aufmerksamer bei der Sache zu bleiben. Sonst komme> ich mir irgendwie verarscht vor.
verstehe ich auch, ich bin sogar der Pointer Diskusion zu Karol gefolgt,
aber irgendwann rauchte mir so der Kopf das ich es lieber probieren
wollte statt nicht weiterzukommen
nur den main Aufruf ändern oder wie, bin grad verwirrt....
reicht es nur IRMP.C und .H zu tauschen oder braucht es noch mehr ?
Joachim B. schrieb:> das ändert nix daran wenn ich nur irmp.c und .h vom Februar mit> September tausche das ich eine Fehlermeldung bekomme [...]
Zwischen Februar und heute liegt mehr als ein halbes Jahr. Da kannst Du
nicht mehr einzelne Module einfach so austauschen, sondern alles oder
gar nichts.
Also:
irmp.c
irmp.h
irmpprotocols.h
irmpsystem.h
irmpconfig.h
Das main.c solltest Du Dir zu Studienzwecken auch noch ansehen.
ich wusste warum ich die Namen ausgeklammert hatte in ARDUINO
lightweight_ws2812.cpp.o:(.progmem.data+0x5e): multiple definition of
`irmp_protocol_names'
irmp.c.o:(.progmem.data+0x0): first defined here
muss ich ein andermal untersuchen....
Joachim B. schrieb:> ich wusste warum ich die Namen ausgeklammert hatte in ARDUINO
Arduino setzt auch intern auf gcc auf.
Joachim B. schrieb:> lightweight_ws2812.cpp.o:(.progmem.data+0x5e): multiple definition of> `irmp_protocol_names'> irmp.c.o:(.progmem.data+0x0): first defined here
Zeige mal bitte lightweight_ws2812.cpp samt dazugehörigem Header. Laut
Fehlermeldung versuchst du dort die Variable irmp_protocol_names zu
definieren. Der Unterschied zwischen einer Definition und einer
Deklaration ist dir klar?
Mit freundlichen Grüßen,
Karol Babioch
Karol Babioch schrieb:> Zeige mal bitte lightweight_ws2812.cpp samt dazugehörigem Header. Laut> Fehlermeldung versuchst du dort die Variable irmp_protocol_names zu> definieren.
ist mir auch schon aufgefallen
ich habe an 2 Stellen das
#include "irmp.h"
in irmp.c und im main
egal wo ich es weglasse, einer meckert immer .......
> Der Unterschied zwischen einer Definition und einer> Deklaration ist dir klar?
jau
die Arduino IDE macht mich wahnsinnig, wie schön ging das im AVR Studio4
aber auf Platinen löten und immer wieder AVRisp mk2 (clone) progger
kaufen fehlt das Geld und die Lust (Zeit).....
es ist mühsam ehemalige C Sourcen und Header in die IDE zu übernehmen,
habe da noch nicht den Durchblick
danke für Hilfe
Joachim B. schrieb:> #include "irmp.h">> in irmp.c und im main
In irmp.c sollst du gar nicht herum werkeln. Das ist Franks Domäne ;).
Lade doch mal das Projekt irgendwo hoch, vielleicht mag sich das ja
jemand anschauen bzw. findet den Fehler.
Übrigens: Ein Arduino ist ein AVR + Bootloader. Du kannst du auch prima
ohne Arduino IDE programmieren und Programme z.B. mittels avrdude auf
den Arduino übertragen. Die IDE macht im Hintergrund nichts anderes.
Mit freundlichen Grüßen,
Karol Babioch
Hallo Frank,
vielen herzlichen Dank für Deine Unterstützung.
Jetzt bin ich unterwegs - kann das also wahrscheinlich erst im Oktober
austesten.
Ich gebe Bescheid, wenn ich so weit bin.
Zu den Doppelbefehlen:
Bei den "normalen = standard" Funktionen (Laut, Leise, Next, Prev)
wurden ca. 1660 Werte ausgegeben.
Bei den "exotischeren" Befehlen (Map, Band) wurden ca. die doppelte
Anzahl von Zeichen ausgegeben.
Bei einigen wenigen Tasten war es möglich mit einem sehr kurzen
Tastendruck nur 1660 Werte zu erhalten. Stabil reproduzierbar war das
aber nicht - meist kamen auch da die doppelte Anzahl.
Zur Diskrepanz der Zeitangaben bei der PC-Auswertung mit IRMP.exe:
Ich hatte eigentlich alle 3 Werte (10.000 15.000 und 20.000) getestet.
Es wurden dann zwar mehr oder weniger Werte über den UART ausgegeben,
aber die Auswertung mit IRMP.exe stimmte nie.
Wie sollte das eigentlich auch gehen: Aus der UART-Ausgabe wird ja nur
eine Textdatei mit "0", "1" und ggf. Zeilenumbruch generiert.(Ich habe
ht-Term verwendet und als RAW gespeichert.)
Ein "Zeitnormal" wird doch nicht mit eingebaut !? (...und die
UART-Baudrate dürfte hier auch nicht mir reinspielen)
Das U2X-Problem hat sich nach kleiner "Reinigung" des Source-Codes mit
dem Holzhammer (siehe oben ;-) undefiniert von selbst aufgelöst... ...ab
jetzt "Never touch a running system"
Nochmal vielen herzlichen Dank
Viele Grüße
SvenK
Joachim B. schrieb:> nur für mich
Dann musst du das auch nur mit dir und deinem Gewissen vereinbaren ;).
Ich persönlich erhebe immer den Anspruch solche Dinge architektonisch so
gut wie möglich zu lösen. Und das notdürftige Verschachteln von
Interrupts aufgrund von I2C Transfers in einem Interrupt gehört da nicht
dazu :).
Frank M. schrieb:> Ich würde kurzfristig IRMP und andere> meiner Programme nicht darauf umstellen wollen, da ich darauf bedacht> bin, dass andere Leute immer noch ältere Compiler verwenden können. Zum> Beispiel ist AVRStudio4 mit avr-gcc 4.3.3 aus WinAVR-2010-01-20 immer> noch sehr verbreitet.
Die Sorge teile ich nicht. Alles außer avr-gcc 4.9.1 ist alt ;). Ich
pflege allerdings auch keine Bibliothek wie IRMP ...
Frank M. schrieb:> Das mit der Schreibweise __flash funktioniert tadellos. Es sieht> natürlich im Quelltext schöner aus. Wenn es Dir nur um eigene Programme> geht, die nur Du kompilierst, kannst Du das bedenkenlos umstellen.
Es geht mir weniger um die Schreibweise, sondern wie man dann den
Zugriff auf Inhalte im Flash am Besten löst. Weiterhin mit jeweils zwei
Funktionen (jeweils eine mit *_P())", oder ggf. nur noch eine mit einem
zusätzliche Parameter in dessen Abhängigkeit man den Pointer
entsprechend zurecht castet.
Frank M. schrieb:> Es ist mir egal, was die Manpage dazu sagt. ;-)
Mir aber nicht. Gerade bei Projekten wie gcc ist die Manpage eigentlich
immer up to date und die Referenz.
Frank M. schrieb:> Die Optionen sind von mir (und anderen!) einzeln und in Gruppen> durchgetestet.
Mich wundert es eben nur ein bisschen.
Frank M. schrieb:> Nur in dieser Kombination bekommt man ein optimales> Ergebnis.
Das kann ich z.B. nicht nachvollziehen. Beim Kompilieren meiner Version
des Wordclock Projekts gewinne ich NUR durch das Zuschalten der LTO
beim Kompilieren (-flto beim Compiler) 1.5 kB. Die zusätzlichen Schalter
(-Os, -flto, -ffunction-sections, -fdata-sections) beim Linken hingegen
bringen keinen zusätzlichen Gewinn. Sogar -Wl,-gc-sections hat dann
keine Auswirkungen mehr, obwohl es ohne die -flto Option etwas bringt.
Frank M. schrieb:> Erst mit dem Linker-Flag -Os funktioniert die flto-Optimierung, d.h. der> gcc behandelt externe Funktionen wie static Funktionen.
Nein, das funktioniert bei mir auch ohne -flto beim Linken.
Frank M. schrieb:> Bildlich> gesprochen zieht er den kompletten Source in einen Quelltext und kann> viel besser optimieren, nämlich z.B. quelltext-übergreifend inlinen.
Ja, das ist die grundsätzliche Idee hinter der LTO und wird so auch in
der Manpage ausgeführt ;).
Frank M. schrieb:> Dazu muss der Linker(!) den Compiler nochmals> aufrufen und ihm (dem Compiler!) das -Os als Optimierungsflag mitgeben.
Also mein finaler Aufruf zum Linken sieht so aus:
Ich vermute (!), dass intern automatisch erkannt wird, in welcher Form
die Objekte generiert worden sind.
Frank M. schrieb:> Siehe dazu auch folgenden Thread, wo das Thema ausführlichst behandelt> wird:>> Beitrag ""Include-Libs" - Teufelswerk?"
So ausführlich wie es mir gerne gewünscht hätte, ist das aber gar nicht.
Aber zumindest in deinem Fall scheint es ja Abhilfe geschafft zu haben.
Leider konnte ich aber das Kommando des finalen Linkens nicht entdecken.
Sicher, dass du das nicht auch über avr-gcc gemacht hast und damit das
Kommando nicht doch an den Compiler bzw. das avr-gcc übergeben hast ;)?
Wie bei mir oben schön zu sehen, ruft man i.d.R. ja nicht den Linker
(avr-ld) selbst auf, sondern erledigt dies über avr-gcc, wo es
entsprechend weitergeleitet wird.
Ich habe eben z.B. mal versucht -ffunction-sections bzw. -fdata-sections
an avr-ld zu übergeben. Das wird mit einer Fehlermeldung quittiert:
> avr-ld: -f may not be used without -shared
All das lässt erhärtet meine zuvor in den Raum gestellte Vermutung nur.
Ich will dich hier keineswegs als anfänglichen "Idioten" abtun, der
nicht weiß wie die einzelnen Komponenten miteinander interagieren. Ganz
im Gegenteil: Du bist schon "etwas" länger dabei und ein weitaus
erfahrenerer Programmierer als ich es bin.
Ich versuche nur eine Erklärung für das Phänomen zu finden und stütze
mich dabei auf die Aussagen aus der Manpage. Zumindest in meinem Kopf
macht mein Erklärungsversuch auch Sinn, vielleicht liege ich aber auch
voll daneben.
Es kann auch gut sein, dass hier verschiedene Compilerversionen
unterschiedlich verhalten. Ich habe meine Experimente alle auf Basis von
avr-gcc 4.9.1 und avr-binutils 2.24 durchgeführt. Du warst, wenn ich das
jetzt richtig sehe bei 4.7.x als das Feature noch relativ neu war.
Vielleicht wurden da im Hintergrund ja noch Umbauarbeiten durchgeführt.
Ist mir jetzt zu mühselig den Changelog durchzugehen ;).
Frank M. schrieb:> Ich kann nichts dafür, dass die Manpage nicht stimmt, s.o. ;-)
Ich kann mir fast nicht vorstellen, dass wir Unstimmigkeiten in der
Manpage von gcc finden. Zumindest mir traue ich das nicht zu :).
Frank M. schrieb:>> [irmp_protocol_names]...>> Ja, und das wird ziemlich schnell ziemlich unleserlich, zumindest>> besonders intuitiv ist es nicht.>> Das liegt daran, dass zum einen die Strings im Flash liegen:
Das war auch überhaupt keine Kritik, sondern nur eine Beobachtung von
mir. Ich selbst mache es bei eigenen Projekten wie gesagt auch nicht
anders. Ist halt einfach eine Konsequenz der Harvard-Architektur und der
von uns verwendeten Werkzeuge (avr-gcc, avr-libc), die damit irgendwie
zurecht kommen müssen.
Mit freundlichen Grüßen,
Karol Babioch
Karol Babioch schrieb:> In irmp.c sollst du gar nicht herum werkeln. Das ist Franks Domäne ;).
da werkel ich auch nicht rum, einige Problemchen muss ich noch lösen,
aber durch das Gespräch mit euch beiden ist mir auf dem Heimweg
wenigstens ein uralter Fehler aufgefallen der historisch gewachsen ist !
klar kann ich i2c in der IRQ nutzen, aber nicht gleichzeitig in der main
loop, das ist erst später dazu gekommen, weswegen ich _i2c_busy (bei
start_i2c) eingefügt hatte, was logisch nicht hilft wenn die in der main
loop durch den IRQ unterbrochen wird.
Als ich die Arduino LIB wire.cpp untersuchte fand ich ähnliches, heisst
hier nur transmission, nur die VAR transmission wird auch nie benutzt,
habe jedenfalls nix gefunden
manchmal können andere zwar nicht sofort helfen, aber das Gespäch
darüber.
danke dafür !
Joachim B. schrieb:> aber durch das Gespräch mit euch beiden ist mir auf dem Heimweg> wenigstens ein uralter Fehler aufgefallen der historisch gewachsen ist !
So ist das, wenn man ab und an mal alles Revue passieren lässt. Ist mir
auch schon des öfteren untergekommen. Von Zeit zu Zeit lernt bzw. sieht
man auch immer mal wieder neue Programmiertechniken bzw. Muster, die man
dann sofort bei sich selbst umsetzen kann.
Joachim B. schrieb:> Als ich die Arduino LIB wire.cpp untersuchte fand ich ähnliches, heisst> hier nur transmission, nur die VAR transmission wird auch nie benutzt,> habe jedenfalls nix gefunden
Bin zwar kein absoluter Arduino Insider, aber immer, wenn ich mich damit
beschäftigt habe, bin ich zu dem Schluss gekommen, dass vieles in Bezug
auf das Interrupt-Handling ungünstig bzw. nicht gut gelöst ist. Die
meisten Einsteiger wissen vermutlich noch nicht einmal etwas über
interrupt-basierte Programmierung, jedenfalls lassen das die vielen
Spaghetticode-artigen Schnipsel vermuten, welche sämtliche Ereignisse
innerhalb von loop() verarbeiten.
Ich will das gar nicht zu einer Arduino Pro und Contro Diskussion werden
lassen, sondern dich nur darauf aufmerksam machen, dass das
Interrupt-Handling bei der Arduino Plattform nicht unbedingt das Maß
aller Dinge ist, und du dich definitiv auch hier im Forum, Wiki und der
Codesammlung umschauen solltest. Da findest du sicherlich mehr als genug
Inspiration für die richtige Konzeption und Behandlung von Interrupts.
Mit freundlichen Grüßen,
Karol Babioch
Hi Karol,
Karol Babioch schrieb:> Die Sorge teile ich nicht. Alles außer avr-gcc 4.9.1 ist alt ;). Ich> pflege allerdings auch keine Bibliothek wie IRMP ...
Eben. Wenn ich da nicht bis herunter zu 4.3.3 kompatibel bleibe,
schreien hier gewiss einige auf. Ich hatte schon mal die flto-Geschichte
ins AVR-Studio4-Projekt eingebaut (weil ich 4.7.2 benutze) und schon
kamen Beschwerden, man könne nicht mehr kompilieren.
> Es geht mir weniger um die Schreibweise, sondern wie man dann den> Zugriff auf Inhalte im Flash am Besten löst. Weiterhin mit jeweils zwei> Funktionen (jeweils eine mit *_P())", oder ggf. nur noch eine mit einem> zusätzliche Parameter in dessen Abhängigkeit man den Pointer> entsprechend zurecht castet.
Ich benutze in diversen Projekten immer einen weiteren Parameter, stelle
aber zusätzlich über Macros die _P-Funktionalität zur Verfügung, also
zum Beispiel:
>> Es ist mir egal, was die Manpage dazu sagt. ;-)>> Mir aber nicht. Gerade bei Projekten wie gcc ist die Manpage eigentlich> immer up to date und die Referenz.
Mein Smiley sollte andeuten, dass ich auch glaube, dass lediglich die
Manpage für Dich nicht stimmt, weil Du die richtige Stelle noch nicht
gefunden hast ;-)
Nein, Scherz. Ich glaube, wir missverstehen uns beide bzgl.
"Linker-Aufruf". Für mich ist dieses hier schon ein Linker-Aufruf:
gcc file1.o file2.o -o file.out
Es geht mir also immer um Flags, die an gcc (der ist weder Compiler noch
Linker, sondern ruft ja bekanntermaßen die entsprechenden Programme auf)
heruntergegeben werden.
Diverse Programmier-Umgebungen sehen das genauso. In AVRStudio4 zum
Beispiel werden die "Linker-Options" an avr-gcc beim Linken
heruntergegeben. Genauso läuft es auch in anderen IDEs.
> Das kann ich z.B. nicht nachvollziehen. Beim Kompilieren meiner Version> des Wordclock Projekts gewinne ich NUR durch das Zuschalten der LTO> beim Kompilieren (-flto beim Compiler) 1.5 kB. Die zusätzlichen Schalter> (-Os, -flto, -ffunction-sections, -fdata-sections) beim Linken hingegen> bringen keinen zusätzlichen Gewinn. Sogar -Wl,-gc-sections hat dann> keine Auswirkungen mehr, obwohl es ohne die -flto Option etwas bringt.
IRMP-Standard-Projekt (wie im SVN abgelegt) nur mit -Os (und diversen
anderen Standard-Optionen) als Compiler-Option:
Program: 2588 bytes (31.6% Full)
Data: 52 bytes (5.1% Full)
IRMP-Projekt zusätzlich mit Compiler-Optionen:
-flto
-ffunction-sections
-fdata-sections
und mit Linker-Optionen:
-flto
-ffunction-sections
-fdata-sections
-Wl,--gc-sections
Program: 3460 bytes (42.2% Full)
Data: 52 bytes (5.1% Full)
Das resultierende Programm wird also fast - wie vorausgesagt -
wesentlich größer!
Woran liegt das? Ganz einfach: Der Compiler wird beim Linkvorgang
nochmals aufgerufen. Wird hier kein Optimierungsflag angegeben, dann
wird das Resultat einfach ganz schlecht.
Nun noch zusätzlich als Linker-Option -Os:
Ergebnis:
Program: 2556 bytes (31.2% Full)
Data: 52 bytes (5.1% Full)
Das Programm ist also um 32 Byte kleiner geworden als die
NICHT-FLTO-Version.
Woran liegt das? Es liegt genau daran, was ich vor ein paar Tagen
beschrieben habe. Es können jede Menge PUSH/POP-Befehle vermieden
werden, die vom Compiler eingebaut werden, wenn eine externe Funktion
von einer ISR-aufgerufen wird.
Genau das ist der Übeltäter:
1
ISR(COMPA_VECT)
2
{
3
(void)irmp_ISR();
4
}
Bei -flto wird irmp_ISR sozusagen inlined und die überzähligen
PUSH/POP-Befehle können entfallen. Dadurch wird die ISR auch ein wenig
schneller. Nichts anderes habe ich hier behauptet, als ich auf diese Art
der Optimierung hier hinwies.
> Frank M. schrieb:>> Erst mit dem Linker-Flag -Os funktioniert die flto-Optimierung, d.h. der>> gcc behandelt externe Funktionen wie static Funktionen.>> Nein, das funktioniert bei mir auch ohne -flto beim Linken.
Siehe oben. Ich habe andere Erfahrungen gemacht und kann sie auch bei so
ziemlich jedem Projekt mit Zahlen belegen. Irgendwas machst Du falsch.
;-)
> Also mein finaler Aufruf zum Linken sieht so aus:>>
Da fehlt ja schon das -flto. Baue das mit rein und Du wirst sehen, dass
das Ergebnis größer als vorher wird. Im zweiten Schritt noch -Os und Du
hast endlich den Gewinn.
> Ich vermute (!), dass intern automatisch erkannt wird, in welcher Form> die Objekte generiert worden sind.
Ich nicht. Es fehlt das -flto beim obigen Aufruf. Erst danach können wir
darüber nochmal reden ;-)
> So ausführlich wie es mir gerne gewünscht hätte, ist das aber gar nicht.
Für mich hat es zum Verständnis gereicht.
> Aber zumindest in deinem Fall scheint es ja Abhilfe geschafft zu haben.
Nicht nur in diesem Fall. Wie Du am IRMP-Projekt siehst, gibt es hier
auch einen - wenn auch kleinen, aber nachvollziehbaren - Gewinn. Beim
WordClock-Projekt sollte das noch Ergebnis wesentlich besser sein.
> Leider konnte ich aber das Kommando des finalen Linkens nicht entdecken.
Johann hat es in dem von mir angeführten Thread beschrieben, wie man
sich die internen Programm-Aufrufe des gcc anschauen kann.
Zitat:
"Um die Aufrufe zu sehen, kann man z.B. -v -Wl,-v angeben."
> Sicher, dass du das nicht auch über avr-gcc gemacht hast und damit das> Kommando nicht doch an den Compiler bzw. das avr-gcc übergeben hast ;)?
Ja, natürlich über avr-gcc, wer ruft denn schon den nativen Linker
auf?!?
> Wie bei mir oben schön zu sehen, ruft man i.d.R. ja nicht den Linker> (avr-ld) selbst auf, sondern erledigt dies über avr-gcc, wo es> entsprechend weitergeleitet wird.
Ja. Schau es Dir mit obigen Optionen mal genauer an.
> Ich habe eben z.B. mal versucht -ffunction-sections bzw. -fdata-sections> an avr-ld zu übergeben. Das wird mit einer Fehlermeldung quittiert:>>> avr-ld: -f may not be used without -shared>> All das lässt erhärtet meine zuvor in den Raum gestellte Vermutung nur.> Ich will dich hier keineswegs als anfänglichen "Idioten" abtun, [...]
Wie gesagt: Wenn ich von "Linker-Optionen" spreche, meine ich die Flags,
die dem avr-gcc beim Linken heruntergegeben werden. So macht es (fast)
jede IDE der Welt, sogar "Microsoft Visual C++". Keiner ruft den nativen
ld direkt auf.
So, ich hoffe, damit ist dieses Missverständnis eindeutig geklärt.
> Es kann auch gut sein, dass hier verschiedene Compilerversionen> unterschiedlich verhalten. Ich habe meine Experimente alle auf Basis von> avr-gcc 4.9.1 und avr-binutils 2.24 durchgeführt. Du warst, wenn ich das> jetzt richtig sehe bei 4.7.x als das Feature noch relativ neu war.> Vielleicht wurden da im Hintergrund ja noch Umbauarbeiten durchgeführt.> Ist mir jetzt zu mühselig den Changelog durchzugehen ;).
Ich vermute eher, dass es bzgl. LTO keine grundlegenden Unterschiede
zwischen 4.7.2 und 4.9.1 gibt. Gib das -flto zusammen mit dem -Os
einfach auch beim Linken runter und Du wirst Dich freuen.
Übrigens: Die von mir zitierten sections-Optionen haben nicht direkt was
mit -flto zu tun, sondern eliminieren nicht benutzte Funktionen aus
externen C-Modulen. So kann man ein großes Objekt-File mit
zig-Funktionen dazulinken, wovon ich vielleicht nur 2 Funktionen
brauche. Die nicht benutzten 98 anderen Funktionen werden dann
wegoptimiert - genau, das was ich mir damals als zweiten Vorteil
gegenüber "Include-Libs" erhoffte.
Ich hoffe, damit ist die Sache nun umfassend geklärt. Ich bin jetzt nur
noch gespannt auf Deine Zahlen bzgl. -flto -Os und WordClock-Projekt.
:-)
Joachim B. schrieb:> die Arduino IDE macht mich wahnsinnig, wie schön ging das im AVR Studio4
Ich benutze teilweise auch Arduino-Boards, weil ich zu faul zum Löten
bin. Das erste, was ich mache: Ich schmeiße den Arduino-Bootloader raus
und programmiere den ATmega auf klassische Art und Weise. Also ohne
Arduino-IDE.
> aber auf Platinen löten und immer wieder AVRisp mk2 (clone) progger> kaufen fehlt das Geld und die Lust (Zeit).....
Du bekommst einen ISP-Programmer für 15 EUR, z.B. bei myAVR.de. Mit dem
entsprechenden Arduino-Board (mit ISP-Stecker) klappt das dann schon.
Frank M. schrieb:> Du bekommst einen ISP-Programmer für 15 EUR, z.B. bei myAVR.de.
ich hatte 2 billige China clones gekauft, die haben die gleiche
Seriennummer und können nicht zusammen am PC genutzt werden, manchmal
verweigern sie auch die Mitarbeit, mit dem echten AVR ISP Mk2clone und
mit meinem USB im Stick design USB prog v2 von Sauter, aber den gibt es
nicht mehr, ist mir das nie passiert . Ich hätte gerne mehr davon, aber
der ist nun bei der 3ten Version so riesig.....
um mich mit den Eigenheiten der Bootloader zu beschäftigen fehlt mir
noch das Wissen und die Zeit, mit jedem Schritt den ich vorwärts komme
tun sich immer wieder neue Fragen auf und dann wechseln die Versionen
was wieder neue Fragen aufwirft. Komme mir manchmal vor wie im
Wettrennen zwischen Hase und Igel
Ich habe die Download-Versionen von IRMP:
http://www.mikrocontroller.net/articles/IRMP#Download
und IRSND:
http://www.mikrocontroller.net/articles/IRMP#Download_IRSND
vom Februar diesen Jahres nun auf denselben Stand gebracht, den man auch
momentan im SVN vorfindet.
Das heisst: Die obigen Links enthalten nun folgende Versionen:
IRMP V2.6.6 vom 18.09.2014
IRSND V2.6.4 vom 15.09.2014
Zukünftig versuche ich, die Synchronisierungs-Intervalle kürzer zu
halten.
Viele Grüße,
Frank
Frank M. schrieb:> Ich benutze in diversen Projekten immer einen weiteren Parameter, stelle> aber zusätzlich über Macros die _P-Funktionalität zur Verfügung
Ok, das macht wahrscheinlich am meisten Sinn und ist ein guter
Kompromiss aus "einmal implementieren" und der Gewohnheit der *_P()
Funktionen. Nutzt du innerhalb der eigentlichen Funktionen dann schon
das __flash Attribut?
Frank M. schrieb:> Ich glaube, wir missverstehen uns beide bzgl.> "Linker-Aufruf".
Ja, das erklärt wohl einiges ;). Gut, dass du mitdenkst, ich hab das
vollständig ausgeblendet. Damit erklärt sich auch die Diskrepanz in der
Auslegung der Manpage, da das meiste sich ja auf avr-gcc und nicht
avr-ld bezieht und es die entsprechenden Optionen dort gibt.
Frank M. schrieb:> Das resultierende Programm wird also fast - wie vorausgesagt -> wesentlich größer!
Zumindest das kann ich aber hier nicht reproduzieren. Um es zu
vereinfachen, beziehe ich mich im Folgenden auf Revision 148 aus dem
IRMP Repository und builde das Ganze komplett manuell:
Also im Vergleich zu davor keine Verbesserung.
Hier nun das Resultat, wenn ich ohne -flto kompiliere und linke (andere
übliche Optionen sind nach wie vor aktiviert).
Bei mir reicht also das reine Kompilieren mit der -flto Option, um Platz
zu sparen. Beim Linken muss ich das nicht nochmal angeben.
Übrigens: Bei mir ist der Gewinn insgesamt 40 Byte groß. Außerdem sind
meine Binaries kleiner. avr-gcc 4.9.x generiert anscheinend besseren
Code ;).
Frank M. schrieb:> Da fehlt ja schon das -flto. Baue das mit rein und Du wirst sehen, dass> das Ergebnis größer als vorher wird. Im zweiten Schritt noch -Os und Du> hast endlich den Gewinn.
Ok, da hatte ich wohl den falschen Ausschnitt kopiert. Aber wie auch
schon beim IRMP Beispiel ändert sich an der Größe nichts, auch nicht mit
diesen Optionen beim Linken:
Fazit: Zumindest bei mir braucht es -flto nur beim Kompilieren. Dort
bringt es auch einen enormen Größengewinn (wobei das natürlich von den
Quellen und deren Abhängigkeiten untereinander abhängt).
Frank M. schrieb:> Übrigens: Die von mir zitierten sections-Optionen haben nicht direkt was> mit -flto zu tun, sondern eliminieren nicht benutzte Funktionen aus> externen C-Modulen.
Ja. Diese Optionen werden ja auch im Wiki und an diversen anderen
Stellen vorgeschlagen bzw. erklärt.
Frank M. schrieb:> Ich hoffe, damit ist die Sache nun umfassend geklärt.
Zumindest teilweise. Reproduzieren kann ich den Größenzuwachs bzw. die
Notwendigkeit die Optionen nochmals anzugeben nach wie vor nicht.
Frank M. schrieb:> Ich bin jetzt nur> noch gespannt auf Deine Zahlen bzgl. -flto -Os und WordClock-Projekt.> :-)
Wie schon gesagt: Nur durch Zuschalten der -flto Option beim Kompilieren
gewinne ich bereits 1500 kB. -Os bzw. -flto beim Linken hingegen bringen
nichts mehr.
Mit freundlichen Grüßen,
Karol Babioch
Karol Babioch schrieb:> Wie schon gesagt: Nur durch Zuschalten der -flto Option beim Kompilieren> gewinne ich bereits 1500 kB.
1,5MB... Wow! :-)))
> -Os bzw. -flto beim Linken hingegen bringen nichts mehr.
Dann arbeitet 4.9.x doch anders als 4.7.x. Ich fand es damals schon
unverständlich, beim Linken eine Compiler-Option angeben zu müssen.
Vielleicht hat man dieses "Feature" ab 4.8.x oder 4.9.x doch besser
gelöst.
Ich habe es gerade nochmal mit avr-gcc 4.8.1 getestet: Das Verhalten ist
identisch zu 4.7.2. Das Ergebnis wird erheblich größer, wenn man -Os
beim Linken weglässt. Das Programm ist zwar insgesamt ein wenig kleiner,
aber ich benutzen den 4.8.1 nicht, weíl dieser den "misspelled signal
handler" bug hat, der doch ziemlich nervt.
Vielen Dank für Deine ausführlichen Infos. Vielleicht gehen wir ja beide
mit folgender Aussage konform:
Bei Verwendung von LTO muss für avr-gcc kleiner als 4.9.x die Option
-Os bei den Linker-Options zwingend angegeben werden, ab 4.9.x
nicht mehr.
Ich glaube, ich sollte mir auch den 4.9.1 besorgen....
Viele Grüße,
Frank
EDIT: Habe gerade sogar den 4.9.2 gefunden :-)
Gerade mit 4.9.2 getestet.
Programm normal: 2488
Programm mit -flto als Compiler- und Linker-Option: 3460
Programm mit -Os zusätzlich als Linker-Option: 2448
Also ich muss auch bei 4.9.2 das -Os angeben, damit ich 40 Byte
gewinne.
Ausschlaggebend ist das Kommando:
Wenn dort -Os fehlt, dann wird es 1KB größer.
EDIT:
Muss mich korrigieren (PATH war noch nicht angepasst): Es reicht nun
tatsächlich ein -flto als Compiler-Option. Ergebnis ist dann 2448.
Also:
Programm normal: 2488
Programm mit -flto als zusätzliche Compiler-Option: 2448
Programm mit -Os zusätzlich als Linker-Option: 2448
Nun ist die Welt wieder in Ordnung :-)
P.S.
40 Byte sind nicht soviel, aber in einer ISR schon.
Frank M. schrieb:> 1,5MB... Wow! :-)))
Meinte natürlich 1,5 kB ;).
Frank M. schrieb:> Bei Verwendung von LTO muss für avr-gcc kleiner als 4.9.x die Option> -Os bei den Linker-Options zwingend angegeben werden, ab 4.9.x> nicht mehr.
Ja, das scheint die Essenz unserer Experimente zu sein. Habe es mit
älteren Versionen aber nicht probiert.
Frank M. schrieb:> EDIT: Habe gerade sogar den 4.9.2 gefunden :-)
Diese Version gibt es offiziell noch gar nicht [1]. Wird laut [2] erst
im Oktober oder November veröffentlicht. Wirst wahrscheinlich irgendein
inoffiziellen Build haben - nehme ich an.
Bin aus Interesse heraus doch mal die Changelogs durchgegangen [3] [4]
[5]. Da wurde zwar einiges an der LTO verändert bzw. verbessert, aber
explizit erwähnt wird das neue Verhalten nicht.
Naja, was solls, letztendlich funktioniert es ja bei uns beiden - und
verhält sich bei gleicher Version auch gleich. Allerdings frage ich mich
gerade wo der Größenunterschied von 4 Byte herkommt? Meine Binary
scheint in beiden Fällen 4 Byte kleiner zu sein?
Hab es jetzt nochmal kompiliert und gelinkt:
Ich habe das Ergebnis zur avr-gcc-Optimierung bzgl. LTO nun in
IRMP-Artikel zusammengefasst:
http://www.mikrocontroller.net/wikisoftware/index.php?title=IRMP&action=submit#avr-gcc-Optimierungen
Damit sollte das Thema LTO nun erschöpfend behandelt zu sein. Die
Sections-Sache habe ich bewusst rausgenommen, das sie im Falle von IRMP
keine tragende Rolle spielt.
Dank an Karol für die doch ziemlich spannende Mitarbeit.
@Karol: Antwort zu Deinem letzten Posting folgt gleich.
Karol Babioch schrieb:> Diese Version gibt es offiziell noch gar nicht [1]. Wird laut [2] erst> im Oktober oder November veröffentlicht. Wirst wahrscheinlich irgendein> inoffiziellen Build haben - nehme ich an.
Habe ich direkt von
http://sourceforge.net/projects/mobilechessboar/files/avr-gcc%20snapshots%20%28Win32%29/
... also die Win32-Version.
> Bin aus Interesse heraus doch mal die Changelogs durchgegangen [3] [4]> [5]. Da wurde zwar einiges an der LTO verändert bzw. verbessert, aber> explizit erwähnt wird das neue Verhalten nicht.
Ja, ich habe auch nichts dazu gefunden. Es scheint so zu sein, dass die
Compiler-Optionen nun mit in der Objekt-Datei gespeichert werden. Anders
kann ich mir das nicht erklären.
> Meine Binary scheint in beiden Fällen 4 Byte kleiner zu sein?
Ja, ist mir auch aufgefallen :-)
> Hab es jetzt nochmal kompiliert und gelinkt:
Ich habe Deine Compiler-Optionen (z.B. c99 statt gnu99 und kein
gdwarf-2) mal im AVR-Studio - soweit es ging - an Deine angepasst.
Ergebnis:
Es bleibt bei einer Differenz von 4 Bytes. Kann aber auch daran liegen,
dass ich jetzt mit 4.9.2 und Du mit 4.9.1 getestet hast.
> Du hast in diesem Fall ja 2448. Ich hänge mal meine resultierende Binary> und das Mapfile mit an. Vielleicht kannst du ja gleiches tun bzw. dir> mal die Unterschiede ansehen?
Habe ich gemacht. Es ist aber schwierig, weil unter Windows die ganzen
Pfade anders sind und ein diff viel zu groß ist.
Ich habe es dann eingeschränkt unter Linux mittels:
Bleiben immer noch 325 Unterschiede, die aber hauptsächlich an der
unterschiedlichen Ausgeformatierung liegt, z.B.
1
< .bss 0x0000000000800104 0x30
2
< 0x0000000000800104 PROVIDE (__bss_start, .)
3
---
4
> .bss 0x00800104 0x30
5
> 0x00800104 PROVIDE (__bss_start, .)
Ich bin da mal mit dem bloßen Auge drüber gegangen und habe eigentlich
keinen signifikanten Unterschied feststellen können. Da ich auch nicht
weiß, ob die 4 Bytes wegen 4.9.2 vs. 4.9.1 entstanden sind, will ich da
auch gar nicht weiter suchen :-)
ELF-Dateien (als Binaries) sind schwer bis gar nicht zu vergleichen,
allein der Größen-Unterschied ist enorm:
-rwxr-xr-x 1 fm users 9764 2014-09-18 17:06 main.elf
Meine ist über 1KB größer. Warum... weiß der Teufel.
Ich habe sie dann mal mit avr-strip um die Symbols erleichtert. Dann
bleiben nur noch 2912 Bytes übrig.
Ich glaube, wir vergessen mal ganz schnell die 4 Bytes ;-)
> Im Übrigen: Danke für deine Geduld, bzw. dass du da überhaupt Interesse> dran hast. Hat ja mittlerweile nur noch ganz peripher mit IRMP zu tun> ;).
Ich bedanke mich ebenfalls. Hat Spaß gemacht! Und es ist immer wieder
befriedigend, wenn man die Phänomene schlussendlich doch erklären kann.
EDIT:
Mir ist gerade aufgefallen, dass ich beim letzten Test doch wieder -Os
als Linker-Flag drin hatte - siehe obiges Protokoll. Habs nun
rausgenommen. Size erhöht sich auf 3460 Bytes :-(
PATH ist korrekt gesetzt. Es wird definitiv die 4.9.2 benutzt.
Vielleicht ist das ein prinzipielles Problem bei der Windows-Version?
Ich habe jedenfalls den Artikel-Abschnitt zur avr-gcc-Optimierung
nochmal angepasst. Jetzt unterscheide ich nicht mehr zwischen 4.7.x und
4.9.x, sondern zwischen Windows und Linux, was avr-gcc angeht.
Frank M. schrieb:> Ich habe sie dann mal mit avr-strip um die Symbols erleichtert. Dann> bleiben nur noch 2912 Bytes übrig.>> Ich glaube, wir vergessen mal ganz schnell die 4 Bytes ;-)
Ich glaube ich habe zumindest dieses Rätsel gelöst: Wir verwenden
einfach unterschiedliche Versionen bzw. Darstellungsformen von avr-size
;). Bei mir muss man die Programm und Datensektion zusammenzählen, dann
kommt man auch auf 2448. Dafür ist meine bss Sektion nur 48 Byte groß,
während deine Datensektion 52 Byte groß ist, weil bss bei dir dort
gezählt wird. Letzendlich wahrscheinlich also doch der gleiche Inhalt.
Frank M. schrieb:> Und es ist immer wieder> befriedigend, wenn man die Phänomene schlussendlich doch erklären kann.
Ja, und in dem Fall hatten wir ja beide irgendwie recht bzw. unrecht ;).
Nur ganz gelöst ist es ja immer noch nicht :'(. Ich bin nochmal die
Manpage durchgegangen. Dort gibt es den folgenden Abschnitt:
> To use the link-time optimizer, -flto and optimization options should> be specified at compile time and during the final link. For example:>> gcc -c -O2 -flto foo.c> gcc -c -O2 -flto bar.c> gcc -o myprog -flto -O2 foo.o bar.o
Das scheint dir ja recht zu geben. Hier wird zwar nicht auf Codegröße
hin optimiert, aber der Satz darüber sagt ja, dass man
Optimierungsoptionen auch beim Linken angeben soll.
Die Frage ist also, warum es bei mir auch ohne funktioniert ;). Ich kann
ja nicht nur das "-Os" sondern auch das "-flto" beim Linken weglassen.
Du hingegen kannst das -flto weglassen, dafür das "-Os" aber nicht.
Wenn ich dein Protokoll oben richtig interpretiere, dann hast du zwar
mit -Os gelinkt, aber ohne "-Wl,--gc-sections". Ich hingegen habe ohne
"-Os" gelinkt, dafür aber mit "-Wl,--gc-sections". Kannst du das einfach
mal anders herum ausprobieren? Ich habe es zwar bei mir probiert, aber
es ist und bleibt bei 2444 bzw. 2448 Byte.
Frank M. schrieb:> Vielleicht ist das ein prinzipielles Problem bei der Windows-Version?
Kann natürlich sein, wobei ich solche Unterschiede dann durchaus als Bug
bezeichnen würde. Rein von der Manpage her ist dein Aufruf aber korrekt.
Keine Ahnung warum ich das beim ersten Lesen übersehen habe. Das hätte
uns ja die ganze Diskussion erspart. Andererseits hätten wir dieses
unterschiedliche Verhalten nicht entdeckt ;). Ich wollte mich ja
eigentlich an die avr-gcc ML wenden, aber die lachen uns wahrscheinlich
aus, wenn wir a.) verschiedene Versionen benutzen und b.) (leicht)
verschiedene Optionen beim Kompilieren bzw. Linken. Wir müssten also
zunächst einmal wirklich exakt das selbe ausführen. Bei dir sind ja
diverse Makefile und Depedency Optionen mit von der Partie, vielleicht
interagieren die ja ungünstig (unwarscheinlich?). Ist auch egal, ich
gebe mich geschlagen ;). Habe den Wiki-Artikel auch etwas angepasst,
weil die Unterscheidung nicht notwendig ist - zumindest laut Manpage.
Sich darauf zu verlassen, dass es auch ohne geht, wäre ja dann
undokumentiertes Verhalten. Das kann man wohl niemandem empfehlen ;).
Danke trotzdem für die viele Geduld bzw. das Interesse.
Mit freundlichen Grüßen,
Karol Babioch
Hi Karol,
Karol Babioch schrieb:> ;). Bei mir muss man die Programm und Datensektion zusammenzählen, dann> kommt man auch auf 2448. Dafür ist meine bss Sektion nur 48 Byte groß,> während deine Datensektion 52 Byte groß ist, weil bss bei dir dort> gezählt wird. Letzendlich wahrscheinlich also doch der gleiche Inhalt.
Gut beobachtet. Ja, wahrscheinlich liegts am avr-size.
>> To use the link-time optimizer, -flto and optimization options should>> be specified at compile time and during the final link.
Aha :-)
> Das scheint dir ja recht zu geben. Hier wird zwar nicht auf Codegröße> hin optimiert, aber der Satz darüber sagt ja, dass man> Optimierungsoptionen auch beim Linken angeben soll.
Ja, eben. Ich hab mir das ja nicht aus den Fingern gesaugt ;-)
> Die Frage ist also, warum es bei mir auch ohne funktioniert ;). Ich kann> ja nicht nur das "-Os" sondern auch das "-flto" beim Linken weglassen.> Du hingegen kannst das -flto weglassen, dafür das "-Os" aber nicht.
Wenn ich das -flto beim Linken weglasse, ist der LTO-Effekt komplett
weg.
> Wenn ich dein Protokoll oben richtig interpretiere, dann hast du zwar> mit -Os gelinkt, aber ohne "-Wl,--gc-sections". Ich hingegen habe ohne> "-Os" gelinkt, dafür aber mit "-Wl,--gc-sections". Kannst du das einfach> mal anders herum ausprobieren? Ich habe es zwar bei mir probiert, aber> es ist und bleibt bei 2444 bzw. 2448 Byte.
Habe ich eben anders herum probiert. Die section-Options haben keinerlei
Auswirkungen. Sie betreffen tatsächlich nur unbenutzte Funktionen, die
es bei IRMP allerdings nicht gibt.
> Kann natürlich sein, wobei ich solche Unterschiede dann durchaus als Bug> bezeichnen würde.
Ja.
> Ich wollte mich ja> eigentlich an die avr-gcc ML wenden, aber die lachen uns wahrscheinlich> aus, wenn wir a.) verschiedene Versionen benutzen und b.) (leicht)> verschiedene Optionen beim Kompilieren bzw. Linken.
Ja, leider. Vielleicht werde ich mir am Wochenende mal die Linux-Version
installieren.
> Habe den Wiki-Artikel auch etwas angepasst,
Danke dafür!
Gruß,
Frank
Hallo Frank,
danke für das Aufnehmen meiner Patche.
In irmp.c ist dir das #else verrutscht, ca. Zeile 743, da fehlt ein
Zeilenumbruch, bzw. er müßte vor statt hinter dem #else sein :-) .
Gruß, Jörg
Frank M. schrieb:> Sie betreffen tatsächlich nur unbenutzte Funktionen, die> es bei IRMP allerdings nicht gibt.
Gut, so genau kenne ich die IRMP Quellen nicht. Ist mir nur beim
Vergleich der Argumente aufgefallen.
Frank M. schrieb:> Ja, leider. Vielleicht werde ich mir am Wochenende mal die Linux-Version> installieren.
Habe mir auch schon überlegt, dass ich auf Version 4.7.x downgrade.
Erschien mir dann aber aufgrund der Abhängigkeiten zu anderen
Bibliotheken als zu viel Aufwand. Wäre zwar ein interessanter Vergleich,
aber eilt alles nicht. Werde mich ggf. vielleicht wirklich einfach mal
an die avr-gcc Mailing-Liste wenden.
Mit freundlichen Grüßen,
Karol Babioch
Hallo Jörg,
Jörg R. schrieb:> In irmp.c ist dir das #else verrutscht, ca. Zeile 743, da fehlt ein> Zeilenumbruch, bzw. er müßte vor statt hinter dem #else sein :-) .
Danke, habe es korrigiert, neu eingecheckt und auch eine neue
Download-Zip-Datei erstellt. So einen blöden Fehler wollte ich nicht in
der Download-Datei belassen.
Obwohl.... den avr-gcc hat es nicht gestört, dass da vor dem #if in
derselben Zeile noch C-Code war. Naja, schön ist es so oder so nicht.
Gruß,
Frank
Hallo Frank,
der Speicherbedarf für irmp_protocol_names lässt sich noch optimieren,
wenn man für jedes nicht aktivierte Protokoll einen Verweis auf
proto_unknown in die Tabelle einfügt und den eigentlichen Protokollnamen
spart. Ungefär so:
Hallo Frank,
ich habe hier folgenden Aufbau
AVR+IRSND --> AVR+IRMP
Auf beiden AVRs ist ausschließlich das SIEMENS-Protokoll einkompiliert.
Ich sende IR-Codes, die ich mal von einer SIEMENS-FB dekodiert habe. Der
Empfänger erkennt den Gerätecode nur manchmal richtig, meist jedoch
falsch. Auch wird teilweise RUWIDO erkannt.
Ich weiß, dass SIEMENS und RUWIDO ähnlich sind und viel Code teilen.
Wenn ich aber nur SIEMENS einkompiliert habe, sollte bitte niemals
RUWIDO erkannt werden.
Auch schleicht mich das Gefühl, dass die Erkennung von SIEMENS schon mal
besser war, so ungefähr bis rev 116/120.
Die Linux-Kommandozeilenversion dekodiert
IR-Data/Siemens-Gigaset-M740AV-15kHz.txt nach wie vor fehlerfrei. Aber
was nützt das, wenn es auf einem AVR nicht zuverlässig funktioniert.
Was können wir tun?
Hallo Frank,
ich teste z.Zt. die Callback-Funktion und das funktioniert auch so weit
(siehe Anlage). Was mir dabei allerdings auffällt ist, daß Du mit high
startest. Ein normales Protokoll startet aber doch immer mit dem
Übergang von low auf high. Kann ich daraus schließen, daß Deine Ausgabe
mit diesem Übergang startet und das low daher unmittelbar davor liegt?
Dann frage ich mich allerdings warum der Pin immer auf high steht, wenn
man kein Signal sendet.
Gruß Bruno
E. K. schrieb:> Auf beiden AVRs ist ausschließlich das SIEMENS-Protokoll einkompiliert.> Ich sende IR-Codes, die ich mal von einer SIEMENS-FB dekodiert habe. Der> Empfänger erkennt den Gerätecode nur manchmal richtig, meist jedoch> falsch. Auch wird teilweise RUWIDO erkannt.
Kannst Du mir ein paar Scans schicken?
Gruß,
Frank
Bruno M. schrieb:> ich teste z.Zt. die Callback-Funktion und das funktioniert auch so weit> (siehe Anlage). Was mir dabei allerdings auffällt ist, daß Du mit high> startest.
Was meinst Du damit? Dass die Callback-Funktion bei der ersten fallenden
Flanke nicht aufgerufen wird?
> Ein normales Protokoll startet aber doch immer mit dem> Übergang von low auf high.
Nein, der TSOP-Emüfänger ist High im Ruhezustand. Das Start-Bit beginnt
mit einer fallenden Flanke, also mit einem Übergang von High auf Low.
Gruß,
Frank
Frank M. schrieb:
> Nein, der TSOP-Emüfänger ist High im Ruhezustand. Das Start-Bit beginnt> mit einer fallenden Flanke, also mit einem Übergang von High auf Low.
Danke, wieder etwas gelernt!
Gruß Bruno
Hallo Frank,
auf Grund Deines Hinweises habe ich erst mal das Datenblatt des
Empfängers studiert und bestätigt bekommen, daß der Empfänger alle Bits
invertiert. Ich habe daher meine Anzeige ebenfalls invertiert um das
richtige Protokoll zu sehen. Daraus ergeben sich aber jetzt eine Reihe
anderer Fragen.
Ich fange mal mit dem NEC-Protokoll an.
UART Anzeige:
protocol: 0x02 = NEC address: 0xEB14 command: 0x0012 flags: 0x00
Bei der Callback-Ausgabe ist so weit alles richtig, mit 2 Ausnahmen.
- die Adresse wird mit 0x14 angezeigt, statt der 0xEB14.
- im Signal wird der Unterschied von 0 und 1 nicht durch die Pausenlänge
definiert, sondern durch die Pulslänge.
Wie erklärt sich das?
Gruß Bruno
Hallo Bruno,
Bruno M. schrieb:> auf Grund Deines Hinweises habe ich erst mal das Datenblatt des> Empfängers studiert und bestätigt bekommen, daß der Empfänger alle Bits> invertiert.
Freut mich :-)
> Ich habe daher meine Anzeige ebenfalls invertiert um das> richtige Protokoll zu sehen.
Ich sehe bei Dir im Bild als Start-Bit:
________________-------
Low High
Wenn Du mit
"Anzeige ebenfalls invertiert um das richtige Protokoll zu sehen"
meinst, dass es 1:1 den TSOP-Pegel zeigen soll: Ja, das ist genau das,
was vom TSOP kommt. Low = Puls, High = Pause.
> UART Anzeige:> protocol: 0x02 = NEC address: 0xEB14 command: 0x0012 flags: 0x00
Zur Adresse: Im Standard-NEC-Protokoll hat die Adresse nur 8 Bit. Danach
folgen dieselben 8 Bit aus Redundanzgründen nochmal - jedoch invertiert.
Im Extended-Protokoll wird die Adresse auf 16 Bit aufgezogen und die
Wiederholung als invertierte Bits entfällt.
IRMP interpretiert die Bits immer im NEC-Extended-Format - also mit 16
Bit als Adresse. Denn dann ist das NEC-Standard-Format nur noch ein
Spezialfall des Extended Formats und IRMP kann alle möglichen
NEC-Adressen - egal, ob Standard oder Extended - eindeutig abbilden.
Jetzt schreiben wir mal 0xEB14 mal als Bits:
1110 1011 0001 0100
--------- ---------
EB 14
Fällt Dir was auf? Die zweite 8er Gruppe enthält genau die zur ersten
Gruppe enthaltenen Bits mit invertiertem Inhalt. Es handelt sich also um
NEC-Standard-Format. Die Adresse wäre dann 0x14.
Aber wie ich eben schon sagte: IRMP speichert die Adresse immer im
Extended-Format, um eben NEC-Signale, welche im Extended-Format gesandt
werden, auch eindeutig abbilden zu können.
Also ist die Adresse 0xEB14. Jetzt schreiben wir mal die Adress-Bits in
umgekehrter Reihenfolge hin:
0010 1000 1101 0111
Grund: Da bei NEC das Least Significant Bit (LSB) als erstes ausgesandt
wird, müssen wir das hier umdrehen. Jetzt schau mal auf Dein Foto. Exakt
diese Bitfolge findest Du dort wieder.
Das Kommando beim NEC-Protokoll besteht immer nur aus 8 Bit, gefolgt von
invertierten 8 Bit. Hier gibt es kein "extended" Format.
0x12 = 0001 0010
Rückwärts geschrieben:
0100 1000
Genau diese Folge siehst Du auch im Bild als drittes Oktett.
Als letztes kommen dann noch die 8 invertierten Bits: 1011 0111
Passt alles haargenau.
> - die Adresse wird mit 0x14 angezeigt, statt der 0xEB14.
Erklärung siehe oben. 0x14 ist die Standard-Adresse, 0xEB14 ist die
Extended-Adresse.
> - im Signal wird der Unterschied von 0 und 1 nicht durch die Pausenlänge> definiert, sondern durch die Pulslänge.
Da Du im Bild die TSOP-Pegel 1:1 zeigst, gilt:
Low = Puls
High = Pause
Die Pulse sind im Bild immer gleich lang, die Pausen sind verschieden.
Daher kann ich Deine Folgerung nicht nachvollziehen.
Gruß,
Frank
Hallo Frank,
eigentlich wollte ich nicht das TSOP Signal darstellen, sondern das
Protokoll.
Ich hatte aus Deinen ersten Antworten geschlossen, daß von Callback das
TSOP Signal abgebildet wird. Das war aber anscheinend ein Trugschluß.
Meine erste Frage war ja:
> Was mir dabei allerdings auffällt ist, daß Du mit high> startest. Ein normales Protokoll startet aber doch immer mit dem> Übergang von low auf high. Kann ich daraus schließen, daß Deine Ausgabe> mit diesem Übergang startet und das low daher unmittelbar davor liegt?> Dann frage ich mich allerdings warum der Pin immer auf high steht, wenn> man kein Signal sendet.
Ich muß also jetzt davon ausgehen, daß meine Vermutung richtig war und
die Callback-Funktion mit dem ersten high startet. Das macht natürlich
auch Sinn, da man ja einen Auslöser für die Funktion braucht und das ist
dann der erste low-high Übergang. Die Frage warum der Pin immer auf high
steht, ist dann aber noch nicht beantwortet.
Deine Erklärung zu NEC und extended NEC leuchtet ein.
Gruß Bruno
Bruno M. schrieb:> eigentlich wollte ich nicht das TSOP Signal darstellen, sondern das> Protokoll.
Wo ist der Unterschied? Ein TSOP filtert die Modulationsfrequenz bereits
und gibt Low für einen modulierten Puls und High für eine Pause aus.
> Ich hatte aus Deinen ersten Antworten geschlossen, daß von Callback das> TSOP Signal abgebildet wird. Das war aber anscheinend ein Trugschluß.
Auszug aus irmp.c:
1
#if IRMP_USE_CALLBACK == 1
2
if(irmp_callback_ptr)
3
{
4
staticuint8_tlast_inverted_input;
5
6
if(last_inverted_input!=!irmp_input)
7
{
8
(*irmp_callback_ptr)(!irmp_input);
9
last_inverted_input=!irmp_input;
10
}
11
}
12
#endif // IRMP_USE_CALLBACK == 1
Die Callback-Funktion wird daher immer dann aufgerufen, wenn sich der
Pegel zum letzten Zeitpunkt ändert, also beim Wechsel High-->Low und
Low-->High. Als Argument wird der augenblickliche Pegel am TSOP
übergeben.
Also eigentlich kannst Du auch direkt den Pegel am TSOP darstellen statt
über eine Callback-Funktion den Pegel wieder auszugeben, um diesen dann
anzuzapfen. Dieser hinkt dem TSOP-Pegel nur minimal nach.
> Ich muß also jetzt davon ausgehen, daß meine Vermutung richtig war und> die Callback-Funktion mit dem ersten high startet.
Immer, wenn der Pegel wechselt. Da eine static-Variable wie
last_inverted_input automatisch vom Compiler mit 0 initialisiert wird
und der Ruhezustand des TSOP High ist, wird die Bedingung
last_inverted_input != !irmp_input
erst TRUE, wenn irmp_input nach 0 springt, denn dann ist:
0 != !0
--> 0 != 1
Also bleibe ich dabei: Die Callback-Funktion wird beim ersten Mal
aufgerufen, nachdem der Pegel auf Low gesprungen ist, also wenn Du einen
Knopf an der FB drückst.
> Das macht natürlich> auch Sinn, da man ja einen Auslöser für die Funktion braucht und das ist> dann der erste low-high Übergang.
Nein, jeder Wechsel des Pegels ruft die Callback-Funktion auf. Wie
auch im IRMP-Artikel erwähnt, dient die Callback-Funktion lediglich
Visualisierungszwecken - z.B. zur Ausgabe mittels LED. Sie ist optional,
also für IRMP absolut nicht lebensnotwendig.
> Die Frage warum der Pin immer auf high> steht, ist dann aber noch nicht beantwortet.
Welcher Pin ist immer auf High? Ich verstehe leider nicht, was Du
meinst.
Gruß,
Frank
Frank M. schrieb:
> Wo ist der Unterschied? Ein TSOP filtert die Modulationsfrequenz bereits> und gibt Low für einen modulierten Puls und High für eine Pause aus.
Ich glaube wir reden etwas aneinander vorbei! Natürlich macht es keinen
Unterschied ob ich das TSOP nehme oder das Protokoll. Für mich ist es
nur eine Frage der Darstellung. Protokolle werden immer mit Licht an =
high und Licht aus = low dargestellt. Und genau so wollte ich es auf
meinem LCD darstellen. TSOP ist dagegen invertiert.
>> Das macht natürlich>> auch Sinn, da man ja einen Auslöser für die Funktion braucht und das ist>> dann der erste low-high Übergang.>> Nein, jeder Wechsel des Pegels ruft die Callback-Funktion auf.
Auch damit hast Du natürlich recht. Wenn ich das aber optisch darstellen
will, dann muß ich warten bis die Fernsteuerung betätigt wird (also ein
Übergang stattfindet), der dann wiederum Auslöser für die Anzeige ist.
> Welcher Pin ist immer auf High? Ich verstehe leider nicht, was Du> meinst.
Der Pin mit dem Callback ausgegeben wird steht in Ruheposition immer auf
high. Inzwischen habe ich aber den Verursacher unseres
Mißverständnissses gefunden! Der Fehler lag in der Ansteuerung meines
LCDs. Ich habe ein low-Signal immer als high ausgegeben und umgekehrt.
Sorry für die Verwirrung;-)
Gruß Bruno
Aus Interesse heraus traue ich mich jetzt einfach mal zu fragen: Wozu
will man den Signalverlauf auf einem LCD-Display anzeigen? Klar, fürs
Debugging bzw. zu Lehrzwecken mag das Sinn machen (wobei Oszilloskop
bzw. Logic-Anaylzer wahrscheinlich nützlicher sind), aber gibt es auch
eine praktische Anwendung hierfür?
Mit freundlichen Grüßen,
Karol Babioch
Bruno M. schrieb:> Protokolle werden immer mit Licht an = high und Licht aus = low> dargestellt.
Naja, ich habe schon beides im Netz gesehen.
Gerade in der Elektronik wird oft Low = Aktiv, High = Inaktiv verwendet,
z.B. bei /CS, /OE, /STROBE und anderen Steuersignalen. Das gleiche gilt
auch für Ausgänge, z.B. bei Open Collector.
> Inzwischen habe ich aber den Verursacher unseres> Mißverständnissses gefunden! Der Fehler lag in der Ansteuerung meines> LCDs. Ich habe ein low-Signal immer als high ausgegeben und umgekehrt.
Gut, dann ist ja jetzt alles klar. :-)
Karol Babioch schrieb:
> Aus Interesse heraus traue ich mich jetzt einfach mal zu fragen:> Wozu> will man den Signalverlauf auf einem LCD-Display anzeigen? Klar, fürs> Debugging bzw. zu Lehrzwecken mag das Sinn machen (wobei Oszilloskop> bzw. Logic-Anaylzer wahrscheinlich nützlicher sind), aber gibt es auch> eine praktische Anwendung hierfür?
Warum steigen manche Leute auf einen Berg;-)
Einfach aus Interesse und weil ichs kann. Oszi bzw. LA würde ich
wahrscheinlich nutzen, wenn ich ein Speichergerät hätte.
Frank M. schrieb:
> Gut, dann ist ja jetzt alles klar. :-)
Ich habe mir jetzt 4 Protokolle angesehen und damit ist es auch gut.
Allerdings sind dabei noch 2 Fragen aufgetaucht.
KASEIKYO: Der Herstellercode paßt, aber das Kommando wird mit 0x90A0 =
0b1001000010100000 angezeigt. Das kann ich nicht nachvollziehen.
RC5: Herstellercode paßt, aber das Kommando wird mit 0x57 = 0b1010111
angezeigt. Das wären ja schon 7 Bits!
Gruß Bruno
Bruno M. schrieb:> KASEIKYO: Der Herstellercode paßt, aber das Kommando wird mit 0x90A0 => 0b1001000010100000 angezeigt. Das kann ich nicht nachvollziehen.>> RC5: Herstellercode paßt, aber das Kommando wird mit 0x57 = 0b1010111> angezeigt. Das wären ja schon 7 Bits!
ja das war doch irgendwie der Trick vom Frank, er meinte mal das
Kaseikyo hat 48 Bit, wie er das in 16 Bit gequetscht hat interessiert
mich auch noch mal....
Bruno M. schrieb:> KASEIKYO: Der Herstellercode paßt, aber das Kommando wird mit 0x90A0 => 0b1001000010100000 angezeigt. Das kann ich nicht nachvollziehen.
Die Daten des Frames:
16 Hersteller-Bits + 4 Parity-Bits + 4 Genre1-Bits + 4 Genre2-Bits + 10
Kommando-Bits + 2 ID-Bits + 8 Parity-Bits
Die 16 Hersteller-Bits werden in der Adresse gespeichert.
IRMP prüft zwar die Parity-Bits auf Validität, aber speichert sie nicht
im Kommando. Grund: sie sind überflüssig, selbst IRSND kann sie fürs
Senden wieder aus den IRMP-Daten reproduzieren.
Dann bleiben übrig:
4 Genre1-Bits + 4 Genre2-Bits + 10 Kommando-Bits + 2 ID-Bits
Wenn man das zusammenzählt, kommt man auf 20 Bit. Wir haben aber nur 16
Bit Platz in irmp_data.command.
IRMP benutzt hier einen Kunstgriff: Da die 4 Genre2-Bits meist 0 sind,
werden diese im oberen Nibble von irmp_data.flags gespeichert. Du musst
also eigentlich die oberen 4 Bit von flags bei Vergleichen etc. mit
berücksichtigen. Aber das ist in der Praxis kaum relevant, da in 9 von
10 Fällen díe Genre2-Bits bei Kaseikyo sowieso 0 sind.
Ich gebe zu, dass ich das im Artikel nicht beschrieben habe. In diesem
Thread wurde das Thema vor einigen Jahren ausführlicher behandelt.
Übrigens: IRSND berücksichtigt beim Senden diese 4 Bits aus flags, d.h.
der Genre2-Code wird wieder in den Frame "eingebaut".
Die Arbeit, die 0en und 1en aus Deinem Bild mit dem oben beschriebenen
Muster abzugleichen, möchte ich mir jetzt nicht machen. Dafür ist mir
meine Zeit zu schade. Aber ich bin mir sicher, dass Du alle Bits
wiederfinden wirst ;-)
> RC5: Herstellercode paßt, aber das Kommando wird mit 0x57 = 0b1010111> angezeigt. Das wären ja schon 7 Bits!
RC5-Frame: (siehe Artikel: Die Protokolle im Detail):
2 Start-Bits + 12 Daten-Bits + 0 Stop-Bits
RC5-Daten:
1 Toggle-Bit + 5 Adress-Bits + 6 Kommando-Bits
Philips kam irgendwann auf den Trichter, dass Ihnen die 6 Kommando-Bits
nicht mehr reichen. Denn damit kann man nur 2 hoch 6 = 64 verschiedene
Kommandos unterscheiden. So kamen sie dann auf die glorreiche Idee, das
2. Start-Bit (was bisher immer 1 war) zu einem Kommando-Bit
umzufunktionieren.
RC5x-Frame:
1 Start-Bit + 13 Daten-Bits + 0 Stop-Bit
RC5x-Daten:
1 invertiertes Kommando-Bit + 1 Toggle-Bit + 5 Adress-Bits
+ 6 Kommando-Bits
Um dies kompatibel zum alten RC5-Frame zu halten, wurde dieses
zusätzliche Kommando-Bit invertiert. D.h. man findet die uralten
6-Bit-Kommando-Codes in den 7-Bit-Kommando-Codes sehr einfach wieder,
denn sie sind identisch. Bei einem 6-Bit-Code ist das 7. Bit Null. Wenn
Du das invertierst, kommt 1 raus. Und dieses hat denselben Wert wie das
2. Start-Bit eines RC5-Frames.
Wenn also das 7. Kommando-Bit als 2. Start-Bit geschickt wird, kann
sogar ein RC5-Empfänger zumindest die Hälfte der Kommandos (das heisst:
alle 64 vom alten RC5!) von einer neueren RC5x-Fernbedienung verstehen.
Ziemlich pfiffig eigentlich.
Die Anzahl der Bits sind beim RC5x-Frame (RC5x: lies "RC5-Extended")
also gleich, aber sie haben ein zusätzliches Daten-Bit (konkret:
Kommando-Bit) "erfunden".
Da hast Du nun das mysteriöse 7. Bit. Deine Fernbedienung spricht damit
RC5x. Das 2. Start-Bit ist also hier 0 statt 1. Alles klar? :-)
Wie Du siehst, wurden in der Vergangenheit immer wieder IR-Protokolle
aufgebohrt, z.B. NEC -> NEC-Extended, RC5 -> RC5x. Ich habe diese im
IRMP-Artikel auch aufgeführt, muss aber zugeben, dass die Hintergründe
(Zugewinn an Informationsmenge wegen vorherigem Mangel) und die
Techniken (s.o.) dazu nicht beschrieben sind. Wenn Du möchtest, kannst
Du das aber gerne nachholen ;-)
Frank M. schrieb:
> Alles klar? :-)
Super!! Herzlichen Dank.
Ich habe mir natürlich die Mühe gemacht und meine KASEIKYO-Ausgabe mit
Deinen Infos abzugleichen. Es paßt wenn ich es so anordne:
1001000010100000 = 1001 + 00 + 0010100000
d.h. 4 Genre1-Bits + 2 ID-Bits+ 10 Kommando-Bits
Gruß Bruno
Bruno M. schrieb:> Ich habe mir natürlich die Mühe gemacht und meine KASEIKYO-Ausgabe mit> Deinen Infos abzugleichen. Es paßt wenn ich es so anordne:>> 1001000010100000 = 1001 + 00 + 0010100000>> d.h. 4 Genre1-Bits + 2 ID-Bits+ 10 Kommando-Bits
Hm, das sollte eigentlich eher:
4 Genre1-Bits + 10 Kommando-Bits + 2 ID-Bits
sein. Kann aber auch sein, dass ich mich irre.
Da IRSND die gespeicherten IRMP-Daten einwandfrei wiedergeben kann (d.h.
IRMP versteht IRSND) und auch die Kaseikyo-Endgeräte die IRSND-Kommandos
allesamt korrekt ausführen, bin ich mir sicher, dass IRMP das schon
richtig macht ;-)
Ich versuche aktuell IRMP mit 2 TSOP4838 zu betreiben, dazu gibt es
prinzipiell 2 Möglichkeiten:
a) Beide TSOPs an einem Input Pin. Das funktioniert sogar, beide TSOPs
gehen, auch im "Doppelbetrieb" gibts keine Probleme. Ist aber unschön.
Oder ist das durchaus so lösbar?
b) Beide TSOPs an jeweils einen Input Pin und IRMP das ganze
softwaremäßig beibringen, wenn möglich mit nur einem Timer.
Ich hab daher die Pin Definitionen verdoppelt und die ISR Routine
dahingehend angepasst, das geprüft wird, ob sich die Werte von TSOP1
oder TSOP2 verändert haben und dann einfach den Wert als neuen
"irmp_input" zu nehmen, egal ob er von TSOP1 oder 2 stammt.
Das tut aber gar nicht, TSOP1 tut, aber TSOP2 löst nichts aus.
Gibt es einen einfacheren Weg als die halbe Lib umzuschreiben? Sehe ich
vllt. Alternativen nicht?
Hat hier jemand einen Rat?
Preisfrage schrieb:> Ich versuche aktuell IRMP mit 2 TSOP4838 zu betreiben, dazu gibt es> prinzipiell 2 Möglichkeiten:>> a) Beide TSOPs an einem Input Pin. Das funktioniert sogar, beide TSOPs> gehen, auch im "Doppelbetrieb" gibts keine Probleme. Ist aber unschön.> Oder ist das durchaus so lösbar?
Das funktioniert deshalb, weil die TSOPs einen Open-Collector-Ausgang
mit eingebautem Pullup haben. Es ist deshalb kein Problem, beide TSOPs
parallel an einem Pin zu betreiben.
> b) Beide TSOPs an jeweils einen Input Pin und IRMP das ganze> softwaremäßig beibringen, wenn möglich mit nur einem Timer.> Ich hab daher die Pin Definitionen verdoppelt und die ISR Routine> dahingehend angepasst, das geprüft wird, ob sich die Werte von TSOP1> oder TSOP2 verändert haben und dann einfach den Wert als neuen> "irmp_input" zu nehmen, egal ob er von TSOP1 oder 2 stammt.> Das tut aber gar nicht, TSOP1 tut, aber TSOP2 löst nichts aus.
Zeig mal Deine Änderung. Wenn beide Pins am gleichen Port hängen,
reicht eigentlich die Änderung des input-Makros, nämlich
Alt (in irmp.h):
1
# define input(x) ((x) & (1 << IRMP_BIT))
Neu:
1
# define IRMP_BIT2 3 // Bit 3 am Port, hier anpassen!
> Gibt es einen einfacheren Weg als die halbe Lib umzuschreiben?
Naja, ich würde diese klitzekleine Änderung nicht unbedingt "halbe Lib
umschreiben" nennen ;-)
Frank M. schrieb:> # define input(x) ((x) & (1 << IRMP_BIT) & (1 << IRMP_BIT2))
versaut dir die möglicherweise zeitliche Differenz nicht dein knappes
Protokolltiming ? (wenn die beiden das selbe optische Signal empfangen
-können- bei gleicher Ausrichtung)
Es wurde schon mal erwähnt das Siemens und Ruwido so dicht liegen das es
zu Fehlerkennungen kommt.
Joachim B. schrieb:> Frank M. schrieb:>> # define input(x) ((x) & (1 << IRMP_BIT) & (1 << IRMP_BIT2))
Ich hatte das Makro nochmal nacheditiert, siehe oben. So ist das nicht
ganz korrekt. Du warst zu schnell beim Zitieren :-)
> versaut dir die möglicherweise zeitliche Differenz nicht dein knappes> Protokolltiming ? (wenn die beiden das selbe optische Signal empfangen> -können- bei gleicher Ausrichtung)
Das glaube ich nicht. Was meinst Du, wie groß diese zeitliche Differenz
denn maximal werden könnte? IRMP hat bei 15kHz lediglich eine zeitliche
Auflösung 66µsec.
> Es wurde schon mal erwähnt das Siemens und Ruwido so dicht liegen das es> zu Fehlerkennungen kommt.
Ja, das ist aber erstens ein exotischer Spezialfall und zweitens glaube
ich nicht, dass das Signal wesentlich verschliffen wird.
P.S.
Ich warte immer noch auf die Scans von E.K. Dann kann ich schauen, wie
ich Siemens und Ruwido ordentlich auseinanderfieseln kann.
Preisfrage schrieb:> Ich versuche aktuell IRMP mit 2 TSOP4838 zu betreiben
Wofür brauchst Du das? Um den Empfangswinkel zu vergrößern (z.B. Vor-
und Rückseite am Empfänger)?
Frank M. schrieb:> Zeig mal Deine Änderung. Wenn beide Pins am gleichen Port hängen,> reicht eigentlich die Änderung des input-Makros, nämlich>> Alt (in irmp.h):> # define input(x) ((x) & (1 << IRMP_BIT))>> Neu:> # define IRMP_BIT2 3 // Bit 3 am Port, hier anpassen!> # define input(x) (((x) & ((1 << IRMP_BIT) | (1 << IRMP_BIT2))) ==> ((1 << IRMP_BIT) | (1 << IRMP_BIT2)))>>> Gibt es einen einfacheren Weg als die halbe Lib umzuschreiben?>> Naja, ich würde diese klitzekleine Änderung nicht unbedingt "halbe Lib> umschreiben" nennen ;-)
Danke erstmal!
So einfach geht es dann aber doch nicht, mit dem Code tut keiner der
beiden TSOPs (ja hängen beide an Port B). Selbst mit
((x) & ((1 << IRMP_BIT) | (1 << IRMP_BIT2))) tut es nicht.
Meinen Code hier zu posten wäre zu lang, ich hab einfach jegliche
Portdefiniton + Init + ISR kopiert, so dass ich für beide nachher im
Timer eine ISR aufgerufen hab. Das ging auch ganz brauchbar, solange das
Signal nicht an beiden IR Sensoren ankam. Aber dennoch erschien mir dein
Ansatz als besser, aber wie gesagt er tut so nicht, auch wenn ich nicht
ganz verstehe warum. Hast du eine Idee?
Conny G. schrieb:> Preisfrage schrieb:>> Ich versuche aktuell IRMP mit 2 TSOP4838 zu betreiben>> Wofür brauchst Du das? Um den Empfangswinkel zu vergrößern (z.B. Vor-> und Rückseite am Empfänger)?
Genau aus dem Grund ;)
Okay, da hatte ich wohl einen kurzen Hirnkrampf, es tut doch.
Im Anhang ist der Patch dafür, es ist genau die Änderung die Frank
erwähnte.
Zur Anwendung den Patch in den Ordner von IRMP (Version 2.6.7, Stand vom
19.09.2014) kopieren und dann: patch -p1 < irmp_two_tsops.patch
Zum Testen ob beide funktioniren reicht es nicht einen von beiden
einfach abzustecken, man muss den Eingangspin auf VCC setzen
(Open-Collector-Ausgang...s.o.).
Danke nochmal an Frank für die Hilfe und tolle Arbeit!
P.S.: Kennst du eigentlich https://github.com/shirriff/Arduino-IRremote
.. ich vermute das bringt dir zwar nichts mehr, aber gerade für den
RC6(A) Teil hättest du dort eventuell einen Blick reinwerfen können.
Auch scheint diese Library problemlos mit 1 MHz zu laufen, ich hab das
aber nur mit RC6A getestet. Der Ansatz selbst ist der afaik der gleiche
(Timer).
Preisfrage schrieb:> Okay, da hatte ich wohl einen kurzen Hirnkrampf, es tut doch.
Hätte mich auch gewundert, wenn nicht ;-)
Klar muss man an den nicht benutzten Pin dann einen Pullup-Widerstand
klemmen, wenn doch nur ein TSOP angeschlossen ist.
Aber wie gesagt: Beide TSOPs parallel zu schalten ist sehr wohl auch
eine Lösung.
Gruß,
Frank
Warum auch sollte das Parallelschalten Probleme machen?
IR ist Licht, Licht ist bekanntlich erstaunlich schnell :-)
Und die TSOPs einer Serie sollten auch bei extremer Streuung immer noch
ein brauchbares Rechteck ausgeben.
Klemm doch einfahc mal zwei oder drei TSOP zusammen und schau auf dem
Oszi wie das Signal "leidet".
Stefan Z. schrieb:> Warum auch sollte das Parallelschalten Probleme machen?> IR ist Licht, Licht ist bekanntlich erstaunlich schnell :-)> Und die TSOPs einer Serie sollten auch bei extremer Streuung immer noch> ein brauchbares Rechteck ausgeben.
dazu müssten aus der Grabbelkiste 3 aus einer Serie vom freundlichen
distributor genommen werden, wenig vorstellbar
> Klemm doch einfahc mal zwei oder drei TSOP zusammen und schau auf dem> Oszi wie das Signal "leidet".
wenn dann am 4 Kanal Oszi und schauen wie die Signale versetzt sind
wenn sie OC sind ist es kein Problem, wenn nicht sondern CMOS oder mit
eingebauten pullup sind Differenzen evtl. schlecht.
Wenn ein TSOP low zieht, der ander noch etwas high ist....
na ja muss jeder selber wissen, Parallelschaltung ist auf dem selben
Substrat eher weniger das Problem, sonst einfach nur ein temporärer
Kurzschluß !
Hallo Frank,
Eine kleine Anmerkung meinerseits.
Ich finde es schade dass du Strings mittels der obsoleten PROGMEM Krücke
in den Flash legst.
Ich würde entweder direkt den __flash Modifier verwenden, oder ihn
hinter einem Define verstecken:
1
#define FLASH_STRING const __flash
Auf Systemen ohne __flash kann man das Makro dann eben "leer"
definieren.
Mein GreenHills Compiler auf Arbeit beispielsweise legt generell
Konstanten in den Flash, da reicht dann ein
1
#define FLASH_STRING const
Ich finde das also portabler und obendrein wird der Code nicht durch
hässliche pgm Funktionen verschandelt.
Joachim B. schrieb:> wenn sie OC sind ist es kein Problem, wenn nicht sondern CMOS oder mit> eingebauten pullup sind Differenzen evtl. schlecht.
Ich wiederhole mich nochmal:
Die TSOPs sind generell Open Collector mit eingebautem Pullup. Von daher
gibt es keinen Kurzschluss. Parallelschaltung ist also kein Problem.
> na ja muss jeder selber wissen, Parallelschaltung ist auf dem selben> Substrat eher weniger das Problem, sonst einfach nur ein temporärer> Kurzschluß !
Nein, in diesem Falle nicht.
Heino schrieb:> Ich finde es schade dass du Strings mittels der obsoleten PROGMEM Krücke> in den Flash legst.
Wenn Du mir sagst, wie ich __flash mit dem gcc-4.3.3 im AVR Studio 4.18
zum Laufen bekomme, gerne ;-)
Da das 4er AVR Studio unter vielen Usern nachwievor ziemlich beliebt
ist, sehe ich da kurzfristig keine Möglichkeit, PROGMEM so einfach
loszuwerden.
> Ich finde das also portabler und obendrein wird der Code nicht durch> hässliche pgm Funktionen verschandelt.
"Portabler" ist es, wenn es mit dem alten und einem aktuellen gcc
läuft - nicht umgekehrt. Schönheit / Hässlichkeit ist eine andere Sache.
Frank M. schrieb:> Die TSOPs sind generell Open Collector mit eingebautem Pullup.
also sorry das ist definitiv ein Widerspruch in sich
entweder der TSOP ist OC ! dann hat er keinen eingebauten Pullup ! oder
er hat Pullup eingebaut, dann ist er kein OC.
OK was logisch funktioniert ist eine low Veroderung was parallelschalten
ja bedeutet und da die eingebauten "Pullups" keine 1 Ohm sein werden
wird das wohl klappen ohne Schädigung der TSOP, aber sauber ist anders.
Wer low verodern will müsste erst mal invertieren, auf ein Odergatter
gehen und wieder invertieren, oder ein NOR wählen.
Einfach parallelschalten empfinde ich (sorry) als unsauber, auch wenn es
hier wohl nix kaputt macht.
Joachim B. schrieb:> Frank M. schrieb:>> Die TSOPs sind generell Open Collector mit eingebautem Pullup.>> also sorry das ist definitiv ein Widerspruch in sich
Nein, ist es nicht. Es soll ausdrücken, dass High nicht aktiv getrieben
wird. Warum? Damit man es low verodern kann. Dabei erspart Dir der
innere Pullup den externen. Bei 30k kann man wahrlich nicht von einem
aktiven Ausgang sprechen - jedenfalls nicht, was die High-Side betrifft.
Schau Dir einfach das angehängte Innenschaltbild eines TSOPs an.
Joachim B. schrieb:> entweder der TSOP ist OC ! dann hat er keinen eingebauten Pullup ! oder> er hat Pullup eingebaut, dann ist er kein OC.
OK. Bei OC ist normal kein Pullup dran. Stimmt. Aber den machst du dann
eh extern dran oder nutzt einen eingebauten im uC-Pin.
Mal dir mal die Schaltung mit 2 TSOPs auf. dann hast du 2 Pullups. Die
kannst Du im Ersatzschaltbild durch einen mit halbem Wert ersetzen. Was
dann noch übrig bleibt sind zwei parallele OC mit einem Pullup.
Bad Urban schrieb:> Mal dir mal die Schaltung mit 2 TSOPs auf. dann hast du 2 Pullups. Die> kannst Du im Ersatzschaltbild durch einen mit halbem Wert ersetzen. Was> dann noch übrig bleibt sind zwei parallele OC mit einem Pullup.
Eben. Die beiden Pullups reduzieren sich dann bei der Parallelschaltung
von 30k auf einen mit 15k. Der eingebaute Transistor kann lt. Datenblatt
5mA liefern. Durch die beiden Pullups fließen dabei jeweils 0,17mA, also
ca. 0,34mA insgesamt. Das ist noch nichtmals ein Zehntel des Stroms, den
jeder der Transistoren leisten kann, um gegen den jeweils anderen TSOP
"anzukämpfen", solange beide nicht denselben Pegel haben. Das Ganze wird
sogar noch mit 3 oder 4 parallelgeschalteten TSOPs funktionieren.
Frank M. schrieb:> Schau Dir einfach das angehängte Innenschaltbild eines TSOPs an.
muss ich nicht, ich kenne sogar noch die Innenbeschaltung von TTL
Bad Urban schrieb:> Mal dir mal die Schaltung mit 2 TSOPs auf.
muss ich nicht malen, soweit funzt der Kopf noch, nur mit dem
Kurzzeitgedächnis haperts
Frank M. schrieb:> Die beiden Pullups reduzieren sich dann bei der Parallelschaltung> von 30k auf einen mit 15k.
auch klar
Ich schrieb schon das es geht (gehen kann, ach ne geht weil wurde
getestet)
nur empfand ich das im ersten Lesen als unsauber, aber OK der Praktiker
freut sich und theoretisiert weniger, ich weiss manchmal nicht wo ich
mich einordnen will.
PS. ich habe dem Atari ST am Floppycontroller mit regulär 8 MHz und DD
Datenstrom auch HD beigebracht durch Auf-Umschaltung von 8MHz zu 16MHz
gesteuert durch das HD Loch. Könnte auch sofort einer aufschreien 16MHz
statt 8MHz das kann nicht gehen.
Denkt Ihr das ich meine IR-Diode und dem IRSEND auch mit einem udn2003
treiben kann?
Würde das funktionieren oder klappt das nur mit der standard
Transistorschaltung?
Hat das schon wer versucht?
Einen UDN2003 gibt / gabs aber auch.
Ob du die Diode jetzt von "links oder rechts" schaltest ist ja egal
(also NPN oder PNP, finde grad kein Datasheet).
Ausschlaggebend ist immer die gewünschte Leistung, das sagt dir das
Datasheet, wenn du es dann findest :-)
Ulli -- schrieb:> IR diode, den> richtigen Vorwiderstand und den uln ...
ja, aber warum einen ganzen ULN für eine IR Diode?
wäre ein Transistor nicht platzsparender?
Hallo Frank,
ich räume gerade den Code von meinem IRMP_STM32 Projekt auf.
Dabei ist mir aufgefallen, dass ich bei den Patchen, die ich vor ein
paar Monaten vorgeschlagen habe, an zwei Stellen übers Ziel hinaus
geschossen bin.
Da können 5 includes entfernt werden.
In irmpsystem.h, Zeile 100 - 103:
1
# define memcpy_P memcpy
2
# define APP_SYSTICKS_PER_SEC 32
3
#elif defined(ARM_STM32F10X)
4
//# include "stm32f10x_gpio.h"
5
//# include "stm32f10x_rcc.h"
6
//# include "stm32f10x_tim.h"
7
//# include "misc.h"
8
# define PROGMEM
9
# define memcpy_P memcpy
10
#else
und in irmp.c, Zeile 613
1
# include "stm32f4xx_usart.h"
2
#elif defined(ARM_STM32F10X)
3
# define STM32_UART_COM USART3 // UART3 on PB10
4
//# include "stm32f10x_usart.h"
5
#else
6
# if IRMP_EXT_LOGGING == 1 // use external logging
7
# include "irmpextlog.h"
Die werden nämlich schon über vorhandene includes eingebunden, wenn man
es richtig macht ;-)
Gruß, Jörg
Jörg R. schrieb:> Die werden nämlich schon über vorhandene includes eingebunden, wenn man> es richtig macht ;-)
Wie macht man es denn richtig?
Ich spiele gerade mit dem STM32F4 Discovery herum und musste die
stm32f4...-Includes dort wieder einbinden. Ich hab sie allerdings in
irmp-system.h eingebaut.
Hallo Frank,
in Zeile 37 von irmpsystem.h wird stm32f10x.h eingebunden.
stm32f10x.h wiederum bindet stm32f10x_conf.h ein (vorausgesetzt
USE_STDPERIPH_DRIVER ist definiert).
Und schließlich wird in stm32f10x_conf.h das eingebunden, was ich
auskommentiert habe, und das ist auch der Ort, wo das hin gehört ;-)
Ich nehme mal an, dass es für den F4xx analog ist.
Gruß, Jörg
Hallo Jörg,
Jörg R. schrieb:> in Zeile 37 von irmpsystem.h wird stm32f10x.h eingebunden.> stm32f10x.h wiederum bindet stm32f10x_conf.h ein (vorausgesetzt> USE_STDPERIPH_DRIVER ist definiert).> Und schließlich wird in stm32f10x_conf.h das eingebunden, was ich> auskommentiert habe, und das ist auch der Ort, wo das hin gehört ;-)>> Ich nehme mal an, dass es für den F4xx analog ist.
Ja, ist analog. Dort gibt es ein stm32f4xx_conf.h, welches allerdings
von der CooCox-IDE nicht nachgepflegt wird. Das Ding muss man immer
manuell nacheditieren. Daher ist der Sinn dieses Includes für mich
zumindest zweifelhaft.
Ich überlege gerade: Wenn man die entsprechenden Includes drinlässt,
schadet es doch nichts, oder? Ich glaube, dann erpart man sich die
entsprechenenden Nachfragen, die entstehen, wenn der User die conf-Datei
nicht up-to-date hat.
Hm, ist wirklich eine Geschmackssache... Man könnte es auch im
IRMP-Artikel dokumentieren. Ich schwanke gerade...
Hallo,
seit langem melde ich mich mal wieder, nachdem ich jahrelang schweigend
genossen habe, wie gut IRMP funktioniert :).
Ich hatte IRMP vor einiger zeit erfolgreich auf einem STM32F4 am laufen,
wobei ich CoIDE und die darin verfügbaren LIBs (GPIO, TIMER, ...)
verwendet habe.
Jetzt bin ich auf das äußerst komfortable CubeMX von ST und eine andere
IDE umgestiegen, und im Hardware Abstraction Layer (HAL) [1] sind jetzt
die Initialisierungsstrukturen etwas anders aufgebaut. Ich schlage
deshalb vor, dass man per #define die Verwendung des HAL von CubeMX
angeben kann, und dann auf die dort definierten Funktionen
zurückgegriffen wird.
Gruß, DiPi
[1]:
HAL Description:
http://www.st.com/web/en/resource/technical/document/user_manual/DM00105879.pdf
(PDF - ca. 4,5 MB)
Jörg R. schrieb:> typedef struct _attribute_ ((_packed_))
In älteren Releases war so realisiert. Da ich an fast demselben Projekt
arbeite wie du (für Windows/MediaPortal), bin ich beim Aktualisieren von
IRMP irgendwann mal da drüber gestolpert als dann plötzlich zwei Bytes
mehr im USB Report landen sollten, die da aber keinen Platz hatten.
Hallo Jörg,
Jörg R. schrieb:> typedef struct _attribute_ ((_packed_))> Nun meine Frage an dich, ob es Sinn macht, das zu übernehmen?
Ja, macht definitiv Sinn. Dann ist die Größe der Struct auf allen µC
gleich.
Kommt mit der nächsten Version.
Jörg R. schrieb:> fast dasselbe Projekt?> Das macht mich neugierig. Lass mal mehr hören, hast du einen Link für> mich auf dein Projekt?
Ich mache da schon ewig dran rum mit niedriger Priorität und vielen
Unterbrechungen [wie lange genau, sage ich jetzt lieber nicht... ;-)].
Im Wesentlichen geht es um den IR-Empfang und das Aufwecken des PCs aus
allen Zuständen. Ich nutze (ausschließlich) MePo und will dafür ein
Plugin schreiben, wobei es auch eine Standalone-Applikation für Windows
gibt (beides in C# mit der Generic HID von Janet Axelson als Basis).
Prinzipiell funktioniert alles schon, im Produktiveinsatz ist es
allerdings noch nicht. Als uC kommt ein STM32L151 auf einer eigens
gelayouteten Platine zum Einsatz. Da ist allerdings noch etwas mehr
drauf, z.B. ein optischer S/PDIF-Ausgang, da mein Board keinen solchen
hat.
Frank M. schrieb:> Ja, macht definitiv Sinn. Dann ist die Größe der Struct auf allen µC> gleich.
In dem Fall ziehe ich obige Aussage zurück und behaupte das Gegenteil.
Dann habe ich das damals wohl selbst entsprechend modifiziert und
inzwischen vergessen.
Hallo Michael,
wollen wir uns gegenseitig unterstützen? Ist dein Projekt als Open
Source geplant?
Ich suche nämlich noch jemanden, der den Windows Teil von meinem Projekt
macht.
Möglicherweise könnte ich da etwas von dir übernehmen.
Vielleicht passt das gut zusammen?
Was meinst du?
Gruß, Jörg
Hallo Frank,
eine Frage zu RC5: wo kommen eigentlich die 45ms
RC5_FRAME_REPEAT_PAUSE_TIME her?
Ich kenne nur 25ms für die Daten und 114ms für einen Zyklus. Das macht
als Pause 114 - 25 = 89ms. Meine Fernbedienung hält sich auch daran.
Verstehe ich was falsch?
Gruß, Jörg
Hallo Jörg,
Jörg R. schrieb:> eine Frage zu RC5: wo kommen eigentlich die 45ms> RC5_FRAME_REPEAT_PAUSE_TIME her?
Diese habe ich irgendwann mal empirisch aus irgendwelchen Scan-Dateien,
die mir zur Verfügung gestellt wurden, herausgelesen. Ich selber habe
keine RC5-FB.
> Ich kenne nur 25ms für die Daten und 114ms für einen Zyklus. Das macht> als Pause 114 - 25 = 89ms. Meine Fernbedienung hält sich auch daran.
Das klingt auch sehr plausibel. Strenggenommen ist die Pausenlänge auch
nicht so kritisch. Sie wird nur von IRSND verwendet, um bei
Wiederholungen (z.B. längerem Druck auf Lautstärke-Taste) einen Abstand
zu erzielen. Bisher hat sich da auch niemand beschwert, dass es nicht
funktionieren würde. Aber wer weiß, wer das überhaupt nutzt?
Original-RC5 findet man heutzutage selten vor.
Hast Du eine Möglichkeit, zu testen, ob es (auch) mit 89ms geht? Dann
ändere ich das im Source.
Gruß,
Frank
P.S.
Viele der definierten FRAME_REPEAT_PAUSE-Zeiten sind nur empirisch oder
aus Plausibilitätsüberlegungen definiert worden. In den seltensten
Fällen habe ich von den Usern Scans mit kurzem und langem Tastendruck
bekommen, um diese dann vergleichen zu können.
Je mehr Du da richtig "messen" kannst, desto besser :-)
Hallo Frank,
am Anfang meiner Experimente mit Makros habe ich sofort nach einem
empfangenem auslösendem IR Event andere IR Events ausgesendet, also Null
Pause. Dadurch ist ein IgorPlug regelmässig abgestürzt. Zu kurze Pause
kann also Geräte verwirren.
Eine andere Frage ist, was passiert, wenn ein Makro verschiedene
Protokolle aussendet, also z.B. verschiedene Geräte mit
unterschiedlichen Protokollen einschalten will.
Beim Überlegen, welcher (möglichst kleine) Wert da mindestens nötig ist,
habe ich mir deine FRAME_REPEAT_PAUSE-Zeiten zur Orientierung
angeschaut.
Gut zu wissen, dass man sich darauf nicht unbedingt verlassen kann.
Die 89ms werde ich noch testen und Feedback geben.
Gruß, Jörg
Hallo Jörg,
Jörg R. schrieb:> mit 89ms geht es auch, aber 45ms schadet bei mir nichts.
Danke für die Rückmeldung. Vielleicht ist es aber trotzdem sicherer, die
89ms einzusetzen. Vielleicht reagieren nicht alle (mittlerweile eher
ausgestorbenen) Geräte so tolerant.
Hallo,
Ich versuche, mit Hilfe Ihrer Bibliothek, meinem ADB Set Top Box
Fernbedienung zu dekodieren.
Wenn ich die IRSND_SUPPORT_A1TVBOX_PROTOCOL Protokoll aktiviere, sehe
Ich einige Buchstaben und Zahlen erscheinen, aber am Ende gibt es ein
ERROR.
Ich denke meinen ADB Fernbedienung hat eine etwas andere Timing. Wie
kann meine Fernbedienung an die Protokoll-Liste hinzugefügt werden? Kann
ich die Fernbedienung an Sie senden? Ich habe nicht genug technisches
knowledge, um die sourcecode selbst zu ändern.
Wim
Wim schrieb:> Ich versuche, mit Hilfe Ihrer Bibliothek, meinem ADB Set Top Box> Fernbedienung zu dekodieren.
Für Dekodierung braucht man nur IRMP, nicht IRSND.
> Wenn ich die IRSND_SUPPORT_A1TVBOX_PROTOCOL Protokoll aktiviere, sehe> Ich einige Buchstaben und Zahlen erscheinen, aber am Ende gibt es ein> ERROR.
Das heisst, Du sendest mit IRSND? Was sendest Du mit IRSND? Das, was Du
vorher mit IRMP empfangen hast? Beachte bitte, dass viele kommerzielle
Geräte beim Timing sehr empfindlich sind. Von daher solltest Du bei
Verwendung von IRSND auch einen Quarz verwenden.
> Ich denke meinen ADB Fernbedienung hat eine etwas andere Timing.
Kann sein.
> Wie> kann meine Fernbedienung an die Protokoll-Liste hinzugefügt werden?
Im Artikel ist beschrieben, wie man Logging per IRMP_LOGGING einschalten
kann. Dann zeichnest Du ein paar Scans Deiner Fernbedienung auf und
schickst mir diese. Dann kann ich IRMP daran anpassen.
Hallo zusammen,
ich habe einen Atmega328p in Betrieb, IRMP und RISND funktioniert auch
wunderbar!
Nur möchte ich nun aus Stromspargründen den Atmega auf 1MHz takten.
Leider funktiniert dabei IRSND nicht mehr.
Hat einer einen Tipp oder die niedrige Taktung schon einmal ausprobiert?
Viele Grüße und Danke!
Ulli schrieb:> aus Stromspargründen
Konfiguriere den TSOP-Pin für Pin-Change-Interrupt und schick den µC in
den Sleep-Mode. Bei auftretendem Pin-Change-Interrupt deaktivierst du
den Pin-Change-Interrupt und IRMP funktioniert normal. Nach einer Weile
Inaktivität fängst du wieder von vorne an. Natürlich wird der µC
manchmal auch durch Fehlalarme geweckt werden.
Ulli schrieb:> So weit bin ich schon ;)> Möchte noch weiter runter weil ich nur aus einer AA Batterie speise..
Schau dir mal
http://www.mikrocontroller.net/articles/DIY_Lernf%C3%A4hige_Fernbedienung_mit_IRMP
an. Dort wird der TSOP, der wohl den meisten Strom zieht, per Pin
abgeschaltet, wenn man ihn nicht braucht. Aufwecken über den TSOP geht
dann aber nicht, dafür müsste dann eine Taste herhalten.
Wieviel Strom zieht denn Deine Schaltung und wie sieht diese aus?
Beschreibe doch mal Deine Anwendung näher.
Ulli -- schrieb:> Heißt das jetzt das irsend nicht bei 1MHz Controller Taktung lauffähig> ist?> Woran liegt das denn?
Bei 1MHz Taktung bleiben bei F_INTERRUPTS = 15000 nur noch 65 Takte pro
Interrupt. Das könnte arg eng werden.
Es steht nicht umsonst im IRMP-Artikel rot umrandet die folgende
Bemerkung:
"Diese sollte mindestens den Wert 8000000UL haben, der Prozessor sollte
also zumindest mit 8 MHz laufen."
Du könntest noch probieren, F_INTERRUPTS auf 10000 zurückzusetzen, dann
sind es immerhin 100 Takte pro Interrupt. Aber dann könnten einige
Protokolle nicht mehr funktionieren und deshalb schon beim Compilieren
abgeschaltet werden. Welche von den aktivierten Protokollen davon
betroffen sind, gibt der Compiler aber aus.
Ist die Stromersparnis bei 1MHz denn so hoch? Je nachdem, welchen TSOP
Du verwendest, zieht der im Ruhezustand bis zu 5mA. Das sind einige
Größenordnungen mehr als der Prozessor zieht. Die Stromaufnahme im
Sleep-Mode beträgt auch bei 8MHz weniger als 1 µA - siehe "Lernfähige
Fernbedienung". Da kommst Du mit einer AA-Batterie monatelang aus. Dein
Problem muss woanders liegen.
Welchen TSOP verwendest Du? Wie sieht Deine Schaltung aus? Beschreibe
bitte Deine Anwendung, sonst ist alles andere nur Spekulation.
Hallo Frank,
ich habe einen bisher unerkannten Fehler in "IRMP auf STM32".
Bestimmten Abläufe (Konfiguration über USB-HID) führen dazu, dass
irmp_get_data 00 00 00 00 00 00 übergibt, bzw. wenn ich vorher RC5
empfangen habe 07 00 00 00 00 00, obwohl kein IR gesendet wurde.
Gibt es einen Grund dafür, dass irmp_protocol nicht auf 0 zurückgesetzt
wird (so wie irmp_command, irmp_address und irmp_flags)?
Wenn irmp_protocol auf 0 zurückgesetzt würde, könnte ich das abfangen.
Solange 07 00 00 00 00 00 übergeben wird, kann das Programm nicht
wissen, ob das eine RC5 Null ist, oder ob was schief ging.
Man könnte eventuell auch rtc auf FALSE setzen, wenn irmp_protocol 0
bleibt, dann merkt man aber nicht, das es ein Problem gibt.
Hast du eine Idee, was der Grund dafür sein könnte, dass 00 00 00 00 00
00 ankommt, obwohl kein IR gesendet wurde? In anderen Worten, was könnte
mein Programm falsch machen, was IRMP bzw. die IRMP ISR auf diese Art
stört?
In irmp.c ab Zeile 1983 wäre es dann so (nur aufgeschrieben, nicht
getestet):
if (rtc)
{
/*if (irmp_protocol == 0) { // JR
rtc = FALSE;
break;
}*/
irmp_data_p->protocol = irmp_protocol;
irmp_data_p->address = irmp_address;
irmp_data_p->command = irmp_command;
irmp_data_p->flags = irmp_flags;
irmp_protocol = 0; // JR
irmp_command = 0;
irmp_address = 0;
irmp_flags = 0;
}
Gruß, Jörg
PS Deine irmp.tar.gz ist zur Zeit unkompilierbar.
Jörg R. schrieb:> ich habe einen bisher unerkannten Fehler in "IRMP auf STM32".> Bestimmten Abläufe (Konfiguration über USB-HID) führen dazu, dass> irmp_get_data 00 00 00 00 00 00 übergibt, bzw. wenn ich vorher RC5> empfangen habe 07 00 00 00 00 00, obwohl kein IR gesendet wurde.
Das darf nicht sein. Ich habe zur Zeit auch IRMP auf dem
STM32F4-Discovery und STM32F401-Nucleo Board ohne Probleme laufen. So
etwas ist mir noch nicht aufgefallen.
Das hieße ja, dass irmp_get_data() ein TRUE zurückliefert, obwohl nichts
empfangen wurde. Hm, das habe ich bisher noch nicht erlebt.
> Gibt es einen Grund dafür, dass irmp_protocol nicht auf 0 zurückgesetzt> wird (so wie irmp_command, irmp_address und irmp_flags)?
Solange nicht 1 zurückgeliefert wird, sind die IRMP_DATA-Member
undefiniert.
> Wenn irmp_protocol auf 0 zurückgesetzt würde, könnte ich das abfangen.
Unschön. Besser wäre es, den Grund dafür zu finden.
> Solange 07 00 00 00 00 00 übergeben wird, kann das Programm nicht> wissen, ob das eine RC5 Null ist, oder ob was schief ging.
Ist schon klar. Das Blöde ist nur, dass ich keine RC5-Fernbedienung
habe, um das zu reproduzieren. Da muss ich wohl mal in den Code schauen.
> Man könnte eventuell auch rtc auf FALSE setzen, wenn irmp_protocol 0> bleibt, dann merkt man aber nicht, das es ein Problem gibt.
Eben.
> Hast du eine Idee, was der Grund dafür sein könnte, dass 00 00 00 00 00> 00 ankommt, obwohl kein IR gesendet wurde?
Nein, im Moment habe ich keine Idee. Ausser Codeanalyse fällt mir dazu
auch nichts ein.
> PS Deine irmp.tar.gz ist zur Zeit unkompilierbar.
Hm, auf einem ATmega schon. Kannst Du mir die Compiler-Meldung zeigen?
Gruß,
Frank
P.S.
Bekommst Du auch für Protokoll eine 7 zurück, wenn Du vor dem Aufruf von
irmp_get_data() das irmp_data.protocol auf 0 zurücksetzt?
Frank M. schrieb:> Jörg R. schrieb:>> Gibt es einen Grund dafür, dass irmp_protocol nicht auf 0 zurückgesetzt>> wird (so wie irmp_command, irmp_address und irmp_flags)?>> Solange nicht 1 zurückgeliefert wird, sind die IRMP_DATA-Member> undefiniert.
Das verstehe ich nicht.
>> Wenn irmp_protocol auf 0 zurückgesetzt würde, könnte ich das abfangen.>> Unschön. Besser wäre es, den Grund dafür zu finden.
Klar. Aber was mache ich solange, bis ich den Fehler gefunden habe?
>> Solange 07 00 00 00 00 00 übergeben wird, kann das Programm nicht>> wissen, ob das eine RC5 Null ist, oder ob was schief ging.>> Ist schon klar. Das Blöde ist nur, dass ich keine RC5-Fernbedienung> habe, um das zu reproduzieren. Da muss ich wohl mal in den Code schauen.
Da sieht man das schnell.
>> PS Deine irmp.tar.gz ist zur Zeit unkompilierbar.>> Hm, auf einem ATmega schon. Kannst Du mir die Compiler-Meldung zeigen?
Hier:
http://www.vdr-portal.de/board18-vdr-hardware/board13-fernbedienungen/p1229073-irmp-auf-stm32-ein-usb-ir-empf%C3%A4nger-sender-einschalter-mit-wakeup-timer/#post1229073> Bekommst Du auch für Protokoll eine 7 zurück, wenn Du vor dem Aufruf von> irmp_get_data() das irmp_data.protocol auf 0 zurücksetzt?
Gute Idee, ich hab leider gerade keine Zeit, aber werde es sobald
möglich ausprobieren.
PS Hab gerade noch mal in den Code geschaut, das würde ja wieder
überschrieben, ich glaube nicht, dass es so geht.
Gruß, Jörg
Jörg R. schrieb:>> Solange nicht 1 zurückgeliefert wird, sind die IRMP_DATA-Member>> undefiniert.>> Das verstehe ich nicht.
irmp_get_data() rührt die IRMP_DATA-Member nur an, wenn etwas gültiges
empfangen wurde. Dann liefert die Funktion 1 zurück. Wenn also 0
zurückgegeben wird, dann sind die Daten unangetastet, d.h. es steht das
drin, was Du vor dem Aufruf von irmp_get_data() runtergegeben hast. Aus
der Sicht von irmp_get_data() sind die Werte also undefiniert - weil
unangetastet.
So sollte es jedenfalls sein. Wenn nicht, ist das ein Fehler.
>> Hm, auf einem ATmega schon. Kannst Du mir die Compiler-Meldung zeigen?>> Hier:> http://www.vdr-portal.de/board18-vdr-hardware/board13-fernbedienungen/p1229073-irmp-auf-stm32-ein-usb-ir-empf%C3%A4nger-sender-einschalter-mit-wakeup-timer/#post1229073
Danke. Fällt auf dem ATmega nicht auf, weil uint8_t identisch ist mit
uint_fast8_t.
Ersetze in irmp.c:
1
uint8_t
2
irmp_get_data(IRMP_DATA*irmp_data_p)
durch
1
uint_fast8_t
2
irmp_get_data(IRMP_DATA*irmp_data_p)
Dasselbe gilt für die Definition von irmp_ISR(). Ich habe es eben aber
auch im SVN korrigiert.
> Gute Idee, ich hab leider gerade keine Zeit, aber werde es sobald> möglich ausprobieren.> PS Hab gerade noch mal in den Code geschaut, das würde ja wieder> überschrieben, ich glaube nicht, dass es so geht.
Wie gesagt: Wenn irmp_get_data() die Daten ändert und trotzdem eine 0
zurückliefert, ist das ein Fehler. Aber ich muss wohl doch in den Code
schauen. Mache ich morgen. Das tritt nur nach dem Empfang eines
RC5-Codes auf?
Was ich sagen wollte:
irmp_get_data() liefert 1 zurück, obwohl kein IR Code gesendet wurde,
und als Protokoll wird 0x00 bzw. das letzte tatsächlich empfangene
Protokoll übergeben, als Adresse und Kommando 0x00 0x00 und als Flags
0x00.
Das passiert nur auf dem F103. Der F105 hat das Problem nicht, und da
der F105 und die F4xx dieselbe USB Bibliothek haben, tritt das auf den
F4xx auch nicht auf. Ich muss also mit meinem USB-HID Teil auf dem F103
etwas falsch machen.
Insofern betrachte ich das nicht als Fehler in IRMP, aber sicherlich
wäre es schöner, IRMP robuster gegen Fehler zu machen.
Der USB-HID Fehler muss irgendwie die irmp_ISR stören, und das wird in
irmp_get_data() nicht abgefangen. Im Code der irmp_get_data() ist das
auch nachvollziehbar. Die irmp_ISR habe ich mir noch nicht genauer
daraufhin angeschaut.
Den Fehler im USB-HID zu finden steht jetzt auf meiner TODO Liste ganz
oben, aber leider nicht viel Zeit.
Da meine Fernbedienungen alle RC5 senden, habe ich nur mit RC5 getestet.
Jörg R. schrieb:> Was ich sagen wollte:> irmp_get_data() liefert 1 zurück, obwohl kein IR Code gesendet wurde,> und als Protokoll wird 0x00 bzw. das letzte tatsächlich empfangene> Protokoll übergeben, als Adresse und Kommando 0x00 0x00 und als Flags> 0x00.
Okay, ich hatte es umgekehrt formuliert. Aber wir sind uns ja einig:
Dass hier eine 1 zurückgeliefert wird, ist ein Fehler. Fragt sich nur,
was die Ursache ist. Bisher hat so etwas noch niemand berichtet noch
habe ich eine Erklärung dafür.
> Das passiert nur auf dem F103. Der F105 hat das Problem nicht, und da> der F105 und die F4xx dieselbe USB Bibliothek haben, tritt das auf den> F4xx auch nicht auf. Ich muss also mit meinem USB-HID Teil auf dem F103> etwas falsch machen.
Was ist denn der Unterschied zwischen F103 und F105 - ausser der
USB-Bibliothek? Vielleicht ist beim F103 weniger Speicher verfügbar und
es passiert irgendwo ein Buffer-Overflow?
Tritt denn dieses Phänomen auch auf, wenn Du die USB-Bibliothek gar
nicht nutzt?
> Insofern betrachte ich das nicht als Fehler in IRMP, aber sicherlich> wäre es schöner, IRMP robuster gegen Fehler zu machen.
Eine Software-Bibliothek "robuster" gegen Fehler zu machen, die aus
anderen Modulen herrühren, sehe ich als Herumdoktern an Symptomen. Man
kann so vielleicht einen Workaround einbauen, um den eigentlich Fehler
zu verschleiern, aber wenn man Pech hat, bricht der Bug dann an einer
anderen Stelle durch und man muss noch ein Pflaster draufkleben.
> Der USB-HID Fehler muss irgendwie die irmp_ISR stören, und das wird in> irmp_get_data() nicht abgefangen. Im Code der irmp_get_data() ist das> auch nachvollziehbar. Die irmp_ISR habe ich mir noch nicht genauer> daraufhin angeschaut.
Ich werde mir irmp_get_data() nochmal genauer anschauen. Sollte ich da
einen (wahrscheinlichen) Fall finden, dass eine 1 zurückgeliefert wird,
obwohl nichts empfangen wurde, werde ich das korrigieren.
Ich melde mich nochmal heute oder morgen dazu.
Gruß,
Frank
Hallo Frank,
es tritt hier auf:
https://github.com/j1rie/IRMP_STM32/blob/master/STM32F103/src/main.c#L513
Vorher schicke ich Konfigurationsdaten über USB-HID vom uC zum PC.
Danach frage ich ab, ob neues IR empfangen wurde.
Im Falle des F103 bekomme ich nach dem USB Transfer von
irmp_get_data(&myIRData) Daten, obwohl kein IR gesendet wurde.
Ich werde da mal einen sleep oder warten auf PrevXferComplete testweise
einbauen, wenn ich wieder zuhause bin.
Aber da sowohl der USB Transfer als auch IRMP das in ihren jeweiligen
ISRs machen, bin ich nicht sicher, ob das hilft.
Sowohl der USB Datenverkehr als auch IRMP an und für sich funktionieren
bis auf den beschriebenen Fehler tadellos.
Gruß, Jörg
Jörg R. schrieb:> Ist in Zeile 2415 von irmp.c> irmp_param_p = (IRMP_PARAMETER *) (IRMP_PARAMETER *) &sircs_param;> so richtig oder ein Verschreiber?
Das ist ein Verschreiber, der glücklicherweise aber nicht schädlich ist.
Danke für den Hinweis, Korrektur kommt mit der nächsten Version.
Hallo Frank,
irgendwie haben sich deine letzten Änderungen und meine Fehlersuche
überkreuzt.
Sobald irmp_get_data() und irmp_ISR() als uint_fast8_t deklariert sind,
ist der Fehler weg!! Es lag genau daran!
Ich bin froh, dass ich das hinter mir habe!
Gruß, Jörg
PS Ich habe auch mal meine relevanten Variablen auf fast umgestellt,
wobei das nur noch eine war, und die macht keinen Unterschied.
Hallo Jörg,
Jörg R. schrieb:> Ich bin froh, dass ich das hinter mir habe!
Verstehe ich :-)
> PS Ich habe auch mal meine relevanten Variablen auf fast umgestellt,> wobei das nur noch eine war, und die macht keinen Unterschied.
Ich habe festgestellt, dass der Zugriff auf uint8_t Variablen ca. 8 mal
langsamer ist als auf uint8_t, z.B. bei Schleifenzählern. Ich wollte
aber nicht alles auf uint32_t umstellen, da dies auf 8-Bit-AVRs eine
zusätzliche CPU- und Speicherbelastung gewesen wäre.
uint_fast8_t ist da ein guter Kompromiss: Auf STM32 wird alles bei
voller Gschwindigkeit als uint32-Zugriff ausgeführt, auf AVRs bleibts
aber bei genügsamen 8Bit.
Jörg R. schrieb:> irmp.c und irmp.h sind noch nicht konsistent:> irmp_is_busy()
Habe die Funktion irmp_is_busy gestrichen, da ich keine sinnvolle
Anwendung dafür sehe. In irmp.c war sie sowieso schon auskommentiert.
> und *cb sind verschieden deklariert
Du meinst irmp_callback_ptr? Bei mir waren sie gleich, kann aber sein,
dass es im SVN noch nicht der Fall war.
Update ist nun im SVN.
Danke,
Frank
Jörg R. schrieb:> Hui! Jetzt gleich alle?!
Ich hatte irgendwann vor ein bis zwei Wochen alles auf fast-Typen
umgestellt, aber nur einen Teil eingecheckt - ich glaube, nur irmp.c und
irmpprotocols.h - wegen eines neuen Protokolls "MERLIN".
Das war mein Fehler und so ist die Inkonsistenz irmp.c <-> irmp.h
überhaupt entstanden, über die Du dann gestolpert bist. Denn diese
Widersprüche hatte ich nämlich schon vor einiger Zeit mit einem
Rundumschlag in Ordnung gebracht, aber leider nicht sofort eingecheckt.
Ist das denn nötig alle umzustellen? Sind die alle zeitkritisch?
In den ST Libs z.B. werden teilweise auch etliche Variablen, obwohl sie
nur einen klitzekleinen Wertebereich haben, als uint32_t deklariert.
Aber viele auch als uint8_t.
Jörg R. schrieb:> Ist das denn nötig alle umzustellen? Sind die alle zeitkritisch?
Die irmp_ISR() ist ziemlich fett, das ist nicht zu übersehen.
Ich habe auf STM32F4-µCs diverse Benchmarks erstellt, wie "schnell"
uint8_t-, uint16_t- und uint32_t-Variablen tatsächlich sind.
Das Ergebnis:
Schon eine simple for-Schleife
for (i = 0; i < 255; i++)
läuft mit uint32_t (bzw. uint_fast8_t) als Zähler insgesamt 8-mal(!)
schneller.
Ist ja auch klar: Die Register des µCs sind 32-Bit breit. Bei
8-Bit-Operationen müssen die Register immer mit einer 8-Bit-Maske
versehen werden. Das kostet einfach Zeit. Und was ist mit dem Alignment
bei STM32? Müssen 8-Bit-Variablen sowieso auf Adressen im RAM zum Liegen
kommen, die durch 4 teilbar sind?
Wenn ja:
Dann braucht uint_fast8_t (alias uint32_t) genauso viel Speicherplatz
wie ein uint8_t, weil sowieso alles vom Compiler aufs 4-fache
aufgeblasen wird.
Wenn nein:
Dann dürfte der RAM-Zugriff auf "ungerade" Adressen ziemlich
ineffektiv sein.
Ergo:
Es ist sehr sinnvoll, bei 32-Bit-µCs auch 32-Bit-breite Variablen zu
verwenden. Ein Einbruch auf ein Achtel der Geschwindigkeit macht den
Vorteil eines 32-Bit-µCs wieder zunichte.
> In den ST Libs z.B. werden teilweise auch etliche Variablen, obwohl sie> nur einen klitzekleinen Wertebereich haben, als uint32_t deklariert.
uint32_t kann ich nicht nehmen. Dann geht IRMP auf AVRs den Bach runter.
Der Witz ist ja gerade, dass bei uint_fast8_t auf STM32 der Typ uint32_t
verwendet wird, bei AVRs aber nur uint8_t.
Schau mal in <stdint.h> rein. Bei STM32 wirst du finden:
Die Verwendung von fast-Variablen ist daher
- portabel
- sehr effektiv
Das darf natürlich nur mit Variablen machen, die den jeweiligen
Wertebereich nicht überschreiten. Sonst wundert man sich später beim
Port von AVR auf STM32, warum beim Überlauf eines Zählers nach 255
plötzlich nicht 0, sondern 256 als Wert drinsteht.
> Aber viele auch als uint8_t.
Die habe ich auch noch, nämlich dann, wenn ich einen Buffer benutze,
dessen Elemente 8 Bit breit sein müssen. Oder wenn ich einen Zähler
benutze, der bei 255 wirklich auf 0 überlaufen soll und nicht auf 256.
Jetzt nochmal zu Deiner Frage:
> Ist das denn nötig alle umzustellen? Sind die alle zeitkritisch?
Wo siehst Du denn da ein Problem? Umstellen muss man da als Anwender der
Lib eigentlich gar nichts, nur neu compilieren.
Auch das funktioniert:
1
uint8_trtc;
2
3
rtc=irmp_get_data(&irmp_data);
Der Compiler wandelt dann uint_fast8_t wieder zurück in uint8_t - was er
übrigens auch machen muss, wenn irmp_get_data() einen uint8_t
zurückliefert. Denn den Returncode muss er in einem 32-Bit-Register
unterbringen. Das muss er dann genauso maskieren, wenn er diesen wieder
auf 8-Bit runterbrechen muss.
Und deshalb:
So ganz habe ich auch immer noch nicht Dein Problem mit dem STM32-F105
verstanden. Wenn in irmp.c die Definition von irmp_get_data() von der
Deklaration in irmp.h abweicht (was ja tatsächlich ein Fehler von mir
war), dann hätte der Compiler eigentlich aussteigen müssen. Wieso konnte
er da fehlerhaften Code erzeugen?
Wie gesagt:
uint8_t rtc = irmp_get_data (&irmp_data);
muss auch jetzt noch korrekt(!) funktionieren.
P.S.
Dass in den ST Libs uint32_t und nicht uint_fast8_t verwendet wird, ist
klar: Die Systemprogrammierer brauchen auf Kompatibilität zu 8-Bit-µCs
keine Rücksicht zu nehmen.
Hallo Frank,
wenn man deiner Argumentation folgt, müsste man, wie du selbst sagst,
(fast) alle Variablen auf uint_fast8_t umstellen.
Ich habe es halt noch nie gesehen, dass jemand gleich alle seine
Variablen auf uint_fast8_t umstellt, deshalb wundert mich das.
Ich kenne das eigentlich nur so, dass nur die Zeitkritischen
umgestellt werden.
Deshalb auch meine Frage, ob tatsächlich alle, die vorher uint8_t waren
und jetzt uint_fast8_t geworden sind, zeitkritisch sind? Das weißt du
besser als ich :-) .
Sonst wäre das imho übers Ziel hinaus geschossen.
Gruß, Jörg
PS Das Problem mit dem F103 gab es schon seit Monaten, und es war weg,
als ich irmp_get_data() und irmp_ISR() auf uint_fast8_t geändert habe.
Hi Jörg,
Jörg R. schrieb:> wenn man deiner Argumentation folgt, müsste man, wie du selbst sagst,> (fast) alle Variablen auf uint_fast8_t umstellen.
Ja.
> Ich habe es halt noch nie gesehen, dass jemand gleich alle seine> Variablen auf uint_fast8_t umstellt, deshalb wundert mich das.> Ich kenne das eigentlich nur so, dass nur die Zeitkritischen> umgestellt werden.
In einer ISR ist alles zeitkritisch ;-)
Aber mal im Ernst: Es war für mich einfacher, global im Editor
stämtliche uint8_t-Variablen auf uint_fast8_t umzustellen und
anschließend die wenigen Stellen, wo es unbedingt ein uint8_t sein muss,
diese wieder zu korrigieren. Dasselbe habe ich mit uint16_t gemacht.
> Deshalb auch meine Frage, ob tatsächlich alle, die vorher uint8_t waren> und jetzt uint_fast8_t geworden sind, zeitkritisch sind? Das weißt du> besser als ich :-) .
Wie gesagt: In einer ISR schon. Okay, ich habe auch irmp_get_data und
anderes umgestellt. Aber warum soll ich denn auf 32 Bit verzichten, wenn
ich auf einem 32-Bit-µC bin?
Wäre da nicht die Kompatibilität zu AVR und PIC, hätte ich halt alles in
ein uint32_t umgewandelt.
> Sonst wäre das imho übers Ziel hinaus geschossen.
Das sehe ich nicht so. Ich bewege mich mit den fast-Typen in der
"natürlichen Umgebung" des µCs, d.h. ich passe mich damit optimal an die
Register-Breite des jeweiligen µCs an. Was soll daran falsch sein?
Ausserdem schadet die Anwendung von fast-Typen in keinster Weise -
jedenfalls solange man sich des Wertebereichs, den man nutzt, im klaren
ist.
Die damaligen C-Erfinder hatten damals ganz bewusst die Breite des Typs
"int" nicht vorgeschrieben. Dieser sollte immer die Breite der
Prozessor-Register verwenden und damit optimalen Code erzeugen.
Leider kann man mit einem "int" der Breite 8 sehr wenig anfangen. Daher
ist ein "int" im avr-gcc auch 16 Bit breit. Es gibt aber auch
AVR-Compiler, bei denen ein "int" tatsächlich nur 8-Bit breit ist.
Aber genau deshalb habe ich mich bei der AVR-Entwicklung des IRMP damals
bewusst gegen "int" gestellt: 16 Bit bedeuten auf einem AVR eine
deutliche Mehrbelastung. Hätte es diese nicht gegeben, hätte ich überall
"int" verwendet.
Die "moderneren" fast-Typen (gibt's noch gar nicht so lange) helfen hier
einem aus dieser Bredouille und erlauben, portablen, aber immer noch
effizienten Code zu schreiben.
Mhm, sollte man dann generell auf den STM32 nur noch uint_fastN_t
Variablen verwenden? Konkret, sollte ich in meinem IRMP auf STM32
Projekt alle Variablen auf uint_fastN_t umstellen?
Jörg R. schrieb:> Mhm, sollte man dann generell auf den STM32 nur noch uint_fastN_t> Variablen verwenden? Konkret, sollte ich in meinem IRMP auf STM32> Projekt alle Variablen auf uint_fastN_t umstellen?
Nur wenn Du Dein Projekt mal auf einen 8-Bit-µC portieren willst. ;-)
Aber ich nehme nicht an, dass Du daran überhaupt denkst.
Sonst kannst Du genauso gut auch uint32_t (oder einfach "int" bzw.
"unsigned int") wählen. Da muss man sich über Wertebereiche keine
Gedanken machen und das Programm ist auf jeden Fall um einiges
schneller.
Ok, dann werde ich das gelegentlich tun ((u)int32_t).
Neulich habe ich in einem russischem Forum gelesen, dass je nachdem mit
welchem Code man eine LED toggeln lässt, die Frequenz 2 bzw. 18 MHz ist
(war glaube ich auf einem F4xx).
Code auf Schnelligkeit zu optimieren kann viel bringen.
Jörg R. schrieb:> Ok, dann werde ich das gelegentlich tun ((u)int32_t).
Ja, auf einem 32-Bit-µC muss man sich vom einengenden uint8_t einfach
lösen. Man spart nichts und hat nur Nachteile.
> Neulich habe ich in einem russischem Forum gelesen, dass je nachdem mit> welchem Code man eine LED toggeln lässt, die Frequenz 2 bzw. 18 MHz ist> (war glaube ich auf einem F4xx).
Ja, so etwas habe ich sogar hier in einem Thread gelesen. Auch da ging
es um die Erzeugung einer möglichst hohen Frequenz mittels STM32.
Quintessenz war, dass ein Funktionsaufruf von
GPIO_WriteBit()
ein Vielfaches braucht gegenüber einer direkten Anweisung übers
Port-Register.
Ist ja auch klar: Funktionsaufrufe bedeuten immer Overhead, solange sie
nicht inline compiliert werden (können).
> Code auf Schnelligkeit zu optimieren kann viel bringen.
In einer ISR() auf jeden Fall. Ziel einer jeden ISR muss sein, sich
möglichst schnell zu beenden. Die Länge des Codes spielt da eigentlich
(entgegen vielen Aussagen anderer) keine Rolle, es kommt nur auf die
Zeit an, die der µC in einer ISR verweilt. Diese muss möglichst kurz
sein.
Die irmp_ISR() ist als Zustandsautomat programmiert. Daher wird immer
nur ein kleiner Teil des Monstrums tatsächlich ausgeführt. Nur so ist es
überhaupt möglich, eine so lange ISR zu schreiben, ohne dass die Zeit
"überläuft".
Daher war die fast-Umstellung von IRMP für STM32 auf jeden Fall
sinnvoll.
Matthias Frank schrieb:> gibt es mittlerweile eigentlich auch schon irmp für den xmega?
Nicht, dass ich wüsste. Sollte aber nicht so schwierig sein.
Was muss dafür getan werden:
1. Neue Timer-Initialisierungsroutine schreiben plus Timer-ISR, welche
irmp_ISR() 15000 mal pro Sekunde aufruft.
2. Den in irmpconfig.h definierten Input-Pin initialisieren und das
Macro input() anpassen.
Das sollte reichen. Evtl. noch ein #ifdef IRGENDWAS_MIT_XMEGA, um die
richtigen System-Includes zu ziehen, z.B. das Pendant zu <avr/io.h> o.ä.
Willst Du es machen?
> Willst Du es machen?
Bin gerade dabei :P
> Was muss dafür getan werden:>> 1. Neue Timer-Initialisierungsroutine schreiben plus Timer-ISR, welche> irmp_ISR() 15000 mal pro Sekunde aufruft.>> 2. Den in irmpconfig.h definierten Input-Pin initialisieren und das> Macro input() anpassen.
Die 2 Sachen hab ich getan. Das Empfangen funktioniert jetzt sogar :P
Jetzt mach ich mich dann mal an das senden.
> Das sollte reichen. Evtl. noch ein #ifdef IRGENDWAS_MIT_XMEGA, um die> richtigen System-Includes zu ziehen, z.B. das Pendant zu <avr/io.h> o.ä.
Ich versteh nicht ganz, wie ich im Programm erkennen kann ob es es sich
um einen Xmega oder einen normalen Mega handelt. Bis jetzt hab ich die
ensprechenden Zeilen einfach direkt geändert, statt es für beide
Controllertypen anzupassen
Matthias Frank schrieb:> Die 2 Sachen hab ich getan. Das Empfangen funktioniert jetzt sogar :P> Jetzt mach ich mich dann mal an das senden.
Gratuliere. Wäre schön, wenn Du mir irgendwann Deine Änderungen
zurückschicken würdest, damit ich sie in den allgemeinen Source
einfließen lassen kann.
> Ich versteh nicht ganz, wie ich im Programm erkennen kann ob es es sich> um einen Xmega oder einen normalen Mega handelt.
Für jeden µC wird im allgemeinen mindestens eine Preprocessor-Konstante
definiert. Wenn Du zum Beispiel für einen ATmega328 übersetzt, dann
heisst die Konstante
1
__AVR_ATmega328P__
Das heisst, man kann mit
1
#ifdef __AVR_ATmega328P__
2
....
3
#endif
prozessor-spezifischen Code einflechten. So eine Konstante wird es für
den Xmega auch geben.
> Bis jetzt hab ich die> ensprechenden Zeilen einfach direkt geändert, statt es für beide> Controllertypen anzupassen
Ich kenne mich mit Xmega nicht aus, aber ich werde die Konstante schon
finden, wenn Du mir den Xmega-Typ und die Änderungen des Codes schickst.
Matthias Frank schrieb:> Was genau muss ich den bei irsnd alles ändern? das kommt mir viel vor
Auch hier brauchst Du den 15kHz-Timer. Aber das hast Du ja schon
erledigt.
Dann brauchst Du noch zusätzlich einen variablen Timer, mit dem die
IR-Modulation durch PWM erledigt wird (z.B. 38kHz für NEC-Protokoll).
Du brauchst also am Xmega einen PWM-fähigen Pin.
Dafür musst Du im wesentlichen anpassen:
- irsnd_init() für die beiden Timer
- irsnd_on() zum Einschalten der PWM
- irsnd_off() zum Abschalten der PWM
- irsnd_set_freq() zum Einstellen der PWM-Frequenz
Das sollte reichen.
danke, das scheint zu gehen :P
Ich lade hier jetzt einfach mal mein Projekt hoch, da ich nicht
weiterkomme.
Aktueller Stand:
-Infrarot wird empfangen und am LCD ausgegeben.
-Infrarot LED sendet dieses Signal nun weiter. Mit der Handykamera sehe
ich, dass die LED für einen kurzen Moment flackert. Allerdings reagiert
kein einziges Gerät darauf :-/
Ich versteh nicht wieso...
Allerdings bin ich mir beim Erzeugen des PWM Signals unsicher ob ich
alles richtig gemacht habe. Welcher Modus beim XMEGA kommt den dem CTC
Modus wieder gleich (siehe Bild: Modus)?
Vlt hab ich hier auch einfach die falschen Register beschrieben und das
PWM läuft mit einer falschen Frequenz....anderst kann ich es mir nicht
erklären.
Ich habe (hoffentlich) alle Änderungen mit einem
# warning Hier wurde etwas veraendert
markiert, damit man meine Änderungen leichter nachvollziehen kann.
Ich denke, dass es sich nur noch um eine Kleinigkeit handeln kann^^
achso eins noch....
ich habe die F_CPU teilweiße in manchen header dateien ganz oben noch
einmal eingefügt, dass sie diese irgenwie nicht gefunden haben.
Hier bitte sehr :P
jetzt sollte alles so passen.
Mein Verwendeter Controller ist der ATxmega128A1U.
Ich hab den Code jetzt nur auf diesen einen Controller angepasst.
Du solltest aber nochmal drüber schauen, bevor du es zu deinem Source
Code hinzufügst:
-Die geänderten stellen habe ich markiert.
-F_CPU habe ich wie gesagt mehrmals definiert. Das ist das einzige, was
ich noch nicht verstehe. Anderst kam immer eine Meldung, dass er dies
nicht kennt.
Hallo,
habe mir die Software hier runtergeladen und auch das Compilieren für
den Mega88 läuft fehlerfrei. Einer halbstündigen Durchsicht der Doku und
des Codes konnte ich noch nicht zweifelsfrei entnehmen, was die
entstandene .hex, was IRMP bzw. die Beispiel-App nun eigentlich tut
(kann ja sein daß es nach zwei Studienstunden klarer wird ;-)
Was meint denn nun Dekodieren? Was wird wo im Ergebnis ausgegeben?
> Einer halbstündigen Durchsicht der Doku und> des Codes konnte ich noch nicht zweifelsfrei entnehmen, was die> entstandene .hex, was IRMP bzw. die Beispiel-App nun eigentlich tuthttp://www.mikrocontroller.net/articles/IRMP
In dem Artikel ist eigentlich alles erklärt.
IRMP kann Daten von einer Infrarot Fernbedienung empfangen und
auswerten, so dass du diese bei bedarf später wieder senden kannst.
Somit kannst du dir zum Beispiel eine eigene Universalfernbedienung oder
ähnliches bauen :P
> Was meint denn nun Dekodieren? Was wird wo im Ergebnis ausgegeben?
In den Variablen
rmp_data.protocol
irmp_data.address
irmp_data.command
wird der dekodierte Code gespeichert.
Wenn man dokodieren ganz grob und einfach beschreiben müsste würde ich
sagen, es wandelt das Signal so um, dass du damit es anfangen kannst.
Hallo Frank,
ein "svn blame <datei>" liefert mir bei IRMP keine Informationen. Ich
möchte herausfinden, mit welcher Version das Timing für das
Siemens-Protokoll geändert wurde, denn die Erkennung ist nach wie vor
zufällig (IRSND->IRMP). Ich habe die Einführung/Zusammenlegung mit dem
RUWIDO in Verdacht, denn IRMP erkennt gerne RUWIDO, wenn es SIEMENS ist.
Matthias Frank schrieb:> In dem Artikel ist eigentlich alles erklärt.
Ja, technisch bis ins Detail- nur eine allgemeinverständliche
Funktionsbeschreibung fehlt. Danke, daß Du die hiermit nachgeliefert
hast.
Mit den Variablen
rmp_data.protocol
irmp_data.address
irmp_data.command
kann ich wenig anfangen, da ich IRMP nicht in eigene Projekte
integrieren, sondern den Beispielcode als M88 Standalone-Lösung
verwenden wollte. Darin sah ich auch was von UART-Ausgabe. Die müsste
doch standardmäßig aktiv sein !?
Sorry für die fehlenden C-Kenntnisse ;-(
Matthias Frank schrieb:> jetzt sollte alles so passen.>> Mein Verwendeter Controller ist der ATxmega128A1U.> Ich hab den Code jetzt nur auf diesen einen Controller angepasst.
Entschuldige bitte die späte Antwort. Ich war in der letzten Woche
unterwegs und daher größtenteils offline.
Vielen Dank. Ich werde Deine Änderungen in den IRMP-Code einarbeiten.
Eventuell komme ich nochmal auf Dich für eine Rückfrage zurück.
> -Die geänderten stellen habe ich markiert.
Prima, das hilft.
> -F_CPU habe ich wie gesagt mehrmals definiert. Das ist das einzige, was> ich noch nicht verstehe. Anderst kam immer eine Meldung, dass er dies> nicht kennt.
Du solltest die Preprocessor-Variable nicht im Source, sondern im
Projekt eintragen. Normalerweise kann man - je nach verwendeter IDE -
eine Compiler-Option hinzufügen, wie zum Beispiel -DF_CPU=8000000L.
Das hat auch den Vorteil, dass man diese Konstante nicht über den ganzen
Source verteilen muss. Ein Fehler ist dann bei einer Änderung
vorprogrammiert.
Hallo Zusammen,
nach Jahren komme ich nun endlich dazu das Projekt WordClock fertig zu
stellen ;)
Auf der Zielgeraden taucht plötzlich doch noch ein Problem auf. In der
IRMP-Anlernprozedur der WordClock werden die Tastendrücke der
B&O-Fernbedienung nur sporadisch erkannt.
Was ich bisher versucht habe:
Hardware: Wordclock Steuerplatine Version 1.0, voll bestückt nach
Teileliste
Letzte vorkomplierte SW (letzter Stand für Atmega 168) geflachst, TSOP
1736 drangehängt und es lief sofort mit Fernbedienung aus der Wühlkiste.
TSOP 7000 drangehängt (Pinbelegung mehrfach überprüft) und die
Anlernprozedur schlägt fehl. Einen weiteren TSOP 7000 getestet - das
ging auch nicht. Hatte noch im Hinterkopf, dass nicht alle Protokolle
default aktiviert sind. War dann auch so. Also Protokoll für B&O
aktiviert, andere deaktiviert, Progmem-Errors wegen neuem AVR-GCC
gefixt, gebaut und geflasht. Uhr läuft auch, aber Anlernprozedur wollte
trotzdem nicht funktionieren. Also direkt an die Beinchen des TSOP Elko
10µF parallel und 100 Ohm in Reihe als Versorgungs-Tiefpass. Auch noch
mal ein anderen TSOP 700 getestet. Nach mehrfachen Versuchen wird
sporadisch mal ein Tastendruck erkannt. TSOP mit ca. 30cm Zuleitung
liegt fern der Steuerplatine.
Wo sollte ich weitermachen? Separate Schaltung bauen, um IRMP und TSOP
7000 standalone zu testen, damit ich diesen Fehler ausschließen kann?
Oder sollte ich die Steuerplatine untersuchen? Obwohl die mit TSOP 1736
sofort lief.
Wäre nett, wenn jemand mir da einen Tipp geben könnte. Vielen Dank.
Kum
kum schrieb:> Letzte vorkomplierte SW (letzter Stand für Atmega 168) geflachst, TSOP> 1736 drangehängt und es lief sofort mit Fernbedienung aus der Wühlkiste.
Hm, Du meinst jetzt aber nicht die B&O-FB, oder?
> TSOP 7000 drangehängt (Pinbelegung mehrfach überprüft) und die> Anlernprozedur schlägt fehl. Einen weiteren TSOP 7000 getestet - das> ging auch nicht. Hatte noch im Hinterkopf, dass nicht alle Protokolle> default aktiviert sind. War dann auch so. Also Protokoll für B&O> aktiviert, andere deaktiviert, Progmem-Errors wegen neuem AVR-GCC> gefixt, gebaut und geflasht.
Gut.
> Uhr läuft auch, aber Anlernprozedur wollte> trotzdem nicht funktionieren. Also direkt an die Beinchen des TSOP Elko> 10µF parallel und 100 Ohm in Reihe als Versorgungs-Tiefpass. Auch noch> mal ein anderen TSOP 700 getestet. Nach mehrfachen Versuchen wird> sporadisch mal ein Tastendruck erkannt. TSOP mit ca. 30cm Zuleitung> liegt fern der Steuerplatine.
Der IRMP-Source im WordClock-Projekt ist schon ein paar Jährchen alt - 3
Jahre mindestens. Könnten auch 4 Jahre sein.
> Wo sollte ich weitermachen?
Du solltest erstmal den aktuellen IRMP-Stand ins WordClock-Projekt
einbauen. Sollte nicht sooo schwierig sein.
Du brauchst dafür:
- irmp.c
- irmpconfig.h
- irmpsystem.h
- irmpprotocols.h
- irmp.h
Dann nochmal irmpconfig.h anpassen.
> Obwohl die mit TSOP 1736 sofort lief.
Nochmal: Welche? Tatsächlich die B&O-FB?
> Wäre nett, wenn jemand mir da einen Tipp geben könnte. Vielen Dank.
Wenn ich es recht in Erinnerung habe, läuft IRMP im WordClock-Projekt
mit F_INTERRUPTS 10000. Das ist bei dem B&O-Protokoll ziemlich
problematisch, da die Pulse hier ultrakurz sind, nämlich nur 200µs. Bei
einer Abtastrate von 10000 Hz "sieht" IRMP nur 1-2 mal hintereinander,
dass da überhaupt etwas ist.
Du könntest F_INTERRUPTS auf 15000 erhöhen. Dann werden die Pulse
wenigstens 2-3 mal aufgezeichnet. Das bedeutet aber auch, dass Du dabei
die Timer-Routine evtl. anpassen musst, weil beim WordClock-Projekt noch
ganz andere Sachen als nur IRMP aus dem Timer aufgerufen wird.
Einfacher wäre es natürlich, Deine erfolgreich getestete FB plus
TSOP1736 oder (heutzutage) TSOP31238 zu verwenden ;-)
Frank M. schrieb:> Der IRMP-Source im WordClock-Projekt ist schon ein paar Jährchen alt - 3> Jahre mindestens. Könnten auch 4 Jahre sein.
Ist WordClock SW 0.13 und in der Tat deine inkludierte irmp.c von Mitte
2010. Habe auch ein wenig länger gebraucht. Habe noch die Frontplatte
aus deiner ersten Sammelbestellung ;) Und als es im Rahmen deiner
IRMP-Entwicklung um das B&O-Protokoll ging, hatte dir Klaus (soweit ich
mich erinnere) Scans zur Verfügung gestellt und ich hatte parallel das
Datalink-Dokument im Netz entdeckt, welches aktuell noch hier im Wiki zu
finden ist.
> Du solltest erstmal den aktuellen IRMP-Stand ins WordClock-Projekt> einbauen. Sollte nicht sooo schwierig sein.
Ok. Mache ich.
>> Obwohl die mit TSOP 1736 sofort lief.>> Nochmal: Welche? Tatsächlich die B&O-FB?
Dann hätte ich vermutlich ein Sonder-Exemplar des 1736 der sooo
breitbandig empfängt, dass er noch bis zum 13-fachen seiner Nennfrequenz
reagiert. Spaß beiseite. Den 1736 habe ich mit einer x-beliebigen
Fernbedienung aus der Wühlkiste - glaube es war Medion - ausprobiert.
Lief auf Anhieb.
> Wenn ich es recht in Erinnerung habe, läuft IRMP im WordClock-Projekt> mit F_INTERRUPTS 10000. Das ist bei dem B&O-Protokoll ziemlich> problematisch, da die Pulse hier ultrakurz sind, nämlich nur 200µs. Bei> einer Abtastrate von 10000 Hz "sieht" IRMP nur 1-2 mal hintereinander,> dass da überhaupt etwas ist.>> Du könntest F_INTERRUPTS auf 15000 erhöhen. Dann werden die Pulse> wenigstens 2-3 mal aufgezeichnet. Das bedeutet aber auch, dass Du dabei> die Timer-Routine evtl. anpassen musst, weil beim WordClock-Projekt noch> ganz andere Sachen als nur IRMP aus dem Timer aufgerufen wird.
Gefühlsmäßig kann das hinkommen, denn es erscheint mir unlogisch, wenn
hardwareseitig sporadisch mal nen Signal durchkommt und mal nicht.
Fühlte sich auch eher so an, als ob mal softwareseitig mal ein Frame
erkannt wird und dann lange Zeit nicht ...
> Einfacher wäre es natürlich, Deine erfolgreich getestete FB plus> TSOP1736 oder (heutzutage) TSOP31238 zu verwenden ;-)
Wenn alle Stricken reißen, dann werde ich genau das tun ;) So viel
Interaktion findet später im Betrieb nun wirklich nicht statt.
Vielen Dank Frank. Für deine Hilfe, für IRMP, für WordClock, für
Frontplatte usw.
Es werden zu viele Bits gesendet. Wird anscheinend durch send_trailer
gesteuert. Was ist der Sinn?
Es wird eine Framewiederholung gesendet, obwohl das vierte Argument des
Aufrufs 0 ist. Das passiert selbst dann, wenn ich n_auto_repetitions=0
im Codezweig für das Protokoll setze (da steht eine 1).
Was mache ich falsch?
E. K. schrieb:> irsnd verhält sich merkwürdig:
Nein, eigentlich nicht ;-)
> Es werden zu viele Bits gesendet. Wird anscheinend durch send_trailer> gesteuert. Was ist der Sinn?
Was meinst Du mit "zu viele Bits"? Den zweiten Frame?
> Es wird eine Framewiederholung gesendet, obwohl das vierte Argument des> Aufrufs 0 ist.
Das ist keine echte Framewiederholung, denn dann würde der zweite Frame
in derselben Zeile stehen. Das passiert aber nur, wenn das vierte
Argument des Aufrufs ungleich 0 ist.
Das, was Du da unter Linux siehst, ist etwas ganz anderes. Im
Linux-main() habe ich eingebaut, dass der zu sendende Code (nicht
unbedingt derselbe Frame!) zweimal ausgesandt wird - mit entsprechender
Pause dazwischen.
Ich rufe einfach irsnd_send_data() zweimal auf:
1
(void)irsnd_send_data(&irmp_data,TRUE);
2
while(irsnd_busy)
3
{
4
irsnd_ISR();
5
}
6
putchar('\n');
7
#if 1 // enable here to send twice
8
(void)irsnd_send_data(&irmp_data,TRUE);
9
while(irsnd_busy)
10
{
11
irsnd_ISR();
12
}
13
putchar('\n');
14
#endif
IRSND unter Linux verhält sich daher so, als ob ein Benutzer 2x auf eine
Taste (mit Pause dazwischen) drückt. Es handelte sich also NICHT um
eine Framewiederholung, die zum Beispiel bei der Angabe eines "echten"
vierten Arguments erscheint.
Warum mache ich das? Damit kann man wunderbar testen, ob bei
Protokollen, die ein Toggle-Bit verwenden, wenn der Benutzer zweimal
(mit Abstand) eine Taste drückt, IRSND das auch korrekt umsetzt. Aber
das ist nur eine Anwendung. Ich möchte auch wissen, ob IRSND
reproduzierbare Ergebnisse liefert.
Beispiel RC5:
1
./irsnd-15kHz 7 2 3 0 | ./irmp-15kHz
2
1100010000011 p= 7 (RC5), a=0x0002, c=0x0003, f=0x00 Erster Tastendruck
Siehst Du das Toggle-Bit? irmp_data.flags bleibt dabei übrigens 0x00
(s.o.), d.h. es handelt sich um keine echte Framewiederholung.
Und jetzt das ganze mit einer Frame-Wiederholung:
1
./irsnd-15kHz 7 2 3 1 | ./irmp-15kHz
2
1100010000011 p= 7 (RC5), a=0x0002, c=0x0003, f=0x00 Erster Tastendruck
Jetzt passiert eine "echte" Frame-Wiederholung. Das Toggle-Bit ändert
sich nicht bei der Wiederholung, flags ist dann auch gleich 0x01. Jetzt
kommt der zweite Tastendruck: Das Toggle-Bit ändert sich, flags geht
aber wieder auf 0. Hier wurde also das zweimalige längere Drücken
einer Taste simuliert.
EDIT: Ich habe gerade dem IRMP-Artikel diese Erklärung in Auszügen
hinzugefügt:
http://www.mikrocontroller.net/articles/IRMP#IRSND_unter_Windows
Frank M. schrieb:> Vielen Dank. Ich werde Deine Änderungen in den IRMP-Code einarbeiten.>> Eventuell komme ich nochmal auf Dich für eine Rückfrage zurück.
Entweder hast du es vergessen, keine Zeit gehabt oder es gibt wohl keine
Rückfragen :P
Hallo Matthias,
Matthias Frank schrieb:> Entweder hast du es vergessen, keine Zeit gehabt oder es gibt wohl keine> Rückfragen :P
Sorry, hatte in letzter Zeit weniger Zeit bzw. war mit anderen Sachen
beschäftigt. Deinen Code habe ich aber mittlerweile im IRMP drin. Das
Update kommt bis spätestens Wochenende.
Gruß,
Frank
So, hier ist es endlich:
Version 2.8.0:
- Portierung auf AVR XMega
Version 2.8.1:
- Neues Protokoll: PENTAX
SVN- und Download-Dateien sind auf dem Stand 2.8.1. Artikel ist
aktualisiert.
Viel Spaß,
Frank
Hallo,
bei einer Multimedia-Anwendung (https://github.com/j1rie/IRMP_STM32 im
Zusammenhang mit VDR und Kodi) habe ich das Problem, dass, obwohl eine
Taste garnicht festgehalten wird, teilweise eine Tastenwiederholung
erkannt wird.
Deshalb die Frage: Wird für RC5 bereits das Toggle-Bit unterstützt und
wenn nein: Ab wann kann man mit einer Unterstützung rechnen?
Danke im Voraus.
Manuel Reimer schrieb:> bei einer Multimedia-Anwendung (https://github.com/j1rie/IRMP_STM32 im> Zusammenhang mit VDR und Kodi) habe ich das Problem, dass, obwohl eine> Taste garnicht festgehalten wird, teilweise eine Tastenwiederholung> erkannt wird.
Geht es dabei konkret um RC5?
> Deshalb die Frage: Wird für RC5 bereits das Toggle-Bit unterstützt und> wenn nein: Ab wann kann man mit einer Unterstützung rechnen?
Wie Jörg bereits bestens recherchiert hat:
1. Das Toggle-Bit wird von IRMP u.a. als Kriterium verwendet, ob eine
Taste kurz oder lang gedrückt wurde.
2. Das Toggle-Bit wird nicht an die Anwendung zurückgegeben.
Stattdessen
wird irmp_data.flag gesetzt, wenn die Taste länger gedrückt wurde.
Jörg R. schrieb:> bei Manuel gibt es mit Logging Probleme, die er ohne nicht hat.> Kann es sein, dass das Logging den STM32 so stark belastet, dass es zu> falscher IR Erkennung kommt? Genauer gesagt, werden bei ihm die Flags> falsch erkannt.
Kann ich mir eigentlich nicht vorstellen - gerade nicht beim STM32.
Aber:
Das Logging ist dafür gedacht, unbekannte Protokolle mitzuschneiden,
damit man sie später am PC auswerten kann. Da unbekannte Protokolle ja
eben unbekannt sind, erhebt die Software keinerlei Anspruch auf korrekte
Funktionalität bezüglich korrektes Erkennen eines Protokolls während
dieser Zeit. Daher schließen sich diese beiden Betriebsmodi eigentlich
gegenseitig aus.
Eingeschaltetes Logging ist nicht für den Normalbetrieb gedacht. Manuel
sollte es daher abschalten.
Frank M. schrieb:> So, hier ist es endlich:>> Version 2.8.0:>> - Portierung auf AVR XMega
Ich habe die neue Version gerade getestet. Leider haben sich dort noch
ein paar kleine Fehler eingebaut, welche behoben werden müssten.
Ich habe die abgeänderten Dateien hochgeladen, aber habe wieder
eine Warnung an den Entsprechenden stellen eingefügt, damit es
gleich ersichtlich ist.
irmp.h Zeile 24-29 bein CONCAT muss immer PORT stehen.
irsnd.c Zeile 477 und Zeile 594
IRSND_XMEGA_OC1A und IRSND_XMEGA_OC1B
wurde falsch behandelt (mein Fehler)
1
# if (IRSND_OCx == IRSND_XMEGA_OC0A) // use OC0A
2
XMEGA_Timer.CTRLB|=(1<<TC0_CCAEN_bp);// Compare A
3
# elif (IRSND_OCx == IRSND_XMEGA_OC0B) // use OC0B
4
XMEGA_Timer.CTRLB|=(1<<TC0_CCBEN_bp);// Compare B
5
# elif IRSND_OCx == IRSND_XMEGA_OC0C // use OC0C
6
XMEGA_Timer.CTRLB|=(1<<TC0_CCCEN_bp);// Compare C
7
# elif IRSND_OCx == IRSND_XMEGA_OC0D // use OC0D
8
XMEGA_Timer.CTRLB|=(1<<TC0_CCDEN_bp);// Compare D
9
# elif IRSND_OCx == IRSND_XMEGA_OC1A // use OC1A
10
XMEGA_Timer.CTRLB|=(1<<TC1_CCAEN_bp);// Compare A
11
# elif IRSND_OCx == IRSND_XMEGA_OC1B // use OC1B
12
XMEGA_Timer.CTRLB|=(1<<TC1_CCBEN_bp);// Compare B
1
if(IRSND_OCx==IRSND_XMEGA_OC0A)// use OC0A
2
XMEGA_Timer.CTRLB&=~(1<<TC0_CCAEN_bp);// Compare A disconnected
3
# elif (IRSND_OCx == IRSND_XMEGA_OC0B) // use OC0B
4
XMEGA_Timer.CTRLB&=~(1<<TC0_CCBEN_bp);// Compare B disconnected
5
# elif IRSND_OCx == IRSND_XMEGA_OC0C // use OC0C
6
XMEGA_Timer.CTRLB&=~(1<<TC0_CCCEN_bp);// Compare C disconnected
7
# elif IRSND_OCx == IRSND_XMEGA_OC0D // use OC0D
8
XMEGA_Timer.CTRLB&=~(1<<TC0_CCDEN_bp);// Compare D disconnected
9
# elif IRSND_OCx == IRSND_XMEGA_OC1A // use OC1A
10
XMEGA_Timer.CTRLB&=~(1<<TC1_CCAEN_bp);// Compare A disconnected
11
# elif IRSND_OCx == IRSND_XMEGA_OC1B // use OC1B
12
XMEGA_Timer.CTRLB&=~(1<<TC1_CCBEN_bp);// Compare B disconnected
irsnd.config Zeile 98 Mir viel hier auf, dass die Timer Nummer
unnötig ist und man hier auch stattdessen direkt IRSND_PORT_PRE
angeben könnte. Außerdem war in den Kommentaren von OC0 statt
OC1 die Rede (mein Fehler).
Matthias Frank schrieb:> Ich habe die neue Version gerade getestet. Leider haben sich dort noch> ein paar kleine Fehler eingebaut, welche behoben werden müssten.> Ich habe die abgeänderten Dateien hochgeladen, aber habe wieder> eine Warnung an den Entsprechenden stellen eingefügt, damit es> gleich ersichtlich ist.
Vielen Dank! Ich habe die Änderungen eingebaut und das ganze als Version
2.8.2 hochgeladen. Der Artikel und die Downloads sind aktualisiert.
Viel Spaß,
Frank
Hi Frank,
Frank M. schrieb:> Der Artikel und die Downloads sind aktualisiert.
Es scheint, als ob du schon seit längerem vergessen hättest die
Versionsnummern in der README Datei zu bumpen, oder?
Mit freundlichen Grüßen,
Karol Babioch
Micha schrieb:> In irmpsystem.h nach Zeile 32 fehlt ein> #define F_CPU (SysCtlClockGet()).
Danke, habe ich nun in Version 2.8.3 hinzugefügt.
Karol Babioch schrieb:> Es scheint, als ob du schon seit längerem vergessen hättest die> Versionsnummern in der README Datei zu bumpen, oder?
Danke für den Hinweis. Ja, da hab ich wohl etwas geschlampt. Ist mit
2.8.3 korrigiert.
Artikel, Downloads & SVN habe ich aktualisiert.
Viel Spaß,
Frank
Ich hab gerade die aktuelle Version noch einmal getestet.
Irgendwie hatte sich bei meiner hochgeladenen Datei doch noch
ein Fehler eingeschlichen.
So ist es jetzt aber richtig:
irsnd.c ab Zeile 471
1
# elif IRSND_OCx == IRSND_XMEGA_OC1A // use OC1A
2
XMEGA_Timer.CTRLB|=(1<<TC1_CCAEN_bp);// Compare A
3
# elif IRSND_OCx == IRSND_XMEGA_OC1B // use OC1B
4
XMEGA_Timer.CTRLB|=(1<<TC1_CCBEN_bp);// Compare B
5
# else
6
# error wrong value of IRSND_OCx
7
# endif // IRSND_OCx
Ich habe in meinem Zimmer einen Ventilator, den ich steuern will. Leider
scheint irmp das Protokoll nicht zu erkennen.
In deinem Artikel hast du geschrieben, dass du dir auch unbekannte
Artikel anschauen würdest und diese vlt hinzufügen würdest, wenn es
möglich ist.
Dafür muss ich aber das Protokoll per serieller Schnittstelle ausgeben.
Ich versteh aber noch nicht ganz was ich alles ändern muss, damit ich
diese Ausgabe mit dem Xmega hinbekomme. Könntest du mir hierzu einen
Ansatz geben?
Eine UART initialisierung beim Xmega sieht in etwas so aus:
1
voidinit_USART(void)
2
{
3
//Alle Level für Prioritätensteuerung der Interrupts freigeben
Matthias Frank schrieb:> Ich hab gerade die aktuelle Version noch einmal getestet.> Irgendwie hatte sich bei meiner hochgeladenen Datei doch noch> ein Fehler eingeschlichen.
Danke, ich habe die Korrektur ins SVN als Version 2.8.4 eingecheckt.
Die Download-Dateien werde ich bei Gelegenheit aktualisieren.
> Ich habe in meinem Zimmer einen Ventilator, den ich steuern will. Leider> scheint irmp das Protokoll nicht zu erkennen.
Ja, die Hersteller denken sich immer wieder neue aus. ;-)
> In deinem Artikel hast du geschrieben, dass du dir auch unbekannte> Artikel anschauen würdest und diese vlt hinzufügen würdest, wenn es> möglich ist.
Ja, klar.
> Dafür muss ich aber das Protokoll per serieller Schnittstelle ausgeben.> Ich versteh aber noch nicht ganz was ich alles ändern muss, damit ich> diese Ausgabe mit dem Xmega hinbekomme. Könntest du mir hierzu einen> Ansatz geben?
Das Prinzip ist eigentlich einfach:
1. Erweiterung von irmp_uart_init() um die µC-spezifischen
UART-Initialisierungen, also Einbau Deiner uart_init().
2. Erweiterung von irmp_uart_putc().
Das wars. Anschließend noch IRMP_LOGGING auf 1 setzen, dann ein
Terminal-Emulationsprogramm starten. Die 0en und 1en sollten nun
ausgegeben werden, sobald Du eine IR-Taste drückst.
Du kopierst die Daten in eine Datei und schickst sie mir.
Aufbau:
- Pro IR-Frame eine Zeile
- Kommentare wie "Taste PowerOn" mit '#' einleiten
Beispiel:
1
# Taste Buuuuuuum!
2
00000000111111110000001111000001111100000.......
Weitere Beispiele findest Du im Unterverzeichnis IR-Data.
> Eigentlich reicht es, wenn du diese Änderung übernimmst, sobald auch die> Serielle Schnittstelle funktioniert.
Fehlt nur noch eine Implementierung von irmp_uart_putc().
ok hat sogar ziemlich schnell geklappt :P
die Tasten haben irgendwie eine unterschiedliche Länge.
ich glaub das hängt damit zusammen, wie lange ich die Taste gedrückt
gehalten haben.
Kürzer wie MODE und OSC habe ich es nicht hinbekommen.
Ich werde nächste Woche den geänderten Code hier hochladen, da ich
schauen will ob ich ihn vlt noch übersichtlicher machen kann.
Hi,
Matthias Frank schrieb:> die Tasten haben irgendwie eine unterschiedliche Länge.> ich glaub das hängt damit zusammen, wie lange ich die Taste gedrückt> gehalten haben.> Kürzer wie MODE und OSC habe ich es nicht hinbekommen.
Keine Sorge, Frank ist mitlerweile richtig fit im Dekodieren von
IR-Protokollen :). Wenn er noch etwas braucht, dann meldet er sich
schon. Ansonsten nimmt er das direkt in eine der nächsten Versionen auf,
sobald er ein paar freie Augenblicke Zeit hat ;).
> Ich werde nächste Woche den geänderten Code hier hochladen, da ich> schauen will ob ich ihn vlt noch übersichtlicher machen kann.
Was meinst du damit? Die Änderungen, die für das Logging notwendig
waren? Ich weiß nicht so recht, inwiefern diese relevant sind bzw. Teil
von IRMP werden sollten.
Mit freundlichen Grüßen,
Karol Babioch
Matthias Frank schrieb:> ok hat sogar ziemlich schnell geklappt :P
Habs gerade mit IRMP unter Linux eingelesen. Hat auch ziemlich schnell
geklappt.... denn es ist das NUBERT-Protokoll, welches eigentlich für
Lautsprechersysteme verwendet wird.
Ich brauche da also nichts in IRMP einzubauen. Aktiviere einfach NUBERT
in irmpconfig.h und es wird funktionieren.
> Ich werde nächste Woche den geänderten Code hier hochladen, da ich> schauen will ob ich ihn vlt noch übersichtlicher machen kann.
Prima.
Viel Spaß,
Frank
Karol Babioch schrieb:> Keine Sorge, Frank ist mitlerweile richtig fit im Dekodieren von> IR-Protokollen :).
War noch nichtmals nötig, IRMP kannte das Protokoll bereits :-)
Ich mache mir mittlerweile Gedanken, wie der User bei der Vielzahl an
Protokollen "seins" selber finden könnte. Mittlerweile sind wir ja bei
über 40 Stück...
>> Ich werde nächste Woche den geänderten Code hier hochladen, da ich>> schauen will ob ich ihn vlt noch übersichtlicher machen kann.>> Was meinst du damit? Die Änderungen, die für das Logging notwendig> waren?
Ja, eine XMega-Variante fürs Logging gibt's noch nicht in IRMP. Daher
wäre das schon wünschenswert.
Gruß,
Frank
Frank M. schrieb:> War noch nichtmals nötig, IRMP kannte das Protokoll bereits :-)>> Ich mache mir mittlerweile Gedanken, wie der User bei der Vielzahl an> Protokollen "seins" selber finden könnte. Mittlerweile sind wir ja bei> über 40 Stück...
Ja stimmt, mit dem NUBERT-Protokoll hat es gleich funktioniert.
Allerdings nicht ganz so wie es soll. Die Taste OFF wird seltsamerweiße
von IRMP nicht erkannt, daher bin ich auch nicht darauf gekommen, dass
es sich um dieses Protokoll handelt, da ich nur diese eine Taste
getestet habe.
Außerdem wird jede Taste beim senden irgendwie 2 mal vom Ventilator
erkannt, obwohl irmp_data.flags auf 0 ist.
Sind da im Protokoll vlt noch kleine Schönheitsfehler? :P
Matthias Frank schrieb:> Ja stimmt, mit dem NUBERT-Protokoll hat es gleich funktioniert.> Allerdings nicht ganz so wie es soll. Die Taste OFF wird seltsamerweiße> von IRMP nicht erkannt, daher bin ich auch nicht darauf gekommen, dass> es sich um dieses Protokoll handelt, da ich nur diese eine Taste> getestet habe.
Stimmt, jetzt sehe ich das auch in Deinem Scan. Das Stop-Bit ist hier
doppelt so lang wie die anderen. Daher wird der Frame verworfen. Das
spricht dafür, dass Deine Ventilator-FB gar keine Stop-Bits verwendet
und der letzte Puls noch ein weiteres Datenbit ist. Das wäre dann ein
klarer Unterschied zu Nubert.
> Außerdem wird jede Taste beim senden irgendwie 2 mal vom Ventilator> erkannt, obwohl irmp_data.flags auf 0 ist.> Sind da im Protokoll vlt noch kleine Schönheitsfehler? :P
Ich habe gerade mal nachgeschaut. Original-Nubert-Lautstprecher wollen
wohl immer mindestens 2 Frames sehen. Deshalb schickt IRSND im Fall
NUBERT für flags=0,1,2 immer 2,4,8... Frames.
Oder derjenige, der mir die Nubert-Scans zugeschickt hat, hat leider
immer die Tasten zu lange gedrückt und ich habe dann daraus die falschen
Schlüsse gezogen. Kommt leider öfters vor, weil die Leute es einfach zu
gut meinen. Auch Dir ist das bei 2 Tasten passiert ;-)
Hm, jetzt weiß ich nicht, wie ich damit umgehen soll. Wenn ich jetzt
IRSND derart ändere, dass NUBERT-Frames nur einmal geschickt werden,
dann kann es sein, dass Nubert-Lautsprecher die Befehle nicht mehr
akzeptieren.
Du kannst jetzt erstmal in irmpprotocols.h ändern:
Alt:
1
#define NUBERT_FRAMES 2 // Nubert sends 2 frames
Neu:
1
#define NUBERT_FRAMES 1 // Nubert sends 1 frame
Dann sollte es bei Dir erstmal laufen - bis auf den Off-Befehl.
Am besten führe ich eine neue Protokoll-Nummer für Dein
Ventilator-Protokoll ein, um das allgemein zu lösen. Dann kann ich beide
Abweichungen (nur 1 Frame statt 2 und ein Datenbit mehr, aber kein
Stop-Bit) berücksichtigen.
Ich melde mich dazu nochmal.