Робот из хлама

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Собрал из того что было робота для детей.

Тележка изготовлена из старого выключателя и мотор-редукторов оставшихся от покупной игрушки после того как дочь с ней "поиграла". Контроллер двигателей взят с тойже игрушки (на одноканальных Н мостах без маркировки). В качестве контроллера используеться Arduino pro mini 5V. Ик бампер выполнен из фотопар шариковой мышки. Аккумулятор от старого мобильника Li-ion. Собрано всё навесом. Местами использовал термоклей.

Планирую добавить управление по блютус, увеличить количество ИК сенсоров и в дальнейшем развести печатку под переферию.

#define sens_LF 0 // левый передний фотосенсор
#define sens_RF 1 //правый передний фотосенсор
#define BL_on   digitalWrite(12, HIGH)//vcc BL on
#define BL_off  digitalWrite(12, LOW)//vcc BL off
#define beeper 11//выход Спикера
#define pwm_f 50//быстрая скорость
#define pwm_l 125//медленная скорость
#define l_motor 8,9 //пины правого мотора
#define r_motor 7,6 //пины левого мотора
byte state_l_motor=0;//статус левого мотора
byte state_r_motor=0;//статус правого мотора
long PreGetDist = 0;//врямя последнего замера дистанции
#define  interval_PGD 50//интервал замера дистанции в мс
byte dist_LF=0;
byte dist_RF=0;
void setup() 
{
  Serial.begin(9600);
  pinMode(12,OUTPUT);//ИК подсветка
  pinMode(13,OUTPUT);//индикатор
  pinMode(8,OUTPUT);//мотор Л
  pinMode(7,OUTPUT);//мотор П
}

void loop() 
{
  if (millis() - PreGetDist > interval_PGD){//опрос датчиков препятствий
    PreGetDist = millis();
    dist_LF = ((dist_LF*2)+IR_sens(sens_LF))/3;//отфильтрованная дистанция
    dist_RF = ((dist_RF*2)+IR_sens(sens_RF))/3;//отфильтрованная дистанция
    Serial.print("L");
    Serial.print(dist_LF);
    Serial.print("  R");
    Serial.println(dist_RF);
  }
//левый мотор
    if (dist_LF > 2){
      reverse(l_motor,state_l_motor);
      state_l_motor=2;
    }
/*    else if (dist_LF > 3){
      forvard_l(l_motor,state_l_motor);
      state_l_motor=1;
    }*/
    else
    {
      forvard(l_motor,state_l_motor);
      state_l_motor=1;
    }
//правый мотор
    if (dist_RF > 2){
      reverse(r_motor,state_r_motor);
      state_r_motor=2;
    }
    /*else if (dist_RF > 3){
      forvard_l(r_motor,state_r_motor);
      state_r_motor=1;
    }*/
    else
    {
      forvard(r_motor,state_r_motor);
      state_r_motor=1;
    }

}

void beep(){
  analogWrite(beeper,125);
  delay (100);
  analogWrite(beeper,0);
} 

byte IR_sens(byte sens){
  int val=0;
  int val2=0;

  for (int i=0; i <= 9; i++){//замер с ИК подсветкой9
    BL_on; // вкл ИК  подсветка
    delay(1);
    val = val + analogRead(sens);// считываем значение с фототранзистора  
    BL_off;// выкл ИК подсветка
    delay(1);
    val2 = val2 + analogRead(sens);    // считываем значение с фототранзистора
  }
  val = val/10;
  /*  Serial.print("Light");
   Serial.println(val);*/

  val2 = val2/10;
  val = val - val2;  // считываем значение с фототранзистора
  //val = (val+dist_LF)/2;
  return abs(val);
}

void stp(byte pin_d, byte pin_s){//СТОП
  digitalWrite(13,1);
  digitalWrite( pin_d, 0 );
  digitalWrite( pin_s, 0 );
  delay(200);
  beep();
  digitalWrite(13,0);
}

void forvard(byte pin_d, byte pin_s, byte state){//ВПЕРЕД
  if (state != 1){
    stp(pin_d,pin_s);
    digitalWrite( pin_d, 1 ); // direction = forward
    analogWrite(pin_s,0);
    delay(50);
  }
  digitalWrite( pin_d, 1 ); // direction = forward
  analogWrite( pin_s, pwm_f); // PWM speed = slow
} 

void forvard_l(byte pin_d, byte pin_s, byte state){//ВПЕРЕД медленно
  if (state != 1){
    stp(pin_d,pin_s);
    digitalWrite( pin_d, 1 ); // direction = forward
    analogWrite(pin_s,0);
    delay(50);
  }
  digitalWrite( pin_d, 1 ); // direction = forward
  analogWrite( pin_s, pwm_l); // PWM speed = slow
} 

void reverse(byte pin_d, byte pin_s, byte state){//НАЗАД
  if (state != 2){
    stp(pin_d,pin_s);
    digitalWrite( pin_d, 0 ); // direction = rev
    analogWrite(pin_s, 255);//ускорение
    delay(50);
  }
  digitalWrite( pin_d, 0 ); // direction = rev
  analogWrite( pin_s, 255-pwm_f); // PWM speed = slow
} 









Видео работы

Vad33
Vad33 аватар
Offline
Зарегистрирован: 02.06.2015

Ужос! Осталось привязать веревкой крышку. 8-|

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Прикольно!

Сверху не хватет коробочки от детского сырочка как крышки!))

 

bpl
Offline
Зарегистрирован: 15.02.2016

yul-i-an - посмотрел видео мне понравилось, фунциклирует по полной.

Олег М.
Олег М. аватар
Offline
Зарегистрирован: 22.11.2015

yul-i-an пишет:
Собрал из того что было робота для детей.

Тележка изготовлена из старого выключателя и мотор-редукторов оставшихся от покупной игрушки после того как дочь с ней "поиграла". Контроллер двигателей взят с тойже игрушки (на одноканальных Н мостах без маркировки). В качестве контроллера используеться Arduino pro mini 5V. Ик бампер выполнен из фотопар шариковой мышки. Аккумулятор от старого мобильника Li-ion. Собрано всё навесом. Местами использовал термоклей.

Планирую добавить управление по блютус, увеличить количество ИК сенсоров и в дальнейшем развести печатку под переферию.


По-моему, здорово!
"Я его слепила из того, что было..." (С)
Очень умелые ручки.
+5!

Joiner
Offline
Зарегистрирован: 04.09.2014

bpl пишет:

yul-i-an - посмотрел видео мне понравилось, фунциклирует по полной.

Ссылку на видео сначала не заметил. Посмотрел....прикольно :) Детишкам, наверное, тоже понравилось. Папа молодец!

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Доработал алгоритм поведения, изменение "характера" можно посмотреть на видео версия 1.2.

Железо не трогал. Очень напрашиваються боковые сенсоры, для движения вдоль препятствий (чтобы бортами их не скребсти), датчик "присутствия пола". и верхний габаритный (чтобы под низкие препятствия не лез).

Простая езда с объездом препятствий конечно занятие интересное, но необходима ЦЕЛЬ идти на звук или свет обходя препятствия (для интер активности).

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

#define sens_LF 0 // левый передний фотосенсор
#define sens_RF 1 //правый передний фотосенсор
#define BL_on   digitalWrite(12, HIGH)//vcc BL on
#define BL_off  digitalWrite(12, LOW)//vcc BL off
#define min_dist 5 //минимальная дистанция
#define max_dist 3 //максимальная дистанция
#define beeper 11//выход Спикера
byte pwm_f=50;//быстрая скорость
#define pwm_l 125//медленная скорость
#define l_motor 8,9 //пины правого мотора
#define r_motor 7,6 //пины левого мотора
byte state_l_motor=0;//статус левого мотора
byte state_r_motor=0;//статус правого мотора
long PreGetDist = 0;//врямя последнего замера дистанции
#define  interval_PGD 50//интервал замера дистанции в мс
byte dist_LF=0;
byte dist_RF=0;
void setup() 
{
  Serial.begin(9600);
  pinMode(12,OUTPUT);//ИК подсветка
  pinMode(13,OUTPUT);//индикатор
  pinMode(8,OUTPUT);//мотор Л
  pinMode(7,OUTPUT);//мотор П
}

void loop() 
{
  if (millis() - PreGetDist > interval_PGD){//опрос датчиков препятствий
    PreGetDist = millis();
    get_dist();//замер растояний
  }

  if ((dist_LF + dist_RF) > max_dist){//если есть препятствие
    beep();
    pwm_f = 150;//замедляемся
  }
  else//иначе
  {
    pwm_f = 50;//ускоряемся
  }
  //левый мотор
  if (dist_LF >= min_dist){//препятствие близко
    pwm_f = 50;//увеличиваем скорость поворота
    do
    {
      reverse(l_motor,state_l_motor);//назад левый
      state_l_motor=2;//статус Л реверс
      get_dist();//проверяем препятствия
      Serial.println(dist_LF);
    } 
    while ((dist_LF + dist_RF) > max_dist);//крутимся влево пока есть препятствия
  }
  else
  {
    forvard(l_motor,state_l_motor);//вперед
    state_l_motor=1;//статус вперед
  }

  //правый мотор
  if (dist_RF >= min_dist){
    pwm_f = 50;
    do
    {
      reverse(r_motor,state_r_motor);
      state_r_motor=2;
      get_dist();
      Serial.println(dist_RF);
    }
    while ((dist_LF + dist_RF) > max_dist);
  }
  else
  {
    forvard(r_motor,state_r_motor);
    state_r_motor=1;
  }
}

void beep(){
  analogWrite(beeper,200);
  delay (25);
  analogWrite(beeper,0);
} 

void get_dist(){
  dist_LF = ((dist_LF*2)+IR_sens(sens_LF))/3;//отфильтрованная дистанция
  dist_RF = ((dist_RF*2)+IR_sens(sens_RF))/3;//отфильтрованная дистанция
  Serial.print("L");
  Serial.print(dist_LF);
  Serial.print("  R");
  Serial.println(dist_RF);
}

byte IR_sens(byte sens){
  int val=0;
  int val2=0;

  for (int i=0; i <= 9; i++){//замер с ИК подсветкой9
    BL_on; // вкл ИК  подсветка
    delay(1);
    val = val + analogRead(sens);// считываем значение с фототранзистора  
    BL_off;// выкл ИК подсветка
    delay(1);
    val2 = val2 + analogRead(sens);    // считываем значение с фототранзистора
  }
  val = val/10;
  val2 = val2/10;
  val = val - val2;  // считываем значение с фототранзистора
  return abs(val);
}

void stp(byte pin_d, byte pin_s){//СТОП
  digitalWrite(13,1);
  digitalWrite( pin_d, 0 );
  digitalWrite( pin_s, 0 );
  delay(100);
  digitalWrite(13,0);
}

void forvard(byte pin_d, byte pin_s, byte state){//ВПЕРЕД
  if (state != 1){
    stp(pin_d,pin_s);
  }
  digitalWrite( pin_d, 1 ); // direction = forward
  analogWrite( pin_s, pwm_f); // PWM speed = fast
} 
void reverse(byte pin_d, byte pin_s, byte state){//НАЗАД
  if (state != 2){
    stp(pin_d,pin_s);
  }
  digitalWrite( pin_d, 0 ); // direction = rev
  analogWrite( pin_s, 255); // PWM speed = slow 255-pwm_f
} 

позже подготовлю и опублекую принципиальную схему.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Возникла необходимость распозновать черные предметы ИК сенсорами.

Необходимо предумать алгоритм определения черных поверхностей не меняя железа. Задумка в следующем, т.к. ИК излучение не отражаеться от темных предметов, то пользоваться показаниями только приемников (окружающей освещенности). В функции

byte IR_sens(byte sens){
  int val=0;
  int val2=0;

  for (int i=0; i <= 9; i++){//замер с ИК подсветкой
    BL_on; // вкл ИК  подсветка
    delay(1);
    val = val + analogRead(sens);// считываем значение с фототранзистора  
    BL_off;// выкл ИК подсветка
    delay(1);
    val2 = val2 + analogRead(sens);    // считываем значение с фототранзистора
  }
  val = val/10;//среднее с ИК подсветкой
  val2 = val2/10;//средняя освещенность
  Serial.print(" Light=");//освещенность
  Serial.print(val2);
  val = val - val2;  //вычесление дистанции
  return abs(val);
}

переменная val2.

Логика такая - если при движении замер освещенности меньше предыдущего на Х%(подбираем эксперементально) то выполняем маневр в сторону большей освещенности. Возможно появление проблеммы с заездом в темные углы (должно решиться подбором Х) и неадекватное поведение при выключении света (приведет к постоянному вращению в кромешной тьме) можно решить замером времени маневра (допустим после 10сек. вращения забить на освещенность и орентироваться по ик сенсорам).

Кто что думает?

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Очень интересно, а что за датчики и мотор-редукторы у вас использованы?

Joiner
Offline
Зарегистрирован: 04.09.2014

Я тоже хотел робота сделать...ну так, когда свободное время будет. Начал делать так

Но пока некогда....может когда-то руки дойдут :(

Vad33
Vad33 аватар
Offline
Зарегистрирован: 02.06.2015

Поставьте доп фары из сверхярких светодиодов, которые будут включаться в проблемных ситуациях. 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Тоже планировал шасси собирать из таких машинок, но дома только одна. Если често на вторую денег лишних нет (ипотека...), так что приходиться работать с тем что есть. Проходимость конечно храмает, а так вроде всё пока работает. Над логикой работать нужно.

Вчера пробовал распозновать темные объекты, какието предпосылки появились, но нужно работать над алгоритмом их опознания (весь интернет уже перерыл). Буду работать задача больно интересная (не меняя железо получить больше информации об обстановке).

Спасибо за проявленный интерес.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Мотор редукторы

от игрушечного робота, если разобрать внутри как в машинках неваляшках, только колеса вовнутрь. На стоячем за колесо не проворачиваеться (Крутящий момент большой).

ИК сенсоры от шариковой мышки видео работы.

Результат измерения растояния очень сильно зависит от алгоритма опроса и фильтрации показаний.

void get_dist(){
  dist_LF = ((dist_LF*2)+IR_sens(sens_LF))/3;//отфильтрованная дистанция
  Serial.print(" Light_L=");//освещенность
  Serial.print(light_LF);
  Serial.print(" L_dist=");
  Serial.print(dist_LF);
  dist_RF = ((dist_RF*2)+IR_sens(sens_RF))/3;//отфильтрованная дистанция
  Serial.print(" Light_R=");//освещенность
  Serial.print(light_RF);
  Serial.print(" R_dist=");
  Serial.println(dist_RF);
}

byte IR_sens(byte sens){
  int val=0;
  int val2=0;
  for (int i=0; i <= 9; i++){//замер с ИК подсветкой
    BL_on; // вкл ИК  подсветка
    delay(1);
    val = val + analogRead(sens);// считываем значение с фототранзистора  
    BL_off;// выкл ИК подсветка
    delay(1);
    val2 = val2 + analogRead(sens);// считываем значение с фототранзистора
  }
  val = val/10;//среднее с ИК подсветкой
  val2 = val2/10;//средняя освещенность
  if (sens == sens_LF){//если опрашивали левый сенсор
    light_LF=val2;//то освещенность сохраняем в light_LF
  }
  if (sens == sens_RF){
    light_RF = val2;
  }
  val = val - val2;  //вычесление дистанции
  return abs(val);
}

 

Олег М.
Олег М. аватар
Offline
Зарегистрирован: 22.11.2015

yul-i-an пишет:
...Вчера пробовал распозновать темные объекты, какието предпосылки появились, но нужно работать над алгоритмом их опознания (весь интернет уже перерыл). Буду работать задача больно интересная (не меняя железо получить больше информации об обстановке).Спасибо за проявленный интерес.

Спасибо, Yul-i-an, за интересную инфу об  интересном решении.

Насчет темных объектов скажу, что ваши глаза и "глаза" Ардуинки совершенно  по-разному видят цвет.
Или не видят из-за разной спектральной чувствительности.
Кошки весь мир видят черно-белым, но лучше нас.
Летучие мыши "видят" ультразвук ушами в полной темноте.
Сначала определитесь, какие предметы и какие цвета вы хотите "увидеть" своей машинкой, тогда и "глаза" ей соответствующие нужно покупать.
Это очень интересно...

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Прбовал следующее

  if ((light_LF < abs(light_LF + light_RF) / 2)){//сли освещенность слева меньше средней
    do {
      beep();//издаем звук
      move_l();//поворачиваем
    }
    while (abs(light_LF-light_RF) > 20);//пока разница межу освещенностью слева и справа не будет меньше 20 уе
  }
  else//иначе
  {
    forvard(l_motor,state_l_motor);//вперед
    state_l_motor=1;//статус вперед
  }
  // с правым аналогично
    if (light_RF < abs(light_LF + light_RF) / 2){
    do {
      beep();//издаем звук
      move_r();
    }
    while (abs(light_LF-light_RF) > 20);
  }
  else
  {
    forvard(r_motor,state_r_motor);//вперед
    state_r_motor=1;//статус вперед
  }
  pre_light_LF = light_LF;
  pre_light_RF = light_RF;

На черные объекты реакция появилась, если раньше их совсем не замечали то теперь реагируем, но както не адекватно (не до конца отворачиваемся от них, блуждания во время отсутствия припятствий). Буду думать дальше.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Хочу прикрутить к роботу индикатор заряда АКБ. Для замера напряжения питания использовать конденцатор, заряжать его от напряжения питания, а затем разряжать и замерять время разряда и переводить в напряжение.

Как думаете по замеру времени разряда конденцатора как тут получиться?

Со светодиодом работает (светодиод в качестве датчика освещенности).

Сегодня попробую, о результатах напишу

Joiner
Offline
Зарегистрирован: 04.09.2014

А почему просто не измерять напряжение?

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

yul-i-an пишет:

Хочу прикрутить к роботу индикатор заряда АКБ. Для замера напряжения питания использовать конденцатор, заряжать его от напряжения питания, а затем разряжать и замерять время разряда и переводить в напряжение.

Как думаете по замеру времени разряда конденцатора как тут получиться?

Со светодиодом работает (светодиод в качестве датчика освещенности).

Сегодня попробую, о результатах напишу

Так делали на старых контроллерах где небыло АЦП а был аналоговый компаратор!)

Вс ардуино просто analogRed.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Joiner пишет:

А почему просто не измерять напряжение?

Ну потому что контроллер питаеться от тогоже напряжения.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

yul-i-an пишет:

Joiner пишет:

А почему просто не измерять напряжение?

Ну потому что контроллер питаеться от тогоже напряжения.

подключайте внутренее опорное 1.1В и меряете напряжение питания.

http://arduino.ru/Reference/AnalogReference

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Спасибо уже нашел (на компараторе).

Пробовал свой метод подключил конденцатор между GND и одним из цифровых выводов через резистор.

Подавал на положительный вывод конденцатора Высокий уровень, переключался на вход и щитал время до появления Низкого уровня, получл некоторые значения, но не пробовал менять напряжение источника питания чтобы проверить зависимость.

Joiner
Offline
Зарегистрирован: 04.09.2014

yul-i-an пишет:

Спасибо уже нашел (на компараторе).

Пробовал свой метод подключил конденцатор между GND и одним из цифровых выводов через резистор.

Подавал на положительный вывод конденцатора Высокий уровень, переключался на вход и щитал время до появления Низкого уровня, получл некоторые значения, но не пробовал менять напряжение источника питания чтобы проверить зависимость.

На Вашем же графике видно, что появление низкого уровня очень сильно размыто по времени. График стремится к горизонтальной линии. Как Вы будете отлавливать "появление Низкого уровня"? 

Вам же написали про 1.1в. Это внутреннее опорное напряжение, которое, как говорят, довольно стабильное, и при изменении напряжения питания ардуины (конечно в разумных пределах) не изменяется, что дает Вам возможность спокойно измерять напряжение аккумулятора (естественно через делитель).

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Набросок схемы

IR диоды планирую запитать через транзистор и параллельно включить конденцатор для повышения мощности излучения, питание в цепи фототранзисторов тоже следует подовать через транзистор во время замера (экономия заряда АКБ).

JR, JL выходы на Н мосты правого и левого моторов.

Схема будет примерно такая

Joiner
Offline
Зарегистрирован: 04.09.2014

yul-i-an пишет:
............

IR диоды планирую запитать через транзистор и параллельно включить конденцатор ..........

Чета Вы перемудряете....транзистор...конценцатор.....

Для мощности излучения можно лазер включить...можно детектор цвета включить....только не понимаю для чего?

Какова конечная цель?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Joiner пишет:

yul-i-an пишет:
............

IR диоды планирую запитать через транзистор и параллельно включить конденцатор ..........

Чета Вы перемудряете....транзистор...конценцатор.....

Для мощности излучения можно лазер включить...можно детектор цвета включить....только не понимаю для чего?

Какова конечная цель?

Ну как в схемах пультов ДУ

releyshic
Offline
Зарегистрирован: 20.11.2015

yul-i-an пишет:

На черные объекты реакция появилась, если раньше их совсем не замечали то теперь реагируем, но както не адекватно (не до конца отворачиваемся от них, блуждания во время отсутствия припятствий). Буду думать дальше.

не пойму зачем ты сравниваешь левую или правую освещённость со средней это не имеет смысла, трогда уже сравнивай среднюю левуую со средней правой и корректируй движение, то есть коэффициент поворота k = (сред.лев-сред.п)/сред.общ + только по свету не получится ориентироваться нужно вместе с ИК или звуком.

Также  у меня вызывает сомнения как ты определяешь Среднее значение вообще? датчик тупо прямо смотрит? лучше развёртку сделать то есть типа как кинескоп у телевизора работает ) только считывать ищи по в поиске "самодельный тепловизор" там есть такое устройство только у тебя датчик света будет

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

releyshic пишет:

yul-i-an пишет:

На черные объекты реакция появилась, если раньше их совсем не замечали то теперь реагируем, но както не адекватно (не до конца отворачиваемся от них, блуждания во время отсутствия припятствий). Буду думать дальше.

не пойму зачем ты сравниваешь левую или правую освещённость со средней это не имеет смысла, трогда уже сравнивай среднюю левуую со средней правой и корректируй движение, то есть коэффициент поворота k = (сред.лев-сред.п)/сред.общ + только по свету не получится ориентироваться нужно вместе с ИК или звуком.

Также  у меня вызывает сомнения как ты определяешь Среднее значение вообще? датчик тупо прямо смотрит? лучше развёртку сделать то есть типа как кинескоп у телевизора работает ) только считывать ищи по в поиске "самодельный тепловизор" там есть такое устройство только у тебя датчик света будет

Мне требуеться средняя освещенность для того чтобы знать что приблизелись к чемуто темному (не важно с какой стороны темнее). Я выше писал что хочу попробовать распозновать темные предметы без изменения железа. Сравнивать среднюю левую и правую освещенности... (у меня не стоит задача ориентироваться на свет). Задача обнаружение и объезд препятствий.

Доработаный код (доработка - если при объезде припятствия застряли то отъезжаем назад и продолжаем маневр)

//СБОР СРЕДСТВ НА КОМПЛЕКТУЮЩИЕ http://yasobe.ru/na/robot_detkam
//Хочеться платформу нормальную заиметь, но ипотека...
#define sens_LF 0 // левый передний фотосенсор
#define sens_RF 1 //правый передний фотосенсор
#define BL_on   digitalWrite(12, HIGH)//vcc BL on
#define BL_off  digitalWrite(12, LOW)//vcc BL off
#define min_dist 4 //минимальная дистанция
#define max_dist 3 //максимальная дистанция
#define beeper 11//выход Спикера
byte pwm_f=50;//быстрая скорость
#define pwm_l 125//медленная скорость
#define l_motor 8,9 //пины правого мотора
#define r_motor 7,6 //пины левого мотора
byte state_l_motor=0;//статус левого мотора
byte state_r_motor=0;//статус правого мотора
long PreGetDist = 0;//врямя последнего замера дистанции
long PreFree = 0;//время последнего ожидания ухода от препятствия
#define  interval_PGD 50//интервал замера дистанции в мс
#define interval_free 3000//интервал ожидания ухода от препятствия
byte dist_LF=0;//дистанция слева
byte dist_RF=0;//дистанция справа
int light_LF=0;//освещенность слева
int light_RF=0;//освещенность справа
int pre_light_LF=0;//освещенность слева предыдущий замер
int pre_light_RF=0;//освещенность справа предыдущий замер
void setup() 
{
  get_dist();//замер растояний
  pre_light_LF = light_LF;
  pre_light_RF = light_RF;
  Serial.begin(9600);
  pinMode(12,OUTPUT);//ИК подсветка
  pinMode(13,OUTPUT);//индикатор
  pinMode(8,OUTPUT);//мотор Л
  pinMode(7,OUTPUT);//мотор П
}

void loop() 
{
  if (millis() - PreGetDist > interval_PGD){//опрос датчиков препятствий
    PreGetDist = millis();
    get_dist();//замер растояний
  }
  if ((dist_LF + dist_RF) > max_dist){//если есть препятствие
    beep();//издаем звук
    pwm_f = 180;//замедляемся
  }
  else//иначе
  {
    pwm_f = 50;//ускоряемся
  }

  //помеха слева
  if (dist_LF >= min_dist){//препятствие близко слева
    //    move_revers();//движение назад
    PreFree = millis();
    do {
      move_l();//маневр влево
      if (millis()-PreFree > interval_free){
        move_reverse(500);
        PreFree = millis();
      }
      move_forvard(100);      
    } 
    while ((dist_LF + dist_RF) > max_dist);//крутимся влево пока есть препятствия
    // while (dist_LF != dist_RF);//крутимся влево пока не равно

  }
  else
  {
    forvard(l_motor,state_l_motor);//вперед
    state_l_motor=1;//статус вперед
  }

  //помеха справа
  if (dist_RF >= min_dist){
    //    move_revers();//движение назад
    PreFree = millis();
    do {
      move_r();
      if (millis()-PreFree > interval_free){
        move_reverse(500);
        PreFree = millis();
      }
      move_forvard(100); 
    } 
    while ((dist_LF + dist_RF) > max_dist);//крутимся влево пока есть препятствия
    // while (dist_LF != dist_RF);//крутимся влево пока не равно 
  }
  else
  {
    forvard(r_motor,state_r_motor);
    state_r_motor=1;
  }
  /* //Определение черных предметов
   if ((light_LF < abs(light_LF + light_RF) / 2)){
   do {
   beep();//издаем звук
   move_l();
   }
   while (abs(light_LF-light_RF) > 20);
   }
   else
   {
   forvard(l_motor,state_l_motor);//вперед
   state_l_motor=1;//статус вперед
   }
   
   if (light_RF < abs(light_LF + light_RF) / 2){
   do {
   beep();//издаем звук
   move_r();
   }
   while (abs(light_LF-light_RF) > 20);
   }
   else
   {
   forvard(r_motor,state_r_motor);//вперед
   state_r_motor=1;//статус вперед
   }
   pre_light_LF = light_LF;
   pre_light_RF = light_RF;*/

  //идем на свет
  /*    if (light_LF > light_RF){
   do {
   beep();//издаем звук
   move_l();
   }
   while (light_LF != light_RF);
   }
   else
   {
   forvard(l_motor,state_l_motor);//вперед
   state_l_motor=1;//статус вперед
   }
   
   if (light_LF < light_RF){
   do {
   beep();//издаем звук
   move_r();
   }
   while (light_LF != light_RF);
   }
   else
   {
   forvard(r_motor,state_r_motor);//вперед
   state_r_motor=1;//статус вперед
   } */
}

void beep(){
  analogWrite(beeper,200);
  delay (25);
  analogWrite(beeper,0);
} 

void get_dist(){
  dist_LF = ((dist_LF*2)+IR_sens(sens_LF))/3;//отфильтрованная дистанция
  Serial.print(" Light_L=");//освещенность
  Serial.print(light_LF);
  Serial.print(" L_dist=");
  Serial.print(dist_LF);
  dist_RF = ((dist_RF*2)+IR_sens(sens_RF))/3;//отфильтрованная дистанция
  Serial.print(" Light_R=");//освещенность
  Serial.print(light_RF);
  Serial.print(" R_dist=");
  Serial.println(dist_RF);
}

byte IR_sens(byte sens){
  int val=0;
  int val2=0;

  for (int i=0; i <= 9; i++){//замер с ИК подсветкой
    BL_on; // вкл ИК  подсветка
    delay(1);
    val = val + analogRead(sens);// считываем значение с фототранзистора  
    BL_off;// выкл ИК подсветка
    delay(1);
    val2 = val2 + analogRead(sens);    // считываем значение с фототранзистора
  }
  val = val/10;//среднее с ИК подсветкой
  val2 = val2/10;//средняя освещенность
  if (sens == sens_LF){//если опрашивали левый сенсор
    light_LF=val2;//то освещенность сохраняем в light_LF
  }
  if (sens == sens_RF){
    light_RF = val2;
  }
  // Serial.print(" Light=");//освещенность
  // Serial.print(val2);
  val = val - val2;  //вычесление дистанции
  return abs(val);
}

void stp(byte pin_d, byte pin_s){//СТОП
  digitalWrite(13,1);
  digitalWrite( pin_d, 0 );
  digitalWrite( pin_s, 0 );
  delay(250);
  digitalWrite(13,0);
}

void forvard(byte pin_d, byte pin_s, byte state){//ВПЕРЕД
  if (state != 1){
    stp(pin_d,pin_s);    
  }
  digitalWrite( pin_d, 1 ); // direction = forward
  analogWrite( pin_s, pwm_f); // PWM speed = fast
} 
void reverse(byte pin_d, byte pin_s, byte state){//НАЗАД
  if (state != 2){
    stp(pin_d,pin_s);    
  }
  digitalWrite( pin_d, 0 ); // direction = rev
  analogWrite( pin_s, 255); // PWM speed = slow 255-pwm_f
  delay(10);
  digitalWrite( pin_d, 0 ); // direction = rev
  analogWrite( pin_s, 255-pwm_f); // PWM speed = slow 255-pwm_f
} 

void move_l (){//поворот влево
  pwm_f = 50;//увеличиваем скорость поворота
  //  do
  // {
  reverse(l_motor,state_l_motor);//назад левый
  state_l_motor=2;//статус Л реверс
  get_dist();//получаем расстояния до препятствия
  Serial.println(dist_LF);
  //  } 
  //  while ((dist_LF + dist_RF) > max_dist);//крутимся влево пока есть препятствия
}

void move_r (){
  pwm_f = 50;
//  do
//  {
    reverse(r_motor,state_r_motor);
    state_r_motor=2;
    get_dist();
    Serial.println(dist_RF);
//  }
//  while ((dist_LF + dist_RF) > max_dist);
}

void move_reverse(int x){//оба назад
  pwm_f = 50;
    reverse(r_motor,state_r_motor);
    reverse(l_motor,state_l_motor);
    state_r_motor=2;
    state_l_motor=2; 
delay(x);
}

void move_forvard(int x){//оба назад
  pwm_f = 50;
    forvard(r_motor,state_r_motor);
    forvard(l_motor,state_l_motor);
    state_r_motor=1;
    state_l_motor=1; 
delay(x);
}

Видео позже выложу

releyshic
Offline
Зарегистрирован: 20.11.2015

yul-i-an пишет:

Мне требуеться средняя освещенность для того чтобы знать что приблизелись к чемуто темному (не важно с какой стороны темнее). Я выше писал что хочу попробовать распозновать темные предметы без изменения железа. Сравнивать среднюю левую и правую освещенности... (у меня не стоит задача ориентироваться на свет). Задача обнаружение и объезд препятствий.

я не понимаю как даже логически определяять препятствия по свету, это как плавать на ощупь ))

варинт со сканированием сработает, а вот такой наврятли, да и зачем если есть ИК и звук?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Переделал схему ИК сенсоров

Выглядит она так (рисовал тут)

Резистор R3 не устанавливал (т.к. ИК диод включаеться на пару милесекунд), а резистор R1 100Ом. Дальность обнаружения выросла вдвое примерно (около 30 см до светлых объектов). Черные матовые объекты распознаються на расстоянии около 3 см.

В программу добавил снижение скорости пропорционально расстоянию до препятствия.

Последняя версия кода

//СБОР СРЕДСТВ НА КОМПЛЕКТУЮЩИЕ http://yasobe.ru/na/robot_detkam
//На нормальную платформу
#define sens_LF 0 // левый передний фотосенсор
#define sens_RF 1 //правый передний фотосенсор
#define BL_on   digitalWrite(12, HIGH)//vcc BL on
#define BL_off  digitalWrite(12, LOW)//vcc BL off
#define min_dist 13 //минимальная дистанция
#define max_dist 9 //максимальная дистанция
#define beeper 11//выход Спикера
byte pwm_f=50;//быстрая скорость
#define pwm_l 125//медленная скорость
#define l_motor 8,9 //пины правого мотора
#define r_motor 7,6 //пины левого мотора
byte state_l_motor=0;//статус левого мотора
byte state_r_motor=0;//статус правого мотора
long PreGetDist = 0;//врямя последнего замера дистанции
long PreFree = 0;//время последнего ожидания ухода от препятствия
#define interval_PGD 100//интервал замера дистанции в мс
#define interval_free 5000//интервал ожидания ухода от препятствия
byte dist_LF=0;//дистанция слева
byte dist_RF=0;//дистанция справа
int light_LF=0;//освещенность слева
int light_RF=0;//освещенность справа
int pre_light_LF=0;//освещенность слева предыдущий замер
int pre_light_RF=0;//освещенность справа предыдущий замер
void setup() 
{
  get_dist();//замер растояний
  pre_light_LF = light_LF;
  pre_light_RF = light_RF;
  Serial.begin(9600);
  pinMode(12,OUTPUT);//ИК подсветка
  pinMode(13,OUTPUT);//индикатор
  pinMode(8,OUTPUT);//мотор Л направление
  pinMode(7,OUTPUT);//мотор П направление
}

void loop() 
{
    get_dist();//замер растояний
  if ((dist_LF + dist_RF) > max_dist){//если есть препятствие
    beep();//издаем звук
    pwm_f = map(((dist_LF+dist_RF)/2), 0, 30, 55, 160);//скорость
  border();//выбор маневра
}
  else//иначе
  {
    pwm_f = 0;//ускоряемся
  }
}

void border(){
  //помеха слева
  if (dist_LF >= min_dist){//препятствие близко слева
    PreFree = millis();
    do {
      move_l();//маневр влево
      if (millis()-PreFree >= interval_free){
        move_reverse(300);
        PreFree = millis();
        break;
      }
      //      move_forvard(100);      
    } 
    //while (dist_LF > max_dist );//крутимся влево пока не пропадет помеха справа
    while ((dist_LF + dist_RF) >= min_dist);//крутимся влево пока есть препятствия
    // while (dist_LF != dist_RF);//крутимся влево пока не равно

  }
  else
  {
    forvard(l_motor,state_l_motor);//вперед
    state_l_motor=1;//статус вперед
  }

  //помеха справа
  if (dist_RF >= min_dist){
    PreFree = millis();
    do {
      move_r();
      if (millis()-PreFree >= interval_free){
        move_reverse(300);
        PreFree = millis();
        break;
      }
      //     move_forvard(100); 
    } 
    //while (dist_RF > max_dist );//крутимся влево пока не пропадет помеха справа
    while ((dist_LF + dist_RF) >= min_dist);//крутимся влево пока есть препятствия
    // while (dist_LF != dist_RF);//крутимся влево пока не равно 
  }
  else
  {
    forvard(r_motor,state_r_motor);
    state_r_motor=1;
  }
}

void beep(){
  analogWrite(beeper,pwm_f);
  delay (25);
  analogWrite(beeper,0);
} 

void get_dist(){
  if (millis() - PreGetDist >= interval_PGD){//опрос датчиков препятствий
    PreGetDist = millis();
    dist_LF = ((dist_LF*2)+IR_sens(sens_LF))/3;//отфильтрованная дистанция
    dist_RF = ((dist_RF*2)+IR_sens(sens_RF))/3;//отфильтрованная дистанция
  }
  Serial.print(" Light_L=");//освещенность
  Serial.print(light_LF);
  Serial.print(" L_dist=");
  Serial.print(dist_LF);
  Serial.print(" Light_R=");//освещенность
  Serial.print(light_RF);
  Serial.print(" R_dist=");
  Serial.println(dist_RF);
}

byte IR_sens(byte sens){
  int val=0;
  int val2=0;

  for (int i=0; i <= 9; i++){//замер с ИК подсветкой
    BL_on; // вкл ИК  подсветка
    delay(1);
    val = val + analogRead(sens);// считываем значение с фототранзистора  
    BL_off;// выкл ИК подсветка
    delay(1);
    val2 = val2 + analogRead(sens);    // считываем значение с фототранзистора
  }
  val = val/10;//среднее с ИК подсветкой
  val2 = val2/10;//средняя освещенность
  if (sens == sens_LF){//если опрашивали левый сенсор
    light_LF=val2;//то освещенность сохраняем в light_LF
  }
  if (sens == sens_RF){
    light_RF = val2;
  }
  val = val - val2;  //вычесление дистанции
  return abs(val);
}

void stp(byte pin_d, byte pin_s){//СТОП
  digitalWrite(13,1);
  digitalWrite( pin_d, 0 );
  digitalWrite( pin_s, 0 );
  delay(250);
  digitalWrite(13,0);
}

void forvard(byte pin_d, byte pin_s, byte state){//ВПЕРЕД
  if (state != 1){
    stp(pin_d,pin_s);    
  }
  digitalWrite( pin_d, 1 ); // direction = forward
  analogWrite( pin_s, pwm_f); // PWM speed = fast
} 
void reverse(byte pin_d, byte pin_s, byte state){//НАЗАД
  if (state != 2){
    stp(pin_d,pin_s);    
  }
  digitalWrite( pin_d, 0 ); // direction = rev
  analogWrite( pin_s, 255); // PWM speed = slow 255-pwm_f
  delay(10);
  digitalWrite( pin_d, 0 ); // direction = rev
  analogWrite( pin_s, 255-pwm_f); // PWM speed = slow 255-pwm_f
} 

void move_l (){//поворот влево
pwm_f = 160;//увеличиваем скорость поворота
  //  do
  // {
  reverse(l_motor,state_l_motor);//назад левый
  state_l_motor=2;//статус Л реверс
  get_dist();//получаем расстояния до препятствия
  Serial.println(dist_LF);
  //  } 
  //  while ((dist_LF + dist_RF) > max_dist);//крутимся влево пока есть препятствия
}

void move_r (){
pwm_f = 160;
//  do
//  {
    reverse(r_motor,state_r_motor);
    state_r_motor=2;
    get_dist();
    Serial.println(dist_RF);
//  }
//  while ((dist_LF + dist_RF) > max_dist);
}

void move_reverse(int x){//оба назад
//  pwm_f = 50;
    reverse(r_motor,state_r_motor);
    reverse(l_motor,state_l_motor);
    state_r_motor=2;
    state_l_motor=2; 
delay(x);
}

void move_forvard(int x){//оба назад
//  pwm_f = 50;
    forvard(r_motor,state_r_motor);
    forvard(l_motor,state_l_motor);
    state_r_motor=1;
    state_l_motor=1; 
delay(x);
}

Теперь схема выглядит так

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Если у кого есть опыт работы с ИК бампером подскажите как лучше расположить ИК диоды и фотосенсоры. У меня сейчас ИК диоды и фототранзисторы расположены по сторонам, тонкие препятствия в центре не замечает (ножка стула например). Еть вариант расположить ИК диоды в центе, а фототранзисторы оставить побокам или добавить ИК диод в центре к тому что есть, как думаете?

Преписал код немного

//СБОР СРЕДСТВ НА КОМПЛЕКТУЮЩИЕ http://yasobe.ru/na/robot_detkam
//На нормальную платформу
#define sens_LF 0 // левый передний фотосенсор
#define sens_RF 1 //правый передний фотосенсор
#define BL_on   digitalWrite(12, HIGH)//vcc BL on
#define BL_off  digitalWrite(12, LOW)//vcc BL off
#define min_dist 20 //минимальная дистанция
#define max_dist 10 //максимальная дистанция
#define beeper 11//выход Спикера

//#define l_motor 8,9 //пины правого мотора
//#define r_motor 7,6 //пины левого мотора

#define stp mov(0,0,0,0,250)//stop
#define forvard mov(1,20+20,1,20,0)//forvard
#define reverse mov(0,255,0,255,0)//revers
#define right_low mov(0,0,1,20,0)//right low
#define right mov(0,255,0,100,0)//right
//#define right mov(0,255,1,255,0)//right
#define left_low mov(1,0,0,0,0)//left low
#define left mov(0,100,0,255,0)//left
//#define left mov(1,0,0,255,0)//left

long PreGetDist = 0;//врямя последнего замера дистанции
//long PreFree = 0;//время последнего ожидания ухода от препятствия
byte interval_PGD=200;//интервал замера дистанции в мс
byte spd=0;
byte front_dist = 0;//дистанция спереди
byte dist_LF=0;//дистанция слева
byte dist_RF=0;//дистанция справа
int light_LF=0;//освещенность слева
int light_RF=0;//освещенность справа
int pre_light_LF=0;//освещенность слева предыдущий замер
int pre_light_RF=0;//освещенность справа предыдущий замер

void setup() 
{
  Serial.begin(9600);
  pinMode(12,OUTPUT);//ИК подсветка
  pinMode(13,OUTPUT);//индикатор
  pinMode(8,OUTPUT);//мотор Л направление
  pinMode(7,OUTPUT);//мотор П направление
}

void loop() 
{
  get_dist();//замер растояний до препятствий
  if (front_dist < 8){
    interval_PGD=150;
    forvard;

  }
  if (dist_LF > 5){
interval_PGD=100;
         right_low;//правее
  }

  if (dist_LF > 8){
    beep();
      interval_PGD=80;
//      stp;//стоп
      right;//вправо
  }

  if (dist_RF > 5){
interval_PGD=100;
    left_low;//левее
  }

  if (dist_RF > 8){
    beep();
      interval_PGD=80;
//      stp;
      left;//влево
  }
/*  if (front_dist >= 15){
   interval_PGD=250;
    reverse;

  }*/
//  spd=0;
}

void beep(){
  analogWrite(beeper,125);
  delay (25);
  analogWrite(beeper,0);
}

void get_dist(){
  if (millis() - PreGetDist >= interval_PGD){//опрос датчиков препятствий
    PreGetDist = millis();
    dist_LF = ((dist_LF*2)+IR_sens(sens_LF))/3;//отфильтрованная дистанция
    dist_RF = ((dist_RF*2)+IR_sens(sens_RF))/3;//отфильтрованная дистанция

  }
  Serial.print(" Light_L=");//освещенность
  Serial.print(light_LF);
  Serial.print(" L_dist=");
  Serial.print(dist_LF);
  Serial.print(" Light_R=");//освещенность
  Serial.print(light_RF);
  Serial.print(" R_dist=");
  Serial.println(dist_RF);
}

byte IR_sens(byte sens){
  int val=0;
  int val2=0;

  for (int i=0; i < 1; i++){//замер с ИК подсветкой
    BL_on; // вкл ИК  подсветка
    delay(1);
    val = val + analogRead(sens);// считываем значение с фототранзистора  
    BL_off;// выкл ИК подсветка
    delay(1);
    val2 = val2 + analogRead(sens);    // считываем значение с фототранзистора
  }
  val = val/2;//среднее с ИК подсветкой
  val2 = val2/2;//средняя освещенность
  if (sens == sens_LF){//если опрашивали левый сенсор
    light_LF=val2;//то освещенность сохраняем в light_LF
  }
  if (sens == sens_RF){
    light_RF = val2;//то освещенность сохраняем в light_RF
  }
  val = val - val2;  //вычесление дистанции
  return abs(val);
}

void mov(boolean R_r, byte R_sp, boolean L_r, byte L_sp, int pause){
  digitalWrite(13,1);
  //правый
  digitalWrite( 8, R_r );
  analogWrite( 9, R_sp );//22 поправка
  //левый
  digitalWrite( 7, L_r );
  analogWrite( 6, L_sp );
  delay(pause);
  digitalWrite(13,0);
}
// схема - http://arduwir.netdo.ru/%D1%81%D1%85%D0%B5%D0%BC%D0%B0-%D1%80%D0%BE%D0%B1%D0%BE%D1%82%D0%B0.html

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Я предпочел УЗВ сенсор (HCSR-04) на серводвигателе (SG-90). У него не очень острая диаграмма направленности +-15 градусов, но при вращении и усреднении пачки замеров дает вполне адекватные расстояния с точностью до 2-3мм. Игрался с разного рода "ушами" на приемник и излучатель .. в принципе, диаграмму можно заузить до +- 6градусов, но качественного улучшения "итого" оно не дает, зато сильно просаживает дальность определения расстояния (примерно с 5метров до 1.5м.). Отказался.

Для движение между объектами вполне достаточно по +- 15 замеров от центрального направления, что не сильно напряжно по памяти. Для повышения скорости движения можно крутить датчиком не непрерывно +-90градусов, а только в наиболее критическом диапазоне направлений.