mikrocontroller.net

Forum: Projekte & Code IRMP - Infrared Multi Protocol Decoder


Autor: kaihs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe in einem Projekt (culfw) das eine ältere Version von IRMP 
nutzte einen Update auf die Version 2.4 gemacht, da das Senden von 
RC6/Philips nicht funktionierte.

Das funktioniert jetzt in der 2.4, dafür funktionierte das Senden von 
Samsung nicht mehr, Samsung32 dagegen immer noch.

Ich habe dann die letzten Änderungen die am Samsung-Timing vorgenommen 
worden sind wieder rückgängig gemacht, d.h.
#define SAMSUNG_1_PAUSE_TIME                    1650.0e-6                       // 1650 usec pause
#define SAMSUNG_0_PAUSE_TIME                     550.0e-6                       //  550 usec pause

wieder in
#define SAMSUNG_1_PAUSE_TIME                    1450.0e-6                       // 1450 usec pause
#define SAMSUNG_0_PAUSE_TIME                     450.0e-6                       //  450 usec pause

geändert.
Dann funktioniert das Senden von Samsung wieder, aber das Senden von 
Samsung32 ist unzuverlässiger geworden.

Kann es sein, dass die beiden Samsung Protokolle unterschiedliches 
Timing haben, 1650/550 für Samsung32 und 1450/450 für Samsung?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kaihs schrieb:
> Kann es sein, dass die beiden Samsung Protokolle unterschiedliches
> Timing haben, 1650/550 für Samsung32 und 1450/450 für Samsung?

Nein, eigentlich ist das Timing identisch. Leider ist es so, dass das 
Timing je nach Hersteller durchaus mal etwas abweichen kann.

Kannst Du mal die Mittelwerte ausprobieren, um festzustellen, ob dann 
wieder beide Protokolle zuverlässig funktionieren?

Also:
#define SAMSUNG_1_PAUSE_TIME                    1550.0e-6 // 1550 usec pause
#define SAMSUNG_0_PAUSE_TIME                     500.0e-6 //  500 usec pause

Wenn das so klappt, werde ich das übernehmen.

Autor: kaihs (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In der Annahme, dass auch Samsung Ingenieure 'glatte' Zahlen bevorzugen 
habe ich die Werte mal auf
#define SAMSUNG_1_PAUSE_TIME                    1500.0e-6 // 1500 usec pause
#define SAMSUNG_0_PAUSE_TIME                     500.0e-6 //  500 usec pause

geändert.

Dann funktionieren beide Codes bei mir.

Wäre schön, wenn du das übernehmen würdest.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kaihs schrieb:
> In der Annahme, dass auch Samsung Ingenieure 'glatte' Zahlen bevorzugen
> habe ich die Werte mal auf
>
>
> #define SAMSUNG_1_PAUSE_TIME                    1500.0e-6 // 1500 usec 
> pause
> #define SAMSUNG_0_PAUSE_TIME                     500.0e-6 //  500 usec 
> pause
> 
>
> geändert.
>
> Dann funktionieren beide Codes bei mir.

Freut mich! Übernehme ich gern. Kommt mit dem nächsten Update.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es sind neue Updates im SVN verfügbar:

IRMP: Version 2.5.3:

    05.06.2014: Neues Protokoll: LGAIR
    30.05.2014: Neues Protokoll: SPEAKER
    30.05.2014: Timings für SAMSUNG-Protokolle optimiert

IRSND: Version 2.5.2:

    03.06.2014: Neues Protokoll: TELEFUNKEN
    30.05.2014: Neues Protokoll: SPEAKER
    30.05.2014: Timings für SAMSUNG-Protokolle optimiert

LGAIR ist ein von LG verwendetes Protokoll für Klimaanlagen. Das habe 
ich anhand von Scans von einem IRMP-User aus Ungarn erfolgreich 
entschlüsseln können. Das Senden über IRSND steht noch aus, kommt aber 
in Kürze. Damit kann man seine Klimaanlage nun auch programmgesteuert 
(oder mit Remote IRMP auch übers INTERNET oder Handy) fernsteuern.

SPEAKER ist ein Protokoll zur Fernsteuerung von Lautsprechersystemen 
(ähnlich NUBERT).

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

Bewertung
0 lesenswert
nicht lesenswert
IRSND auf STM32F10x

Ich habe IRMP und IRSND auf einen STM32F105 angepasst.
Ich hätte ein paar Verbesserungsvorschläge.
Timer10 gibt es oft nicht, daher schlage ich als Default Timer4 vor. Der 
liegt per Default an B6.
Der Kommentar in Zeile 610 in irsnd.c („TODO: remapping required“) 
klingt für mich so, als ob remapping nötig wäre. Falls man den Default 
Pin benutzt, ist das aber nicht der Fall.
Falls man tatsächlich remappen muss, ist zusätzlich noch die Aktivierung 
von AFIO nötig, sonst geht es nicht.
Man sollte sich unbedingt Kapitel 9.3.7 im Referenzhandbuch (RM0008) und 
im Datenblatt die Tabelle "Pin definitions" ansehen und in 
stm32f10._gpio.c die diversen GPIO_Remap Argumente.

--- IRMP1/irsnd.c       2014-06-23 08:58:42.000000000 +0200
+++ IRMP2/irsnd.c       2014-07-04 16:18:27.891586612 +0200
@@ -590,6 +590,7 @@
         RCC_AHBPeriphClockCmd(IRSND_PORT_RCC, ENABLE);
 #    elif defined (ARM_STM32F10X)
         RCC_APB2PeriphClockCmd(IRSND_PORT_RCC, ENABLE);
+//        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // only 
in case of remapping, not necessary for default port-timer mapping
 #    elif defined (ARM_STM32F4XX)
         RCC_AHB1PeriphClockCmd(IRSND_PORT_RCC, ENABLE);
 #    endif
@@ -607,7 +608,7 @@
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
         GPIO_Init(IRSND_PORT, &GPIO_InitStructure);
-        GPIO_PinRemapConfig(, ENABLE);         // TODO: remapping 
required
+//        GPIO_PinRemapConfig(GPIO_*Remap*_TIM[IRSND_TIMER_NUMBER], 
ENABLE); // only in case of remapping, not necessary for default 
port-timer mapping
 #    endif

         /* TIMx clock enable */
diff -Nru IRMP1/irsndconfig.h IRMP2/irsndconfig.h
--- IRMP1/irsndconfig.h 2014-06-23 08:58:42.000000000 +0200
+++ IRMP2/irsndconfig.h 2014-07-04 16:03:28.815837848 +0200
@@ -113,10 +113,10 @@
  * ARM STM32 section:
  *----------------------------------------------------------------------- 
------------------------------------------------------------------------ 
----
  */
-#elif defined (ARM_STM32) 
// use A6 as IR output on STM32
-#  define IRSND_PORT_LETTER                     A
+#elif defined (ARM_STM32) 
// use B6 as IR output on STM32
+#  define IRSND_PORT_LETTER                     B
 #  define IRSND_BIT_NUMBER                      6
-#  define IRSND_TIMER_NUMBER                    10
+#  define IRSND_TIMER_NUMBER                    4
 #  define IRSND_TIMER_CHANNEL_NUMBER            1 
// only channel 1 can be used at the moment, others won't work

 /*---------------------------------------------------------------------- 
------------------------------------------------------------------------ 
-----

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

Jörg R. schrieb:
> Ich habe IRMP und IRSND auf einen STM32F105 angepasst.

Danke für die Verbesserungsvorschläge. Ich schaue, dass ich die 
Änderungen in die nächste IRMP-Version mit einfließen lasse. Könnstest 
Du dann - wenn es soweit ist - das Resultat nochmal testen, um 
auszuschließen, dass ich etwas übersehen habe?

Könntest Du Deine diffs nochmal eingebettet in
[code]
...
[/code]

reinstellen? Das lässt sich wegen den Zeilenumbrüchen dann besser lesen.

Viele Grüße,

Frank

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

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,
ok, und hier nochmal in Code Tags:
--- IRMP1/irsnd.c       2014-06-23 08:58:42.000000000 +0200
+++ IRMP2/irsnd.c       2014-07-04 16:18:27.891586612 +0200
@@ -590,6 +590,7 @@
         RCC_AHBPeriphClockCmd(IRSND_PORT_RCC, ENABLE);
 #    elif defined (ARM_STM32F10X)
         RCC_APB2PeriphClockCmd(IRSND_PORT_RCC, ENABLE);
+//        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // only in case of remapping, not necessary for default port-timer mapping
 #    elif defined (ARM_STM32F4XX)
         RCC_AHB1PeriphClockCmd(IRSND_PORT_RCC, ENABLE);
 #    endif
@@ -607,7 +608,7 @@
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
         GPIO_Init(IRSND_PORT, &GPIO_InitStructure);
-        GPIO_PinRemapConfig(, ENABLE);         // TODO: remapping required
+//        GPIO_PinRemapConfig(GPIO_*Remap*_TIM[IRSND_TIMER_NUMBER], ENABLE); // only in case of remapping, not necessary for default port-timer mapping
 #    endif

         /* TIMx clock enable */
diff -Nru IRMP1/irsndconfig.h IRMP2/irsndconfig.h
--- IRMP1/irsndconfig.h 2014-06-23 08:58:42.000000000 +0200
+++ IRMP2/irsndconfig.h 2014-07-04 16:03:28.815837848 +0200
@@ -113,10 +113,10 @@
  * ARM STM32 section:
  *---------------------------------------------------------------------------------------------------------------------------------------------------
  */
-#elif defined (ARM_STM32)                                               // use A6 as IR output on STM32
-#  define IRSND_PORT_LETTER                     A
+#elif defined (ARM_STM32)                                               // use B6 as IR output on STM32
+#  define IRSND_PORT_LETTER                     B
 #  define IRSND_BIT_NUMBER                      6
-#  define IRSND_TIMER_NUMBER                    10
+#  define IRSND_TIMER_NUMBER                    4
 #  define IRSND_TIMER_CHANNEL_NUMBER            1                       // only channel 1 can be used at the moment, others won't work

 /*---------------------------------------------------------------------------------------------------------------------------------------------------
Viele Grüße,
Jörg

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

Bewertung
0 lesenswert
nicht lesenswert
Jörg R. schrieb:
> ok, und hier nochmal in Code Tags:

Vielen Dank! Ich habe Deine Änderungen als Version 2.6.1 ins SVN 
eingecheckt.

Gruß,

Frank

Autor: Jörg R. (jrie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,

hier noch zusätzliche Änderungen.

* C13 ist ungeeignet, daher lieber C6.
* includes für STM32F10x
diff -Nru I1/irmpconfig.h I2/irmpconfig.h
--- I1/irmpconfig.h     2014-07-21 11:05:03.000000000 +0200
+++ I2/irmpconfig.h     2014-07-25 16:33:35.819776900 +0200
@@ -121,9 +121,9 @@
  * Change hardware pin here for ARM STM32
  *---------------------------------------------------------------------------------------------------------------------------------------------------
  */
-#elif defined (ARM_STM32)                                               // use C13 as IR input on STM32
+#elif defined (ARM_STM32)                                               // use C6 as IR input on STM32
 #  define IRMP_PORT_LETTER                      C
-#  define IRMP_BIT_NUMBER                       13
+#  define IRMP_BIT_NUMBER                       6

 /*---------------------------------------------------------------------------------------------------------------------------------------------------
  * Change hardware pin here for Stellaris ARM Cortex M4
diff -Nru I1/irmpsystem.h I2/irmpsystem.h
--- I1/irmpsystem.h     2014-07-21 11:05:03.000000000 +0200
+++ I2/irmpsystem.h     2014-07-25 16:49:36.760388800 +0200
@@ -95,6 +95,11 @@
 #  define PROGMEM volatile
 #  define memcpy_P memcpy
 #  define APP_SYSTICKS_PER_SEC          32
+#elif defined(ARM_STM32F10X)
+#  include "stm32f10x_gpio.h"
+#  include "stm32f10x_rcc.h"
+#  define PROGMEM
+#  define memcpy_P                      memcpy
 #else
 #  define PROGMEM
 #  define memcpy_P                      memcpy

Und falls es jemanden interessiert, hier der Link zu meinem Projekt:
http://www.vdr-portal.de/board18-vdr-hardware/boar...

Viele Grüße,
Jörg

Autor: Ulli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich bau gerade eine neue Schaltung auf und habe eine Frage an euch.
Ich möchte einen TSOP4836 über 5Volt versorgen, habe einen Pullup (10K) 
am Ausgang nach 5Volt, 100Ohm in Reihe und 4.7µF parallel. Wie im 
Datenblatt beschrieben.
Der Ausgang des TSOP4836 hängt an einen ADC Eingang eines Atmega 328p, 
welcher 3.3Volt versorgt ist.
Denkt Ihr das ich aufgrund der unterschiedlichen Versorgungsspannungen 
ein Problem bekomme, oder sollte das so funktionerien? ggf. den Pullup 
raus?

Wäre sehr dankebar über Hinweise. Habe die Schaltung nämlich schon beim 
Ätzer.....

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ulli schrieb:
> ich bau gerade eine neue Schaltung auf und habe eine Frage an euch.
> Ich möchte einen TSOP4836 über 5Volt versorgen, habe einen Pullup (10K)
> am Ausgang nach 5Volt, 100Ohm in Reihe und 4.7µF parallel. Wie im
> Datenblatt beschrieben.

Der TSOP4836 hat intern schon einen 30k Pullup, siehe Blockdiagramm. 
Daher ist ein weiterer Pullup nur optional und nicht unbedingt vonnöten.

> Der Ausgang des TSOP4836 hängt an einen ADC Eingang eines Atmega 328p,
> welcher 3.3Volt versorgt ist.

Warum nimmst Du dann keinen TSOP, der auch mit 3,3V als 
Versorgungsspannung auskommt?

> Denkt Ihr das ich aufgrund der unterschiedlichen Versorgungsspannungen
> ein Problem bekomme, oder sollte das so funktionerien? ggf. den Pullup
> raus?

Ja, nimm den Pullup raus. Ob der ATmega328 Dir das übel nimmt, wenn er 
über 30kOhm 5V sieht, kann ich nicht beurteilen. Aber schön ist anders 
;-)

Autor: Ulli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem ist die Schaltung ist schon fix...müsste aus der geätzten 
Platine dann mit dem Dremel die Leitung unterbrechen und fädeln...suche 
gerade eine Lösung für ein schon verbocktes Layout :)

Eigentlich wäre der TSOP34836 auf 3.3V die Lösung richtig?
Den gibt es nur weder bei Conrad noch bei Bürklin....

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ulli schrieb:
> Eigentlich wäre der TSOP34836 auf 3.3V die Lösung richtig?

Ja, der wäre richtig.

> Den gibt es nur weder bei Conrad noch bei Bürklin....

Alternative wäre TSOP 31238 bzw. TSOP 31236, den gibts bei Reichelt. 
Allerdings hat der ein anderes Pinout.

Autor: Ulli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja stimmt, das Problem sind überall die Versandkosten. Reichelt hat auch 
5.6€. Conrad und Bürklin kann ich abholen :)
Sehe nicht ein Cent Artikel zu bestellen und 6€ Versand dafür zu 
bezahlen.

Autor: Michael K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Laut http://www.vishay.com/docs/82459/tsop48.pdf kann doch der TSOP4836 
mit 3.3V betrieben werden, oder sehe ich das falsch?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael K. schrieb:
> Laut http://www.vishay.com/docs/82459/tsop48.pdf kann doch der TSOP4836
> mit 3.3V betrieben werden, oder sehe ich das falsch?

Ja. Hier steht ab 2,5V. Gestern hatte ich über Google ein älteres 
erwischt (1. Link unterhalb der Bilder), das stand noch 4,5-5.V drin. 
Aber auch das Datenblatt, welches bei Conrad verlinkt ist, sagt ab 2,5V.

Passt also wohl.

Autor: Joachim B. (Gast)
Datum:
Angehängte Dateien:

Bewertung
-1 lesenswert
nicht lesenswert
hallo Frank, ich mal wieder....

ich habe immer noch Probleme mit der Entprellung der Tasten

bin ich zu doof spinnt meine Hardware ?

vielleicht schaust du noch mal

autorepeat geht, aber Einzelschritt halt nie, entweder es kommen gleich 
2 Schritte oder keiner was bei PRG++/-- doof ist

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich weiß nicht, ob meine Frage hier an die richtige Stelle kommt, aber 
ich bekomme den Code im Studio 4 nicht zum Laufen. Leider kenne ich bei 
"C" nur Grundbegriffe, bin schon eher in ASM zu Hause.

Die Fehlermeldung sieht wie folgt aus:

quote
Build started 6.8.2014 at 15:01:36
mmcu=atmega88 -Wall -gdwarf-2 -std=gnu99               -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
/usr/bin/sh: -Wall: command not found
make: [main.o] Error 127 (ignored)
mmcu=atmega88 -Wall -gdwarf-2 -std=gnu99               -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
/usr/bin/sh: -Wall: command not found
make: [irmp.o] Error 127 (ignored)
mmcu=atmega88 -Wl,-Map=irmp.map main.o irmp.o     -o irmp.elf
/usr/bin/sh: -Wl,-Map=irmp.map: command not found
make: [irmp.elf] Error 127 (ignored)
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  irmp.elf 
irmp.hex
avr-objcopy: 'irmp.elf': No such file
make: *** [irmp.hex] Error 1
Build failed with 1 errors and 0 warnings...
unquote

Ich habe den Ursprungscode nicht verändert.

Kann mir jemand helfen?

Gruß Bruno

Autor: Joachim B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Ich weiß nicht, ob meine Frage hier an die richtige Stelle kommt, aber
> ich bekomme den Code im Studio 4 nicht zum Laufen.

ist Studio 4 richtig installiert ?

schon einmal eine LED zum blinken bekommen ?

ich habe es gerade versucht

neues Projekt Test eröffnet

Source Code von IRMP eingestellt im Projektordner
MCU gewählt, Takt bekannt gemacht und läuft durch ohne Fehler.....



avr-gcc -mmcu=atmega88 -Wl,-Map=nurso.map nurso.o irmp.o irmpextlog.o 
-o nurso.elf
.....
Program:    2356 bytes (28.8% Full)
Build succeeded with 0 Warnings...

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Build started 6.8.2014 at 15:01:36
> mmcu=atmega88 -Wall -gdwarf-2 -std=gnu99               -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
> /usr/bin/sh: -Wall: command not found

Da fehlt vorne am Anfang der Zeile der Compiler-Aufruf. Scheinbar ist 
Dein WinAVR (avr-gcc toolchain) zum AVR Studio nicht installiert bzw. 
AVR Studio hat es nicht gefunden.

Autor: Joachim B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Da fehlt vorne am Anfang der Zeile der Compiler-Aufruf. Scheinbar ist
> Dein WinAVR (avr-gcc toolchain) zum AVR Studio nicht installiert bzw.
> AVR Studio hat es nicht gefunden.

Ich habe mir die Installationsreihenfolge so notiert:

1. winAVR
2. AVR-Studio

dann findet A-Studio auch gleich den AVR gcc und bindet ihn mit ein

Frank, kannst du bitte noch mal zu meiner Frage schauen 3 Beiträge höher 
?
danke

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vorab herzlichen Dank für die verschiedenen Hinweise.

Auch wenn das Problem richtig erkannt wurde, hat es mir noch nicht 
geholfen.

Nachdem ich WINAVR und das Studio insgesamt 3 x in unterschiedlichen 
Verzeichnissen neu installiert habe und die Fehlermeldung gleich 
geblieben ist, habe ich versucht im Internet eine Antwort zu finden. Nun 
bin ich insoweit schlauer, dass bei meinem Studio 4.19 der Link zu 
WINAVR nicht mehr automatisch hergestellt wird, da jetzt eine eigene AVR 
- Toolchain integriert ist. Ich habe auch gefunden, wie und wo man die 
entsprechenden Links manuell eintragen kann, was ich dann mit älteren 
Codes, die früher schon mal gelaufen sind, erfolgreich versucht habe.

Bei IRMP hat aber auch das nicht zum Erfolg geführt. Es gibt jetzt eine 
neue Fehlermeldung, mit der ich nichts anfangen kann.

quote
rm -rf main.o irmp.o  irmp.elf dep/* irmp.hex irmp.eep irmp.lss irmp.map
Build succeeded with 0 Warnings...
gcc  -mmcu=atmega88 -Wall -gdwarf-2 -std=gnu99 
-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

gcc: CreateProcess: No such file or directory
make: *** [main.o] Error 1
Build failed with 1 errors and 0 warnings...
unquote

Bruno

Autor: Joachim B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> dass bei meinem Studio 4.19

das kann der Ärger sein, ich glaube ich habe die 4.19 wieder 
rausgeworfen und arbeite überall mit der 4.18

Autor: Joachim B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> gcc: CreateProcess: No such file or directory

hast du win-avr (gcc) nicht installiert ?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> gcc: CreateProcess: No such file or directory

Der Compiler heisst avr-gcc, nicht gcc. Schau doch mal in Deiner 
Toolchain im Verzeichnis bin nach.

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Der Compiler heisst avr-gcc, nicht gcc. Schau doch mal in Deiner
> Toolchain im Verzeichnis bin nach.

In meinem WINAVR heißt er tatsächlich gcc.exe und darauf habe ich den 
Link gesetzt. Auch ein Umbenennen der Datei in avr-gcc.exe ergibt den 
gleichen Fehler, nur eben dann mit avr-gcc.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> In meinem WINAVR heißt er tatsächlich gcc.exe [...]

Merkwürdig. Habe ich noch nie gesehen. Wo liegt er denn? Also in welchem 
Pfad? Ich habe mein WinAVR direkt unter C:\ liegen. Es könnte Probleme 
geben, wenn im Pfad Leerzeichen sind.

Ausserdem habe ich hier mittlerweile avr-gcc V.4.8.1 laufen.

Vorgehen:

  http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx

Dort

    Atmel AVR 8-bit Toolchain 3.4.4 - Windows

heruntergeladen. Dieses habe ich dann unter C:\WinAVR\avr-gcc-4.8.1 
abgelegt, also dass avr-gcc.exe in dem Ordner 
C:\WinAVR\avr-gcc-4.8.1\bin zum Liegen kommt.

Dann folgendes als reg-Datei gespeichert und ausgeführt:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WinAVR]
"DisplayVersion"="20100110"
"UninstallString"="C:\\WinAVR\\avr-gcc-4.8.1\\WinAVR-20100110-uninstall.exe"

Das ist ein bisschen tricky: Das AVR Studio 4.18 (ja, ich benutze 18 und 
nicht 19) merkt sich im UninstallString, wo das WinAVR-Verzeichnis 
liegt.

Das dort angegebene Programm WinAVR-20100110-uninstall.exe existiert gar 
nicht. Ist auch vollkommen schnuppe. Es geht nur um den Pfad.

Dann kann man unter den Projekt-Eigenschaften (Project -> Configuration 
Options -> Custom Options) einfach bei "Use WinAVR" ein Häkchen machen 
und es wird der neue Compiler benutzt.

Achja, in dem alten Verzeichnis WinAVR-20100110 (oder so ähnlich) gibt 
es ein Unterverzeichnis namens utils. Es empfiehlt sich, dieses nach 
WinAVR\avr-gcc-4.8.1 rüberzukopieren und die Umgebungsvariable PATH 
entsprechend auf den Pfad ....\utils\bin auszurichten. Denn dort 
befinden sich make & Co, die nicht Bestandteil der avr-gcc-Toolchain 
sind.

Wenn das alles bei Dir nicht funktioniert, dann versuchs doch lieber mit 
einer aktuelleren IDE, z.B. Atmel Studio 6.2. Da hast Du alles 
"all-in-one".

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,
Du gibst Dir wirklich Mühe. Ich bin beeindruckt.

> Merkwürdig. Habe ich noch nie gesehen. Wo liegt er denn? Also in welchem
> Pfad? Ich habe mein WinAVR direkt unter C:\ liegen. Es könnte Probleme
> geben, wenn im Pfad Leerzeichen sind.

Ich habe mir für Dein Projekt die aktuellste Version von WINAVR 
runtergeladen.

Der Pfad ist : C:\WINAVR\avr\bin

Nun aber die gute Nachricht:

Da ich es leid war habe ich mir das Studio 4.18 installiert und siehe da 
alles lief wie geschmiert.

Das diente aber nur zum Testen auf meinem alten XP-Rechner. Eigentlich 
arbeite ich auch schon länger mit Studio 6. Weil ich aber schon mehrfach 
Probleme hatte beim Import von Studio 4 Projekten, hatte ich das gar 
nicht erst versucht.
Nun habe ich aber auch das mit Erfolg gelöst. Importieren klappte zwar 
nicht, aber ein neues Projekt mit Einfügen der Dateien läuft jetzt 
problemlos. Ich mußte allerdings die PROGMEM Variablen von static in 
const ändern.

Nochmals herzlichen Dank für die Unterstützung.

Gruß Bruno

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Nun habe ich aber auch das mit Erfolg gelöst. Importieren klappte zwar
> nicht, aber ein neues Projekt mit Einfügen der Dateien läuft jetzt
> problemlos.

Eben, das habe ich auch so im Artikel IRMP beschrieben. Ist 
einfacher, als ein Projekt zu importieren.

> Ich mußte allerdings die PROGMEM Variablen von static in const ändern.

Wo hast Du denn diese Uralt-Version von IRMP her? Das habe ich bereits 
vor ca. 2 Jahren angepasst.

Hole Dir besser eine aktuelle Version, siehe Artikel.

Autor: Joachim B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Da ich es leid war habe ich mir das Studio 4.18 installiert und siehe da
> alles lief wie geschmiert.

sag ich doch, ich habe 4.19 auch von allen Rechnern runtergeworfen....


freut mich das es klappte 1

und so bin ich auch vorgegangen, neues Projekt und dort alles reingetan, 
klappt eben am Besten.

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Wo hast Du denn diese Uralt-Version von IRMP her? Das habe ich bereits
> vor ca. 2 Jahren angepasst.

Sorry, ich hatte mir wohl die aktuelle Version runtergeladen, dann aber 
offensichtlich bei wiederholtem Kopieren Dateien aus einem 
Anwendungsprojekt (IRMP-LCD) genommen.

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Frank,

was hat es eigentlich mit der Differenz der Versionen im SVN und dem 
Wiki auf sich? Im Wiki ist Version 2.4.0 aktuell, im SVN findet sich 
schon Version 2.6.2 und ein entsprechender Tarball kann heruntergeladen 
werden.

Hast du nur vergessen den Wiki-Artikel zu aktualisieren, oder gibt es 
Gründe warum du Version 2.6.2 noch "zurück" hältst? Nicht, dass ich 
konkrete Probleme hätte, würde aber gerne stets so aktuell wie möglich 
bleiben, um später die notwendigen Anpassungsarbeiten so gering wie 
möglich zu halten.

Wie immer: Super Arbeit, welche du hier ablieferst, weiter so ;).

Mit freundlichen Grüßen,
Karol Babioch

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Karol,

Karol Babioch schrieb:

> was hat es eigentlich mit der Differenz der Versionen im SVN und dem
> Wiki auf sich?

Reine Faulheit ;-)

Ich habe mir angewöhnt, im SVN immer einen aktuellen (aber nicht 
instabilen) Stand zu halten, um dann Rückmeldungen (Korrekturen, 
Verbesserungen) der User zu den Neuerungen abzuwarten. Nach einer 
gewissen Zeit "erkläre" ich dann den aktuellen SVN-Stand zur stabilen 
Version und erstelle dann ein neues ZIP-Archiv zum Download und biete es 
im Artikel an.

Sozusagen eine "very stable" Version als Zip, eine "stable" Version im 
SVN. Eine "unstable" gibts nur auf meinem Rechner.

Leider habe ich aus Zeitgründen diese Abstände immer größer werden 
lassen, wobei ich mir denke, dass dies nicht ganz so schlimm ist. In die 
letzten SVN-Versionen sind eher exotische Protokolle wie Klimaanlagen 
mit eingeflossen. Größere Korrekturen an den bereits etablierten 
Protokollen gab es auch nicht.

Ein weiterer Grund für den großen Abstand ist auch die nötige Pflege des 
Artikels. Solange die Zip-Version sich nicht ändert, muss ich im Artikel 
auch nicht soviel ändern - auch wenn ich hier und da durchaus 
Aktualisierungen vornehme, z.B. die "Entschlüsselung" des 
LG-Air-Protokolls, damit man seine Klimaanlage per µC steuern kann.

> Hast du nur vergessen den Wiki-Artikel zu aktualisieren, oder gibt es
> Gründe warum du Version 2.6.2 noch "zurück" hältst? Nicht, dass ich
> konkrete Probleme hätte, würde aber gerne stets so aktuell wie möglich
> bleiben, um später die notwendigen Anpassungsarbeiten so gering wie
> möglich zu halten.

Wenn Dir an Aktualität gelegen ist, nimm einfach die aktuelle 
SVN-Version. Im allgemeinen ist es so, dass ich diese einfach irgendwann 
in das  Download-Zip-Archiv kopiere.

Aber Du hast recht: Es ist mal wieder Zeit für ein Update. Ich schaue, 
dass ich es bis zum Wochenende schaffe.

> Wie immer: Super Arbeit, welche du hier ablieferst, weiter so ;).

Vielen Dank :-)

Gruß,

Frank

Autor: Jörg R. (jrie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,
hier weitere Änderungen für den STM32F10x.
diff -Nru B/irmpsystem.h A/irmpsystem.h
--- B/irmpsystem.h      2014-07-21 11:05:03.000000000 +0200
+++ A/irmpsystem.h      2014-08-19 00:24:52.346944900 +0200
@@ -37,6 +37,7 @@
 #  include <stm32f10x.h>
 #  define ARM_STM32
 #  define ARM_STM32F10X
+#  define F_CPU (SysCtlClockGet())
 #elif defined(STM32F4XX)                                                            // ARM STM32
 #  include <stm32f4xx.h>
 #  define ARM_STM32
@@ -95,6 +96,13 @@
 #  define PROGMEM volatile
 #  define memcpy_P memcpy
 #  define APP_SYSTICKS_PER_SEC          32
+#elif defined(ARM_STM32F10X)
+#  include "stm32f10x_gpio.h"
+#  include "stm32f10x_rcc.h"
+#  include "stm32f10x_tim.h"
+#  include "misc.h"
+#  define PROGMEM
+#  define memcpy_P                      memcpy
 #else
 #  define PROGMEM
 #  define memcpy_P                      memcpy
und für main.c:
/*---------------------------------------------------------------------------------------------------------------------------------------------------
 * STM32:
 *---------------------------------------------------------------------------------------------------------------------------------------------------
 */
#elif defined(ARM_STM32)

uint32_t
SysCtlClockGet(void)
{
    RCC_ClocksTypeDef RCC_ClocksStatus;
    RCC_GetClocksFreq(&RCC_ClocksStatus);
    return RCC_ClocksStatus.SYSCLK_Frequency;
}

void
timer2_init (void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period = 7;
    TIM_TimeBaseStructure.TIM_Prescaler = ((F_CPU / F_INTERRUPTS)/8) - 1;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
    NVIC_Init(&NVIC_InitStructure);

    TIM_Cmd(TIM2, ENABLE);
}

void
TIM2_IRQHandler(void)                                                  // Timer2 Interrupt Handler
{
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  (void) irmp_ISR();                                                        // call irmp ISR
  // call other timer interrupt routines...
}

int
main (void)
{
    IRMP_DATA irmp_data;
        
    irmp_init();                                                            // initialize irmp
    timer2_init();                                                          // initialize timer2

    for (;;)
    {
        if (irmp_get_data (&irmp_data))
        {
            // ir signal decoded, do something here...
            // irmp_data.protocol is the protocol, see irmp.h
            // irmp_data.address is the address/manufacturer code of ir sender
            // irmp_data.command is the command code
            // irmp_protocol_names[irmp_data.protocol] is the protocol name (if enabled, see irmpconfig.h)
        }
    }
}
Das sollte jetzt alles gewesen sein :-)
Gruß, Jörg

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Hallo Jörg,

Jörg R. schrieb:
> hier weitere Änderungen für den STM32F10x.

Vielen Dank, ich habe die Änderungen übernommen. Kommen in die nächste 
SVN-Version und ins ZIP-Release.

Gute Arbeit!

Gruß,

Frank

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,

nachdem ich Deinen Code im Studio6 zum Laufen gebracht habe und auch die 
Hardware funktioniert, tun sich natürlich neue Frage auf:

Für mich als blutigen Anfänger in 'C' ist das Verstehen des Programms 
eine besondere Herausforderung, insbesondere durch die vielen if's.

Was jetzt funktioniert, ist das Loggen der Daten mittels UART. Wenn ich 
aber nun die Protokollnamen haben möchte, muß dann zwangsläufig auch das 
Loggen gewählt werden? Für mich ist das eine Frage des Speichers.

Gruß Bruno

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Für mich als blutigen Anfänger in 'C' ist das Verstehen des Programms
> eine besondere Herausforderung, insbesondere durch die vielen if's.

Du meinst wohl eher die vielen #if ;-)

Dies ist 2 Dingen geschuldet:

 1. Nur den Code für diejenigen Protokolle compilieren, die auch
    aktiviert sind. Das spart jede Menge Flash und RAM.

 2. Unterstützung von möglichst vielen µCs, u.a. AVR, STM32 und PICs.

> Was jetzt funktioniert, ist das Loggen der Daten mittels UART. Wenn ich
> aber nun die Protokollnamen haben möchte, muß dann zwangsläufig auch das
> Loggen gewählt werden? Für mich ist das eine Frage des Speichers.

Natürlich brauchst Du dafür kein Logging. Dies ist nur dann 
erforderlich, wenn man ein bislang unbekanntes Protokoll analysieren 
möchte. Schalte dies also ab.

Schaue Dir dann die Muster-Main-Datei an. Dort sieht man nach dem Aufruf 
von irmp_get_data(), was zu tun ist, nämlich Protokoll-, Adress und 
Kommando-Vergleich, um dann gezielt zu reagieren.

Viele Grüße,

Frank

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

So lag auch meine Interpretation.

> Schaue Dir dann die Muster-Main-Datei an. Dort sieht man nach dem Aufruf
> von irmp_get_data(), was zu tun ist, nämlich Protokoll-, Adress und
> Kommando-Vergleich, um dann gezielt zu reagieren.

Was passiert aber, wenn kein Protokoll erkannt wird, kommt dann eine 
Negativmeldung oder passiert einfach nichts?

Gruß Bruno

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Was passiert aber, wenn kein Protokoll erkannt wird, kommt dann eine
> Negativmeldung oder passiert einfach nichts?

Bitte schaue Dir im IRMP-Artikel den folgenden Abschnitt an:

  http://www.mikrocontroller.net/articles/IRMP#Anwen...

Auszug:
   if (irmp_get_data (&irmp_data))
   {
      if (irmp_data.protocol == IRMP_NEC_PROTOCOL &&     // NEC-Protokoll
          irmp_data.address == 0x1234)                   // Adresse 0x1234
      {
         switch (irmp_data.command)
         {
            case 0x0001: key1_pressed(); break;          // Taste 1
            case 0x0002: key2_pressed(); break;          // Taste 2
            ...
            case 0x0009: key9_pressed(); break;          // Taste 9
         }
      }
   }

irmp_get_data() liefert also TRUE zurück, wenn ein Protokoll erkannt 
wurde, anderenfalls FALSE.

Im obigen Beispiel wird der Block nur durchlaufen, wenn irmp_get_data() 
TRUE zurückliefert.

Dann sollte man das Protokoll und die Adresse überprüfen, anschließend 
die Kommando-Codes, um dann entsprechend eine Aktion auszuführen.

Obige Werte sind natürlich fiktiv. Diese musst Du erst selbst empirisch 
für Deine Fernbedienung ermitteln, um sie dann verwenden zu können. Dazu 
kannst Du die erhaltenen Werte zunächst auf einem Display oder über UART 
ausgeben... oder was Du sonst noch so an Ausgabeschnittstellen hast.

Eine UART-Routine kann ich gerne hier posten, falls gewünscht.

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bedeutet das, daß ich mit

>
>    if (irmp_get_data (&irmp_data))
>    {
>       if (irmp_data.protocol == FALSE
>    }
> 

weiterarbeiten kann?

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,

ich habe es einfach mal probiert, aber so geht es nicht.

Was muß ich tun um eine Negativmeldung ausgeben zu können?

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Was muß ich tun um eine Negativmeldung ausgeben zu können?

Die Rückgabe von irmp_get_data() selbst auswerten.

Also in etwa so (ungetestet):
if (irmp_get_data(&irmp_data))
{
    // Es wurde irgendetwas erkannt
} else {
    // Es wurde nichts erkannt
}

Ich bin mir allerdings nicht so recht sicher was du überhaupt bezwecken 
möchtest. irmp_get_data() ruft man i.d.R. regelmäßig auf und es wird 
wohl weit aus öfter false zurück liefern als umgekehrt.

Mit freundlichen Grüßen,
Karol Babioch

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

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Bedeutet das, daß ich mit
>
>>
>>    if (irmp_get_data (&irmp_data))
>>    {
>>       if (irmp_data.protocol == FALSE
>>    }
>> 
>
> weiterarbeiten kann?

Das erste if ist richtig. Dann wurden Daten empfangen und erkannt.

Bedenke auch: irmp_get_data() wartet nicht, sondern kommt sofort zurück, 
wenn nichts empfangen wurde!

Wenn Du warten willst:
     while (! irmp_get_data (&irmp_data))
     {
          ;                // warten
     }

Das zweite if ist falsch. Hier musst Du auf einen Wert prüfen, nämlich 
die Protokollnummer. IRMP unterstützt ca. 40 Protokolle. In 
irmp_data.protocol steht dann die erkannte Protokollnummer. Wenn Du sie 
nicht weisst, solltest Du erstmal alle Werte ausgeben, die Deine FB 
sendet, z.b. so:
    if (irmp_get_data (&irmp_data))
    {
        gebeWertaus (irmp_data.command);
        gebeWertaus (irmp_data.address);
        gebeWertaus (irmp_data.command);
        gebeWertaus (irmp_data.flags);
    }

Die Funktion gebeWertAus() musst Du selber schreiben, denn ich weiß ja 
nicht, was Du für Hardware benutzt.

Hier siehst Du das z.B. auf Youtube:

  Youtube-Video "IRMP. AVR (atmega8, avr-gcc) IR decoder."

Wenn Du dann alle Werte hast, kannst Du sie benutzen. Nehmen wir an, Du 
hast empfangen: Protokoll = 2, Adresse = 0x1234 mit

   Kommando = 0x1111   für Taste 1
   Kommando = 0x1112   für Taste 2

Dann kannst Du nun statt dem obigen Block schreiben:
    if (irmp_get_data (&irmp_data))
    {
        if (irmp_data.protocol == 2 && irmp_data.address == 0x1234)
        {
            switch (irmp_data.command)
            {
                case 0x1111: led_aus(); break;
                case 0x1112: led_an();  break;
            }
        }
    }

Die Funktionen led_aus() und led_an() sind natürlich nur Beispiele.

: Bearbeitet durch Moderator
Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Das zweite if ist falsch.

Ich mag die Frage falsch verstanden haben, aber nach meiner Auffassung 
will er gerade denjenigen Fall abdecken, in welchem IRMP nichts erkannt 
hat, d.h. die Rückgabe von "irmp_get_data()" false ist.

Mit freundlichen Grüßen,
Karol Babioch

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karol Babioch schrieb:
> Ich mag die Frage falsch verstanden haben, aber nach meiner Auffassung
> will er gerade denjenigen Fall abdecken, in welchem IRMP nichts erkannt
> hat, d.h. die Rückgabe von "irmp_get_data()" false ist.

Okay, den hast Du ja schon beschrieben.

Das Wichtigste: irmp_get_data() wartet nicht.

Wenn man unbedingt warten will:
     while (1)                // Hauptschleife
     {
         ...

         while (! irmp_get_data (&irmp_data))
         {
             ;                // warten
         }

         // Jetzt wurde etwas empfangen
         verarbeite_daten();
     }

Wenn man zwischendurch etwas anderes machen will:
     while (1)                // Hauptschleife
     {
         if (irmp_get_data (&irmp_data))
         {
             // Jetzt wurde etwas empfangen
             verarbeite_daten();
         }
         else
         {
              tue_was_anderes ();
         }
     }

Es kommt also immer auf den Anwendungsfall an.

: Bearbeitet durch Moderator
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube ich muß meine Frage doch noch etwas präzisieren. Wenn ich es 
richtig verstande4n habe, wird mit

if (irmp_get_data (&irmp_data))

auf ein IR Signal gewartet. Wenn es kommt, kann ich das Signal weiter 
auswerten.
Mir geht es aber jetzt nicht darum festzustellen, ob ein IR Signal 
empfangen wurde (das kann ich ja mit dem Loggen sehr einfach 
überprüfen), sondern ich möchte wissen ob ein passendes Protokoll 
gefunden wurde. Ich kann ja aus der Vielzahl der möglichen Protokolle 
einige auswählen, andere nicht. Das hängt ja schon davon ab wieviel 
Speicher man zur Verfügung hat.
Habe ich also das richtige Protokoll nicht eingeschlossen, reagiert IRMP 
gar nicht. Da hat man (oder auch nur ich) nun am Anfang das Problem, daß 
man nicht genau weiß warum IRMP nicht reagiert. Vielleicht liegt es ja 
auch nur an meinem Code.
Ich habe mir deshalb gedacht, es wäre sinnvoll eine Info zu bekommen, 
wenn zwar ein Signal empfangen wurde, aber kein passendes Protokoll 
gefunden wurde. Diese Info kann ich dann über UART ausgeben und eine 
andere Auswahl bei den Protokollen treffen.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Habe ich also das richtige Protokoll nicht eingeschlossen, reagiert IRMP
> gar nicht.

Schalte am Anfang soviele Protokolle frei wie möglich. Also alle 
"typical protocols" (4 Stück) und die unter "more protocols" angegebenen 
(9 Stück).

Damit hast Du dann eine 95%-ige Chance, dass IRMP den Code kennt. 
Anschließend kannst Du die nicht benötigten Protokolle wieder 
deaktivieren.

Alternativ kopierst Du hier eine Zeile aus dem LOGGING-Protokoll rein. 
Ich brauche keine Minute, um festzustellen, ob IRMP das Protokoll 
versteht und welches das ist.

: Bearbeitet durch Moderator
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Inzwischen bin ich ein Stückchen weiter. Ich habe jetzt mal protocol und 
command abgefragt und bekomme bei einer Fernbedienung als Ausgabe 16 und 
10, bei der anderen nichts. Bedeutet 16 nun das NOKIA Protokoll?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Inzwischen bin ich ein Stückchen weiter. Ich habe jetzt mal protocol und
> command abgefragt und bekomme bei einer Fernbedienung als Ausgabe 16 und
> 10, bei der anderen nichts. Bedeutet 16 nun das NOKIA Protokoll?

10 = SAMSUNG32
16 = Nokia

Siehe auch irmpprotocols.h. Da stehen sie alle direkt am Anfang drin.

Insofern kann ich Deine Frage mit "Ja" beantworten :-)

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
>> Inzwischen bin ich ein Stückchen weiter. Ich habe jetzt mal protocol und
>> command abgefragt und bekomme bei einer Fernbedienung als Ausgabe 16 und
>> 10, bei der anderen nichts. Bedeutet 16 nun das NOKIA Protokoll?

Achso, 10 ist bei Dir ein empfangenes Kommando, nicht eine 
Protokollnummer.

Du solltest aber protocol immer in Kombination mit der Adresse abfragen. 
Denn es könnte durchaus Fernbedienungen in Deinem Haushalt geben, die 
dasselbe Protokoll (z.B. Fernseher und DVD-Player) sprechen, aber 
unterschiedliche Adressen verwenden. Wenn die Adresse verschieden ist, 
kannst Du davon ausgehen, dass gleiche Kommando-Codes nicht von 
derselben Fernbedienung stammen.

Also: Die meisten FBs senden immer dasselbe Protokoll und dieselbe 
Adresse - egal welche Taste gedrückt ist.[*]

Wenn Du diese prüfst, kannst Du davon ausgehen, dass der Anwender die 
richtige Fernbedienung in den Händen hat.

[*] Ausnahmen bestätigen die Regel.

: Bearbeitet durch Moderator
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,
bis hierhin schon mal herzlichen Dank. Ich hatte keine Ahnung, daß 
Fernbedienungen so viel Spaß machen können. Ich habe jetzt mal etwas 
variiert und bekomme nur bei protocol die zwei Werte 10 und 16 
hintereinander. Wenn ich command hinzunehme und zwei bestimmte Tasten 
drücke, bekomme ich folgende ASCII Anzeige.

(10) (16) UNKNOWN (10)
(10) (16) SAMSG32 (10) (die Zahlenwerte sind DEZ)

Welche Erklärung hast Du dafür?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> bis hierhin schon mal herzlichen Dank. Ich hatte keine Ahnung, daß
> Fernbedienungen so viel Spaß machen können. Ich habe jetzt mal etwas
> variiert und bekomme nur bei protocol die zwei Werte 10 und 16
> hintereinander.

Von ein- und derselben FB bekommst Du 2 verschiedene Protokollnummern? 
Zu 99% kann ich das nicht glauben ;-)

> Wenn ich command hinzunehme und zwei bestimmte Tasten
> drücke, bekomme ich folgende ASCII Anzeige.
>
> (10) (16) UNKNOWN (10)
> (10) (16) SAMSG32 (10) (die Zahlenwerte sind DEZ)

Warum wird einmal UNKNOWN und einmal SAMSG32 ausgegeben, obwohl die 
Zahlenwerte identisch sind?

Welche Tasten sind das? Was ist das für eine Fernbedienung?

Zeige bitte mal Dein dazugehörendes Programm im Ausschnitt, also z.B. 
die while-Hauptschleife. Ich vermute da eher den Fehler.

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Warum wird einmal UNKNOWN und einmal SAMSG32 ausgegeben, obwohl die
> Zahlenwerte identisch sind?
>
> Welche Tasten sind das? Was ist das für eine Fernbedienung?

Es ist die FB für einen Panasonic DVD Player und es sind die Tasten 
'Pause' und 'Play'


> Zeige bitte mal Dein dazugehörendes Programm im Ausschnitt, also z.B.
> die while-Hauptschleife. Ich vermute da eher den Fehler.

[c]
for (;;)
    {
        if (irmp_get_data (&irmp_data))
        {
         irmp_uart_putc(0x0a);
    irmp_uart_puts(irmp_data.protocol);
    //irmp_uart_puts(irmp_data.address);
    //irmp_uart_puts(irmp_data.command);
    irmp_uart_putc(0x0a);
  }
    }
[c/]

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
>     irmp_uart_puts(irmp_data.protocol);

irmp_uart_puts() erwartet einen String und keine Nummer.

>     //irmp_uart_puts(irmp_data.address);

Dito.

>     //irmp_uart_puts(irmp_data.command);

Dito.

Das erklärt das Verhalten. Du bekommst absoluten Unsinn zu sehen. Die 
übergebene Nummer wird als String-Adresse interpretiert und damit greift 
irmp_uart_puts() irgendwo in Deinen Speicher und versucht das als String 
auszugeben, was da zufälligerweise rumliegt.

Du hast da keine Compiler-Warnung bekommen???

Ausserdem benutzt Du da die IRMP-Logging-Funktionen. Da hauen Dir ja 
noch jede Menge 1en und 0en in den Output. Nicht schön.

Schalte das Logging aus (das ist nur für Analysezwecke) und ersetze den 
kompletten(!) Inhalt Deines main.c mal durch diesen:
#include "irmp.h"
#define BAUD  9600L
#include <util/setbaud.h>

#ifdef UBRR0H

#define UART0_UBRRH                             UBRR0H
#define UART0_UBRRL                             UBRR0L
#define UART0_UCSRA                             UCSR0A
#define UART0_UCSRB                             UCSR0B
#define UART0_UCSRC                             UCSR0C
#define UART0_UDRE_BIT_VALUE                    (1<<UDRE0)
#define UART0_UCSZ1_BIT_VALUE                   (1<<UCSZ01)
#define UART0_UCSZ0_BIT_VALUE                   (1<<UCSZ00)
#ifdef URSEL0
#define UART0_URSEL_BIT_VALUE                   (1<<URSEL0)
#else
#define UART0_URSEL_BIT_VALUE                   (0)
#endif
#define UART0_TXEN_BIT_VALUE                    (1<<TXEN0)
#define UART0_UDR                               UDR0
#define UART0_U2X                               U2X0
        
#else

#define UART0_UBRRH                             UBRRH
#define UART0_UBRRL                             UBRRL
#define UART0_UCSRA                             UCSRA
#define UART0_UCSRB                             UCSRB
#define UART0_UCSRC                             UCSRC
#define UART0_UDRE_BIT_VALUE                    (1<<UDRE)
#define UART0_UCSZ1_BIT_VALUE                   (1<<UCSZ1)
#define UART0_UCSZ0_BIT_VALUE                   (1<<UCSZ0)
#ifdef URSEL
#define UART0_URSEL_BIT_VALUE                   (1<<URSEL)
#else
#define UART0_URSEL_BIT_VALUE                   (0)
#endif
#define UART0_TXEN_BIT_VALUE                    (1<<TXEN)
#define UART0_UDR                               UDR
#define UART0_U2X                               U2X

#endif //UBRR0H

static void
uart_init (void)
{
    UART0_UBRRH = UBRRH_VALUE;                                                                      // set baud rate
    UART0_UBRRL = UBRRL_VALUE;

#if USE_2X
    UART0_UCSRA |= (1<<UART0_U2X);
#else
    UART0_UCSRA &= ~(1<<UART0_U2X);
#endif

    UART0_UCSRC = UART0_UCSZ1_BIT_VALUE | UART0_UCSZ0_BIT_VALUE | UART0_URSEL_BIT_VALUE;
    UART0_UCSRB |= UART0_TXEN_BIT_VALUE;                                                            // enable UART TX
}

static void
uart_putc (unsigned char ch)
{
    while (!(UART0_UCSRA & UART0_UDRE_BIT_VALUE))
    {
        ;
    }

    UART0_UDR = ch;
}

static void
uart_puts (unsigned char * s)
{
    while (*s)
    {
        uart_putc (*s);
        s++;
    }
}

static uint8_t
itox (uint8_t val)
{
    uint8_t rtc;

    val &= 0x0F;

    if (val <= 9)
    {
        rtc = val + '0';
    }
    else
    {
        rtc = val - 10 + 'A';
    }
    return (rtc);
}

static void
itoxx (unsigned char * xx, unsigned char i)
{
    *xx++ = itox (i >> 4);
    *xx++ = itox (i & 0x0F);
    *xx = '\0';
}

static void
timer1_init (void)
{
#if defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__)                // ATtiny45 / ATtiny85:

#if F_CPU >= 16000000L
    OCR1C   =  (F_CPU / F_INTERRUPTS / 8) - 1;                              // compare value: 1/15000 of CPU frequency, presc = 8
    TCCR1   = (1 << CTC1) | (1 << CS12);                                    // switch CTC Mode on, set prescaler to 8
#else
    OCR1C   =  (F_CPU / F_INTERRUPTS / 4) - 1;                              // compare value: 1/15000 of CPU frequency, presc = 4
    TCCR1   = (1 << CTC1) | (1 << CS11) | (1 << CS10);                      // switch CTC Mode on, set prescaler to 4
#endif

#else                                                                       // ATmegaXX:
    OCR1A   =  (F_CPU / F_INTERRUPTS) - 1;                                  // compare value: 1/15000 of CPU frequency
    TCCR1B  = (1 << WGM12) | (1 << CS10);                                   // switch CTC Mode on, set prescaler to 1
#endif

#ifdef TIMSK1
    TIMSK1  = 1 << OCIE1A;                                                  // OCIE1A: Interrupt by timer compare
#else
    TIMSK   = 1 << OCIE1A;                                                  // OCIE1A: Interrupt by timer compare
#endif
}

#ifdef TIM1_COMPA_vect                                                      // ATtiny84
#define COMPA_VECT  TIM1_COMPA_vect
#else
#define COMPA_VECT  TIMER1_COMPA_vect                                       // ATmega
#endif

ISR(COMPA_VECT)                                                             // Timer1 output compare A interrupt service routine, called every 1/15000 sec
{
  (void) irmp_ISR();                                                        // call irmp ISR
  // call other timer interrupt routines...
}

int
main (void)
{
    IRMP_DATA irmp_data;
    unsigned char buf[3];

    irmp_init();                                                            // initialize irmp
    timer1_init();                                                          // initialize timer1
    uart_init();                                                            // initialize uart

    sei ();                                                                 // enable interrupts

    for (;;)
    {
        if (irmp_get_data (&irmp_data))
        {
            uart_puts ((unsigned char *) "protocol: 0x");
            itoxx (buf, irmp_data.protocol);
            uart_puts (buf);

            uart_puts ((unsigned char *) "   address: 0x");
            itoxx (buf, irmp_data.address >> 8);
            uart_puts (buf);
            itoxx (buf, irmp_data.address & 0xFF);
            uart_puts (buf);

            uart_puts ((unsigned char *) "   command: 0x");
            itoxx (buf, irmp_data.command >> 8);
            uart_puts (buf);
            itoxx (buf, irmp_data.command & 0xFF);
            uart_puts (buf);

            uart_puts ((unsigned char *) "   flags: 0x");
            itoxx (buf, irmp_data.flags);
            uart_puts (buf);

            uart_puts ((unsigned char *) "\r\n");
        }
    }
}


Da sind entsprechende UART-Routinen drin, die unabhängig vom 
IRMP-Logging arbeiten. Ausserdem werden die Nummern hier in Hexwerte in 
Form von Strings gewandelt, die dann ausgegeben werden.

Wenn das dann funktioniert, Dir aber die Hex-Ausgabe nicht behagt, 
kannst Du dann in einem 2. Schritt die Aufrufe von itoxx() durch itoa() 
ersetzen (Achtung, andere Parameter!).

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Du hast da keine Compiler-Warnung bekommen???

der Compiler hat sich nicht gerührt!

> Ausserdem benutzt Du da die IRMP-Logging-Funktionen. Da hauen Dir ja
> noch jede Menge 1en und 0en in den Output. Nicht schön.
>
> Schalte das Logging aus (das ist nur für Analysezwecke) und ersetze den
> kompletten(!) Inhalt Deines main.c mal durch diesen:

Das Logging ist ausgeschaltet!
Ich habe aber die komlette UART Funktion aus irmp.c nach main.c 
verschoben.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Das Logging ist ausgeschaltet!
> Ich habe aber die komlette UART Funktion aus irmp.c nach main.c
> verschoben.

Achso... und weiterhin gleich genannt. Damit hast Du mich natürlich aufs 
Glatteis geführt. ;-)

Trotzdem hätte der Compiler meckern müssen, denn der Aufruf mit falschen 
Parametern kann einen Fehler bewirken, der hier (also in diesem 
speziellen Falle) ganz offensichtlich ist.

Wenn ich es probiere, bekomme ich sofort eine Warnung:
uart_puts (irmp_data.address);

../main.c:178:1: warning: passing argument 1 of 'uart_puts' makes pointer from integer without a cast [enabled by default]
../main.c:74:1: note: expected 'unsigned char *' but argument is of type 'uint16_t'

Schau mal unten in die Ausgabe Deiner IDE, da gibt es normalerweise noch 
"Reiter", mit denen man die Ansicht des Ausgabefensters ändern kann. 
Vermutlich schaust Du Dir den falschen Output an.

In meiner main.c (s. oben) habe ich die irmp_uart_xxxx() Funktionen in 
uart_xxx() (also ohne Prefix irmp_) umbenannt, damit es da keine 
Missverständnisse bzw. Konflikte gibt. Ausserdem habe ich sie auf die 
Zeilen eingestampft, die man im konkreten Fall (AVR) überhaupt braucht.

Versuche bitte mal meine Fassung von main.c (s. Posting oben) und 
berichte.

: Bearbeitet durch Moderator
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Versuche bitte mal meine Fassung von main.c (s. Posting oben) und
> berichte.

Ja, so sieht das natürlich ganz professionell aus. Jetzt ist es auch 
nicht mehr das Protokoll 10 oder 16, sondern 02.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Frank M. schrieb:
>
>> Versuche bitte mal meine Fassung von main.c (s. Posting oben) und
>> berichte.
>
> Ja, so sieht das natürlich ganz professionell aus. Jetzt ist es auch
> nicht mehr das Protokoll 10 oder 16, sondern 02.

Also NEC. Das klingt plausibel für Deine Panasonic-FB. Na also, dann 
hast Du ja die Haupthürde geschafft :-)

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Schau mal unten in die Ausgabe Deiner IDE, da gibt es normalerweise noch
> "Reiter", mit denen man die Ansicht des Ausgabefensters ändern kann.
> Vermutlich schaust Du Dir den falschen Output an.

Ich habe mein main.c nochmals laufen lassen und bekomme tatsächlich 
entsprechende Warnungen, aber keine Fehler, die einen Abbruch auslösen.

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Ich habe mein main.c nochmals laufen lassen und bekomme tatsächlich
> entsprechende Warnungen, aber keine Fehler, die einen Abbruch auslösen.

Deswegen sind beim gcc die Compiler-Flags -Wall und -Werror immer eine 
gute Idee ;).

Mit freundlichen Grüßen,
Karol Babioch

Autor: Jörg R. (jrie)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Logging für den STM32F10x:
diff -Nru A/irmp.c B/irmp.c
--- A/irmp.c  2014-08-28 01:54:03.770837120 +0200
+++ B/irmp.c  2014-08-28 01:54:08.585836842 +0200
@@ -564,6 +564,9 @@
 #  define  STM32_UART_COM     USART2
 #  define  STM32_UART_BAUD    115200                                  // mit 115200 Baud
 #  include "stm32f4xx_usart.h"
+#elif defined(ARM_STM32F10X)
+#  define  STM32_UART_COM     USART3                                  // UART3 an PB10
+#  include "stm32f10x_usart.h"
 #else
 #  if IRMP_EXT_LOGGING == 1                                           // use external logging
 #    include "irmpextlog.h"
@@ -661,7 +664,38 @@
 
     // UART enable
     USART_Cmd(STM32_UART_COM, ENABLE);
+#elif defined(ARM_STM32F10X)
+    GPIO_InitTypeDef GPIO_InitStructure;
+    USART_InitTypeDef USART_InitStructure;
+
+    // Clock enable vom TX Pin
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // UART3 an PB10
+
+    // Clock enable der UART
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
+
+    // UART als Alternative-Funktion mit PushPull
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+
+    // TX-Pin
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+    // Oversampling
+    USART_OverSampling8Cmd(STM32_UART_COM, ENABLE);
+
+    // init mit Baudrate, 8Databits, 1Stopbit, keine Parität, kein RTS+CTS
+    USART_InitStructure.USART_BaudRate = 115200;
+    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
+    USART_InitStructure.USART_StopBits = USART_StopBits_1;
+    USART_InitStructure.USART_Parity = USART_Parity_No;
+    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+    USART_InitStructure.USART_Mode = USART_Mode_Tx;
+    USART_Init(STM32_UART_COM, &USART_InitStructure);
 
+    // UART enable
+    USART_Cmd(STM32_UART_COM, ENABLE);
 #else
 #if (IRMP_EXT_LOGGING == 0)                                                                         // use UART
     UART0_UBRRH = UBRRH_VALUE;                                                                      // set baud rate
@@ -692,7 +726,7 @@
 irmp_uart_putc (unsigned char ch)
 {
 #ifndef UNIX_OR_WINDOWS
-#if defined(ARM_STM32F4XX)
+#if defined(ARM_STM32F4XX) || defined(ARM_STM32F10X)
     // warten bis altes Byte gesendet wurde
     while (USART_GetFlagStatus(STM32_UART_COM, USART_FLAG_TXE) == RESET)
     {
Gruß, Jörg

Autor: E. K. (eku)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,

die Definition von irmp_protocol_names führt auf AVR MCUs dazu, dass die 
Strings beim Start vom FLASH ins RAM dupliziert werden. Das vereinfacht 
zwar den Zugriff, verschwendet aber wertvollen RAM.

Besser ist folgende Implementierung:
static const char proto_unknown[] PROGMEM = "unknown";
static const char proto_sircs[] PROGMEM = "SIRCS";
static const char proto_nec[] PROGMEM = "NEC";
.....

const PGM_P const irmp_proto_names[] PROGMEM = {
  proto_unknown,
  proto_sircs,
  proto_nec,
....
};



  printf_P(PSTR("IRMP RX: proto %02" PRId8 " %S, address %04" PRIX16
                ", command %04" PRIX16 ", flags %02" PRIX8 "\n"),
           irmp_data_p->protocol,
           pgm_read_word(&irmp_proto_names[irmp_data_p->protocol]),
           irmp_data_p->address, irmp_data_p->command, irmp_data_p->flags);

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
E. K. schrieb:
> Das vereinfacht
> zwar den Zugriff, verschwendet aber wertvollen RAM.

Ja.

E. K. schrieb:
> Besser ist folgende Implementierung:

Naja, ganz so einfach ist es dann doch nicht - zumindest wenn man 
plattformübergreifend funktionieren möchte ;).

E. K. schrieb:
> const PGM_P const irmp_proto_names[] PROGMEM = {

Zunächst einmal ist das hier doppelt gemoppelt. PGM_P ist bereits als 
"const char*" definiert, insofern kann man sich das erste (!) const 
sparen.

Das Problem ist aber, dass es pgm_read_word() auf anderen Plattformen 
nicht gibt. Man müsste also irgendwelche Hilfskonstrukte einführen, oder 
aber das Ganze von der aktuellen Plattform abhängig machen, was ggf. 
etwas unübersichtlich werden kann.

Prinzipiell halte ich das aber auch für eine gute Idee, weil das in etwa 
150 Byte RAM sind, der auch sinnvoller verwendet werden kann ;). Ich bin 
mir nur nicht sicher was die beste Option ist, um möglichst plattform 
kompatibel zu bleiben. Da hat Frank ggf. mehr Erfahrung bzw. bessere 
Ideen.

Mit freundlichen Grüßen,
Karol Babioch

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
E. K. schrieb:
> die Definition von irmp_protocol_names führt auf AVR MCUs dazu, dass die
> Strings beim Start vom FLASH ins RAM dupliziert werden. Das vereinfacht
> zwar den Zugriff, verschwendet aber wertvollen RAM.

Hm, ich hab das wohl übersehen. Normalerweise achte ich auf so etwas. 
Hat wohl historische Gründe - weil ich das Array ursprünglich nur für 
den Analyze-Modus auf dem PC brauchte.

Karol Babioch schrieb:
> Das Problem ist aber, dass es pgm_read_word() auf anderen Plattformen
> nicht gibt. [...]
> Da hat Frank ggf. mehr Erfahrung bzw. bessere Ideen.

Ja, normalerweise mache ich das mit

#define PROGMEM

auf Zielplattformen != AVR.

Ich kümmere mich drum. Im Moment bin ich aber ziemlich ausgelastet.

Autor: SvenK (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo an Alle,

zuerst mal vielen Dank an die IRMP-Macher für die vielen wertvollen 
Infos. Möge sich Euer Sehspektrum immer weiter ins Langwellige 
vergrößern ;-)

Nach einigen Schwierigkeiten habe ich IRMP auf einem ATmega 1284P mit 8 
Mhz (auf Pollin Eval-Board) laufen und konnte mir von diversen 
Fernbedienungen (Samsung TV, Yamaha Receiver) die Codes auf einem LCD 
darstellen.

Ich benötige nun für ein Projekt die Codes der Fernbedienung eines JVC 
KW-NX7000 Navis. Die Fernbedienung mit dem Namen RM-RX250 wird aber 
leider nicht korrekt erkannt. Manchmal kam „Telefunken“, aber bei 
verschiedenen Tasten immer genau derselbe Code, teilweise auch kam auch 
„Siemens“ – alle Tasten gleicher Code

Mit der IRMP.exe auf dem PC analysiert erhalte ich eine weitere 
„Eigenartigkeit“:
Im Artikel bei Mikrocontroller.net sind die „dimensionslosen Zahlen“ 
1/100 der Zeit in µs
z.B.
 pulse avg: 91.0=9102.8 us
Bei mir sind es 1,5/100 !? – unabhängig von der Logging-Frequenz (10, 15 
oder 20 kHz)
z.B.
 pulse avg: 40.8=2720.0 us

Ich habe die Loggings der nötigen Befehle in einer ZIP-Datei angehäng – 
mit 10kHz jeweils 5-mal hintereinander aufgenommen und zusätzich nochmal 
alle zusammengefasst in einer Datei - falls das hilfreicher ist.

Einige Tasten der FB ergeben „kurze“ Sequenzen, andere ca. doppelt so 
lange.

Falls jdm damit etwas anfangen kann und mir einen Tip geben könnte, wie 
ich da weiterkomme wäre es schön wenn er sich melden würde.

Vielen Dank schon mal

SvenK

P.S.: die oben genannten Schwierigkeiten hatte ich bei der RS232 
Übertragung. Mit „U2X“ kam nichts oder nur „Matsch“ im PC an – ohne 
„U2X“ läuft es problemlos !?

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SvenK schrieb:
> Falls jdm damit etwas anfangen kann und mir einen Tip geben könnte, wie
> ich da weiterkomme wäre es schön wenn er sich melden würde.

Das müsste sich Frank mal genauer ansehen, der ist hier der Experte was 
die verschiedenen Protokolle und deren Dekodierung angeht ;).

SvenK schrieb:
> P.S.: die oben genannten Schwierigkeiten hatte ich bei der RS232
> Übertragung. Mit „U2X“ kam nichts oder nur „Matsch“ im PC an – ohne
> „U2X“ läuft es problemlos !?

Dies sollte eigentlich nicht der Fall sein. Das U2X Bit verkleinert den 
Baudraten-Teiler und verdoppelt damit die Frequenz. Für das Senden von 
Daten sollte das eigentlich überhaupt keine Konsequenz haben. Es wirkt 
sich laut Datenblatt nur auf das Empfangen von Daten aus, da es weniger 
Samples gibt.

Sicher, dass alle anderen Einstellungen (z.B. Baud Rate) stimmen und 
auch die richtigen Werte in den UBRR Registern stehen? Die Werte 
unterscheiden sich - je nachdem ob U2X gesetzt ist, oder eben nicht. 
Entweder händisch berechnen, die Tabelle im Datenblatt benutzen, oder 
die Hilfsfunktionalität aus <util/setbaud.h> benutzen, um Fehler zu 
vermeiden.

Mit welcher IDE entwickelst du? Hast du sicherheitshalber das Projekt 
einmal "gesäubert" und komplett neu kompiliert? Damit habe ich schon so 
allerlei unerklärliche Symptome beheben können, unter anderem auch 
Unstimmigkeiten in der Baud Rate, die sich in dem von dir beschriebenem 
Problem geäußert haben.

Mit freundlichen Grüßen,
Karol Babioch

: Bearbeitet durch User
Autor: SvenK (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karol,

danke für Deine Antwort. Ich arbeite mit AVR-Studio 6.1 bis dato 
funktionierte das auch immer ganz gut.

Mit der Holzhammermethode:
#if (IRMP_EXT_LOGGING == 0) //  use UART
UBRR0H  = 0;                   //  9600 Baud
UBRR0L  = 103;                 //  51 ohne / 103 mit U2X
UCSR0A |= (1<<1);              //  U2X
//         76543210
UCSR0C = 0b10000110;
UCSR0B = 0b00001000;

geht es jetzt auch mit U2X.

Den Rest der ganzen "#ifdef's in der Nähe" habe ich dann alle zu 
Kommentaren degradiert. Das könnte man wohl für diesen Bereich als 
"gesäubert" bezeichnen!?

Ansonsten habe ich die ganzen Möglichkeiten für Windows,Linux,Pic,STM 
etc. bis jetzt dringelassen, da der Rest ja (mit anderen 
Fernbedienungen) funktioniert.

...dann bin ich mal gespannt, ob Frank sich rührt / mit meinen Loggings 
was anfangen kann...

Viele Grüße

Sven

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachdem Frank so freundlich war mir ein UART-main hier reinzustellen, 
funktioniert das problemlos. Aber, der Mensch verlangt ja immer mehr und 
jetzt stehe ich wieder vor einem "C" Problem.

Ich habe versucht die Ausgabe um die Protokollnamen zu erweitern und 
dazu folgendes eingegeben:
uart_puts ((unsigned char *) "protocol: 0x");
      itoxx (buf, irmp_data.protocol);
      uart_puts (buf);
      uart_puts ((unsigned char *) " = ");
      uart_puts ((unsigned char *) irmp_protocol_names[irmp_data.protocol]);

Wenn ich dabei "define IRMP_PROTOCOL_NAMES" auf 1 stelle funktioniert 
das auch super. Stelle ich aber statt dessen "define IRMP_LOGGING" auf 1 
beschwert sich der Compiler, daß irmp_protocol_names nicht definiert 
ist, obwohl ich zusätzlich vor der gesamten Ausgabe ein

#if defined IRMP_PROTOCOL_NAMES == 1

gesetzt habe. Was muß ich tun um das zu bereinigen?

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Wenn ich dabei "define IRMP_PROTOCOL_NAMES" auf 1 stelle funktioniert
> das auch super.

Ja, so ist das innerhalb der irmp.c auch definiert:
#if defined(UNIX_OR_WINDOWS) || IRMP_PROTOCOL_NAMES == 1
const char *
irmp_protocol_names[IRMP_N_PROTOCOLS + 1] =
// ...

Bruno M. schrieb:
> Stelle ich aber statt dessen "define IRMP_LOGGING" auf 1
> beschwert sich der Compiler,

Wie kommst du darauf, dass sie die beiden Optionen ausschließen bzw. 
warum schreibst du von "statt dessen"?

Bruno M. schrieb:
> obwohl ich zusätzlich vor der gesamten Ausgabe ein
>
> #if defined IRMP_PROTOCOL_NAMES == 1

Wozu? Übrigens verwendest du "defined" hier falsch. Damit prüfst du, ob 
ein bestimmtes Makro definiert ist, und nicht dessen Wert. Korrekt wäre
#if defined IRMP_PROTOCOL_NAMES && IRMP_PROTOCOL_NAMES == 1

Wobei man die Überprüfung mittels defined i.d.R. weglässt, da es zu 0 
ausgewertet wird, wenn das Makro nicht existiert, siehe [1].

Bruno M. schrieb:
> Was muß ich tun um das zu bereinigen?

Setzt doch einfach beides auf 1?

Mit freundlichen Grüßen,
Karol Babioch

[1]: https://gcc.gnu.org/onlinedocs/cpp/Defined.html

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karol,

danke für die Hinweise!

> Setzt doch einfach beides auf 1?

das geht nicht, da es mein Speicher nicht zuläßt.

Gruß Bruno

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> das geht nicht, da es mein Speicher nicht zuläßt.

Von welcher Plattform und welchem Speicher (RAM oder Flash) sprechen wir 
denn hier? Ein paar Beiträge über dir wurde Frank darauf aufmerksam 
gemacht, dass die Stringkonstanten nicht im Programmspeicher landen. Das 
lässt sich optimieren, wodurch ein "wenig" (150?) Byte RAM frei würden.

Gibt es denn nicht eine Möglichkeit für dich bestimmte Protokoll 
abzuschalten? Oder einen größeren Mikrocontroller zu verwenden? Im 
Notfall müsstest du halt in den Quellen herumpfuschen und unnötiges 
herauswerfen. Ist aber nicht unbedingt empfehlenswert, wenn man 
kompatibel bleiben möchte und von zukünftigen Updates profitieren will.

Mit freundlichen Grüßen,
Karol Babioch

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Von welcher Plattform und welchem Speicher (RAM oder Flash) sprechen wir
> denn hier?

Ich arbeite mit einem AT8, bei dem das Data Memory überläuft.

> Ein paar Beiträge über dir wurde Frank darauf aufmerksam
> gemacht, dass die Stringkonstanten nicht im Programmspeicher landen. Das
> lässt sich optimieren, wodurch ein "wenig" (150?) Byte RAM frei würden.

Das habe ich wohl gelesen, aber meine C-Kenntnisse reichen da bei weitem 
nicht.

> Gibt es denn nicht eine Möglichkeit für dich bestimmte Protokolle
> abzuschalten? Oder einen größeren Mikrocontroller zu verwenden?

Diese Möglichkeit gibt es sicher, aber da ich ja mit der Alternative 
loggen oder Protokoll gut klar kam, habe ich gar nicht weiter versucht.

> Im
> Notfall müsstest du halt in den Quellen herumpfuschen und unnötiges
> herauswerfen. Ist aber nicht unbedingt empfehlenswert, wenn man
> kompatibel bleiben möchte und von zukünftigen Updates profitieren will.

Das scheitert schon an meinen C-Kenntnissen.

Ich habe es jetzt mal mit

#if IRMP_PROTOCOL_NAMES == 1

versucht. Damit ist das Problem gelöst!

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karol Babioch schrieb:
> Von welcher Plattform und welchem Speicher (RAM oder Flash) sprechen wir
> denn hier? Ein paar Beiträge über dir wurde Frank darauf aufmerksam
> gemacht, dass die Stringkonstanten nicht im Programmspeicher landen. Das
> lässt sich optimieren, wodurch ein "wenig" (150?) Byte RAM frei würden.

ich bin ja grad beim Arduino

und diese kleine Änderung an vielen Stellen:

#ifdef IRMP_SUPPORT_KASEIKYO_PROTOCOL
  case IRMP_KASEIKYO_PROTOCOL: Serial.print("IR: "); 
Serial.print("KASEIKYO"); Serial.print(", Address: "); 
Serial.print(irmp_data.address); Serial.print(", Command: "); 
Serial.println(irmp_data.command); break;
#endif

zu

#ifdef IRMP_SUPPORT_KASEIKYO_PROTOCOL
  case IRMP_KASEIKYO_PROTOCOL: Serial.print(F("IR: ")); 
Serial.print(F("KASEIKYO")); Serial.print(F(", Address: ")); 
Serial.print(irmp_data.address); Serial.print(F(", Command: ")); 
Serial.println(irmp_data.command); break;
#endif

hat min. 800 Byte RAM freigemacht !

was so direktes Schreiben aus dem flash doch bewirken kann :-))) !

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

Bewertung
0 lesenswert
nicht lesenswert
Hallo SvenK,

entschuldige bitte die späte Antwort. Ich war letzte Woche unterwegs.

SvenK schrieb:
> Ich benötige nun für ein Projekt die Codes der Fernbedienung eines JVC
> KW-NX7000 Navis. Die Fernbedienung mit dem Namen RM-RX250 wird aber
> leider nicht korrekt erkannt. Manchmal kam „Telefunken“, aber bei
> verschiedenen Tasten immer genau derselbe Code, teilweise auch kam auch
> „Siemens“ – alle Tasten gleicher Code

Ja, das scheint etwas neues zu sein, was IRMP noch nicht kennt.

> Mit der IRMP.exe auf dem PC analysiert erhalte ich eine weitere
> „Eigenartigkeit“:
> Im Artikel bei Mikrocontroller.net sind die „dimensionslosen Zahlen“
> 1/100 der Zeit in µs
> z.B.
 pulse avg: 91.0=9102.8 us
> Bei mir sind es 1,5/100 !? – unabhängig von der Logging-Frequenz (10, 15
> oder 20 kHz)
> z.B.
 pulse avg: 40.8=2720.0 us

Bei IRMP_INTERRUPTS = 10000 sollte man erhalten:

  pulse avg: 91.0=9102.8 us

Bei einer Scan-Frequenz von 15000 sollte der Zähler links aber das 
1,5-fache betragen, nämlich ungefähr:

  pulse avg: 136.0=9102.8 us

> Ich habe die Loggings der nötigen Befehle in einer ZIP-Datei angehäng –
> mit 10kHz jeweils 5-mal hintereinander aufgenommen und zusätzich nochmal
> alle zusammengefasst in einer Datei - falls das hilfreicher ist.

Danke. Ich habe gerade mal kurz reingeschaut. Das Protokoll sollte 
einfach in den IRMP einzubauen sein. Kann ich heute oder morgen machen. 
Ich stelle dann eine Testversion ins SVN.

> P.S.: die oben genannten Schwierigkeiten hatte ich bei der RS232
> Übertragung. Mit „U2X“ kam nichts oder nur „Matsch“ im PC an – ohne
> „U2X“ läuft es problemlos !?

Hm. Dafür habe ich leider keine Erklärung.

Gruß,

Frank

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:

> Ich arbeite mit einem AT8, bei dem das Data Memory überläuft.

Ist dieser auf einem Sockel aufgesteckt? Wenn ja, dann könntest Du den 
ATmega8 durch einen ATmega328 ersetzen. Dieser ist pinkompatibel und hat 
den vierfachen Speicher.

>> Ein paar Beiträge über dir wurde Frank darauf aufmerksam
>> gemacht, dass die Stringkonstanten nicht im Programmspeicher landen. Das
>> lässt sich optimieren, wodurch ein "wenig" (150?) Byte RAM frei würden.
>
> Das habe ich wohl gelesen, aber meine C-Kenntnisse reichen da bei weitem
> nicht.

Ich kümmere mich kurzfristig darum.

> #if IRMP_PROTOCOL_NAMES == 1
>
> versucht. Damit ist das Problem gelöst!

Ich schaue mir die Stelle im Code mal an.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Ich arbeite mit einem AT8, bei dem das Data Memory überläuft.

Ich habe nun irmp_protocol_names[] auf PROGMEM umgestellt und 
desweiteren in das Beispiel-main.c UART-Routinen aufgenommen, so dass 
man nun die Daten zum empfangenen Protokoll direkt auf dem UART ausgeben 
kann. Für PROGMEM-Strings habe ich neben uart_puts() auch uart_puts_P() 
implementiert. Damit schrumpft bei Verwendung von irmp_protocol_names[] 
der RAM-Bedarf um 300 Bytes. Damit sollte bei Dir genügend Speicher 
übrig bleiben.

Eingecheckt sind die Änderungen im SVN als Version 2.6.3.

Viel Spaß,

Frank

Autor: Joachim B. (jar)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Für PROGMEM-Strings habe ich neben uart_puts() auch uart_puts_P()
> implementiert.

könnte man nicht durch ein "geschicktes" #define

wie hier:
#define usart_write(format, args...)   usart_write_P(PSTR(format) , ## 
args)

diese Unterscheidung für den User eliminieren oder ist das schon drin 
und der User merkt davon nix ?

ich nutze da immer den Ulrich Radig Code und finde das so genial das ich 
mich nie drum kümmern muss, Textkonstanten kommen direkt aus dem Flash 
ohne Ramverbrauch und ich muss beim proggen auch nie darauf achten 
welche usart_write ich aufrufen muss

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

Bewertung
0 lesenswert
nicht lesenswert
SvenK schrieb:
> Ich benötige nun für ein Projekt die Codes der Fernbedienung eines JVC
> KW-NX7000 Navis. Die Fernbedienung mit dem Namen RM-RX250 wird aber
> leider nicht korrekt erkannt.

Nach Analyse Deiner Scans konnte ich feststellen, dass es sich um das 
Kaseikyo-Protokoll handelt. Es wurde nur nicht von IRMP erkannt, weil 
das Timing Deiner Fernbedienung sich nicht ganz an das 
Kaseikyo-Protokoll hält.

IRMP toleriert beim Kaseikyo-Protokoll eine Abweichung des 
Startbit-Timings um 10 Prozent. Das reicht aber nicht für Deine FB.

Abhilfe in irmp.c:

Alt:
#define KASEIKYO_START_BIT_PULSE_LEN_MIN        ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KASEIKYO_START_BIT_PULSE_LEN_MAX        ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define KASEIKYO_START_BIT_PAUSE_LEN_MIN        ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KASEIKYO_START_BIT_PAUSE_LEN_MAX        ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)

Neu mit Toleranz von 20%:
#define KASEIKYO_START_BIT_PULSE_LEN_MIN        ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define KASEIKYO_START_BIT_PULSE_LEN_MAX        ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define KASEIKYO_START_BIT_PAUSE_LEN_MIN        ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define KASEIKYO_START_BIT_PAUSE_LEN_MAX        ((uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)

Dann sollte es gehen. Die Änderung ist auch im SVN (Version 2.6.4) 
eingecheckt.

Was mir noch auffiel in Deinen Scans: Einige Tasten wiederholen den 
Frame ein zweites Mal (irmp_data.flag = 1). Das kann entweder daran 
liegen, dass Du diese Tasten länger gedrückt hast oder die FB es bei 
bestimmten Tasten prinzipiell macht. In diesem Fall könntest Du bei 
flag=1 den Frame ignorieren, falls die doppelte Erkennung Deine 
Anwendung "durcheinander bringen" könnte.

Gruß,

Frank

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> könnte man nicht durch ein "geschicktes" #define
>
> wie hier:
> #define usart_write(format, args...)   usart_write_P(PSTR(format) , ##
> args)
>
> diese Unterscheidung für den User eliminieren oder ist das schon drin
> und der User merkt davon nix ?

Nein. Dieses usart_write() erwartet IMMER einen konstanten String als 
Format. Eine Variable kannst Du da nicht übergeben! Das PSTR()-Makro 
funktioniert nämlich nur für konstante Strings. Wenn Du einen variablen 
String ausgeben willst, musst Du den ins Argument hinter das Format 
packen. Aber nur dann! Denn hier kannst Du wiederum keinen konstanten 
PROGMEM-String als Argument übergeben.

Daher ist dieses Makro gar nicht so genial, wie es ausschaut. Denn es 
funktioniert ausschließlich bei PROGMEM-Strings fürs Format.

Mein uart_puts() kann auch variable Strings (z.B. einen Buffer) 
ausgeben.

Da musst Du mit

   usart_write ("%s", buffer);

arbeiten. Die Unterscheidung (P vs. non P) machst Du also bei der 
Parameterübergabe, ich beim Funktions-Aufruf.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Mein uart_puts() kann auch variable Strings (z.B. einen Buffer)
> ausgeben.
>
> Da musst Du mit
>
>    usart_write ("%s", buffer);
>
> arbeiten.

danke, nur dann verstehe ich nicht wieso folgendes funktioniert ?

aus Hyperterminal
NIC init:READY!

aus dem Sourcecode
/*NIC Initialisieren*/
usart_write("NIC init:");
ETH_INIT();
usart_write("READY!\r\n");

hier arbeite ich doch nicht mit:
>    usart_write ("%s", buffer);

und trotzdem funktioniert es ....

: Bearbeitet durch User
Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> und trotzdem funktioniert es ....

Du gibst ja auch konstante Strings aus. Diese werden durch das PSTR() 
Makro im Flash abgelegt und können ausgegeben werden. Franks Aussage 
bezog sich auf Strings, welche zur Laufzeit zusammen gesetzt werden.

Mit freundlichen Grüßen,
Karol Babioch

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gleich noch ne Frage hinterher

besser mit 2 Interrupts arbeiten oder einen

weil nicht jeder Atmel genug Timer hat und mir kein Interrupt entgehen 
soll

habe ich alles in einen Timer gepackt

der macht Interrups 15000, eine Var zählt bis 150 für 10ms und dort wird 
ne Menge gemacht was über 64µs dauern kann, Folge es entgehen mir 
Interupts für IR, ist zwar bis jetzt nicht so auffällig kritisch ABER

ich grübel gerade ob nicht nicht doch besser bei Vorhandensein 2er Timer 
diese Interrupts trenne und den 10ms Interrupt durch ISR(irmp) 
unterbrechbar mache, die kurze IRMP Unterbrechung stört in meiner 10ms 
Routine nicht.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> und trotzdem funktioniert es ....

Wie Karol schon wiederholte: Der Format-String muss bei Deiner 
usart_write() konstant sein.

Versuch doch mal folgendes:
char buffer[] = "Hello World";

oder
char buffer[64];
strcpy (buffer, "Es ist egal, wie dieser String in diesen Buffer gelangte");

und dann:
usart_write (buffer);

Das wird so nicht funktionieren.

: Bearbeitet durch Moderator
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karol Babioch schrieb:
> Franks Aussage
> bezog sich auf Strings, welche zur Laufzeit zusammen gesetzt werden.

OK ich glaube ich verstehe so langsam, aber bei der typischen

printf("%s", buffer); wirds genauso gemacht und stört doch kein bischen 
....

OK verschiedene Ansätze und Philosophien, kommt ja öfter mal vor bei C

ich werde nie begreifen warum irgendweche STRING Funktionen mal

(signed) char mal unsigned char sind und warum manche char Funktionen 
int (16-bit) zurück geben (wo nur ein Zeichen drin ist)


Frank M. schrieb:
> Versuch doch mal folgendes:

da sehe ich aber nicht den Zusammenhang, char buffer im PROGMEM

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

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> printf("%s", buffer); wirds genauso gemacht und stört doch kein bischen
> ....

Wenn ich eine printf-ähnliche Funktion, die einen Format-String scannen 
kann, in das Beispiel-Main einpflanze, wird das ausführbare Programm 
ungleich viel größer als das jetzige.

Und genau darum geht es nicht bei IRMP! main.c ist lediglich ein 
Beispiel-Programm, welches möglichst ohne große Anforderungen zeigen 
soll, wie man schnell etwas auf die Beine stellen kann.

> ich werde nie begreifen warum irgendweche STRING Funktionen mal
>
> (signed) char mal unsigned char sind

Wenn man 8-Bit-Zeichen (also Umlaute etc) übertragen muss, dann kann man 
unter Umständen bei signed-chars Probleme bekommen. Denn dann werden 
diese Zeichen negativ. Leider sind aus historischen Gründen Strings in 
Gänsefüßchen immer char und nicht unsigned char. Das liegt daran, dass 
die Amerikaner, die Anfang der 70er Jahre C entwickelten, überhaupt 
nicht daran dachten, dass jemand mal mehr als 7-Bit-Zeichen (US-ASCII) 
braucht.

> und warum manche char Funktionen
> int (16-bit) zurück geben (wo nur ein Zeichen drin ist)

Das liegt wohl am Sonder"zeichen" EOF, welches unter UNIX den Wert -1 
hat. Ist auch eine historische Altlast. Auf Rechnern außerhalb von µCs 
ist das aber auch sehr sinnvoll so.

> da sehe ich aber nicht den Zusammenhang, char buffer im PROGMEM

char buffer im PROGMEM? Wie soll das gehen, wenn die Daten erst zur 
Laufzeit per I2C, ETH, RF oder sonstwie in den Buffer gelangt sind?

Die Welt ist nicht so einfach, wie Du sie Dir machst ;-)

: Bearbeitet durch Moderator
Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> printf("%s", buffer);

printf() ist im aber gerade im Bereich der Mikrocontroller oft 
ziemlicher Overkill, gerade bei stark beschränkten Ressourcen.

Frank M. schrieb:
> Leider sind aus historischen Gründen Strings in
> Gänsefüßchen immer char und nicht unsigned char.

Ja, aber für char ohne Angabe von signed bzw. unsigned ist nicht 
festgelegt wie diese zu implementieren sind und hängt daher vom Compiler 
ab, siehe [1].

Aber ja, das korrekte Verwenden von Datentypen innerhalb von C ist oft 
gar nicht so einfach. Dabei sind die historische Altlasten nur ein 
Grund, ein weiterer ist es den verschiedenen Plattformen ohne viel 
Overhead gerecht zu werden. Dadurch ist kaum etwas festgelegt. Gibt es 
nicht sogar Plattformen auf denen gilt: sizeof(short) = sizeof(int) = 
sizeof(long).

Das ganze Rumgegurke mit uint8_t bei den kleinen Mikrocontrollern ist ja 
auch nicht unbedingt portabel. Besser wäre wohl uint8_fast_t, aber das 
kann wiederum zu Nebeneffekten führen, wenn man sich irgendwo (implizit) 
auf den Wertebereich und damit verbundene Wrap-Arounds verlässt.

Wirklich portablen C Code zu produzieren ist gar nicht so einfach [2], 
und dürfte in den meisten Fällen zu einem Dschungel aus typedefs und 
Konditionen beim Kompilieren führen.

Joachim B. schrieb:
> OK verschiedene Ansätze und Philosophien, kommt ja öfter mal vor bei C

In diesem Zusammenhang interessant ist auch die "Rückgabe" von Fehlern. 
Je nach Gusto ist es hier üblich negative Werte für Fehler 
vorzubehalten, oder auch nicht. Dass 0 "success" bedeutet, beißt sich 
manchmal auch etwas mit der ansonsten üblichen Notation von false = 0 
bzw. true = 1.

Wie du schon sagst: Da ist man in C relativ frei. Als jemand der mit 
besser typisierten Programmiersprachen angefangen hat, wünsche ich mir 
manchmal schon etwas mehr Vorgaben herbei, aber was solls, ist eh etwas 
Off-Topic.

Mit freundlichen Grüßen,
Karol Babioch

[1]: 
https://stackoverflow.com/questions/2054939/is-cha...
[2]: 
https://www.mikrocontroller.net/articles/Plattform...

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Die Welt ist nicht so einfach, wie Du sie Dir machst ;-)

dafür betreibst du aber eine Menge Aufwand (in IRMP) um es anderen Usern 
doch einfach zu machen :-)

wollen wir nicht alle irgendwie einfach ?

noch mal zur obigen Frage, doch besser meine 10ms Berechnungen aus der 
IRMP ISR rausnehmen und in meiner 10ms ISR lieber IRMP ISR erlauben ?

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> Eingecheckt sind die Änderungen im SVN als Version 2.6.3.

Hallo Frank,

herzlichen Dank für den prompten Service.
Speicher habe ich jetzt genug! Allerdings bekomme ich keine Protokolle 
angezeigt. Das Loggen funktioniert normal.

Ich muß mir das morgen mal näher ansehen, heute habe ich keine Lust 
mehr;-)

Gruß Bruno

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> besser mit 2 Interrupts arbeiten oder einen

Es kommt so oder so auf dasselbe heraus.

> weil nicht jeder Atmel genug Timer hat und mir kein Interrupt entgehen
> soll
>
> habe ich alles in einen Timer gepackt
> der macht Interrups 15000, eine Var zählt bis 150 für 10ms und dort wird
> ne Menge gemacht was über 64µs dauern kann,

Das wird im WordClock-Projekt genauso gemacht. Die ISR ruft neben 
irmp_ISR() noch jede Menge anderer Funktionen auf, welche durch Zähler 
in der ISR "getimed" werden.

> Folge es entgehen mir Interupts für IR

Dann machst Du zuviel in der ISR.

> ich grübel gerade ob nicht nicht doch besser bei Vorhandensein 2er Timer
> diese Interrupts trenne

Nein. Das bringts nicht. Ganz im Gegenteil: Dein zweiter Timer sorgt 
u.U. dafür, dass der IRMP-Timer nicht immer in gleichen Zeitabständen 
aufgerufen wird, sondern erst, wenn die zweite ISR beendet wird. Das 
verfälscht das Scan-Ergebnis.

Schau lieber, dass Du Deine eigenen Timer-Routinen abkürzen kannst, z.B. 
durch Setzen eines Flags, welches von der Hauptschleife ausgewertet 
wird.

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

Linker:
 -Os                    # ja, beim Linker!
 -flto
 -ffunction-sections
 -fdata-sections
 -Wl,--gc-sections

Diese Flags bewirken unter anderem, dass der avr-gcc sämtliche 
Funktionen, die aus einer ISR aufgerufen werden, inline behandeln kann - 
auch wenn sie in verschiedenen C-Quelltexten stecken. Dadurch können 
einige PUSH-/POP-Befehle eingespart werden. Der Nachteil, dass bei 
Funktionsaufrufen aus der ISR auf Verdacht viel zuviele Register 
gesichert werden, wird dadurch eliminiert und das Zeitverhalten 
verbessert sich etwas.

Sinnvoller ist natürlich, das Übel an der Wurzel zu packen - d.h. Deine 
ISR-Funktionen zu überarbeiten.

: Bearbeitet durch Moderator
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Dann machst Du zuviel in der ISR.

das ist ja klar, wenn IRMP Interrupts "verloren" gehen

> Schau lieber, dass Du Deine eigenen Timer-Routinen abkürzen kannst, z.B.
> durch Setzen eines Flags, welches von der Hauptschleife ausgewertet
> wird.

OK das hatte ich ja bei meinem anderen Projekt schon mit Erfolg gemacht, 
nun muss ich mal sehen wie ich das der Arduino IDE beibringe, die ist 
etwas zickiger sprich undurchsichtiger (für mich)

Danke.

> Nein. Das bringts nicht. Ganz im Gegenteil: Dein zweiter Timer sorgt
> u.U. dafür, dass der IRMP-Timer nicht immer in gleichen Zeitabständen
> aufgerufen wird, sondern erst, wenn die zweite ISR beendet wird. Das
> verfälscht das Scan-Ergebnis.

das verstehe ich nicht, ich kann am Anfang meiner 10ms Interrupts die 
IRMP Interrupt wieder erlauben und dann wird sofort meine 10ms ISR durch 
IRMP unterbrochen, im Timing passend !

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

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> das verstehe ich nicht, ich kann am Anfang meiner 10ms Interrupts die
> IRMP Interrupt wieder erlauben und dann wird sofort meine 10ms ISR durch
> IRMP unterbrochen, im Timing passend !

Ja, das kannst Du natürlich machen, ist aber unüblich bei AVRs. Ich sehe 
da auch keinen Gewinn, denn 100% Auslastung bleibt 100% Auslastung.

Besser wäre ein µC mit priorisierten Interrupts. Das liefern die AVRs 
aber nicht von Haus aus.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> ich kann am Anfang meiner 10ms Interrupts die
>> IRMP Interrupt wieder erlauben und dann wird sofort meine 10ms ISR durch
>> IRMP unterbrochen, im Timing passend !

Frank M. schrieb:
> Ja, das kannst Du natürlich machen, ist aber unüblich bei AVRs. Ich sehe
> da auch keinen Gewinn, denn 100% Auslastung bleibt 100% Auslastung.

ich glaube du hast was falsch verstanden, der Controller ist nicht zu 
100% ausgelastet, nur in meiner alle 10ms Routine kann es länger als 
64µs (INTERRUPT IRMP) dauern, was IRMP stört, ob ich meine maximal 100µs 
Berechnung im Hauptprogramm mache durch Flags oder in meiner 10ms 
Timerroutine und diese durch IRMP unterbrechen lasse ist doch egal.
Zudeinem ist doch unüblich lese ich hier durchaus anderes.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Aber ich will nicht mit dir streiten, ich danke dir für IRMP und freue 
mich über unseren fruchtbaren Gedankenaustausch (nicht furchtbar hoffe 
ich für dich)

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> Zudeinem ist doch unüblich lese ich hier durchaus anderes.
>
> 
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Zitat daraus:

"Bei unsachgemässer Handhabung kann dies zu erheblichen Problemen durch 
Rekursion wie einem Stack-Overflow oder anderen unerwarteten Effekten 
führen und sollte wirklich nur dann eingesetzt werden, wenn man sich 
sicher ist, das Ganze auch im Griff zu haben."

Genau deshalb sehe ich das als "unüblich", aber natürlich auch nicht als 
ausgeschlossen.

> Aber ich will nicht mit dir streiten, [...]

Ja, lassen wir das. Es wird auch langsam offtopic.

: Bearbeitet durch Moderator
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Frank,

> Allerdings bekomme ich keine Protokolle
> angezeigt. Das Loggen funktioniert normal.
>
> Ich muß mir das morgen mal näher ansehen, heute habe ich keine Lust
> mehr;-)

Ich komme leider nicht weiter! Da ich die Vorgängerversion schon 
gelöscht habe, kann ich auch nicht mehr vergleichen und testen.

Funktioniert es bei dir denn normal?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Bruno,

Bruno M. schrieb:
> Ich komme leider nicht weiter! Da ich die Vorgängerversion schon
> gelöscht habe, kann ich auch nicht mehr vergleichen und testen.
>
> Funktioniert es bei dir denn normal?

Konnte ich leider selber nicht testen, weil ich momentan keinen µC in 
Griffweite habe. Da die Änderungen gegenüber der oben geposteten Version
nur marginal waren, muss ich da irgendwas verkorkst haben. Ich schaue 
gleich mal danach.

Hier findest Du die Version wieder, die ich damals für Dich hier 
gepostet hatte:

  Beitrag "Re: IRMP - Infrared Multi Protocol Decoder"

Wenn diese jetzt plötzlich auch nicht mehr funktioniert, dann machst Du 
aber was falsch und nicht ich ;-)

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bruno M. schrieb:
> Ich komme leider nicht weiter! Da ich die Vorgängerversion schon
> gelöscht habe, kann ich auch nicht mehr vergleichen und testen.

Ein Grund mehr für den Einsatz einer Versionsverwaltung. Ohne ist das 
Selbstmord auf Raten.

Mit freundlichen Grüßen,
Karol Babioch

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karol Babioch schrieb:
> Ein Grund mehr für den Einsatz einer Versionsverwaltung. Ohne ist das
> Selbstmord auf Raten.

SVN ist eine Versionsverwaltung. ;-)

Aber das main.c, was Bruno vorher verwendet hatte, hatte ich hier damals 
lediglich in diesem Thread gepostet - speziell für Bruno als 
Einstiegshilfe.

Hier noch zu finden:

  Beitrag "Re: IRMP - Infrared Multi Protocol Decoder"

Verloren ist es also nicht.

EDIT:
Der Unterschied besteht im AVR-Teil der main.c nur durch neue Anwendung 
der uart_puts_P()-funktion. Sonst ist er identisch.

: Bearbeitet durch Moderator
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> "Bei unsachgemässer Handhabung kann dies zu erheblichen Problemen durch
> Rekursion wie einem Stack-Overflow oder anderen unerwarteten Effekten
> führen und sollte wirklich nur dann eingesetzt werden, wenn man sich
> sicher ist, das Ganze auch im Griff zu haben."
>
> Ja, lassen wir das. Es wird auch langsam offtopic.

so zum Abschluß, Testroutine geschrieben und das Tektronix TDS3014 
angehängt

meine 10ms Timerroutine braucht ca. 200µs damit entgehen mir 3 IRMP 
Impulse
deine IRMP ISR braucht 4µs (meine Hochachtung) an 16MHz atmega328p

ich sehe also keinerlei Problematik an Rekursion wenn ich mich an die 
Anleitung im AVR-GCC-Tutorial halte:
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

wenn meine 10ms ISR 200µs Ausführungsdauer hat -> keinerlei 
Rekusionsgefahr !

ich sehe nicht wenn in "meiner" ISR noch mal zusätzlich IRMP zum Zuge 
kommt, kostet mich lächerliche 4µs (oder 3x 4µs) die in meinen 200µs 
nicht auffallen

und alle sollten glücklich sein

noch jemand einen Einwand ?

vielen Dank, jar

PS, das ist mit einem Arduino nano (micro) mit atmega 328p die 
Vorbereitung zu 2x word clock

1x 25x25 cm Test mit IKEA ribba Rahmen LEDstripe WS2812b 60 LED/m
1x 50x50 cm Test mit IKEA ribba Rahmen LEDstripe WS2812b 30 LED/m

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

Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> meine 10ms Timerroutine braucht ca. 200µs damit entgehen mir 3 IRMP
> Impulse

Wofür zum Teufel brauchst Du 200µs? Zeig mal, was Du da alles machst.

> deine IRMP ISR braucht 4µs (meine Hochachtung) an 16MHz atmega328p

Womit gezeigt wäre, dass nicht die Länge, sondern die Geschwindigkeit 
einer ISR ausschlaggebend ist ;-)

> noch jemand einen Einwand ?

Grundsätzlich nicht, aber schön ist das nicht. Das kann man gewiss 
sauberer lösen.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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,
ISR(COMPA_VECT)                                                             // Timer1 output compare A interrupt service routine, called every 1/15000 sec
{
  uint8_t ii;

#ifdef IRQ_TEST
PORT_QUITT_LED |= (1<<QUITT_LED);
#endif

  (void) irmp_ISR();                                                        // call irmp ISR

#ifdef IRQ_TEST
PORT_QUITT_LED &= ~(1<<QUITT_LED);
#endif

  if(teiler)
    teiler--;
  else
  {

#ifdef IRQ_TEST
PORT_CRTL_LED |= (1<<CRTL_LED);
#endif

    teiler=150; count++;
    if(lcd_time_update) 
      lcd_time_update--;
    else 
      lcd_time_update=33;
    
    if(warte_ms)
      warte_ms--;

    if(count==1)
      PORT_POW_LED |= (1<<POW_LED);
    else  
    {
      if(count==21)
        PORT_POW_LED &= ~(1<<POW_LED);
      if(count==100)
      {  count=0;
#ifdef RTCTEST
         sek_offset++;
#endif
      }
    }

#ifndef IRQ_TEST
    if(quitt_count)
    { PORT_QUITT_LED |= (1<<QUITT_LED); quitt_count--;    
    }
    else
      PORT_QUITT_LED &= ~(1<<QUITT_LED);
#endif

    if(_i2c_key)
    {  if(!_i2c_busy)
      {  _i2c_busy=1;
          if(_i2c_key=='A')
         {  if(!i2c_start(PCF8574A_0+I2C_READ))  //;  // set device address and write mode
              ii = key_state ^ ( ( ~(unsigned char)i2c_readNak() ) ); //jar key1 kaputt    
              // ii = key_state ^ ( ( ~(unsigned char)i2c_readNak() ) ___ ); //jar key1 kaputt    
            i2c_stop();
         }
         else
         {  if(!i2c_start(PCF8574_0+I2C_READ))  //;  // set device address and write mode
            ii = key_state ^ ( ( ~(unsigned char)i2c_readNak() ) ); //jar key1 kaputt    
            // ii = key_state ^ ( ( ~(unsigned char)i2c_readNak() ) ___ ); //jar key1 kaputt    
            // ___ | ((~ALARM_int1_PIN & (1<<_ALARM_int1_pin))>>2)
            i2c_stop();
         }
         _i2c_busy=0;
      }
  
      ii &= ALL_KEYS;
      //cam = ii & (1<<CAM_F || 1<<CAM_S);
      ct0 = ~( ct0 & ii );                             // reset or count ct0
      ct1 = ct0 ^ (ct1 & ii);                          // reset or count ct1
      ii &= ct0 & ct1;                                 // count until roll over ?
      key_state ^= ii;                                 // then toggle debounced state
      key_press |= key_state & ii;                     // 0->1: key press detect
   
      if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
      rpt = REPEAT_START;                          // start delay
      if( --rpt == 0 )
      {  rpt = REPEAT_NEXT;                            // repeat delay
         key_rpt |= key_state & REPEAT_MASK;
      }
    }
#ifdef IRQ_TEST
PORT_CRTL_LED &= ~(1<<CRTL_LED);
#endif
  }
} // ISR (TIMER1_COMPA_vect)

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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>

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

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

Du hast jetzt auch die irmp.c-Version, wo
static const char proto_unknown[]       PROGMEM = "UNKNOWN";
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
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
    uart_puts_P (irmp_protocol_names[irmp_data.protocol]);

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

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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:
    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/lo...
[2]: 
https://github.com/Wordclock/firmware/blob/feat/lo...

: Bearbeitet durch User
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

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

: Bearbeitet durch Moderator
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
static const char proto_unknown[]       PROGMEM = "UNKNOWN";
static const char proto_sircs[]         PROGMEM = "SIRCS";
static const char proto_nec[]           PROGMEM = "NEC";
...

... und zum anderen das Array selbst:
const char * const
irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM =
{
    proto_unknown,
    proto_sircs,
    ...

> Fehlt da nicht noch ein "&" samt passender Klammerung innerhalb von
> pgm_read_word()? Also in etwa so:
>
>
>     PGM_P p = (PGM_P) pgm_read_word 
> (&(irmp_protocol_names[irmp_data.protocol]));
> 

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

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bruno M. (brumay)
Datum:

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


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

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
>
>
strcpy_P(p ,(PGM_P) pgm_read_word 
> (&(irmp_protocol_names[irmp_data.protocol])));
>       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 ;-)

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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?"

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke mache ich, nichts für ungut .....

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: SvenK (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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:
Building target: Wordclock.elf
Invoking: AVR C Linker
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   
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

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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 !

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
#define lcd_printyx_P(__line, __column, __text) lcd_printyx_s (__line, __column, (unsigned char *) PSTR(__text), TRUE)
#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
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
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
avr-gcc -mmcu=atmega88 -flto  -ffunction-sections  -fdata-sections  -Wl,--gc-sections  -Wl,-Map=irmp.map main.o irmp.o     -o irmp.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  irmp.elf irmp.hex
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
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:
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
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
avr-gcc -mmcu=atmega88 -flto  -ffunction-sections  -fdata-sections  -Wl,--gc-sections  -Os  -Wl,-Map=irmp.map main.o irmp.o     -o irmp.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  irmp.elf irmp.hex
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
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:
ISR(COMPA_VECT)
{
  (void) irmp_ISR();
}

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:
>
>
> Building target: Wordclock.elf
> Invoking: AVR C Linker
> 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
> Finished building target: Wordclock.elf
> 

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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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:
[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

[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

[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wl,--gc-sections -Wl,-Map=main.map main.o irmp.o -o main.elf

[johnpatcher@vpcs irmp]$ avr-size main.elf 
   text     data      bss      dec      hex  filename
   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:
[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

[johnpatcher@vpcs irmp]$ avr-size main.elf 
   text     data      bss      dec      hex  filename
   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).
[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

[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

[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

[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

[johnpatcher@vpcs irmp]$ avr-size main.elf 
   text     data      bss      dec      hex  filename
   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:
Building target: Wordclock.elf
Invoking: AVR C Linker
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   
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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
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
Autor: Karol Babioch (johnpatcher)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:

[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

[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

[johnpatcher@vpcs irmp]$ avr-gcc -mmcu=atmega88 -Wl,--gc-sections -Wl,-Map=main.map main.o irmp.o -o main.elf

[johnpatcher@vpcs irmp]$ avr-size main.elf 
   text     data      bss      dec      hex  filename
   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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das Ergebnis zur avr-gcc-Optimierung bzgl. LTO nun in 
IRMP-Artikel zusammengefasst:

  http://www.mikrocontroller.net/wikisoftware/index....

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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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/fi...

... 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:
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
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
avr-gcc -mmcu=atmega88 -Os -Wl,-Map=irmp.map main.o irmp.o     -o irmp.elf
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature  irmp.elf irmp.hex
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
avr-objdump -h -S irmp.elf > irmp.lss

AVR Memory Usage
----------------
Device: atmega88

Program:    2448 bytes (29.9% Full)
(.text + .data + .bootloader)

Data:         52 bytes (5.1% Full)
(.data + .bss + .noinit)

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:
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.
< .bss            0x0000000000800104       0x30
<                 0x0000000000800104                PROVIDE (__bss_start, .)
---
> .bss            0x00800104       0x30
>                 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:
$ ls -l *.elf ../*.elf
-rw-r--r-- 1 root root  10940 2014-09-18 18:01 ../irmp.elf
-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
Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg R. (jrie)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: E. K. (eku)
Datum:

Bewertung
0 lesenswert
nicht 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:
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
static const char proto_nec[]           PROGMEM = "NEC";
#endif

....

const char * const
irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM =
{
    proto_unknown,
    proto_sircs,
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
    proto_nec
#else
    proto_unknown
#endif
....


: Bearbeitet durch User
Autor: E. K. (eku)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Bruno M. (brumay)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bruno M. (brumay)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
#if IRMP_USE_CALLBACK == 1
    if (irmp_callback_ptr)
    {
        static uint8_t last_inverted_input;

        if (last_inverted_input != !irmp_input)
        {
            (*irmp_callback_ptr) (! irmp_input);
            last_inverted_input = !irmp_input;
        }
    }
#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
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karol Babioch (johnpatcher)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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. :-)

Autor: Bruno M. (brumay)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Bruno M. (brumay)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Preisfrage (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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):
#  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 ;-)

: Bearbeitet durch Moderator
Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Conny G. (conny_g)
Datum:

Bewertung
0 lesenswert
nicht 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)?

Autor: Preisfrage (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: Preisfrage (Gast)
Datum:

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

Autor: Preisfrage (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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).

Autor: Andreas SaerdnA (preisfrage)
Datum:
Angehängte Dateien:

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

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Z. (stefan_z)
Datum:

Bewertung
0 lesenswert
nicht 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".

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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ß !

Autor: Heino (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#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
#define FLASH_STRING          const

Ich finde das also portabler und obendrein wird der Code nicht durch 
hässliche pgm Funktionen verschandelt.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
Autor: Bad Urban (bad_urban)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ulli (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Joachim B. (jar)
Datum:

Bewertung
0 lesenswert
nicht 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