1

im controlling some small dc motors using arduino uno and tle94112el shield. currently, i can independently controll motors by pressing remote's buttons, but i wanna keep one motor rotating by holding a button. for example, by holding "unu" button, i wanna power the motor with 50% duty cycle, as i currently do by just pressing "unu". thank you!

#include <TLE94112.h>
#include <Tle94112Motor.h>
#include <IRremote.h>

#define unu 0x1
#define patru 0x4
#define sapte 0x7

int RECV_PIN = 2;

// Tle94112 Object
Tle94112 controller = Tle94112();

// Tle94112Motor Objects
Tle94112Motor motor1(controller);
Tle94112Motor motor2(controller);
Tle94112Motor motor3(controller);


IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  // Enable MotorController Tle94112
  // Note: Required to be done before starting to configure the motor

   irrecv.enableIRIn();
  controller.begin();

   // Connect motor1 to HB1 and HB3
  motor1.connect(motor1.HIGHSIDE, controller.TLE_HB1);
  motor1.connect(motor1.LOWSIDE, controller.TLE_HB2);

  // Drive HB1 with signal from PWM1
  // Note: This allows to control the speed of the motor

  motor1.setPwm(motor1.HIGHSIDE, controller.TLE_PWM2);

  // Set PWM Frequency, default is 80 Hz
  motor1.setPwmFreq(motor1.HIGHSIDE, controller.TLE_FREQ200HZ);

  motor1.begin();
}

void loop()
{
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value

    if (results.value == unu)
    {
      motor1.start(127);
    }

    if (results.value == patru)
    {
      motor1.start(255);
    }

    if (results.value == sapte)
    {
      motor1.start(0);
    }
  }

}

thanks for replying. i followed your instructures. when i hold the button, my remote sends continuously the same code it sends for a single press too. so in the brackets of second "if", i used the same condition that i used in first "if". following your instructions, when i prees the button, motor starts, even if i release or keep holding the button, the motor keeps rotating, but when i press the same button second time, the motor stops. so instead of "timestamp = millis()", i used "timestamp < millis()", so in this situation, the motor was rotating as long as i kept the button pressed. now the problem is that the motor is powered with pulses, aprox. 2 impulses per second, it doesnt rotate smoothly. i tryed incresing and decreasing TIMEOUT with no effects. i also used all the pwm frequencies (80, 100, 200 hz) that the shield provides, and different duty cycles, also with no effects. but when i add 2 more motors, to controll them in the same way, each with it's own button, the pulses period was even bigger, with aprox one impuls on second. do you have any ideea about this? sorry, but its my first arduino project, i also have no experience on engineering forums. thaks for your time.

here is the code im using now:

#include <TLE94112.h>
#include <Tle94112Motor.h>
#include <IRremote.h>

#define unu 0x1


unsigned long timestamp = 0;
#define TIMEOUT   200

int RECV_PIN = 2;

// Tle94112 Object
Tle94112 controller = Tle94112();

// Tle94112Motor Objects
Tle94112Motor motor1(controller);



IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  // Enable MotorController Tle94112
  // Note: Required to be done before starting to configure the motor

   irrecv.enableIRIn();
  controller.begin();

   // Connect motor1 to HB1 and HB3
  motor1.connect(motor1.HIGHSIDE, controller.TLE_HB1);
  motor1.connect(motor1.LOWSIDE, controller.TLE_HB2);

  // Drive HB1 with signal from PWM1
  // Note: This allows to control the speed of the motor

  motor1.setPwm(motor1.HIGHSIDE, controller.TLE_PWM2);

  // Set PWM Frequency, default is 80 Hz
  motor1.setPwmFreq(motor1.HIGHSIDE, controller.TLE_FREQ200HZ);

  motor1.begin();
}

void loop()
{
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value

    if (results.value == unu)
    {
      motor1.start(127);
      timestamp < millis();

    }

    if(results.value == unu){
      timestamp < millis();
    }

    if(millis() - timestamp > TIMEOUT){
      motor1.start(0);
    }
  }
}
5
  • Please format your code correctly, so that it gets readable. In the question editor select the code and click the {}button or press control+K
    – chrisl
    Commented May 9, 2020 at 10:25
  • Replacing the assignment = with a comparison < breaks the logic of my solution. You are doing something else wrong. Please add your new code to the question
    – chrisl
    Commented May 11, 2020 at 10:41
  • i understood now the logic of your solution, and i understood that replacing = with < breacks the logic, but it worked as i described.
    – Tincu Ioan
    Commented May 11, 2020 at 11:51
  • I formatted the code for you and put the old part of the question back in. That way future readers can understand the thoughts and learnings behind the question.
    – chrisl
    Commented May 11, 2020 at 11:55
  • I edited my question to address the problems of the new code
    – chrisl
    Commented May 11, 2020 at 12:08

1 Answer 1

1

As I understood you want the motor to run only while you are pressing the button, stopping as you release the button. IR remote controls normally don't send a "release" signal. But they often send a "repeat" signal in a defined frequency. The value of this signal depends on the remote, that you use. A quick search showed this forum thread, where the value is 0xFFFFFFFF.

So to check, if the button is still pressed, you need to regularly check, if the repeat code was received. When receiving the unu signal, turn on the motor and start a timeout counter. Every time you receive the repeat signal, you reset the timeout counter. If the timeout hits (meaning, that no repeat signal was received anymore), stop the motor.

The timeout counter is best done with the millis() function, which returns the number of milliseconds since startup. Refer to the BlinkWithoutDelay example, that comes with the Arduino IDE. Basically you save the time in a variable, when the unu code is received (the receive if statement is pseudo code). You reset the timestamp in the same way for every repeat code. Then you check, if the different between the current time (returned by millis() and the timestamp is over the timeout value (here 200ms). If yes, turn the motor off.

unsigned long timestamp = 0;
#define TIMEOUT   200

void loop(){
    if(unu was received){
        // turn on motor here
        timestamp = millis(); //take timestamp
    }
    if(repeat was received){
        timestamp = millis();
    }

    if(millis() - timestamp > TIMEOUT){
        // turn off motor here
    }
}

In your new version you replaces the = with a < to make it work. That is wrong. The lines, where you did it, will just do nothing then. Instead the problem lies at a different place:

The millis() if statement

if(millis() - timestamp > TIMEOUT)

has to be placed directly in void loop(), outside of the receive if statement. In your current version the timeout will only take effect, when something was received, which was not unu. But you want it to take effect also when nothing is received. In that case the receive if statement will not execute. So just move the millis() if statement outside of that receive if statement:

#include <TLE94112.h>
#include <Tle94112Motor.h>
#include <IRremote.h>

#define unu 0x1


unsigned long timestamp = 0;
#define TIMEOUT   700

int RECV_PIN = 2;

// Tle94112 Object
Tle94112 controller = Tle94112();

// Tle94112Motor Objects
Tle94112Motor motor1(controller);



IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  // Enable MotorController Tle94112
  // Note: Required to be done before starting to configure the motor

   irrecv.enableIRIn();
  controller.begin();

   // Connect motor1 to HB1 and HB3
  motor1.connect(motor1.HIGHSIDE, controller.TLE_HB1);
  motor1.connect(motor1.LOWSIDE, controller.TLE_HB2);

  // Drive HB1 with signal from PWM1
  // Note: This allows to control the speed of the motor

  motor1.setPwm(motor1.HIGHSIDE, controller.TLE_PWM2);

  // Set PWM Frequency, default is 80 Hz
  motor1.setPwmFreq(motor1.HIGHSIDE, controller.TLE_FREQ200HZ);

  motor1.begin();
}

void loop()
{
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value

    if (results.value == unu)
    {
      motor1.start(127);
      timestamp < millis();

    }

    if(results.value == unu){
      timestamp < millis();
    }
  }

  if(millis() - timestamp > TIMEOUT){
    motor1.start(0);
  }
}

That way the timeout will be checked at every loop() iteration. As you described, that you get the code about 2 times per second, I increased the timeout value here to 700ms, which then should be enough to not let the motor stop between the receiving of the unu command.


Btw: To stop the motor you are using motor.start(0);. While it works perfectly, you might want to write your code more speaking. The used library internally just calls it's motor.coast(); function, when the parameter is zero. So to make it more obvious in your code, what you are doing there, you could replace motor.start(0); by motor.coast(). That can help others to understand your code better and also yourself, when you are revising the code yourself after some time, when you may have forgotten, what you thought at that time about the code. It is always better to write code, that speaks by itself about what it is doing.

1
  • 1
    oh thanks!!!! it works now!!
    – Tincu Ioan
    Commented May 11, 2020 at 12:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.