IR Controlled DC Motor (Variable Speed)

I am working on a project where I can control a DC motor with an IR controller. I am using a breadboard setup similar to the photo below, except I obviously have an IR receiver attached to my Arduino as well:

I am having issues getting my code to run correctly. Basically, when I click the button I want, I can get the motor to run at full speed (or decrease the speed to 0), but I cannot get it to run where I increase the speed incrementally by pressing the same button.

Here is my code. Thanks in advance for any and all help/suggestions.

#include <IRremote.h>

int IRpin = 2;
int motorPin = 3;
int speed = 0;

#define right 0xFD609F
#define left 0xFD20DF

IRrecv irrecv (IRpin);
decode_results results;
 
void setup() 
{ 
  Serial.begin(9600);
  pinMode(motorPin, OUTPUT);
  irrecv.enableIRIn();
} 
 
 
void loop() 
{

  if (speed > 255) {
    speed = 255;
  }
  
  if (speed < 0) {
    speed = 0;
  }
  
  analogWrite(motorPin, speed);
  
  if (irrecv.decode(&results)) {
  irrecv.resume();
  }  
  
  if (results.value == right) {
    speed = speed + 10; 
  	delay(15);
  }
  
    if (results.value == left) {
    speed = speed - 10;
    delay(15);
  }
    

}

I rearranged the code a bit. Try it now. Note that I changed left and right so that I could test with my remote. Change back for yours.

#include <IRremote.h>

int IRpin = 2;
int motorPin = 3;
int speed = 0;

#define right 0x4EB312ED  //0xFD609F 
#define left 0x4EB338C7  //0xFD20DF


IRrecv irrecv (IRpin);
decode_results results;

void setup()
{
   Serial.begin(9600);
   pinMode(motorPin, OUTPUT);
   irrecv.enableIRIn();
}


void loop()
{
   if (irrecv.decode(&results))
   {
      irrecv.resume();


      if (results.value == right)
      {
         speed = speed + 10;
         delay(15);
      }

      if (results.value == left)
      {
         speed = speed - 10;
         delay(15);
      }
      if (speed > 255)
      {
         speed = 255;
      }

      if (speed < 0)
      {
         speed = 0;
      }

      Serial.println(speed);
      analogWrite(motorPin, speed);
   }
}

This way the speed is changed only when a new IR signal is received, not every time through loop(). This works for my remote, but mine uses oxffffffff for the repeat code. What is the repeat code for your remote?

Thanks for the quick reply!

Unfortunately I was unable to get the code to work for me... I am still going through it to see what I am missing. I think it is likely to have something to do with my variable (speed) because even if I set my speed variable to an arbitrary number, when I run my code the motor does not spin, nor does any IR have an effect.

My remote also uses 0xffffffff as the repeat code. It would be great if I can hold the button down and have it continue to increase/decrease speed, but that's a whole new problem all together.

First, powering a motor from the Uno 5V may be problematic. It would be better, likely necessary, to power the motor from an external supply like a battery pack.

What are the specifications of the motor? Rated voltage and stall (starting) current need to be known.

What is the part number of the transistor? Do you have a data sheet for it?

nor does any IR have an effect.

You changed the right and left codes from the codes for my remote, right?
In my code there is a serial print. Do you see that in serial monitor when you try the remote? Serial prints are your best and about only debugging tool. Use them to keep track of variable and monitor program flow.

Can you post a photo of your wiring? More sets of eyes and all that.

I hooked up a motor and transistor and ran the code and the motor did not run. I experimented a bit and found that it will run if I change motorPin to pin 6. Pin 3 is used by the IRremote library for an IR LED to send IR codes. For some reason that makes it not useful for output to the transistor.

My remote also uses 0xffffffff as the repeat code. It would be great if I can hold the button down and have it continue to increase/decrease speed

Example code to do that. Works on my setup.

#include <IRremote.h>

const byte IRpin = 2;
const byte motorPin = 6;  // **********  change per reply #4.
int speed = 0;

#define NONE  0
#define UP 1
#define DOWN 2
#define right 0x4EB312ED  //0xFD609F
#define left 0x4EB338C7  //0xFD20DF


IRrecv irrecv (IRpin);
decode_results results;

void setup()
{
   Serial.begin(9600);
   pinMode(motorPin, OUTPUT);
   irrecv.enableIRIn();
   digitalWrite(motorPin, HIGH);
}


void loop()
{
   static byte direction = NONE;
   static unsigned long timer = 0;
   unsigned long interval = 50;
   if (millis() - timer >= interval)
   {
      timer = millis();
      if (irrecv.decode(&results))
      {
         irrecv.resume();
         if (results.value == right)
         {
            speed = speed + 10;
            direction = UP;
         }

         if (results.value == left)
         {
            speed = speed - 10;
            direction = DOWN;
         }
         if (results.value == 0xffffffff)
         {
            if (direction == UP)
            {
               speed = speed + 10;
            }
            if (direction == DOWN)
            {
               speed = speed - 10;
            }
         }

         if (speed > 255)
         {
            speed = 255;
            direction = NONE;
         }

         if (speed < 0)
         {
            speed = 0;
            direction = NONE;
         }
         Serial.println(speed);
         analogWrite(motorPin, speed);
      }
   }
}

Oh great!! I was able to get it working if I used pin 6!

Thank you very much for looking into that. I had no idea that the IR library used pin 3 for another function.

Thanks again

I knew that pin is used for IR send. I did not know that the library makes pin 3 unusable with analogWrite().