https://neutrino-images.de/board/viewto ... 11#p40411/
angekündigt, hier jetzt eine Möglichkeit der Anwendung für gewonnene Erkenntnisse.
Die ursprüngliche Schaltung (Arduino Nano V3, KY-022) bleibt bestehen, wird aber um eine IR-Sendediode KY-005 erweitert.
Die SFH409-2 ist dabei nur durch die KY-005 zu ersetzen. IROUT wird mit Pin 3 vom Arduino Nano V3 verbunden.
Das neue Programm sieht jetzt so aus:
main.cpp
Code: Alles auswählen
/*
* Interrupt.cpp
*
* Receives IR protocol data by using pin change interrupts and no polling by timer.
* !!! This WILL NOT work for all protocols.!!!
* Tested for NEC, Kaseiko, Denon, RC6, Samsung + Samsg32.
*
* To disable one of them or to enable other protocols, specify this before the "#include <irmp.hpp>" line.
* If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example).
* The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example).
*
* Copyright (C) 2019-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/ukw100/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
#include <Arduino.h>
/*
* Set input pin and output pin definitions etc.
*/
#include "PinDefinitionsAndMore.h"
#define IRSND_IR_FREQUENCY 38000
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. Must before #include <irmp*>
#define IRSND_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH.
#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality
#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT 1 // Enable interrupt functionality
// #define IRMP_ENABLE_RELEASE_DETECTION 1
// #include <irmpSelectMain15Protocols.h> // This enables 15 main protocols
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // this enables only one protocol
// #include <irsndSelectMain15Protocols.h>
// or use only one protocol to save programming space
#define IRSND_SUPPORT_NEC_PROTOCOL 1
#ifdef ALTERNATIVE_IR_FEEDBACK_LED_PIN
#define IRMP_FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN
#endif
#define USE_ONE_TIMER_FOR_IRMP_AND_IRSND 1 // otherwise we get an error on AVR platform:
// redefinition of 'void __vector_8()
/*
* After setting the definitions we can include the code and compile it.
*/
#include <irmp.hpp>
#include <irsnd.hpp>
IRMP_DATA irmp_data;
IRMP_DATA irsnd_data;
bool bJustReceived = false;
uint8_t _ButtonDebounceCounter = 0;
uint16_t IRMP_KEY = 0;
uint16_t IRMP_LASTKEY = 0;
// uint16_t IRMP_COUNTER = 0;
#define BUTTON_DEBOUNCE_COUNTER_MAX 2;
void handleReceivedIRData();
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) || \
defined(ARDUINO_attiny3217) || defined(ARDUINO_AVR_NANO)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out.
// Do not wait for an attached Serial Monitor!
#endif
#if defined(ESP8266) || defined(ESP32)
Serial.println(); // to separate it from the internal boot output
#endif
// Just to know which program is running on my Arduino
Serial.println(F("\r\nSTART " __FILE__ " from " __DATE__ "\r\n\r\nUsing library version " VERSION_IRMP));
irmp_init();
irmp_irsnd_LEDFeedback(true); // Enable send signal feedback at LED_BUILTIN
irmp_register_complete_callback_function(&handleReceivedIRData);
irsnd_init();
Serial.print(F("\r\nReady to send / receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
#if defined(ARDUINO_ARCH_STM32)
Serial.println(F("at pin " IRMP_INPUT_PIN_STRING));
#else
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
#endif
#if defined(ARDUINO_ARCH_STM32)
Serial.println(F("Ready to send IR signals at pin " IRSND_OUTPUT_PIN_STRING)); // the internal pin numbers are crazy for the STM32 Boards library
#else
Serial.println(F("Ready to send IR signals at pin " STR(IRSND_OUTPUT_PIN)));
#endif
#ifdef ALTERNATIVE_IR_FEEDBACK_LED_PIN
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at ALTERNATIVE_IR_FEEDBACK_LED_PIN
Serial.println(F("\r\nIR feedback pin is " STR(ALTERNATIVE_IR_FEEDBACK_LED_PIN)));
#endif
Serial.println(F("\r\n"));
/*
* Send NEC
*/
irsnd_data.protocol = IRMP_NEC_PROTOCOL;
irsnd_data.address = 0xCD27;
irsnd_data.command = 0x00; // The required inverse of the 8 bit command is added by the send routine.
}
void loop()
{
/*
* Check if new data available and get them
*/
if (bJustReceived == true)
{
bJustReceived = false;
if ((irmp_data.protocol == IRMP_NEC_PROTOCOL) && (irmp_data.address == 0xFF80))
{
if (irmp_data.flags == 0x00)
{
IRMP_KEY = irmp_data.command;
IRMP_LASTKEY = IRMP_KEY;
/*
Serial.print(F("IRMP_COUNTER: "));
Serial.print(IRMP_COUNTER++);
Serial.print(F(" "));
irmp_result_print(&irmp_data);
*/
if (irmp_data.command == 0x0A)
{
irsnd_data.flags = 1; // repeat frame 1 times
irsnd_send_data(&irsnd_data, true);
// irsnd_data_print(&Serial, &irsnd_data);
}
else
{
// irmp_result_print(&Serial, &irmp_data);
Serial.println(irmp_data.command);
}
_ButtonDebounceCounter = BUTTON_DEBOUNCE_COUNTER_MAX;
}
if ((irmp_data.flags & IRMP_FLAG_REPETITION) && (irmp_data.command == IRMP_LASTKEY))
{
if (_ButtonDebounceCounter > 0)
{
_ButtonDebounceCounter--;
}
else
{
/*
Serial.print(F("IRMP_COUNTER: "));
Serial.print(IRMP_COUNTER++);
Serial.print(F(" "));
irmp_result_print(&irmp_data);
*/
if (irmp_data.command == 0x0A)
{
irsnd_data.flags = 1; // repeat frame 1 times
// irmp_result_print(&Serial, &irsnd_data);
irsnd_send_data(&irsnd_data, true);
}
else
{
// irmp_result_print(&Serial, &irmp_data);
Serial.println(irmp_data.command);
}
}
}
}
}
}
/*
* Here we know, that data is available.
* Since this function is executed in Interrupt handler context, make it short and do not use delay() etc.
* In order to enable other interrupts you can call sei() (enable interrupt again) after getting data.
*/
#if defined(ESP8266)
void ICACHE_RAM_ATTR handleReceivedIRData()
#elif defined(ESP32)
void IRAM_ATTR handleReceivedIRData()
#else
void handleReceivedIRData()
#endif
{
irmp_get_data(&irmp_data);
#if defined(ARDUINO_ARCH_MBED) || defined(ESP32) || defined(ARDUINO_AVR_NANO)
bJustReceived = true; // Signal new data for main loop, this is the recommended way for handling a callback :-)
#else
interrupts(); // enable interrupts
// irmp_result_print(&Serial, &irmp_data); // this is not allowed in ISR context for any kind of RTOS
#endif
}
Es wird gewartet, bis ein IR-Signal empfangen wird, danach ob das Protokoll=NEC ist und die Geräteadresse=0xFF80
Entspricht der Fernbedienung für die Coolstream HD2.
Wenn ja wird noch unterschieden, ob das eine neue Taste ist oder nur deren Wiederholung (Repeat).
Es ist noch etwas "Tasten-Entprellung" eingebaut, ansonsten wird dann nur der Code der Taste über die Serielle Schnittstelle gesendet.
Beispiel:
für die Tasten 1 bis 6 der Coolstream HD2 Fernbedienung.
Es gibt eine Ausnahme: wenn der Code für die Taste 0x0A ist, wird nur dafür ein IR-Signal auf dann Geräteadresse 0xCD27 gesendet.
Nicht wundern, der gesendete Code ist =0x00 und entspricht der Taste der Fernbedienung zum einschalten für meine Zgemma H7C.
Das ganze jetzt an eine Zgemma H7C per USB-Hub verbunden / angeschlossen.
Bedingung -> /dev/ttyUSB0 entspricht der Verbindung zum Arduino Nano V3.
Die Scripte auf der Box:
iremote_client
Code: Alles auswählen
#!/bin/bash
echo "iremote_client - start"
INPUT="/tmp/queue.txt"
PIDFILE="/tmp/.jobserver"
if [[ ! -f "$INPUT" ]]; then
touch "$INPUT"
fi
if [ -e /dev/ttyUSB0 ]; then
/var/bin/iremote_jobserver &
/var/bin/iremote_observer &
else
echo "ERROR: /dev/ttyUSB0 not found"
echo "exiting ..."
exit 1
fi
# stty icrnl -F /dev/ttyUSB0 115200
# sleep 3
stty inlcr -hupcl -F /dev/ttyUSB0 115200
# cat < /dev/ttyUSB0 &
# sleep 1
exec 3>&-
sleep 1
exec 3<> /dev/ttyUSB0
sleep 1
read line <&3
echo $line
read line <&3
echo $line
read line <&3
echo $line
read line <&3
echo $line
while true
do
read line <&3
# echo $line
KEYNAME=""
# do somthing with it
if [ $line -eq "31" ]; then
KEYNAME="KEY_OK"
elif [ $line -eq "28" ]; then
KEYNAME="KEY_HOME"
elif [ $line -eq "0" ]; then
KEYNAME="KEY_UP"
elif [ $line -eq "2" ]; then
KEYNAME="KEY_RIGHT"
elif [ $line -eq "3" ]; then
KEYNAME="KEY_LEFT"
elif [ $line -eq "13" ]; then
KEYNAME="KEY_MUTE"
elif [ $line -eq "2" ]; then
KEYNAME="KEY_RIGHT"
elif [ $line -eq "1" ]; then
KEYNAME="KEY_DOWN"
elif [ $line -eq "7" ]; then
KEYNAME="KEY_PAGEDOWN"
elif [ $line -eq "76" ]; then
KEYNAME="KEY_PAGEUP"
elif [ $line -eq "4" ]; then
KEYNAME="KEY_SAT"
elif [ $line -eq "90" ]; then
KEYNAME="KEY_NEXT"
elif [ $line -eq "95" ]; then
KEYNAME="KEY_PREVIOUS"
elif [ $line -eq "29" ]; then
KEYNAME="KEY_RADIO"
elif [ $line -eq "64" ]; then
KEYNAME="KEY_MODE"
elif [ $line -eq "63" ]; then
KEYNAME="KEY_SUBTITLEST"
elif [ $line -eq "12" ]; then
KEYNAME="KEY_GAMES"
elif [ $line -eq "27" ]; then
KEYNAME="KEY_FAVORITES"
elif [ $line -eq "73" ]; then
KEYNAME="KEY_AUDIO"
elif [ $line -eq "15" ]; then
KEYNAME="KEY_HELP"
elif [ $line -eq "62" ]; then
KEYNAME="KEY_LAST"
elif [ $line -eq "30" ]; then
KEYNAME="KEY_EPG"
elif [ $line -eq "11" ]; then
KEYNAME="KEY_INFO"
elif [ $line -eq "14" ]; then
KEYNAME="KEY_VOLUMEUP"
elif [ $line -eq "72" ]; then
KEYNAME="KEY_VOLUMEDOWN"
elif [ $line -eq "89" ]; then
KEYNAME="KEY_RECORD"
elif [ $line -eq "68" ]; then
KEYNAME="KEY_REWIND"
elif [ $line -eq "69" ]; then
KEYNAME="KEY_FORWARD"
elif [ $line -eq "47" ]; then
KEYNAME="KEY_WWW"
elif [ $line -eq "70" ]; then
KEYNAME="KEY_PLAYPAUSE"
elif [ $line -eq "65" ]; then
KEYNAME="KEY_PLAYPAUSE"
elif [ $line -eq "71" ]; then
KEYNAME="KEY_STOP"
elif [ $line -eq "5" ]; then
KEYNAME="KEY_RED"
elif [ $line -eq "9" ]; then
KEYNAME="KEY_GREEN"
elif [ $line -eq "66" ]; then
KEYNAME="KEY_YELLOW"
elif [ $line -eq "67" ]; then
KEYNAME="KEY_BLUE"
elif [ $line -eq "16" ]; then
KEYNAME="KEY_0"
elif [ $line -eq "17" ]; then
KEYNAME="KEY_1"
elif [ $line -eq "18" ]; then
KEYNAME="KEY_2"
elif [ $line -eq "19" ]; then
KEYNAME="KEY_3"
elif [ $line -eq "20" ]; then
KEYNAME="KEY_4"
elif [ $line -eq "21" ]; then
KEYNAME="KEY_5"
elif [ $line -eq "22" ]; then
KEYNAME="KEY_6"
elif [ $line -eq "23" ]; then
KEYNAME="KEY_7"
elif [ $line -eq "24" ]; then
KEYNAME="KEY_8"
elif [ $line -eq "25" ]; then
KEYNAME="KEY_9"
elif [ $line -eq "46" ]; then
KEYNAME="KEY_SLEEP"
elif [ $line -eq "60" ]; then
KEYNAME="KEY_MOVE"
elif [ $line -eq "94" ]; then
KEYNAME="KEY_TIME"
elif [ $line -eq "26" ]; then
KEYNAME="KEY_MENU"
fi
if [[ -n $KEYNAME ]]; then
# echo $KEYNAME
# /usr/bin/wget -O /dev/null -q "http://localhost/control/rcem?$KEYNAME"
/var/bin/queue.sh offer "$KEYNAME"
if [[ ! -f "$PIDFILE" ]]; then
if [ -e /dev/ttyUSB0 ]; then
/var/bin/iremote_jobserver &
else
echo "ERROR: /dev/ttyUSB0 not found"
echo "exiting ..."
exit 1
fi
fi
else
echo "unknown KEYNAME"
fi
done
exec 3<&-
iremote_jobserver
Code: Alles auswählen
#!/bin/bash
INPUT="/tmp/queue.txt"
OUTPUT="/tmp/trash.txt"
PIDFILE="/tmp/.jobserver"
if [[ ! -f "$PIDFILE" ]]; then
touch "$PIDFILE"
fi
CNT="0"
while true
do
if [[ -f "$INPUT" ]]; then
COUNTER=0
COUNTER="$(stat -c %s "$INPUT")"
# if [ -s "$INPUT" ]; then
if [ "$COUNTER" -gt 0 ]; then
# echo "polling ..."
/var/bin/queue.sh poll
CNT="0"
else
# echo "sleeping ..."
CNT=$((CNT + 1))
if [[ "$CNT" -gt "100" ]]; then
break
fi
usleep 50000
# sleep 1
fi
else
# echo "$INPUT" "not exist"
sleep 1
fi
# COUNTER=$(wc -l "$INPUT" | cut -d " " -f 1)
# if [ $COUNTER -gt 0 ]; then
# /var/bin/queue.sh poll
# else
# usleep 10000
# fi
done
if [[ -f "$PIDFILE" ]]; then
rm -f "$PIDFILE"
fi
exit 0
iremote_observer
Code: Alles auswählen
#!/bin/bash
while true
do
if [ -e /dev/ttyUSB0 ]; then
sleep 60
else
killall iremote_client
reboot
fi
done
queue.sh
Code: Alles auswählen
#!/bin/bash
#
# This script encapsulates the functionality of a queue. It requires there to be
# an input file with the data in the queue being separated on different lines.
#
INPUT=/tmp/queue.txt
OUTPUT=/tmp/trash.txt
CMD=/usr/bin/wget
if [ ! -f "$INPUT" ] ; then
touch "$INPUT"
fi
#
#
#
wait_rcsim_done() {
COUNTER=0
# /bin/usleep 10000
while [ $(ps acux | grep -c '[/]usr/bin/wget -t 2 --no-cache -O /dev/null -q') -gt 0 ]; do
COUNTER=$((COUNTER + 1))
/bin/usleep 10000
if [ $COUNTER -gt 200 ]; then
killall wget
break
fi
# echo $COUNTER >> /tmp/wait_rcsim.txt
done
}
#
# poll() removes the top line from $INPUT and appends it to the $OUTPUT file
#
poll() {
if [ ! -f "$CMD" ] ; then
echo "$CMD does not exist" 1>&2
exit 1
fi
if [ ! -x "$CMD" ] ; then
echo "$CMD is not executable" 1>&2
exit 1
fi
head -1 "$INPUT" >> "$OUTPUT" && sed -i '1d' "$INPUT"
ENTRY="`tail -1 "$OUTPUT"`"
# $("$CMD" "$ENTRY")
if [[ -n $ENTRY ]]; then
if [[ $ENTRY == "KEY_TIME" ]]; then
/usr/bin/rcsim $ENTRY > /dev/null 2>&1
else
# /usr/bin/wget -t 2 --no-cache -O /dev/null -q "http://127.0.0.1/control/rcem?$ENTRY" &
# wait_rcsim_done
/usr/bin/rcsim $ENTRY > /dev/null 2>&1
/bin/usleep 100000
fi
sed -i '1d' "$OUTPUT"
fi
}
#
# offer() appends the given arguments to the $INPUT file
#
offer() {
for arg in ${@:2} ; do
if [ -n "$arg" ] ; then
# echo "$arg"
echo "$arg" >> "$INPUT"
fi
done
}
#
# peek() prints the next entry in the queue
#
peek() {
head -1 "$INPUT"
}
#
# random() passes a random line from $INPUT to $CMD
#
random() {
if [ ! -f "$CMD" ] ; then
echo "$CMD does not exist" 1>&2
exit 1
fi
if [ ! -x "$CMD" ] ; then
echo "$CMD is not executable" 1>&2
exit 1
fi
COUNT=`cat "$INPUT" | wc -l`
if [ "$COUNT" -lt 1 ] ; then
exit 0
fi
RANDOM_LINE_NO=$[ ( $RANDOM % $COUNT ) + 1 ]
RANDOM_LINE=`sed -n ''"$RANDOM_LINE_NO"'p' "$INPUT"`
$("$CMD" "$RANDOM_LINE")
}
print_help() {
cat << EOF
USAGE:
queue COMMAND
COMMANDS:
poll
removes the top line from \$INPUT and appends it to the \$OUTPUT file
offer
appends the given arguments to the \$INPUT file
peek
prints the next entry in the queue
random
passes a random line from \$INPUT to \$CMD
EXAMPLES:
To offer a list of files to the queue:
find /path/to/files | xargs ./queue.sh offer
EOF
}
if [ "$1" == "poll" ]
then
poll
elif [ "$1" == "offer" ]
then
offer $*
elif [ "$1" == "peek" ]
then
peek
elif [ "$1" == "random" ]
then
random
else
print_help
exit 1
fi
Muss ich mal noch genau klären, was die Ursache ist (Kernel-Treiber / USB-Spannung).
Die Scripte befinden sich bei mir derzeit unter /var/bin/ , können sich aber auch wo anders befinden.
Bei Bootvorgang muss iremote_client mit gestartet werden. Ich habe das mit der /etc/rc.local erledigt.
Code: Alles auswählen
#!/bin/sh -e
#
# /etc/rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
/var/bin/iremote_client &
exit 0
lege ein selbst gewünschtes Neutrino-KEYNAMES-Mapping fest. Das wandert in einer Arbeitsqueue, welche dann abgearbeitet wird.
Damit gewährleiste ich, das jedes Signal vom Arduino auch empfangen wird und dann asynchron verarbeitet werden kann.
Es kann z.B. wunderbar durch lange Filmlisten gescrollt werden.
Hoffentlich habe ich nichts vergessen. Bei Unklarheiten kann gerne nachgefragt werden.