Problems with IR

Hi,
I'm trying to add an IR Controller to mimic hardware buttons.
I have added all the code and it runs.

I added a print statement so I could see the value of sign.
It should be with -1,0,1.
However, it always shows a value of -1.

Might I ask for some help please?




#include <AccelStepper.h>
#include <IRremote.h> 

// Define the stepper and the pins it will use
AccelStepper stepper1(AccelStepper::DRIVER, 9, 8);

// Define our three input button pins
#define  LEFT_PIN  4
#define  STOP_PIN  5
#define  RIGHT_PIN 2

// Define our analog pot input pin
#define  SPEED_PIN 0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define  MAX_SPEED 1000
#define  MIN_SPEED 0.5

// Setup of the IR Sensor
int RECV_PIN =7;
IRrecv irrecv(RECV_PIN); 
decode_results results;

void setup() {
  // IR Stuff
  Serial.begin(9600); 
  irrecv.enableIRIn();
  // The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go 
  stepper1.setMaxSpeed(10000.0);
  
  // Set up the three button inputs, with pullups
  pinMode(LEFT_PIN, INPUT_PULLUP);
  pinMode(STOP_PIN, INPUT_PULLUP);
  pinMode(RIGHT_PIN, INPUT_PULLUP);
}

void loop() {
  static float current_speed = 0.0;         // Holds current motor speed in steps/second
  static int analog_read_counter = 1000;    // Counts down to 0 to fire analog read
  static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
  static int analog_value = 0;              // Holds raw analog value.

  // Start with checking if a remote switch has been pressed
  if (irrecv.decode(&results)){ 
    int value = results.value; 
    Serial.println(value);  
        switch(value){ 
          case 4335: //Keypad button "left" 
          //set direction left 
          sign = -1;
        } 
  switch(value){ 
          case 23205: //Keypad button "right" 
          //set direction left 
          sign = 1;
        } 
switch(value){ 
          case 14535: //Keypad button "ok / stop" 
          //set direction left 
          sign = 0;
        } 
irrecv.resume();  
    } 
  
  // If a switch is pushed down (low), set the sign value appropriately
  if (digitalRead(LEFT_PIN) == 0) {
    sign = -1;
  }
  else if (digitalRead(RIGHT_PIN) == 0) {    
    sign = 1;
  }
  else if (digitalRead(STOP_PIN) == 0) {
    sign = 0;
  }

  // We only want to read the pot every so often (because it takes a long time we don't
  // want to do it every time through the main loop).  
  
  if (analog_read_counter > 0) {
    analog_read_counter--;
    
  }
  else {
    analog_read_counter = 3000;
    // Now read the pot (from 0 to 1023)
    analog_value = analogRead(SPEED_PIN);
    // Give the stepper a chance to step if it needs to
    stepper1.runSpeed();
    //  And scale the pot's value from min to max speeds
    current_speed = sign * (((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED);
    // Update the stepper to run at this new speed
    stepper1.setSpeed(current_speed);
    ;
    
  }

  // This will run the stepper at a constant speed
  stepper1.runSpeed();
}
1 Like

That is an odd way to use the switch structure. Why do it that way? Usually there is one switch statement and several cases. See the switch reference.

What version of the IRremote library are you using? Your code is written for an older (<3.0) version of the library. The code may not work correctly. To see how to change the code to work with the newest version of the library see the IRremote library git hub page.

Suggest you look at switch changes rather than switch levels.


BTW
There is a new IR library, I think version 3.3 ?

It is quite a bit different in application so be careful if you ever upgrade.

The more usual way to write a switch/case is:

    switch (value)
    {
      case 4335: //Keypad button "left"
        //set direction left
        sign = -1;
        break;

      case 23205: //Keypad button "right"
        //set direction left
        sign = 1;
        break;

      case 14535: //Keypad button "ok / stop"
        //set direction left
        sign = 0;
        break;
    }

The only thing I can think of that would force 'sign' to be -1 all the time was if 'LEFT_PIN' (4) is shorted to Ground. It has priority over the other two so if all three were shorted to Ground you'd get -1.

Are you using those little square tactile switches? If you install it turned 90° it will short the two sides together.

A schematic would be helpful.

I'm just running the code on a board on my desk.
The existing code is working fine, as are the switches.

It is just my attempts at adding code that causes problems :slight_smile:
wait till I get to trying to use the up and down to change speed and then use the numbers to mark position :slight_smile:

thanks, will try that code change and see what happens.
and thank you so much for all the quick answers.

Have tried the code change, still getting -1 as the output.

Just noticed this warning message fly pass:
The function decode(&results)) is deprecated and may not work as expected! Just use decode() without a parameter and IrReceiver.decodedIRData.

See replies 2 and 3.

That is a warning message from the new (>3.0) version of the IRremote library that your code is not written for the new version. There are instructions in the linked page for converting older version code to work with the new version.

Or delete the IRremote library from the libraries folder in your sketchbook and use the IDE library manager to install a <3.0 version.

Thank you.
Apologises for not following.

Will downgrade the library and see what happens.

I downloaded to version 2.8.1
I followed the instruction to change a parameter:

if (irrecv.decode()){

However, all I get now is 0 when I push any of the buttons.
Sorry to bother with this - am doing my best :slight_smile:

Now I am really confused.
Went off and found a guide about how to use the version 3 of the IR library.
I changed my code, as I thought I had to, however, I am getting an error.
"IRReceiver' was not declared in this scope"




#include <AccelStepper.h>
#include <IRremote.h> 

// Define the stepper and the pins it will use
AccelStepper stepper1(AccelStepper::DRIVER, 9, 8);

// Define our three input button pins
#define  LEFT_PIN  4
#define  STOP_PIN  5
#define  RIGHT_PIN 2

// Define our analog pot input pin
#define  SPEED_PIN 0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define  MAX_SPEED 1000
#define  MIN_SPEED 0.5

// Setup of the IR Sensor
const byte IR_RECEIVE_PIN = 7;

void setup() {
  // IR Stuff
  Serial.begin(9600); 
  IRReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go 
  stepper1.setMaxSpeed(10000.0);
  
  // Set up the three button inputs, with pullups
  pinMode(LEFT_PIN, INPUT_PULLUP);
  pinMode(STOP_PIN, INPUT_PULLUP);
  pinMode(RIGHT_PIN, INPUT_PULLUP);
}

void loop() {
  static float current_speed = 0.0;         // Holds current motor speed in steps/second
  static int analog_read_counter = 1000;    // Counts down to 0 to fire analog read
  static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
  static int analog_value = 0;              // Holds raw analog value.

  // Start with checking if a remote switch has been pressed
  if (IrReceiver.decodedIRData.decodedRawData)
  { 
    Serial.println(value);  
        switch(value){ 
          case 4335: //Keypad button "left" 
          //set direction left 
          sign = -1;
        } 
  switch(value){ 
          case 23205: //Keypad button "right" 
          //set direction left 
          sign = 1;
        } 
switch(value){ 
          case 14535: //Keypad button "ok / stop" 
          //set direction left 
          sign = 0;
        } 
irrecv.resume();  
    } 
  
  // If a switch is pushed down (low), set the sign value appropriately
  if (digitalRead(LEFT_PIN) == 0) {
    sign = -1;
  }
  else if (digitalRead(RIGHT_PIN) == 0) {    
    sign = 1;
  }
  else if (digitalRead(STOP_PIN) == 0) {
    sign = 0;
  }

  // We only want to read the pot every so often (because it takes a long time we don't
  // want to do it every time through the main loop).  
  
  if (analog_read_counter > 0) {
    analog_read_counter--;
    
  }
  else {
    analog_read_counter = 3000;
    // Now read the pot (from 0 to 1023)
    analog_value = analogRead(SPEED_PIN);
    // Give the stepper a chance to step if it needs to
    stepper1.runSpeed();
    //  And scale the pot's value from min to max speeds
    current_speed = sign * (((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED);
    // Update the stepper to run at this new speed
    stepper1.setSpeed(current_speed);
    ;
    Serial.begin(9600);Serial.println(sign);
  }

  // This will run the stepper at a constant speed
  stepper1.runSpeed();
}

many thanks

Which two, of the three different names you used, are the error messages complaining about?

John, are you saying that I have really screwed up in my understanding?
The error is:
'IRReceiver' was not declared in this scope

It compiles for me if I change both 'IRReceiver' and 'irrecv' to 'IrReceiver'. (and define 'value' which you use but don't define)

Maybe you should start over with a basic receiver example from the IRRemote library.

Note: You are STILL using 'switch/case' statements as overly complicated 'if' statements.

    switch (value)
    {
      case 4335: //Keypad button "left"
        //set direction left
        sign = -1;
    }

works the same as:

    if (value == 4335) //Keypad button "left"
        sign = -1;    //set direction left

A single 'switch/case' statement is designed to consolidate your three 'if'-ish statements:

  if (IrReceiver.decodedIRData.decodedRawData)
  { 
    Serial.println(value);  
    switch(value) 
    { 
    case 4335: //Keypad button "left" 
      sign = -1;
      break;

    case 23205: //Keypad button "right" 
      sign = 1;
      break;

    case 14535: //Keypad button "ok / stop" 
      sign = 0;
      break;
    } 

John,
Thank you for taking the time to explain - and provide examples.
The code I for the IR was taken from "proper" examples from this forum.

What one must allow for is my Muppet Effect :slight_smile:
I will go and redo my code again, cross fingers and toes - then hit compile

Regards

Okay, made the changes, got an error, figured it out :slight_smile:
However, now when a button is pressed the displayed value is 0 and sign is 0 - for every button on the remote.

Now I started this with a basic IR sketch to get the codes for each button. For example ok is 3810328320.
However, when my code was giving values earlier, the displayed one was for ok 14535.

Any help /pointers gratefully received (unlike IR codes ;))




#include <AccelStepper.h>
#include <IRremote.h> 

// Define the stepper and the pins it will use
AccelStepper stepper1(AccelStepper::DRIVER, 9, 8);

// Define our three input button pins
#define  LEFT_PIN  4
#define  STOP_PIN  5
#define  RIGHT_PIN 2

// Define our analog pot input pin
#define  SPEED_PIN 0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define  MAX_SPEED 1000
#define  MIN_SPEED 0.5

// Setup of the IR Sensor
const byte IR_RECEIVE_PIN = 7;
#define value IrReceiver.decodedIRData.decodedRawData

void setup() {
  // IR Stuff
  Serial.begin(9600); 
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);

// The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go 
  stepper1.setMaxSpeed(10000.0);
  
  // Set up the three button inputs, with pullups
  pinMode(LEFT_PIN, INPUT_PULLUP);
  pinMode(STOP_PIN, INPUT_PULLUP);
  pinMode(RIGHT_PIN, INPUT_PULLUP);
}

void loop() {
  static float current_speed = 0.0;         // Holds current motor speed in steps/second
  static int analog_read_counter = 1000;    // Counts down to 0 to fire analog read
  static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
  static int analog_value = 0;              // Holds raw analog value.

  // Start with checking if a remote switch has been pressed
   if (IrReceiver.decodedIRData.decodedRawData)
  { 
    Serial.println(value);  
    switch(value) 
    { 
    case 4144561920: //Keypad button "left" 
      sign = -1;
      break;

    case 2774204160: //Keypad button "right" 
      sign = 1;
      break;

    case 3810328320: //Keypad button "ok / stop" 
      sign = 0;
      break;
    } 
IrReceiver.resume();  
    } 
  
  // If a switch is pushed down (low), set the sign value appropriately
  if (digitalRead(LEFT_PIN) == 0) {
    sign = -1;
  }
  else if (digitalRead(RIGHT_PIN) == 0) {    
    sign = 1;
  }
  else if (digitalRead(STOP_PIN) == 0) {
    sign = 0;
  }

  // We only want to read the pot every so often (because it takes a long time we don't
  // want to do it every time through the main loop).  
  
  if (analog_read_counter > 0) {
    analog_read_counter--;
    
  }
  else {
    analog_read_counter = 3000;
    // Now read the pot (from 0 to 1023)
    analog_value = analogRead(SPEED_PIN);
    // Give the stepper a chance to step if it needs to
    stepper1.runSpeed();
    //  And scale the pot's value from min to max speeds
    current_speed = sign * (((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED);
    // Update the stepper to run at this new speed
    stepper1.setSpeed(current_speed);
    ;
    Serial.begin(9600);Serial.println(sign);
  }

  // This will run the stepper at a constant speed
  stepper1.runSpeed();
}

You have not even started the IR receiver so how does that do anything.

 if (IrReceiver.decodedIRData.decodedRawData)
  { 
    Serial.println(value);  
    switch(value) 

The value variable has no value so it is 0. It is not changed.

The new library return decoded data in the form of an address and a command. Use those when you read the remote buttons and in your switch statement. The address is usually the same for all buttons on a remote. The command will identify each button.

Try like this:

 if (IrReceiver.decode())  // new button code available
   {
      value = IrReceiver.decodedIRData.command;  // get the button code (command) into the value variable
      Serial.println(value);
      switch (value)

You will need to get the command codes for the buttons that you will use.

Man, all I can say is that it wasn't a deliberate mistake.
I go over all the examples I find very carefully.
I do put my best into code I post on here, as asking for help is a big thing for me.

Thank you for that.
I will now go and see what I can screw up this time :slight_smile:

I thought this line started the IR:
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);

Don't be hard on yourself. It took me a bit of time to figure out the new library.

I will help where I can.