Forum: Projekte & Code IRMP - Infrared Multi Protocol Decoder


von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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_t ii;
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
60
              ii = key_state ^ ( ( ~(unsigned char)i2c_readNak() ) ); //jar key1 kaputt    
61
              // ii = key_state ^ ( ( ~(unsigned char)i2c_readNak() ) ___ ); //jar key1 kaputt    
62
            i2c_stop();
63
         }
64
         else
65
         {  if(!i2c_start(PCF8574_0+I2C_READ))  //;  // set device address and write mode
66
            ii = key_state ^ ( ( ~(unsigned char)i2c_readNak() ) ); //jar key1 kaputt    
67
            // ii = key_state ^ ( ( ~(unsigned char)i2c_readNak() ) ___ ); //jar key1 kaputt    
68
            // ___ | ((~ALARM_int1_PIN & (1<<_ALARM_int1_pin))>>2)
69
            i2c_stop();
70
         }
71
         _i2c_busy=0;
72
      }
73
  
74
      ii &= ALL_KEYS;
75
      //cam = ii & (1<<CAM_F || 1<<CAM_S);
76
      ct0 = ~( ct0 & ii );                             // reset or count ct0
77
      ct1 = ct0 ^ (ct1 & ii);                          // reset or count ct1
78
      ii &= ct0 & ct1;                                 // count until roll over ?
79
      key_state ^= ii;                                 // then toggle debounced state
80
      key_press |= key_state & ii;                     // 0->1: key press detect
81
   
82
      if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
83
      rpt = REPEAT_START;                          // start delay
84
      if( --rpt == 0 )
85
      {  rpt = REPEAT_NEXT;                            // repeat delay
86
         key_rpt |= key_state & REPEAT_MASK;
87
      }
88
    }
89
#ifdef IRQ_TEST
90
PORT_CRTL_LED &= ~(1<<CRTL_LED);
91
#endif
92
  }
93
} // ISR (TIMER1_COMPA_vect)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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?

von Joachim B. (jar)


Lesenswert?

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.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Bruno M. (brumay)


Lesenswert?

> 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!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Bruno M. (brumay)


Lesenswert?

> 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.

von Bruno M. (brumay)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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 ;-)

von Bruno M. (brumay)


Lesenswert?

> 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>

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Bruno M. schrieb:
> protocol: 0x05   YO   address: 0x2002   command: 0x90A0   flags:
> 0x00<\r><\n>

Du hast jetzt auch die irmp.c-Version, wo
1
static const char proto_unknown[]       PROGMEM = "UNKNOWN";
2
usw. (viele PROGMEM-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.

: Bearbeitet durch Moderator
von Bruno M. (brumay)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
    uart_puts_P (irmp_protocol_names[irmp_data.protocol]);

durch:
1
    PGM_P p = (PGM_P) pgm_read_word (irmp_protocol_names[irmp_data.protocol]);
2
    uart_puts_P (p);

von Bruno M. (brumay)


Lesenswert?

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

von Joachim B. (jar)


Lesenswert?

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.

: Bearbeitet durch User
von Karol B. (johnpatcher)


Lesenswert?

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

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

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.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
   PGM_P p = (PGM_P) pgm_read_word (&(irmp_protocol_names[irmp_data.protocol]));

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
static const char proto_unknown[]       PROGMEM = "UNKNOWN";
2
static const char proto_sircs[]         PROGMEM = "SIRCS";
3
static const char proto_nec[]           PROGMEM = "NEC";
4
...

... und zum anderen das Array selbst:
1
const char * 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

von Karol B. (johnpatcher)


Lesenswert?

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

: Bearbeitet durch User
von Bruno M. (brumay)


Lesenswert?

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.

von Bruno M. (brumay)


Lesenswert?

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?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Karol B. (johnpatcher)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Bruno M. (brumay)


Lesenswert?

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
1
strcpy_P(p ,(PGM_P) pgm_read_word (&(irmp_protocol_names[irmp_data.protocol])));
2
      lcd_string(p);


probiert. Geht auch, aber dann warnt der Compiler wegen char und const 
char.

von Bruno M. (brumay)


Lesenswert?

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.

von Karol B. (johnpatcher)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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 ;-)

von Karol B. (johnpatcher)


Lesenswert?

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?"

von Joachim B. (jar)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

: Bearbeitet durch Moderator
von Joachim B. (jar)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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 ?

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Joachim B. (jar)


Lesenswert?

danke mache ich, nichts für ungut .....

von Joachim B. (jar)


Lesenswert?

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....

von Karol B. (johnpatcher)


Lesenswert?

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

von Joachim B. (jar)


Lesenswert?

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

: Bearbeitet durch User
von Karol B. (johnpatcher)


Lesenswert?

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

von SvenK (Gast)


Lesenswert?

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

von Karol B. (johnpatcher)


Lesenswert?

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:
1
Building target: Wordclock.elf
2
Invoking: AVR C Linker
3
avr-gcc -Wl,-Map,Wordclock.map -Wl,-gc-sections -mmcu=atmega328p -o "Wordclock.elf"  ./src/base.o ./src/brightness.o ./src/color.o ./src/datetime.o ./src/dcf77.o ./src/display.o ./src/display_wc.o ./src/display_wc_eng.o ./src/display_wc_ger.o ./src/display_wc_ger3.o ./src/eeprom.o ./src/fifo.o ./src/i2c_master.o ./src/i2c_rtc.o ./src/ldr.o ./src/log.o ./src/main.o ./src/memcheck.o ./src/preferences_eeprom.o ./src/prng.o ./src/pwm.o ./src/shift.o ./src/timer.o ./src/uart.o ./src/uart_protocol.o ./src/user.o  ./lib/IRMP/irmp.o   
4
Finished building target: Wordclock.elf

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

von Joachim B. (jar)


Lesenswert?

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 !

von Karol B. (johnpatcher)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
#define lcd_printyx_P(__line, __column, __text) lcd_printyx_s (__line, __column, (unsigned char *) PSTR(__text), TRUE)
2
#define lcd_printyx(__line, __column, __text)   lcd_printyx_s (__line, __column, (unsigned char *) __text, FALSE)

>> 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
1
avr-gcc  -mmcu=atmega88 -Wall -gdwarf-2 -std=gnu99     -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -flto  -ffunction-sections  -fdata-sections  -MD -MP -MT main.o -MF dep/main.o.d  -c  ../main.c
2
avr-gcc  -mmcu=atmega88 -Wall -gdwarf-2 -std=gnu99     -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -flto  -ffunction-sections  -fdata-sections  -MD -MP -MT irmp.o -MF dep/irmp.o.d  -c  ../irmp.c
3
avr-gcc -mmcu=atmega88 -flto  -ffunction-sections  -fdata-sections  -Wl,--gc-sections  -Wl,-Map=irmp.map main.o irmp.o     -o irmp.elf
4
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  irmp.elf irmp.hex
5
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex irmp.elf irmp.eep || exit 0
6
avr-objdump -h -S irmp.elf > irmp.lss

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:
1
avr-gcc  -mmcu=atmega88 -Wall -gdwarf-2 -std=gnu99      -flto  -ffunction-sections  -fdata-sections   -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT main.o -MF dep/main.o.d  -c  ../main.c
2
avr-gcc  -mmcu=atmega88 -Wall -gdwarf-2 -std=gnu99      -flto  -ffunction-sections  -fdata-sections   -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT irmp.o -MF dep/irmp.o.d  -c  ../irmp.c
3
avr-gcc -mmcu=atmega88 -flto  -ffunction-sections  -fdata-sections  -Wl,--gc-sections  -Os  -Wl,-Map=irmp.map main.o irmp.o     -o irmp.elf
4
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  irmp.elf irmp.hex
5
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex irmp.elf irmp.eep || exit 0
6
avr-objdump -h -S irmp.elf > irmp.lss

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:
>
>
1
> Building target: Wordclock.elf
2
> Invoking: AVR C Linker
3
> avr-gcc -Wl,-Map,Wordclock.map -Wl,-gc-sections -mmcu=atmega328p -o 
4
> "Wordclock.elf"  ./src/base.o ./src/brightness.o ./src/color.o 
5
> ./src/datetime.o ./src/dcf77.o ./src/display.o ./src/display_wc.o 
6
> ./src/display_wc_eng.o ./src/display_wc_ger.o ./src/display_wc_ger3.o 
7
> ./src/eeprom.o ./src/fifo.o ./src/i2c_master.o ./src/i2c_rtc.o 
8
> ./src/ldr.o ./src/log.o ./src/main.o ./src/memcheck.o 
9
> ./src/preferences_eeprom.o ./src/prng.o ./src/pwm.o ./src/shift.o 
10
> ./src/timer.o ./src/uart.o ./src/uart_protocol.o ./src/user.o 
11
> ./lib/IRMP/irmp.o
12
> Finished building target: Wordclock.elf
13
>

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. 
:-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hallo Jörg,

Jörg R. schrieb:
> Logging für den STM32F10x:

Danke für den Port, ich habs ins SVN eincheckt als Version 2.6.6.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Karol B. (johnpatcher)


Lesenswert?

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:
1
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wall -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -flto -ffunction-sections -fdata-sections -c irmp/main.c
2
3
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wall -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -flto -ffunction-sections -fdata-sections -c irmp/irmp.c
4
5
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wl,--gc-sections -Wl,-Map=main.map main.o irmp.o -o main.elf
6
7
[johnpatcher@vpcs irmp]$ avr-size main.elf 
8
   text     data      bss      dec      hex  filename
9
   2444        4       48     2496      9c0  main.elf

Ich habe also mit -flto kompiliert aber ohne -flto gelinkt.

Wenn ich dann nochmal mit allen von dir o.g. Optionen (samt -flto und 
-Os) linke:
1
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wl,--gc-sections -flto -ffunction-sections -fdata-sections -Os -Wl,-Map=main.map main.o irmp.o -o main.elf
2
3
[johnpatcher@vpcs irmp]$ avr-size main.elf 
4
   text     data      bss      dec      hex  filename
5
   2444        4       48     2496      9c0  main.elf

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).
1
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wall -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -c irmp/irmp.c
2
3
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wall -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -c irmp/main.c
4
5
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wall -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -c irmp/main.c
6
7
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wl,--gc-sections -ffunction-sections -fdata-sections -Wl,-Map=main.map main.o irmp.o -o main.elf
8
9
[johnpatcher@vpcs irmp]$ avr-size main.elf 
10
   text     data      bss      dec      hex  filename
11
   2484        4       48     2536      9e8  main.elf

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:
1
Building target: Wordclock.elf
2
Invoking: AVR C Linker
3
avr-gcc -Wl,-Map,Wordclock.map -Wl,-gc-sections -Os -flto -mmcu=atmega328p -o "Wordclock.elf"  ./src/base.o ./src/brightness.o ./src/color.o ./src/datetime.o ./src/dcf77.o ./src/display.o ./src/display_wc.o ./src/display_wc_eng.o ./src/display_wc_ger.o ./src/display_wc_ger3.o ./src/eeprom.o ./src/fifo.o ./src/i2c_master.o ./src/i2c_rtc.o ./src/ldr.o ./src/log.o ./src/main.o ./src/memcheck.o ./src/preferences_eeprom.o ./src/prng.o ./src/pwm.o ./src/shift.o ./src/timer.o ./src/uart.o ./src/uart_protocol.o ./src/user.o  ./lib/IRMP/irmp.o   
4
Finished building target: Wordclock.elf

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

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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 :-)

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
avr-gcc -mmcu=atmega88 -flto  -Os  -Wl,-Map=irmp.map main.o irmp.o     -o irmp.elf

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.

: Bearbeitet durch Moderator
von Karol B. (johnpatcher)


Angehängte Dateien:

Lesenswert?

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:
1
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -flto -Wall -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -c irmp/main.c
2
3
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -flto -Wall -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -c irmp/irmp.c
4
5
[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wl,--gc-sections -Wl,-Map=main.map main.o irmp.o -o main.elf
6
7
[johnpatcher@vpcs irmp]$ avr-size main.elf 
8
   text     data      bss      dec      hex  filename
9
   2444        4       48     2496      9c0  main.elf

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?

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 
;).

Mit freundlichen Grüßen,
Karol Babioch

[1]: https://www.gnu.org/software/gcc/gcc-4.9/
[2]: https://gcc.gnu.org/ml/gcc/2014-07/msg00163.html
[3]: https://www.gnu.org/software/gcc/gcc-4.7/changes.html
[4]: https://www.gnu.org/software/gcc/gcc-4.8/changes.html
[5]: https://www.gnu.org/software/gcc/gcc-4.8/changes.html

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
avr-gcc  -mmcu=atmega88 -Wall -flto -ffunction-sections -fdata-sections -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums  -MD -MP -MT main.o -MF dep/main.o.d  -c  ../main.c
2
avr-gcc  -mmcu=atmega88 -Wall -flto -ffunction-sections -fdata-sections -std=c99 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums  -MD -MP -MT irmp.o -MF dep/irmp.o.d  -c  ../irmp.c
3
avr-gcc -mmcu=atmega88 -Os -Wl,-Map=irmp.map main.o irmp.o     -o irmp.elf
4
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  irmp.elf irmp.hex
5
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex irmp.elf irmp.eep || exit 0
6
avr-objdump -h -S irmp.elf > irmp.lss
7
8
AVR Memory Usage
9
----------------
10
Device: atmega88
11
12
Program:    2448 bytes (29.9% Full)
13
(.text + .data + .bootloader)
14
15
Data:         52 bytes (5.1% Full)
16
(.data + .bss + .noinit)
17
18
Build succeeded with 0 Warnings...

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:
1
diff -b main.map ../irmp.map | grep -iv c: | grep -v /usr/ |less

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:
1
$ ls -l *.elf ../*.elf
2
-rw-r--r-- 1 root root  10940 2014-09-18 18:01 ../irmp.elf
3
-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.

: Bearbeitet durch Moderator
von Karol B. (johnpatcher)


Lesenswert?

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

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Jörg R. (jrie)


Lesenswert?

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

von Karol B. (johnpatcher)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von E. K. (eku)


Lesenswert?

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:
1
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
2
static const char proto_nec[]           PROGMEM = "NEC";
3
#endif
4
5
....
6
7
const char * const
8
irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM =
9
{
10
    proto_unknown,
11
    proto_sircs,
12
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
13
    proto_nec
14
#else
15
    proto_unknown
16
#endif
17
....

: Bearbeitet durch User
von E. K. (eku)


Lesenswert?

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?

von Bruno M. (brumay)


Angehängte Dateien:

Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Bruno M. (brumay)


Lesenswert?

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

von Bruno M. (brumay)


Angehängte Dateien:

Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

: Bearbeitet durch Moderator
von Bruno M. (brumay)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
        static uint8_t last_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

: Bearbeitet durch Moderator
von Bruno M. (brumay)


Lesenswert?

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

von Karol B. (johnpatcher)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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. :-)

von Bruno M. (brumay)


Angehängte Dateien:

Lesenswert?

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

von Joachim B. (jar)


Lesenswert?

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....

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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 ;-)

: Bearbeitet durch Moderator
von Bruno M. (brumay)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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 ;-)

von Preisfrage (Gast)


Lesenswert?

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?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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!
2
#  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 ;-)

: Bearbeitet durch Moderator
von Joachim B. (jar)


Lesenswert?

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.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Conny G. (conny_g)


Lesenswert?

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)?

von Preisfrage (Gast)


Lesenswert?

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 ;)

von Preisfrage (Gast)


Lesenswert?

Achso ich hab deinen Code natürlich nicht mit meinem rumgewurstelten 
Code ausprobiert, sondern in einer sauberen Codebasis.

von Preisfrage (Gast)


Angehängte Dateien:

Lesenswert?

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).

von Andreas S. (preisfrage)


Angehängte Dateien:

Lesenswert?

Und man sollte natürlich den Pin auch entsprechend setzen, das hatte ich 
im oberen Patch vergessen. Korrigierte Version im Anhang.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Stefan Z. (stefan_z)


Lesenswert?

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".

von Joachim B. (jar)


Lesenswert?

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ß !

von Heino (Gast)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

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.

: Bearbeitet durch Moderator
von Bad U. (bad_urban)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Joachim B. (jar)


Lesenswert?

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.

von Ulli (Gast)


Lesenswert?

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?

von Joachim B. (jar)


Lesenswert?

Ulli schrieb:
> udn2003

wenn du ULN meinst den richtig benutzt und den Port und in Summe über 
alle Ports nicht GND überlastest gehts

: Bearbeitet durch User
von Stefan Z. (stefan_z)


Lesenswert?

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 :-)

von Ulli -. (ulli2k)


Lesenswert?

Super danke für die Rückmeldung. D.h. ich brauch blos die IR diode, den 
richtigen Vorwiderstand und den uln ... Damit sollte es dann klappen 
richtig?

von Joachim B. (jar)


Lesenswert?

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?

: Bearbeitet durch User
von Ulli -. (ulli2k)


Lesenswert?

Habe noch paar Relais...wäre ein chip für alles

von Jörg R. (jrie)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hallo Jörg,

Jörg R. schrieb:

> Da können 5 includes entfernt werden.

Danke für den Hinweis, Änderungen kommen mit der nächsten Version.

Gruß,

Frank

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Jörg R. (jrie)


Lesenswert?

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

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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...

von Di P. (drpepper) Benutzerseite


Lesenswert?

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)

von Jörg R. (jrie)


Lesenswert?

Hallo Frank,

"olebowle", der meinem Code vom "IRMP auf STM32" Projekt "den letzten 
Schliff" gibt, bevorzugt IRMP_DATA  anstatt als
1
typedef struct
 lieber als
1
typedef struct __attribute__ ((__packed__))
zu deklarieren. Das hat den Vorteil, dass man einfach mit memcpy und 
memcmp arbeiten kann, während ich bisher eigene Funktionen dafür benutzt 
habe. Nicht dass mich das stören würde, aber mit packed struct ist es 
einfach viel eleganter.

Nun meine Frage an dich, ob es Sinn macht, das zu übernehmen?  Oder 
stört es andere Projekte? Es macht wohl nur auf 32-bit uCs einen 
Unterschied, aber da "stören" eben die Füllbytes.

Gruß,
Jörg

https://github.com/olebowle/STM32_IRMP/commit/33be1a37471267c3af5935374ca25b96470df544
https://github.com/olebowle/STM32_IRMP/commit/db0bdbb52e345c37fecd7cdc46b9c8655119f3d0

von Michael K. (Gast)


Lesenswert?

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.

von Jörg R. (jrie)


Lesenswert?

Hallo Michael,

fast dasselbe Projekt?
Das macht mich neugierig. Lass mal mehr hören, hast du einen Link für 
mich auf dein Projekt?

Gruss,
Jörg

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Michael K. (Gast)


Lesenswert?

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.

von Jörg R. (jrie)


Lesenswert?

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

von M. K. (kichi)


Lesenswert?

Hi Jörg,
um den Beitrag hier nicht weiter zuzuspammen, habe ich dir eine 
Nachricht geschrieben.
Grüße,
Michael

von Jörg R. (jrie)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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 :-)

: Bearbeitet durch Moderator
von Jörg R. (jrie)


Lesenswert?

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

von Jörg R. (jrie)


Lesenswert?

Hallo Frank,

mit 89ms geht es auch, aber 45ms schadet bei mir nichts.

Gruß, Jörg

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Wim (Gast)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Ulli (Gast)


Lesenswert?

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!

von Konrad S. (maybee)


Lesenswert?

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.

von Ulli (Gast)


Lesenswert?

So weit bin ich schon ;)
Möchte noch weiter runter weil ich nur aus einer AA Batterie speise..

von Konrad S. (maybee)


Lesenswert?

Dann sollte der Hauptverbraucher der TSOP sein (abgesehen vom Step-Up). 
Viel mehr wird nicht zu machen sein.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Ulli -. (ulli2k)


Lesenswert?

Heißt das jetzt das irsend nicht bei 1MHz Controller Taktung lauffähig 
ist?
Woran liegt das denn?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Jörg R. (jrie)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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?

: Bearbeitet durch Moderator
von Jörg R. (jrie)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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?

von Jörg R. (jrie)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Jörg R. (jrie)


Lesenswert?

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

von Jörg R. (jrie)


Lesenswert?

Ist in Zeile 2415 von irmp.c
irmp_param_p = (IRMP_PARAMETER *) (IRMP_PARAMETER *) &sircs_param;
so richtig oder ein Verschreiber?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg R. (jrie)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg R. (jrie)


Lesenswert?

irmp.c und irmp.h sind noch nicht konsistent:
irmp_is_busy() und *cb sind verschieden deklariert

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Jörg R. (jrie)


Lesenswert?

Hui! Jetzt gleich alle?!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg R. (jrie)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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:
1
     typedef uint32_t  uint_fast8_t;

Bei AVRs jedoch:
1
     typedef uint8_t  uint_fast8_t;


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_t rtc;
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.

: Bearbeitet durch Moderator
von Jörg R. (jrie)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Jörg R. (jrie)


Lesenswert?

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?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg R. (jrie)


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Matthias F. (frank91)


Lesenswert?

gibt es mittlerweile eigentlich auch schon irmp für den xmega?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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?

von Matthias F. (frank91)


Lesenswert?

> 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

von Matthias F. (frank91)


Lesenswert?

Was genau muss ich den bei irsnd alles ändern? das kommt mir viel vor 
:-/

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Konrad S. (maybee)


Lesenswert?

Frank M. schrieb:
> So eine Konstante wird es für
> den Xmega auch geben.
1
echo | avr-gcc -E -dDM - -mmcu=atxmega128a1 | grep -i xmega
2
#define __AVR_XMEGA__ 1
3
#define __AVR_ATxmega128A1__ 1

von Matthias F. (frank91)


Angehängte Dateien:

Lesenswert?

>
1
> echo | avr-gcc -E -dDM - -mmcu=atxmega128a1 | grep -i xmega
2
> #define __AVR_XMEGA__ 1
3
> #define __AVR_ATxmega128A1__ 1
4
>

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^^

von Matthias F. (frank91)


Lesenswert?

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.

von Matthias F. (frank91)


Lesenswert?

Ich hab den Fehler gefunden, jetzt geht es :P
Ich schreibe alles noch ein bisschen schöner zusammen und lade es dann 
hoch.

von Matthias F. (frank91)


Angehängte Dateien:

Lesenswert?

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.

von Einsteiger (Gast)


Lesenswert?

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?

von Matthias F. (frank91)


Lesenswert?

> 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

http://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.

von eku (Gast)


Lesenswert?

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.

von Einsteiger (Gast)


Lesenswert?

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 ;-(

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von kum (Gast)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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 ;-)

von kum (Gast)


Lesenswert?

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.

von E. K. (eku)


Lesenswert?

Hallo Frank,

irsnd verhält sich merkwürdig:
1
./irsnd-15kHz 17 01b1 01 0
2
00001111111100001111000000001111000011111111000000001111000011111111000011110000111100000000111111110000111100001111000011110000111100001111000011110000111100001111000000001111111100001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
3
00001111111100001111000000001111000011111111000000001111000011111111000011110000111100000000111111110000111100001111000011110000111100001111000011110000111100001111000000001111111100001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

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?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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
3
1000010000011 p= 7 (RC5), a=0x0002, c=0x0003, f=0x00  Zweiter Tastendruck
4
 ^
5
 Toggle-Bit

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
3
1100010000011 p= 7 (RC5), a=0x0002, c=0x0003, f=0x01  Halten
4
1000010000011 p= 7 (RC5), a=0x0002, c=0x0003, f=0x00  Zweiter Tastendruck
5
1000010000011 p= 7 (RC5), a=0x0002, c=0x0003, f=0x01  Halten

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

: Bearbeitet durch Moderator
von Matthias F. (frank91)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

: Bearbeitet durch Moderator
von Manuel Reimer (Gast)


Lesenswert?

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.

von Jörg R. (jrie)


Lesenswert?


von Jörg R. (jrie)


Lesenswert?

Hier wurde ja mal was eingebaut dafür:
https://www.mikrocontroller.net/svnbrowser/irmp/irmp.c?r1=74&r2=73&pathrev=74
1
#if IRMP_SUPPORT_RC5_PROTOCOL == 1
2
            case IRMP_RC5_PROTOCOL:
3
                irmp_address &= ~0x20;                              // clear toggle bit
4
                rtc = TRUE;
5
                break;
6
#endif
https://www.mikrocontroller.net/svnbrowser/irmp/irmp.c?view=log&pathrev=74
"improved key repetition detection for RC5"

Ankündigung:
Beitrag "Re: IRMP - Infrared Multi Protocol Decoder"

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Jörg R. (jrie)


Lesenswert?

Hallo Frank,

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.

Mich erinnert das an die Probleme, die ich vor der Umstellung auf fast 
Variablen hatte.
Kann es sein, dass das Logging für den STM32 irgendwie optimiert werden 
muss?

Andererseits treten bei mir die Probleme, die Manuel hat, nicht auf.

Gruß,
Jörg

PS Mit allen Details ab hier:
http://www.vdr-portal.de/board18-vdr-hardware/board13-fernbedienungen/p1242784-irmp-auf-stm32-ein-usb-ir-empf%C3%A4nger-sender-einschalter-mit-wakeup-timer/#post1242784
und ab hier nachzulesen:
http://www.vdr-portal.de/board18-vdr-hardware/board13-fernbedienungen/p1242908-irmp-auf-stm32-ein-usb-ir-empf%C3%A4nger-sender-einschalter-mit-wakeup-timer/#post1242908

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

von Matthias F. (frank91)


Angehängte Dateien:

Lesenswert?

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.
1
#  define IRMP_PORT_PRE                         CONCAT(PORT, IRMP_PORT_LETTER)
2
#  define IRMP_DDR_PRE                          CONCAT(PORT, IRMP_PORT_LETTER)
3
#  define IRMP_PIN_PRE                          CONCAT(PORT, IRMP_PORT_LETTER)

irsnd.c Zeile 189-191 Vor .OUT .DIR und .IN muss immer
IRSND_PORT_PRE stehen.
1
#  define IRSND_PORT                                IRSND_PORT_PRE.OUT
2
#  define IRSND_DDR                                 IRSND_PORT_PRE.DIR
3
#  define IRSND_PIN                                 IRSND_PORT_PRE.IN

irsnd.c Zeile 751 folgendes wurde vergessen:
1
# elif defined (__AVR_XMEGA__)
2
#    warning hier wurde etwas vergessen
3
    IRSND_PORT &= ~(1<<IRSND_BIT);                                              // set IRSND_BIT to low
4
    IRSND_DDR |= (1<<IRSND_BIT);                                                // set IRSND_BIT to output
5
6
    XMEGA_Timer.PER = 0xFFFF; //Topwert
7
    XMEGA_Timer.CTRLB |= TC_WGMODE_FRQ_gc; //Modus: Frequenz entspricht CTC
8
9
#       if AVR_PRESCALER == 8
10
    XMEGA_Timer.CTRLA |= TC_CLKSEL_DIV8_gc;                                           // start Timer  prescaler = 8
11
#       else
12
    XMEGA_Timer.CTRLA |= TC_CLKSEL_DIV1_gc;                                           // start Timer  prescaler = 1
13
#       endif

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).
1
*                                              IRSND_XMEGA_OC1A = OC1A on ATxmegas  supporting OC1A, e.g. ATxmega128A1U
2
 *                                              IRSND_XMEGA_OC1B = OC1B on ATxmegas  supporting OC1B, e.g. ATxmega128A1U
3
 *---------------------------------------------------------------------------------------------------------------------------------------------------
4
 */
5
#if defined(__AVR_XMEGA__)                                              // XMEGA
6
#  define IRSND_PORT_PRE      PORTD                   
7
#  define XMEGA_Timer                           TCD0
8
#  define IRSND_OCx                             IRSND_XMEGA_OC0B        // use OC0B

irsnd.c Zeile 150 dementsprechend können hier folgende Zeilen entfernt 
werden
1
//#  if (XMEGA_Timer_NR == 1)
2
//#               define IRSND_PORT_PRE               PORTC
3
//#  elif (XMEGA_Timer_NR == 2)
4
//#               define IRSND_PORT_PRE               PORTD
5
//#  elif (XMEGA_Timer_NR == 3)
6
//#               define IRSND_PORT_PRE               PORTE
7
//#  elif (XMEGA_Timer_NR == 4)
8
//#               define IRSND_PORT_PRE               PORTF
9
//#  else
10
//#    warning wrong XMEGA_Timer_NR, choose correct value in irsndconfig.h

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Micha (Gast)


Lesenswert?

In irmpsystem.h nach Zeile 32 fehlt ein
#define F_CPU (SysCtlClockGet()).

von Karol B. (johnpatcher)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Matthias F. (frank91)


Angehängte Dateien:

Lesenswert?

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
void init_USART (void)
2
{
3
  //Alle Level für Prioritätensteuerung der Interrupts freigeben
4
  PMIC.CTRL |= PMIC_HILVLEN_bm|PMIC_MEDLVLEN_bm|PMIC_LOLVLEN_bm;
5
  
6
  //Einstellen der Baudrate
7
  //Formel zur Berechnung siehe Datenblatt Seite 282
8
  //9600 Baud => BSEL = 207 = 0xCF
9
  USARTC1.BAUDCTRLB = 0;
10
  USARTC1.BAUDCTRLA = 0xCF;
11
  USARTC1.CTRLA = USART_RXCINTLVL_HI_gc; // High Level (Empfangen)
12
  USARTC1.CTRLB = USART_TXEN_bm | USART_RXEN_bm; //Aktiviert Senden und Empfangen
13
  USARTC1.CTRLC = USART_CHSIZE_8BIT_gc; //Größe der Zeichen: 8 Bit
14
  PORTC.DIR |= (1<<7);  //TXD als Ausgang setzen
15
  PORTC.DIR &= ~(1<<6);
16
}

Eigentlich reicht es, wenn du diese Änderung übernimmst, sobald auch die 
Serielle Schnittstelle funktioniert.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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().

von Matthias F. (frank91)


Angehängte Dateien:

Lesenswert?

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.

von Karol B. (johnpatcher)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

: Bearbeitet durch Moderator
von Matthias F. (frank91)


Lesenswert?

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

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.