Помогите объединить два скетча

yanbaev72
Offline
Зарегистрирован: 08.11.2013

Всем привет!

Есть скетч управления двухколесным шаси пультом дистанционногоуправления через ИК.

#include <IRremote.h>
#include <AFMotor.h>

int RECV_PIN = 9;//вход ИК приемника

AF_DCMotor motor_a(1, MOTOR12_64KHZ);
AF_DCMotor motor_b(2, MOTOR12_64KHZ);

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  irrecv.enableIRIn(); // включить приемник
  motor_a.setSpeed(255);
  motor_b.setSpeed(255);
}

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


    if (results.value == 0x806FE01F) { //вперед
      motor_a.run(FORWARD);
      motor_b.run(FORWARD);
      delay(1000);
      motor_a.run(RELEASE);
      motor_b.run(RELEASE);
    }

    if (results.value == 0x806FF00F) { //назад
      motor_a.run(BACKWARD);
      motor_b.run(BACKWARD);
      delay(1000);
      motor_a.run(RELEASE);
      motor_b.run(RELEASE);
    }

    if (results.value == 0x806F20DF) { //налево
      motor_a.run(BACKWARD);
      motor_b.run(FORWARD);
      delay(500);
      motor_a.run(RELEASE);
      motor_b.run(RELEASE);
    }

    if (results.value == 0x806F50AF) { //направо
      motor_a.run(FORWARD);
      motor_b.run(BACKWARD);
      delay(500);
      motor_a.run(RELEASE);
      motor_b.run(RELEASE);
    }
    irrecv.resume();
  }
}

но работает это все только по нажатию соответствующей кнопки заданное количество времени и пока например робот не проедет заданные заранее 3 секунды он не реагирует на нажатие других кнопок и т.д.

Хочется сделать чтобыробот двигался например вперед только до тех пор пока нажата соответствующая кнопка на пульте и после того как отпускаю кнопку робот останавливался...

Нашел вот такой скетч:

#include <IRremote.h> // это скачанная библиотека

int RECV_PIN = 11; //вход ИК приемника
IRrecv irrecv(RECV_PIN);
decode_results results;

//eventTime, для паузы,  вместо delay,будем использовать функцию millis. 
unsigned long eventTime=0;
//индикация таймера
int timer = 12;

int L13 = 13; //пины управляющие моторами, светодиодами, или реле, чем угодно.
int L2 = 2;
int L3 = 3;
int L4 = 4;
int L5 = 5;
int L6 = 6;
int L7 = 7;
int L8 = 8;

void setup(){
  irrecv.enableIRIn(); // включить приемник

  pinMode(L13, OUTPUT); // назначаем пины как выходы
  pinMode(L2, OUTPUT);
  pinMode(L3, OUTPUT); 
  pinMode(L4, OUTPUT);
  pinMode(L5, OUTPUT);
  pinMode(L6, OUTPUT);
  pinMode(L7, OUTPUT);
  pinMode(L8, OUTPUT);

  pinMode(timer, OUTPUT);
} 
void loop() {
  // Эта конструкция нужна чтобы конвертировать пульсирующий (-) с (ИК) преемника сигнал в постоянный.
  //После появление и пропадания сигнала, состояние сразу не меняется! а ждет  100 миллисекунд.
  //Если 100 миллисекунд не прошло, и поступил еще один сигнал с пульта, тогда таймер заново запускается на 100 миллисекунд.

  //Проще говоря, пока кнопка на пульте нажата таймерПИН остается вКлюченным, если кнопка на пульте отпущена таймерПИН вЫключен.

  // Читаем данные с (ИК) преемника. В момент приема данных у (ИК) приемника на выходе появляется пульсирующий (-)отрицательный сигнал
  if (digitalRead(RECV_PIN) == LOW) 
    //  Если обнаружен отрицательный сигнал запускаем таймер,и включаем таймерПИН //(timer, HIGH);
    eventTime=millis(),digitalWrite(timer, HIGH);
  //  Продолжительность работы таймера >100 миллисекунд. И ТаймерПИН выключаем //(timer, LOW)
  if(millis()-eventTime>100) digitalWrite(timer, LOW)
    //  и вЫключаем все
    ,digitalWrite(L13, LOW),digitalWrite(L2, LOW),digitalWrite(L3, LOW)
      ,digitalWrite(L4, LOW),digitalWrite(L5, LOW),digitalWrite(L6, LOW),digitalWrite(L7, LOW),digitalWrite(L8, LOW);

  if (irrecv.decode(&results)) {
    //ВАЖНО !!! ( 1000809 ) это код кнопки №1 - моего (ИК)! (инфракрасного пульта)!, -
    //-у вашего пульта будет другой код, замените на свой!
    // У моего пульта при нажатии на одну и ту же кнопку, могут отсылаться два разных (КОДА) сигнала,  чтобы обойти эту проблему
    //я использовал Логический оператор "или" (||) if (results.value == 0x1000809 || results.value == 0xF7283C77
    // Теперь неважно какой код отправлен  с кнопки пульта, первый или второй
    // Если ваша кнопка пульта не страдает раздвоением личности, можете написать так if (results.value == 0x1000809 

    //Только при условии если, (Одновременно),Обнаружен поступивший код кнопки
    // и выключен ТаймерПИН,"и" "&&" (digitalRead(timer) == HIGH)
    // включаем нужный нам pin, digitalWrite(L13, HIGH);

    if (results.value == 0x1000809 || results.value == 0xF7283C77 && (digitalRead(timer) == HIGH) )digitalWrite(L13, HIGH); 
    if (results.value == 0x1008889 || results.value == 0x757FB4DF && (digitalRead(timer) == HIGH) )digitalWrite(L2, HIGH);
    if (results.value == 0x1004849 || results.value == 0xB33B4597 && (digitalRead(timer) == HIGH) )digitalWrite(L3, HIGH); 
    if (results.value == 0x100C8C9 || results.value == 0x3C03E507 && (digitalRead(timer) == HIGH) )digitalWrite(L4, HIGH);
    if (results.value == 0x1002829 || results.value == 0xE705551F && (digitalRead(timer) == HIGH) )digitalWrite(L5, HIGH); 
    if (results.value == 0x100A8A9 || results.value == 0xA4A58EC7 && (digitalRead(timer) == HIGH) )digitalWrite(L6, HIGH);
    if (results.value == 0x1006869 || results.value == 0xE2E45F7F && (digitalRead(timer) == HIGH) )digitalWrite(L7, HIGH); 
    if (results.value == 0x100E8E9 || results.value == 0x6BACFEEF && (digitalRead(timer) == HIGH) )digitalWrite(L8, HIGH);

    irrecv.resume(); 
  }
}

Но этот скетч сделан на примере светодиодов и на библиотеке <IRremote.h>

Подскажите как можно объеденить эти два скетчана библиотеках <IRremote.h> и <AFMotor.h> (или без них) чтобы робот двигался только когда нажата соответствующая кнопка?

Мои попытки объединения не увенчались успехом....

Заранее благодарю каждого откликнувшегося и пошедшего мне на помощь!

maksim
Offline
Зарегистрирован: 12.02.2012

Что ж все никак не осилите, то... ведь тут не навыки программирования нужны, а всего лишь придумать логику работы...

#include <IRremote.h>
#include <AFMotor.h>

int RECV_PIN = 9;//вход ИК приемника

AF_DCMotor motor_a(1, MOTOR12_64KHZ);
AF_DCMotor motor_b(2, MOTOR12_64KHZ);

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  irrecv.enableIRIn(); // включить приемник
  motor_a.setSpeed(255);
  motor_b.setSpeed(255);
}

void loop() {
  if (irrecv.decode(&results))
  {
    if (results.value == 0x806FE01F) { //вперед
      motor_a.run(FORWARD);
      motor_b.run(FORWARD);
    }

    if (results.value == 0x806FF00F) { //назад
      motor_a.run(BACKWARD);
      motor_b.run(BACKWARD);
    }

    if (results.value == 0x806F20DF) { //налево
      motor_a.run(BACKWARD);
      motor_b.run(FORWARD);
    }

    if (results.value == 0x806F50AF) { //направо
      motor_a.run(FORWARD);
      motor_b.run(BACKWARD);
    }
    irrecv.resume();
  }
  else
  {
    motor_a.run(RELEASE);
    motor_b.run(RELEASE);
  }
  delay(100);
}

Если как то не так заработает, то думаю ход мыслей ясен...

yanbaev72
Offline
Зарегистрирован: 08.11.2013

maksim пишет:

Что ж все никак не осилите, то... ведь тут не навыки программирования нужны, а всего лишь придумать логику работы...

#include <IRremote.h>
#include <AFMotor.h>

int RECV_PIN = 9;//вход ИК приемника

AF_DCMotor motor_a(1, MOTOR12_64KHZ);
AF_DCMotor motor_b(2, MOTOR12_64KHZ);

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  irrecv.enableIRIn(); // включить приемник
  motor_a.setSpeed(255);
  motor_b.setSpeed(255);
}

void loop() {
  if (irrecv.decode(&results))
  {
    if (results.value == 0x806FE01F) { //вперед
      motor_a.run(FORWARD);
      motor_b.run(FORWARD);
    }

    if (results.value == 0x806FF00F) { //назад
      motor_a.run(BACKWARD);
      motor_b.run(BACKWARD);
    }

    if (results.value == 0x806F20DF) { //налево
      motor_a.run(BACKWARD);
      motor_b.run(FORWARD);
    }

    if (results.value == 0x806F50AF) { //направо
      motor_a.run(FORWARD);
      motor_b.run(BACKWARD);
    }
    irrecv.resume();
  }
  else
  {
    motor_a.run(RELEASE);
    motor_b.run(RELEASE);
  }
  delay(100);
}

Если как то не так заработает, то думаю ход мыслей ясен...

Блин, все работает, только не всегда стабильно реагирует на кнопки, видимо из-за хлама которые сыпятся при нажитии на ту или иную кнопку, но это можно поправить (добавив параллельные коды кнопок) спасибо вам за помощь, я уже несколько дней не могу добиться этого эффекта.

P.S. По моим наблюдениям Вы на этом форуме единственный настоящий профессианал который не просто знает, но и не брезгует в помощи тем людям которые хотят, но по каким то причинам не могут сделать то что хотят! Когда создаю новую тему всегда надеюсь и жду когда Вы будете в онлайне! Спасибо Вам!

maksim
Offline
Зарегистрирован: 12.02.2012

yanbaev72 пишет:

только не всегда стабильно реагирует на кнопки

Попробуйте задержку уменьшить до 50 или еще меньше.

yanbaev72
Offline
Зарегистрирован: 08.11.2013

maksim пишет:

yanbaev72 пишет:

только не всегда стабильно реагирует на кнопки

Попробуйте задержку уменьшить до 50 или еще меньше.

Да, уже попробовал, уменьшил до 30 стало дергаться рывками, увеличил до 200 стало заметно лучше но после нажатия кнопки нужно немного больше времени ждать для следующего нажатия,оставил 150-вроде самое оптимальное получилось))

Скажите, а можно как то сделать чтобы мое "творение" ехало прямо когда я нажимаю вперед, просто у меня сейчас она едет по небольшому радиусу как бы слегка поворачивает направо, а вот когда еду назад то едет ровно?!

есть такие  штуковины и еще такая незнаю может ли это как топомочь в моей проблеме....

maksim
Offline
Зарегистрирован: 12.02.2012

Снизте скорость левого мотора, когда едете вперед:

  if (results.value == 0x806FE01F) { //вперед
      motor_a.setSpeed(235);
      motor_a.run(FORWARD);
      motor_b.run(FORWARD);
    }
    else motor_a.setSpeed(255);

 

yanbaev72
Offline
Зарегистрирован: 08.11.2013

maksim пишет:

Снизте скорость левого мотора, когда едете вперед:

  if (results.value == 0x806FE01F) { //вперед
      motor_a.setSpeed(235);
      motor_a.run(FORWARD);
      motor_b.run(FORWARD);
    }
    else motor_a.setSpeed(255);

 

Получилось)Спасибо!

yanbaev72
Offline
Зарегистрирован: 08.11.2013

Немного отойду от темы...

подключаю сонар по этой схеме

заливаю этот скетч

#include <CyberLib.h>
#include <avr/wdt.h> 

#define motors_init {D4_Out; D5_Out; D6_Out; D7_Out;}
#define robot_go {D4_Low; D5_High; D6_High; D7_Low;}
#define robot_stop {D4_Low; D5_Low; D6_Low; D7_Low;}
#define robot_rotation_left {D4_Low; D5_High; D6_Low; D7_High;}
#define robot_rotation_right {D4_High; D5_Low; D6_High; D7_Low;}

#define size_buff 5 //размер массива sensor
uint16_t sensor[size_buff]; //массив для хранения замеров дальномера
uint8_t stat=0;

void setup()  
{
  motors_init;  //инициализация выходов моторов
  D11_Out; //динамик
  D14_Out; D14_Low; //пин trig ультразвукового сонара
  D15_In; //пин echo  ультразвукового сонара
  for(uint8_t i=0; i<12; i++) beep(50, random(100, 1000)); //звуковое оповещение готовности робота
  wdt_enable (WDTO_500MS);    //Сторожевая собака 1сек.
}

void loop()
{Start  
  uint16_t dist=GetDistance(); //производим замер 

    if( dist < 10) {rotation(stat, 255);} else   
    if( dist < 20) {rotation(stat, 200);} else 
    if( dist < 40) {rotation(stat, 130);} else
                   {robot_go; stat=~stat;}           //поехали!!!
      
     wdt_reset(); //покормить собаку
End;}

//***************************************************
void rotation(uint8_t arr, uint8_t dur) 
{
    switch (arr) 
    {
    case 0:    robot_rotation_right;
      break;
    case 255:    robot_rotation_left; 
      break;    
    } 
    delay_ms(dur);    
    robot_stop;
}
//***************************************************
uint16_t GetDistance() 
{
 uint16_t dist;
 for (uint8_t i = 0; i < size_buff; ++i) //производим несколько замеров
  { 
    D14_High; delay_us(10);  D14_Low;  //запустить измерение
   dist = pulseIn(15, HIGH, 2400); //считываем длительность времени прохождения эха, ограничить время ожидания
   if(dist==0) dist=2400;  
   sensor[i]=dist;
   delay_ms(40); //задержка между посылками
   wdt_reset(); //покормить собаку, что бы она не сбежала 
  }
  dist=(find_similar(sensor, size_buff, 58))/58; // //фильтруем показания датчика и переводим в см
  return dist;
} 
//***************************************************  
void beep(uint8_t dur, uint16_t frq)
{
  dur=(1000/frq)*dur;  //расчет длительности бипа
  for(byte i=0; i<dur; i++)
  {
    D11_High; 
    delay_us(frq); 
    D11_Low;
    delay_us(frq);
  } 
} 

Но при попытке залить скетч выскакивает ошибка

motor_IR_forum.ino: In function 'uint16_t GetDistance()':
motor_IR_forum:62: error: 'find_similar' was not declared in this scope
и выделяется строчка
  dist=(find_similar(sensor, size_buff, 58))/58; // //фильтруем показания датчика и переводим в см

В чем может быть проблема?