Problems with IR sensor and DC motors

Hi,
I premise I'm a beginner with electonic. My project is to build a simple little robot, two wheels and a few sensors. I'm using two DC bipolar motors, bought on the Arduino store, the Arduino Uno, the Arduino Motor Shield and for now only an IR receiver sensor, also bought on the store. I want to control direction of the spin, speed and brakes of the motors by sending IR with a remote i had at home. I can decode without problems the IR it sends, using the IRremote library of 'shirrif', which I think you all know (A Multi-Protocol Infrared Remote Library for the Arduino) so the problems aren't caused by a not proper use of the IR receiver. But when I wrote the sketch, i found out that I couldn't control in any way the speed of the motor; it also doesn't work with a speed setup in the setup method different from 255. i checked every single component to make sure everything works. I cannot really understand what could cause this problem! in theory there shouldn't be any. I read that the Ir receiving of the shirriff library works by interrupts, so while the Ir isn't receiving it should leave Arduino free of using the method analogWrite() on the PWM channels of the motors. If anyone has some suggestion please answer

Perhaps there is a programming error somewhere. If you show your sketch then maybe someone will spot the error.

here it is!

/////////////////////////////////////////
#include <IRremote.h>
/////////////////////////////////////////
#define DIR_A 12
#define SPEED_A 3
#define BRAKE_A 9
/////////////////////////////////////////
#define ON_OFF 0x827D58A7 //brakes engaged/disengaged
#define BASS_UP 0x827D6897 //increase speed
#define BASS_DOWN 0x827D40BF //decrease speed
#define PLAY_PAUSE 0x827DF20D //inverts spinning direction
#define LONG_PRESS 0xFFFFFFFF
/////////////////////////////////////////
int recv_pin=5;
IRrecv irrecv(recv_pin);
decode_results results;

//these variables are modified according
//to the IR code read
int dir_a=HIGH;
int brk_a=HIGH;
byte spd_a=255;

//this led is on when the motor is working
int led_pin=7;

//keeps in memory which was the last signal
//received, to repeat it if is a command which
//increases or decreases speed
int last_command=0x0;
/////////////////////////////////////////

void setup() {
  irrecv.enableIRIn(); //enables IR receiver
  //defines pins
  pinMode(led_pin,OUTPUT);
  pinMode(DIR_A,OUTPUT);
  pinMode(BRAKE_A,OUTPUT);
  pinMode(SPEED_A,OUTPUT);
  //writes initial values of direction speed and brakes
  digitalWrite(DIR_A,dir_a);
  digitalWrite(BRAKE_A,brk_a);
  analogWrite(SPEED_A,spd_a);
}

void loop() {
  //waits for a signal
  if (irrecv.decode(&results)) {
    //passes the signal to the decode method to act consequently
    decode_command(results.value);
    //refreshes the situation, which means
    //writes again the dir speed and brakes value
    refresh();
    //let the receiver free to read onother signal
    irrecv.resume();
  }
}
/////////////////////////////////////////
void decode_command(int value) {
  switch (value) {
    //enables or disables brakes to stop/start the motor
    case ON_OFF:
      brk_a=!brk_a;
      last_command=ON_OFF;
    break;
    //increases speed
    case BASS_UP:
      if (speed_a<255) {
        speed_a+=10; }
      last_command=BASS_UP;
    break;
    //decreases speed
    case BASS_DOWN:
      if (speed_a>0) {
        speed_a-=10; }
      last_command=BASS_DOWN;
    break;
    //inverts spinning direction
    case PLAY_PAUSE:
      dir_a=!dir_a;
      last_command=PLAY_PAUSE;
    break;
    case LONG_PRESS:
      if (last_command==BASS_UP) {
        if (speed_a<255) {
          speed_a+=10; }
      }
      else if (last_command==BASS_DOWN) {
        if (speed_a>0) {
          speed_a-=10; }
      }
    break;
  }
}
/////////////////////////////////////////
void refresh() {
  digitalWrite(DIR_A,dir_a);
  digitalWrite(BRAKE_A,brk_a);
  digitalWrite(led_pin,!brk_a);
  analogWrite(SPEED_A,speed_a);
}
/////////////////////////////////////////

I saw there is a mistake, i wrote spd_a instead of speed_a in two cases (one is the declaration of the variable) but this is not the problem

Your speed starts at 255 and goes down by 10 when you slow down. Things are going to go wonky if the speed reaches 5 (after 25 steps) and you try to decrease it more. Since 5>0 it will decrease by 10, wrap around and become 251 (very fast). Then if you try to go faster, 251<255 so it will wrap back to 5 (very slow).

You should probably check for <=(255-10) before adding 10 and >=(0+10) before subtracting 10.

yes I found out the same error and solved it adding/subtracting 10 and then checking if the speed would be out of range and if so adjusting it; but the problem is still present! the fact is that the pin used by the shield to control the speed acts like a digital pin which is not using PWM! I mean, the motor can work all the way on or all the way off! if I only decrease once the speed, the motor, which I made initially spin at 255, stops like if I engaged the brakes. I really cannot understand what could cause this problem!

Show your new code. Perhaps there is another mistake.

/////////////////////////////////////////
#include <IRremote.h>
/////////////////////////////////////////
#define DIR_A 12
#define SPEED_A 3
#define BRAKE_A 9
/////////////////////////////////////////
#define ON_OFF 0x827D58A7 //brakes engaged/disengaged
#define BASS_UP 0x827D6897 //increase speed
#define BASS_DOWN 0x827D40BF //decrease speed
#define PLAY_PAUSE 0x827DF20D //inverts spinning direction
#define LONG_PRESS 0xFFFFFFFF
/////////////////////////////////////////
int recv_pin=5;
IRrecv irrecv(recv_pin);
decode_results results;

//these variables are modified according
//to the IR code read
int dir_a=HIGH;
int brk_a=HIGH;
byte speed_a=255;

//this led is on when the motor is working
int led_pin=7;

//keeps in memory which was the last signal
//received, to repeat it if is a command which
//increases or decreases speed
int last_command=0x0;
/////////////////////////////////////////

void setup() {
  irrecv.enableIRIn(); //enables IR receiver
  //defines pins
  pinMode(led_pin,OUTPUT);
  pinMode(DIR_A,OUTPUT);
  pinMode(BRAKE_A,OUTPUT);
  pinMode(SPEED_A,OUTPUT);
  //writes initial values of direction speed and brakes
  digitalWrite(DIR_A,dir_a);
  digitalWrite(BRAKE_A,brk_a);
  analogWrite(SPEED_A,speed_a);
}

void loop() {
  //waits for a signal
  if (irrecv.decode(&results)) {
    //passes the signal to the decode method to act consequently
    decode_command(results.value);
    //refreshes the situation, which means
    //writes again the dir speed and brakes value
    refresh();
    //let the receiver free to read onother signal
    irrecv.resume();
  }
}
/////////////////////////////////////////
void decode_command(int value) {
  switch (value) {
    //enables or disables brakes to stop/start the motor
    case ON_OFF:
      brk_a=!brk_a;
      last_command=ON_OFF;
    break;
    //increases speed
    case BASS_UP:
      speed_a+=10;
        if (speed_a>255) {
          speed_a=255;
        }
    break;
    //decreases speed
    case BASS_DOWN:
      speed_a-=10;
        if (speed_a<0) {
          speed_a=0;
        } 
      last_command=BASS_DOWN;
    break;
    //inverts spinning direction
    case PLAY_PAUSE:
      dir_a=!dir_a;
      last_command=PLAY_PAUSE;
    break;
    case LONG_PRESS:
      if (last_command==BASS_UP) {
        speed_a+=10;
        if (speed_a>255) {
          speed_a=255;
        }
      }
      else if (last_command==BASS_DOWN) {
        speed_a-=10;
        if (speed_a<0) {
          speed_a=0;
        }        
      }
    break;
  }
}
/////////////////////////////////////////
void refresh() {
  digitalWrite(DIR_A,dir_a);
  digitalWrite(BRAKE_A,brk_a);
  analogWrite(SPEED_A,speed_a);
  digitalWrite(led_pin,!brk_a);
}
/////////////////////////////////////////

here it is! I could perfectly have done another mistake, but i think the problems could be caused by something else. i don't know anything about electronic but could it be a problem of supply? I say so because i have other difficulties by controlling the speed of a motor with a pot; if i print to serial monitor the values read by the pot i find that its range is not fully used; the supply i give to the motor shield is from a 9volt battery and to the Arduino through serial usb

If you take out the IR code from the sketch, do you still have the problem?
If you move to another PWM pin, does it work?
Do you have minimal test (like really short sketch) that has the problem?

Can you plug an LED into the PWM pin, and see it fade?

Jack

yes i tryied everything to find out the causes but all seems working right! the IR part has no problems, even if i move to on other pin. the PWM of the pin i attached the ir receiver works good, i veryfied with a fade sketch. everything works good, but when i put together receiving IR and changing motor's speed i have the same problem. i also tryied with different and easier sketches, but i cannot control the speed of the motor by sending ir! it works all the way on or all the way off, and that's all... i really don't know how to solve this

'speed_a' is a 'byte' which I think means 'unsigned char'. It will NEVER be <0 or >255. Try changing speed_a to an int so you can detect overflow and underflow.

We are here to help you. We need to know more information. It is hard to understand your sentences. Can you make proper sentences please.

You say:

yes i tryied everything to find out the causes but all seems working right!

I have no idea what that means. Does all seem to be working right now?

You say:

the PWM of the pin i attached the ir receiver works good,

Please explain that.

You say:

but i cannot control the speed of the motor by sending ir!

Are you sending IR to the motor?

I suggest you test the minimal sketch that can fade a led (no IR code), then replace the led with the motor control. This should be a good starting point. Did they both work, or which one? Send us the minimal sketch, and the two results.

Thanks, Jack

Sorry for my confused last post! what i wanted to say is that: i tried all the parts of the circuit separately, and everything works good. the IR part has no error and works as it should. i checked if the PWM of the pin i used to read the IR could have problem but it doesn't; also the motor, used with another sketch is OK. everything it's OK until i don't put motor and IR receiver together!

I tried to change the var speed_a to an int as you suggested but nothing changed.

i checked if the PWM of the pin i used to read the IR could have problem but it doesn't

Are you using the same pin to send out PWM, and also to read the IR ? What pin(s)?

NicolaBastianello:
I tried to change the var speed_a to an int as you suggested but nothing changed.

That should have fixed it. Please show your code again.

to Jack: sorry for my bad english! i just wanted to say that all the pins work good, so it's not a problem of the arduino or the shield.

to johnwasser: sadly it didn't!! i really cannot understand! here's the code, i just changed the type of the variable speed_a

/////////////////////////////////////////
#include <IRremote.h>
/////////////////////////////////////////
#define DIR_A 12
#define SPEED_A 3
#define BRAKE_A 9
/////////////////////////////////////////
#define ON_OFF 0x827D58A7 //brakes engaged/disengaged
#define BASS_UP 0x827D6897 //increase speed
#define BASS_DOWN 0x827D40BF //decrease speed
#define PLAY_PAUSE 0x827DF20D //inverts spinning direction
#define LONG_PRESS 0xFFFFFFFF
/////////////////////////////////////////
int recv_pin=5;
IRrecv irrecv(recv_pin);
decode_results results;

//these variables are modified according
//to the IR code read
int dir_a=HIGH;
int brk_a=HIGH;
int speed_a=0;

//this led is on when the motor is working
int led_pin=7;

//keeps in memory which was the last signal
//received, to repeat it if is a command which
//increases or decreases speed
int last_command=0x0;
/////////////////////////////////////////

void setup() {
  irrecv.enableIRIn(); //enables IR receiver
  //defines pins
  pinMode(led_pin,OUTPUT);
  pinMode(DIR_A,OUTPUT);
  pinMode(BRAKE_A,OUTPUT);
  pinMode(SPEED_A,OUTPUT);
  //writes initial values of direction speed and brakes
  digitalWrite(DIR_A,dir_a);
  digitalWrite(BRAKE_A,brk_a);
  analogWrite(SPEED_A,speed_a);
}

void loop() {
  //waits for a signal
  if (irrecv.decode(&results)) {
    //passes the signal to the decode method to act consequently
    decode_command(results.value);
    //refreshes the situation, which means
    //writes again the dir speed and brakes value
    refresh();
    //let the receiver free to read onother signal
    irrecv.resume();
  }
}
/////////////////////////////////////////
void decode_command(int value) {
  switch (value) {
    //enables or disables brakes to stop/start the motor
    case ON_OFF:
      brk_a=!brk_a;
      last_command=ON_OFF;
    break;
    //increases speed
    case BASS_UP:
      speed_a+=10;
      if (speed_a>255) {
        speed_a=255;
      }
      last_command=BASS_UP;
    break;
    //decreases speed
    case BASS_DOWN:
      speed_a-=10;
      if (speed_a<0) {
          speed_a=0;
      } 
      last_command=BASS_DOWN;
    break;
    //inverts spinning direction
    case PLAY_PAUSE:
      dir_a=!dir_a;
      last_command=PLAY_PAUSE;
    break;
    case LONG_PRESS:
      if (last_command==BASS_UP) {
        speed_a+=10;
        if (speed_a>255) {
          speed_a=255;
        }
      }
      else if (last_command==BASS_DOWN) {
        speed_a-=10;
        if (speed_a<0) {
          speed_a=0;
        }        
      }
    break;
  }
}
/////////////////////////////////////////
void refresh() {
  digitalWrite(DIR_A,dir_a);
  digitalWrite(BRAKE_A,brk_a);  
  digitalWrite(led_pin,!brk_a);
  analogWrite(SPEED_A,speed_a);
}
/////////////////////////////////////////

Well I can't thing of anything else to ask (you never answer what I ask anyway), and no more suggestions to test with, (you did not use any of my suggestions). You say whats not wrong, so you must have a good idea what is wrong then.

Good Luck, Jack

I'm starting to wonder if the IR library is using Pin 3 (IR Send) even though you are not doing any IR sending.

Try bending Pin 3 of the motor shield and jumpering it to an unused PWM output. Then switch your 'speed_a' definition to that other pin.

to jack: sorry we did not understand each other! I followed all your suggestion, I tried separately all the parts of hardware and software, like you told to do. i found no problems at all!
to johnwasser: i will try as soon as possible, thanks! maybe i could modify the library cutting away the sending part

Old thread, but: I think I post this problem as well here since it might be related. When I run my DC motor, the IR signal get's jammed somehow. Setup: Keyes L298, ENA=Pin10, IN1=Pin8, IN2=Pin12. IR receiver=Pin5. Keyes IR Remote. I power the Arduino Mini Pro 16 through the L298. JLINKE 12V/10A power source. Motor has no capacitor filters installed (I'll try that next)

When the motor runs, the IR's attached LED lights up to indicate a signal has been received, and the actually sent remote codes are not deciphered correctly any more.

When I disrupt the motor's power supply, receiving codes works perfectly.