Управление двигателем с помощью ИК-пульта дистанционного управления
я управляю некоторыми небольшими двигателями постоянного тока с помощью arduino uno и экрана tle94112el. в настоящее время я могу самостоятельно управлять двигателями, нажимая кнопки пульта дистанционного управления, но я хочу, чтобы один двигатель вращался, удерживая кнопку. например, удерживая кнопку "unu", я хочу включить двигатель с рабочим циклом 50%, как я делаю в настоящее время, просто нажав "unu". Спасибо!
#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()
{
// Включить контроллер двигателя Tle94112
// Примечание: Это необходимо сделать перед началом настройки двигателя
irrecv.enableIRIn();
controller.begin();
// Подключите мотор1 к HB1 и HB3
motor1.connect(motor1.HIGHSIDE, controller.TLE_HB1);
motor1.connect(motor1.LOWSIDE, controller.TLE_HB2);
// Привод HB1 с сигналом от PWM1
// Примечание: Это позволяет контролировать скорость двигателя
motor1.setPwm(motor1.HIGHSIDE, controller.TLE_PWM2);
// Установите частоту ШИМ, по умолчанию 80 Гц
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);
}
}
}
спасибо, что ответили. я следовал вашим указаниям. когда я удерживаю кнопку, мой пульт дистанционного управления непрерывно отправляет тот же код, что и при одном нажатии. поэтому в скобках второго "если" я использовал то же условие, что и в первом "если". следуя вашим инструкциям, когда я нажимаю кнопку, двигатель запускается, даже если я отпускаю или продолжаю удерживать кнопку, двигатель продолжает вращаться, но когда я нажимаю ту же кнопку во второй раз, двигатель останавливается. поэтому вместо "отметка времени = миллис ()" я использовал "отметку времени теперь проблема в том, что двигатель питается импульсами, примерно. 2 импульса в секунду, он не вращается плавно. я попытался увеличить и уменьшить время ожидания без каких-либо эффектов. я также использовал все частоты шим (80, 100, 200 Гц), которые обеспечивает экран, и различные рабочие циклы, также без каких-либо эффектов. но когда я добавил еще 2 двигателя, чтобы управлять ими таким же образом, каждый со своей собственной кнопкой, период импульсов был еще больше, примерно один импульс в секунду. у вас есть какие-нибудь идеи по этому поводу? извините, но это мой первый проект arduino, у меня также нет опыта работы на инженерных форумах. спасибо за ваше время.
вот код, который я сейчас использую:
#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);
}
}
}
@Tincu Ioan, 👍1
Обсуждение1 ответ
Как я понял, вы хотите, чтобы двигатель работал только во время нажатия кнопки, останавливаясь при отпускании кнопки. ИК-пульты дистанционного управления обычно не посылают сигнал "отпустить". Но они часто посылают "повторный" сигнал на определенной частоте. Значение этого сигнала зависит от используемого вами пульта дистанционного управления. Быстрый поиск показал эту тему форума, где значение равно 0xFFFFFFFF
.
Поэтому, чтобы проверить, по-прежнему ли нажата кнопка, вам нужно регулярно проверять, был ли получен код повтора. При получении сигнала UNU
включите двигатель и запустите счетчик времени ожидания. Каждый раз, когда вы получаете сигнал повтора, вы сбрасываете счетчик времени ожидания. Если истечет время ожидания (это означает, что повторный сигнал больше не был получен), остановите двигатель.
Счетчик времени ожидания лучше всего использовать с помощью функции millis ()
, которая возвращает количество миллисекунд с момента запуска. Обратитесь к примеру BlinkWithoutDelay, который поставляется с Arduino IDE. В основном вы экономите время в переменной, когда
получен код unu (оператор receive if является псевдокодом). Вы сбрасываете метку времени таким же образом для каждого кода повтора. Затем вы проверяете, не превышает ли разница между текущим временем (возвращаемым
millis()
и меткой времени значение тайм-аута (здесь 200 мс). Если да, выключите двигатель.
unsigned long timestamp = 0;
#define TIMEOUT 200
void loop(){
if(unu was received){
// включить двигатель здесь
timestamp = millis(); //взять метку времени
}
if(repeat was received){
timestamp = millis();
}
if(millis() - timestamp > TIMEOUT){
// выключить двигатель здесь
}
}
В вашей новой версии вы заменяете =
на<
, чтобы заставить его работать. Это неправильно. Линии, где вы это сделали, тогда просто ничего не сделают. Вместо этого проблема кроется в другом месте:
Оператор millis()
if
if(millis() - timestamp > TIMEOUT)
должен быть помещен непосредственно в цикл void()
, вне оператора receive if. В вашей текущей версии тайм-аут вступит в силу только в том случае, если было получено что-то, что не было unu
. Но вы хотите, чтобы это вступило в силу и тогда, когда ничего не получено. В этом случае инструкция receive if не будет выполнена. Поэтому просто переместите оператор millis()
if за пределы этого оператора receive if:
#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()
{
// Включить контроллер двигателя Tle94112
// Примечание: Это необходимо сделать перед началом настройки двигателя
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);
}
}
Таким образом, время ожидания будет проверяться на каждой итерации цикла ()
. Как вы описали, что вы получаете код примерно 2 раза в секунду, я увеличил значение тайм-аута здесь до 700 мс, чего должно быть достаточно, чтобы двигатель не останавливался между получением команды unu
.
Кстати: Для остановки двигателя вы используете motor.start(0);
. Хотя это работает идеально, вы, возможно, захотите написать свой код более четко. Используемая библиотека внутренне просто вызывает функцию motor.coast ();
, когда параметр равен нулю. Поэтому, чтобы сделать более очевидным в вашем коде, что вы там делаете, вы могли бы заменить motor.start(0);
на motor.coast()
. Это может помочь другим лучше понять ваш код, а также вам самим, когда вы сами пересматриваете код через некоторое время, когда вы, возможно, забыли, что вы думали в то время о коде. Всегда лучше писать код, который сам по себе говорит о том, что он делает.
о, спасибо!!!! теперь это работает!!, @Tincu Ioan
- Использование VS1838B с Arduino
- Tone() конфликтует с библиотекой IRremote (множественное определение `__vector_7')
- Как остановить вращение сервопривода?
- Arduino IRremote перестает работать
- Использование ИК-пульта с Arduino
- ИК приемник принимает только 0
- Переключение между циклами Arduino ИК-пульт дистанционного управления
- Эмулятор Nikon IR remote trigger (ML-L3) не работает
Пожалуйста, отформатируйте свой код правильно, чтобы он стал читабельным. В редакторе вопросов выберите код и нажмите кнопку
{}
или нажмите control+K, @chrislЗамена присваивания = сравнением < ломает логику моего решения. Вы делаете что-то еще неправильно. Пожалуйста, добавьте свой новый код к вопросу, @chrisl
теперь я понял логику вашего решения и понял, что замена = на < ломает логику, но она работала так, как я описал., @Tincu Ioan
Я отформатировал код для вас и вернул старую часть вопроса. Таким образом, будущие читатели смогут понять мысли и знания, стоящие за этим вопросом., @chrisl
Я отредактировал свой вопрос, чтобы решить проблемы нового кода, @chrisl