Hello all.
I’ve stumbled on strange problem with IR remote and trying to control DC motor via PWM on pin 11.
Project is to make motor for Lego train, i have original Lego train motor, just want to make custom “brain” to drive it. I have TSOP1838B to receive remote signals (I used z3t0’s irremote library) and then act accordingly. Turn on or off headlights/taillights, go forward, accelerate, decelerate, go backwards. This is of course not done directly with Arduino but with L298D chip.
I already made all of this and it works. I used mini universal remote.
Now comes the problem. I found cheaper remote, it’s not universal, but it cost around $0.69 a piece and, what’s more important, it has more buttons. I could control more than one train with it. I would just need to use different key codes for each controller board, no problem, in theory.
I recorded codes from all buttons and changed command to them to give it a test drive. It almost worked, lights turned on/off, but when I told it to start it went on but didn’t respond to any other command.
To cut the story a bit shorter, turned out that as soon as PWM starts IR command received is different.
I.e. stop code is 16736925, start code is 16769565. I can press stop button any number of times while PWM is not active and I’ll get 16736925 every time, but as soon as I press forward button, it’ll receive 16769565 OK, pwm will start with analogWrite value 175 and further presses of forward button (that should now accelerate) will be received as 4001918335, what was before stop code would now be 5316027, backwards/decelerate will be received as 3810010651 instead of 16753245.
It’s not DC motor noise that does this. Currently I have Arduino Uno on table, only TSOP1838B connected to it, no motor, no L298D, and the same thing happens. Only thing that happens is PWM starts on pin 11.
I don’t have a clue what could be at fault here. More so because that other remote works fine, every time it gets the same code. Same code, same arduino, only different remote/code set.
Another interesting thing is that I tried to switch PWM pin to pin 9 and for some reason it worked fine. No problem. Only difference is timers related to these PWM pins.
Here’s the code, I’ve removed unneeded parts that control direction of motor (INPUT1/2 pins on L298D) and left only these that are relevant to this problem
/*
CH- - 16753245
CH - 16736925
CH+ - 16769565
Prev - 16720605
Next - 16712445
Play - 16761405
Vol- - 16769055
Vol+ - 16754775
EQ - 16748655
0 - 16738455
100+ - 16750695
200+ - 16756815
1 - 16724175
2 - 16718055
3 - 16743045
4 - 16716015
5 - 16726215
6 - 16734885
7 - 16728765
8 - 16730805
9 - 16732845
*/
// to remove serial comm comment line below
#define DEBUGMODE
#ifdef DEBUGMODE
#define DEBUG_PRINT(x) Serial.print(x);
#define DEBUG_PRINTLN(x) Serial.println(x);
#define DEBUG_PRINTDEC(x) Serial.print(x, DEC);
#define DEBUG_PRINTLNDEC(x) Serial.println(x, DEC);
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTDEC(x)
#define DEBUG_PRINTLNDEC(x)
#endif
#include <IRremote.h>
int IRpin = 14; // signal pin from TSOP1838B is connected to Atmega PC0 pin, or A0 with Arduino, but when called as 14 it acts as digital IO
IRrecv irrecv(IRpin);
decode_results results;
uint8_t RFinc;
uint8_t Buffer;
int controlpin = 11; // connected to enable PIN on L298D, PWM pin to controll speed
int frontled = 16; // front led control, Atmega PC2 - Arduino A2, 16 as digital IO
int rearled = 17; // rear led control, Atmega PC3 - Arduino A3, 17 as digital IO
int mode = 0; // used to differentiate from backwards and forwards
int pwmspeed = 0; // counter for PWM array "position"
int pwmsettings[] = {0, 175, 225, 255}; // array with values for PWM output that controlls speed
void setup() {
pinMode(controlpin, OUTPUT);
pinMode(frontled, OUTPUT);
pinMode(rearled, OUTPUT);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
irrecv.enableIRIn(); // Start the receiver
#ifdef DEBUGMODE
Serial.begin(9600);
#endif
DEBUG_PRINTLN("waiting for input");
Buffer = 0;
}
void loop() {
// put your main code here, to run repeatedly:
if (irrecv.decode(&results)) {
DEBUG_PRINT("Decoded value: ");
DEBUG_PRINTLNDEC(results.value);
irrecv.resume(); // Receive the next value
delay(300);
}
switch(results.value){
case 16769565: // button CH+
results.value = 0;
if ((pwmspeed > 0) && (mode == 2)){
DEBUG_PRINTLN("Slower");
pwmspeed--;
}
else if ((pwmspeed == 0) && (mode != 1)){
DEBUG_PRINTLN("Starting forward");
pwmspeed++;
mode = 1;
}
else {
DEBUG_PRINTLN("Faster");
pwmspeed++;
}
apply();
break;
case 16753245: // button CH+
results.value = 0;
if ((pwmspeed > 0) && (mode == 1)){
DEBUG_PRINTLN("Slower");
pwmspeed--;
}
else if ((pwmspeed == 0) && (mode != 2)){
DEBUG_PRINTLN("Starting backwards");
pwmspeed++;
mode = 2;
}
else {
DEBUG_PRINTLN("Faster");
pwmspeed++;
}
apply();
break;
case 16736925: // tipka power
results.value = 0;
DEBUG_PRINTLN("Stop");
allStop();
break;
case 16712445: // tipka left
digitalWrite(frontled, !digitalRead(frontled));
break;
case 16720605: // tipka right
digitalWrite(rearled, !digitalRead(rearled));
break;
}
}
void allStop(){
mode = 0;
pwmspeed = 0;
analogWrite(controlpin, 0);
}
void apply(){
if (pwmspeed < 4) {
analogWrite(controlpin, pwmsettings[pwmspeed]);
DEBUG_PRINTLN(pwmsettings[pwmspeed]);
}
else pwmspeed = 3;
}
Example of terminal output for this code
waiting for input
Decoded value: 16736925
Stop
Decoded value: 16769565
Starting forward
175
Decoded value: 4001918335
Decoded value: 4001918335
Decoded value: 4001918335
Decoded value: 5316027
Decoded value: 5316027
Decoded value: 5316027
Decoded value: 3810010651
Decoded value: 3810010651
Decoded value: 3810010651
Reason why I simply don’t switch to pin9 is because for final PCB I use Atmega8, and in case of Atmega8 irremote library uses timer that’s related to PWM on these pins. Btw. same problem happens on Atmega8.
Sorry for the wall of text