Let's get an Arduino to listen to a TV remote first:
I have a Sharp Aquos TV that is also controlled with a Dish Hopper (I guess) remote. Will show testing with both later.
Here is some code, some copied from the examples in the library you need to download from the Arduino-IRremote github. There is a  button at the top right, get the zip file on your PC. And then I unzipped all the files into a folder on my borrowed Windows 7 computer into: C:\Users\Speed\Documents\Arduino\libraries\Arduino-IRremote-master
You could also use the menu to Sketch -> Include Library -> Manage Libraries... to download and install IRremote:
On my computer, however, there was some RobotIRremote library (found in C:\Program Files (x86)\Arduino\libraries\RobotIRremote) providing an IRremote.h as needed in our #include <IRremote.h> , which was not the correct file...kept getting a " IRremoteTools.cpp:5:16: error: 'TKD2' was not declared in this scope ", so I simply closed the Arduino software and moved the RobotIRremote folder to another temporary safe house. Far far away from the libraries folder.
Here we go:
// A TSOP34438 connected to 5V, GND and its OUT to pin 11 on a Nano. // The pin 13 LED toggles every second, until a code is received and matched as Volume UP, then the LED toggles faster // Volume DOWN will slow the toggle down again
#include <IRremote.h>
#define LEDPIN 13
#define DELAY 1000
IRrecv irrecv( 11 ); // Receive on pin 11
decode_results results;
unsigned long now;
unsigned long before;
unsigned int delayed = DELAY;
void setup() {
pinMode( LEDPIN, OUTPUT );
Serial.begin( 115200 );
irrecv.enableIRIn(); // Start the receiver
now = millis();
before = now;
Serial.println("TxCar 2016.05.12_002");
} // setup
void loop() {
now = millis();
if ( now - before > delayed ) {
digitalWrite( LEDPIN, !digitalRead( LEDPIN ) );
before = before + delayed;
} // if
if ( irrecv.decode( &results ) ) {
Serial.println( results.value, HEX );
switch ( results.value ) {
case 0x1BE8C80D : delayed = delayed / 2;
break;
case 0x7E16B93A : delayed = 2 * delayed;
break;
default:
break;
} // switch
irrecv.resume(); // Continue receiving
} // if
} // loop
And what you see is a millis() calculated delay to turn the LED on pin 13 on and off, where the delay is " delayed " long, starting at 1000 ms, which is 1 second. So, when the TSOP34438 delivers data on pin 11, and the decoding brings news that 0x1BE8C80D or 0x7E16B93A was delivered, the delay is either doubled or cut in half. So, which buttons are those, volume up and volume down, of course! But not so fast, there are a few more codes sent when you press the volume buttons on the Sharp remote, and even more when you use the Dish Hopper remote. Most likely more so the Hopper knows what is happening too, even though I believe the Hopper might be using RF to get its commands.
So, back to the basics, the remote is sending some code for each button, encoded and carried on a 38 kHz infrared signal. Sent over the air to the TSOP34438 sensor, which in turn has its OUTPUT connected to pin 11 on the Nano and the data is then received and decoded to produce a value in results.value. So, now you can press every button, find the unique code it sends, and stuff it in the switch () { case NewCodeConstant: DoSomething(); break; } to do something useful when it gets that code.
We are heading to use two sensors on the left and right side of the TxCar, so we are either going to AND two sensors together into pin 11, or see if pin 10 can receive data at the same time. The first would be preferred, since we need every pin we can get for all the lights and action we want. And here is the real code:
////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////// // // Controlling a TxCar with a TV remote control
//
// A TSOP34438 connected to 5V, GND and its OUT to pin 11 on an Arduino Atmel ATMEGA328P.
// Pin 13 LED flash with every IR command received.
// Remote POWER-OFF turns everything off, and VOL-UP and DOWN will increase and decrease the motor speed
// Remote buttons, 0-9, will turn the headlights on, high-beam, left or right indicator or break lights.
// Hazards on remote 3
// Clearance lights on pin 4
//
// next improvement would be to keep the indicator on after hazards turn off, if it was on before
//
// Author: Speed aka Gert 'Jim' Muller, 2016.08.11
// ////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <IRremote.h>
// version log at the bottom...
#define VERSIONSTRING "TxCar controller 2016.08.11 005"
// this turns some Serial.println's on to help debug
#define DEBUG false
#define DEBUG2 false
//
// pins
//
#define MOTORPIN 10
#define DEBUGLEDPIN 13
#define CLEARANCEPIN 4
#define TAILBRAKEPIN 5
#define HEADLIGHTPIN 6
// not enough PWM pins, the next two are pulsed in software
#define LTURNPIN 8
#define RTURNPIN 7
#define IRPIN 11
//
// remote codes
//
#define REMOTE_0 0xEF1008F7
#define REMOTE_1 0xEF108877
#define REMOTE_2 0xEF1048B7
#define REMOTE_3 0xEF10C837
#define REMOTE_4 0xEF1028D7
#define REMOTE_5 0xEF10A857
#define REMOTE_6 0xEF106897
#define REMOTE_7 0xEF10E817
#define REMOTE_8 0xEF1018E7
#define REMOTE_9 0xEF109867
#define REMOTE_MUTE 0xEF10906F
#define REMOTE_POWER 0xEF1010EF
#define REMOTE_CENTER 0xEF1022DD
#define REMOTE_MENU 0xEF10C23D
#define REMOTE_EXIT 0xEF10DA25
#define REMOTE_VOLUP 0xEF1040BF
#define REMOTE_VOLDN 0xEF10C03F
#define REMOTE_DNARR 0xEF10A05F
#define REMOTE_UPARR 0xEF1020DF
//
// times
//
#define TURNUPDATE 7
#define TURNBLINKRATE 500
#define HAZARDBLINKRATE 700
//
// brightnesses
//
#define HEADLIGHTLOWBEAM 20
#define TAILLIGHTLOWBEAM 70
#define INDICATORLOWBEAM 10
#define INDICATORHIGHBEAM 200
#define HIBEAM 200
#define MOTORSPEEDMAX 60
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
// PWM pin driving an N-channel FET with a small DC motor above it.
class Motor {
const bool MOTOR_DEBUG = true;
byte pwmPin;
byte motorState;
unsigned int motorSpeed;
unsigned long _now;
unsigned long _before;
unsigned long _DELAY;
void output() {
if ( MOTOR_DEBUG ) {
Serial.print( "motor out " );
Serial.println( motorSpeed );
} // if
analogWrite( pwmPin, motorSpeed );
} // output
public:
Motor( int motorPwmPin ) {
pwmPin = motorPwmPin;
motorState = 0; // off
motorSpeed = 0; // not flashing
_DELAY = 1000;
} // Constructor Motor( int )
void powerOff() {
motorSpeed = 0;
output();
} // powerOff
void increaseSpeed() {
if ( motorSpeed < ( MOTORSPEEDMAX - 10 ) )
motorSpeed += 10;
else
motorSpeed = MOTORSPEEDMAX;
output();
} // increaseSpeed
void decreaseSpeed() {
if ( motorSpeed > 10 )
motorSpeed -= 10;
else
motorSpeed = 0;
output();
} // decreaseSpeed
void fullSpeed() {
motorSpeed = MOTORSPEEDMAX;
output();
} // fullSpeed
void midSpeed() {
motorSpeed = MOTORSPEEDMAX / 2;
output();
} // midSpeed
void setupPin() {
pinMode( pwmPin, OUTPUT );
motorState = 0; // off
_now = millis();
_before = _now;
} // setupPin
void update() {
_now = millis();
if ( ( _now - _before ) > _DELAY ) {
if ( motorState == 1 ) {
Serial.print( "motor at " );
Serial.println( motorSpeed );
} else {
Serial.print( "motor off." );
} // if else
} // if
} // update
}; // class motor
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
class RunningTurnSignalManualPWM { // this is on or off, low or high brightness on PWM pin
// Class Member Variables
// These are initialized at startup
int ledPin; // the number of the LED pin
int ledState; // 0==off, 1==on
int ledFlash; // 0==off, 1==flashing
int ledValue; // 0 through 255
int lightsOn; // 0==off, 1==on
int lowValue; // value for off (0 for on/off, else for headlights on)
byte count = 0; // counting for manual pwm
unsigned long _now;
unsigned long _before;
unsigned long _flashbefore;
void output() {
if ( DEBUG2 ) {
Serial.print( "Output: " );
Serial.print( ledPin );
Serial.print( " " );
Serial.print( ledState );
Serial.print( " " );
Serial.print( ledFlash );
Serial.print( " " );
Serial.print( ledValue );
Serial.print( "cnt " );
Serial.print( count );
Serial.print( " " );
Serial.println( lightsOn );
} // if DEBUG
if ( ledState == 0 ) digitalWrite( ledPin, LOW );
if (( ledState == 1 ) && ( lightsOn == 1 ) && ( ledValue == 255 )) digitalWrite( ledPin, HIGH );
} // output
public:
// Constructor - creates a Flasher
// and initializes the member variables and state
RunningTurnSignalManualPWM( int pin ) {
ledPin = pin;
ledValue = INDICATORLOWBEAM; // above or below 127
lowValue = INDICATORLOWBEAM;
ledState = 0; // off
ledFlash = 0; // not flashing
lightsOn = 0; // lights off be default
} // Constructor RunningTurnSignalManualPWM( int )
void setupPin() {
pinMode( ledPin, OUTPUT );
ledState = 0; // off
_flashbefore = millis();
_now =_flashbefore;
_before = _now;
} // setupPin
void toggleFlash() {
if ( ledFlash == 0 ) {
if ( DEBUG ) Serial.println( "Flash was off" );
ledFlash = 1;
_flashbefore = millis();
ledState = 1;
} else {
if ( DEBUG ) Serial.println( "Flash was on" );
ledFlash = 0;
ledValue = lowValue; // above or below 127
} // if else
output();
} // toggleFlash
void togglePower() {
if ( ledState == 0 )
ledState = 1;
else
ledState = 0;
output();
} // togglePower
void toggleBeam() {
if ( ledValue == lowValue )
ledValue = INDICATORHIGHBEAM;
else
ledValue = lowValue;
output();
} // toggleBeam
void fullOn() {
lightsOn = 1;
ledState = 1;
ledValue = 255;
output();
} // fullOn
void powerOn() {
lightsOn = 1;
ledState = 1;
ledValue = INDICATORHIGHBEAM;
} // powerOn
void powerOff() {
lightsOn = 0;
ledState = 0; // this turns it OFF
ledFlash = 0;
ledValue = lowValue;
output();
} // powerOff
void headlightOn() {
lowValue = INDICATORLOWBEAM;
lightsOn = 1;
ledState = 1; // this turns it ON
} // headlightOn
void headlightOff() {
lowValue = 0;
lightsOn = 0;
if ( ledFlash == 0 )
ledState = 0; // this turns it OFF
} // headlightOff
void high() {
ledValue = INDICATORHIGHBEAM; // when the light is ON, it will have this brightness
ledState = 1;
output();
} // high
void low() {
ledValue = lowValue; // when the light is ON, it will have this brightness
ledState = 1;
output();
} // low
bool isFlashing() {
return ledFlash == 1;
} // isFlashing
bool stopFlashing() {
ledFlash = 0;
if ( lightsOn == 1 )
ledValue = 10;
else
ledValue = 0;
} // stopFlashing
void update() {
_now = millis();
if ( ledFlash > 0 ) {
if ( ( _now - _flashbefore ) > (unsigned long)TURNBLINKRATE ) {
_flashbefore = _now;
if ( ledValue > 127 )
ledValue = lowValue;
else
ledValue = 200;
} // if time to change state
} // if flashing
if ( ( _now - _before ) > (unsigned long)TURNUPDATE ) {
_before = _now;
if ( ledState == 0 ) { // if off
digitalWrite( ledPin, LOW );
} else { // you are on
if ( ledValue > 127 )
digitalWrite( ledPin, HIGH );
else {
if ( lightsOn == 1 ) {
count++;
if ( count >= 6 )
count = 0;
switch (count) {
case 0:
case 1: digitalWrite( ledPin, LOW ); break;
case 2: digitalWrite( ledPin, HIGH ); break;
case 3:
case 4: digitalWrite( ledPin, LOW ); break;
case 5: digitalWrite( ledPin, HIGH ); break;
default: break;
} // switch
} else {
digitalWrite( ledPin, LOW );
} // if else
} // if else
} // if else
} // if
} // update
}; // class RunningTurnSignalManualPWM
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
class Hazards { // this toggle two indicators on and off
// Class Member Variables
RunningTurnSignalManualPWM *left;
RunningTurnSignalManualPWM *rite;
int ledState; // 0==off, 1==on
int enabled; // 0==off, 1==on
unsigned long _now;
unsigned long _before;
unsigned long _flashbefore;
void output() {
if ( left == NULL )
return;
if ( DEBUG2 ) Serial.println( "haz out" );
if ( ledState == 1 ) {
if ( DEBUG2 ) Serial.println( "haz on" );
left->fullOn();
rite->fullOn();
} else {
if ( DEBUG2 ) Serial.println( "haz off" );
left->powerOff();
rite->powerOff();
} // if
} // output
public:
// Constructor - creates a Hazards
// and initializes the member variables and state
Hazards( int ena ) {
left = NULL;
rite = NULL;
enabled = ena;
ledState = 0; // off
} // Constructor Hazards( RunningTurnSignalManualPWM, RunningTurnSignalManualPWM )
void setupLites(RunningTurnSignalManualPWM *l, RunningTurnSignalManualPWM *r ) {
left = l;
rite = r;
} // setup( RunningTurnSignalManualPWM *, RunningTurnSignalManualPWM * )
bool isEnabled() {
return enabled == 1;
} // bool isEnabled
void togglePower() {
if ( enabled == 0 )
enabled = 1;
else {
enabled = 0;
ledState = 0;
} // else
output();
} // togglePower
void toggleState() {
if ( ledState == 0 )
ledState = 1;
else
ledState = 0;
output();
} // toggleState
void powerOn() {
enabled = 1;
ledState = 1;
output();
} // powerOn
void powerOff() {
enabled = 0;
ledState = 0;
output();
} // powerOff
void update() {
_now = millis();
if ( enabled > 0 ) {
if ( ( _now - _flashbefore ) > (unsigned long)HAZARDBLINKRATE ) {
_flashbefore = _now;
toggleState();
} // if time
} // if on
} // update
}; // class Hazards
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
class HeadLight { // this is on or off, low or high beam on PWM pin
// Class Member Variables
// These are initialized at startup
int ledPin; // the number of the LED pin
int ledState; // 0==off, 1==on
int ledValue; // 0 through 255
int lowBeamValue;
void output() {
if ( ledState > 0 )
analogWrite( ledPin, ledValue );
else
analogWrite( ledPin, 0 );
} // output
public:
// Constructor - creates a Flasher
// and initializes the member variables and state
HeadLight( int pin, int beamVal ) {
ledPin = pin;
lowBeamValue = beamVal;
ledValue = lowBeamValue;
ledState = 0;
} // Constructor HeadLight( int, int )
void setupPin() {
pinMode( ledPin, OUTPUT );
} // setupPin
void togglePower() {
if ( ledState == 0 )
ledState = 1;
else
ledState = 0;
output();
} // togglePower
void toggleFullPower() {
if ( ledState == 0 ) {
ledState = 1;
ledValue = HIBEAM;
} else
ledState = 0;
output();
} // toggleFullPower
void powerOn() {
ledState = 1;
output();
} // powerOn
void powerOff() {
ledState = 0;
output();
} // powerOff
void toggleBeam() {
if ( ledValue == lowBeamValue )
ledValue = HIBEAM;
else
ledValue = lowBeamValue;
output();
} // toggleBeam
void high() {
ledValue = HIBEAM; // when the light is ON, it will have this brightness
ledState = 2;
output();
} // high
void low() {
ledValue = lowBeamValue; // when the light is ON, it will have this brightness
ledState = 1;
output();
} // low
bool isLow() {
return ( ( ledValue == lowBeamValue ) && ( ledState == 1 ) );
} // isLow
bool isOn() {
return ledState == 1;
} // isOn
}; // class HeadLight
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
class Light { // this is on or off
// Class Member Variables
// These are initialized at startup
int ledPin; // the number of the LED pin
int ledState; // 0==off, 1==on
void output() {
digitalWrite( ledPin, ledState );
} // output
public:
// Constructor - creates a Light
// and initializes the member variables and state
Light( int pin ) {
ledPin = pin;
ledState = 0;
} // Constructor HeadLight( int, int )
void setupPin() {
pinMode( ledPin, OUTPUT );
} // setupPin
void togglePower() {
if ( ledState == 0 )
ledState = 1;
else
ledState = 0;
output();
} // togglePower
void powerOn() {
ledState = 1;
output();
} // powerOn
void powerOff() {
ledState = 0;
output();
} // powerOff
bool isOn() {
return ledState == 1;
} // isOn
}; // class Light
////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////
Light clearance( CLEARANCEPIN );
HeadLight headlite( HEADLIGHTPIN, HEADLIGHTLOWBEAM );
HeadLight taillite( TAILBRAKEPIN, TAILLIGHTLOWBEAM );
RunningTurnSignalManualPWM leftlite( LTURNPIN );
RunningTurnSignalManualPWM ritelite( RTURNPIN );
Motor motor( MOTORPIN );
Hazards hazards( 0 );
IRrecv irrecv( IRPIN ); // Receive on IRPIN (like 11)
decode_results results;
void setup() {
pinMode( DEBUGLEDPIN, OUTPUT );
irrecv.enableIRIn(); // Start the receiver (this kills pin 3 PWM!)
Serial.begin( 115200 );
leftlite.setupPin();
ritelite.setupPin();
motor.setupPin();
clearance.setupPin();
headlite.setupPin();
taillite.setupPin();
hazards.setupLites( &leftlite, &ritelite );
Serial.println( VERSIONSTRING );
} // setup
//
// loop only updates the indicator lights and act on a command if sent by IR
//
void loop() {
if ( hazards.isEnabled() ) {
hazards.update();
} else {
leftlite.update();
ritelite.update();
} // if
if ( irrecv.decode( &results ) ) {
digitalWrite( DEBUGLEDPIN, HIGH );
if ( DEBUG ) Serial.println( results.value, HEX );
switch ( results.value ) {
// power off will be code WHICH IS THE POWER BUTTON
case REMOTE_POWER: if ( DEBUG ) Serial.println( "Turn off WHAT???" );
motor.powerOff(); // Motor off
leftlite.powerOff(); // Left turn signal off
ritelite.powerOff(); // Right turn signal off
headlite.powerOff(); // Headlight off
leftlite.headlightOff(); // Left turn signal
ritelite.headlightOff(); // Right turn signal
taillite.powerOff(); // Taillight off
clearance.powerOff(); // Clearance off
hazards.powerOff(); // Hazards off
break;
case REMOTE_MUTE: if ( DEBUG ) Serial.println( "Motor Mute" );
motor.powerOff();
break;
case REMOTE_0: if ( DEBUG ) Serial.println( "Heads" );
headlite.togglePower(); // Headlight on-off
clearance.togglePower();
if ( headlite.isOn() ) {
leftlite.headlightOn();
//leftlite.powerOn(); // Left turn signal
ritelite.headlightOn();
//ritelite.powerOn(); // Right turn signal
if ( !taillite.isOn() ) taillite.low();
} else {
if ( taillite.isLow() ) taillite.powerOff();
leftlite.headlightOff(); // Left turn signal
//leftlite.powerOff(); // Left turn signal off
ritelite.headlightOff(); // Right turn signal
//ritelite.powerOff(); // Right turn signal off
} // if
break;
case REMOTE_1: if ( DEBUG ) Serial.println( "Remote 1" );
break;
case REMOTE_2: if ( DEBUG ) Serial.println( "HI-BEAM" );
headlite.toggleBeam(); // Headlight high-low
break;
case REMOTE_3: if ( DEBUG ) Serial.println( "Hazards" );
hazards.togglePower();
if ( !hazards.isEnabled() && headlite.isOn() ) {
leftlite.headlightOn();
ritelite.headlightOn();
} // if
break;
case REMOTE_4: if ( DEBUG ) Serial.println( "LEFT" );
if ( hazards.isEnabled() ) {
if ( DEBUG ) Serial.println( "Haz still on" );
break; // no action whan hazards are on
} // if
leftlite.toggleFlash(); // Left turn signal
if ( leftlite.isFlashing() ) {
ritelite.stopFlashing();
} // if
break;
case REMOTE_5: if ( DEBUG ) Serial.println( "Remote 5" );
break;
case REMOTE_6: if ( DEBUG ) Serial.println( "RIGHT" );
if ( hazards.isEnabled() ) {
if ( DEBUG ) Serial.println( "Haz still on" );
break; // no action whan hazards are on
} // if
ritelite.toggleFlash(); // Right turn signal
if ( ritelite.isFlashing() ) {
leftlite.stopFlashing();
} // if
break;
case REMOTE_7: if ( DEBUG ) Serial.println( "Remote 7" );
break;
case REMOTE_8: if ( DEBUG ) Serial.println( "Brakes" );
if ( headlite.isOn() )
taillite.toggleBeam();
else
taillite.toggleFullPower();
if ( DEBUG ) Serial.println( "Tail light" );
break;
case REMOTE_9: if ( DEBUG ) Serial.println( "Remote 9" );
break;
case REMOTE_DNARR: if ( DEBUG ) Serial.println( "SPEED1/2" );
motor.midSpeed();
break;
case REMOTE_UPARR: if ( DEBUG ) Serial.println( "SPEED!!" );
motor.fullSpeed();
break;
case REMOTE_VOLUP: if ( DEBUG ) Serial.println( "SPEED++" );
motor.increaseSpeed();
break;
case REMOTE_VOLDN: if ( DEBUG ) Serial.println( "SPEED--" );
motor.decreaseSpeed();
break;
default: if ( DEBUG ) Serial.println( "Unknown" );
break;
} // switch
irrecv.resume(); // Continue receiving
digitalWrite( DEBUGLEDPIN, LOW );
} // if
} // loop
//======================================== END OF CODE ==================================//
You can of course put the classes in their own files to use something like #include <motor.h> which is the whole idea behind reusing code written in C++. But for now, a single file, attached below, keeps it all together. Enjoy!
|
 Updating...
Ċ Gert (TxAdmin) Muller, Oct 2, 2016, 8:01 PM
TxCar005_20160811.ino (22k) Gert (TxAdmin) Muller, Aug 11, 2016, 7:57 PM
Gert (TxAdmin) Muller, May 11, 2016, 9:39 PM
|