Что-то здесь не так.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Доброго времени суток. Это мой первый опыт работы с ардуино и соответственно первый скетч, посему сильно не смейтесь, особенно не ругайтесь, если что не так.

   Итак. Задача: сделать робота, движущегося по линии. 

Успешно выполнил. Далее пытаюсь добавить функцию определения расстояния и при наличии препятствия - должен останавливаться, либо если препятствие перед началом движения - не начинать движение. Внес соответсвующие изменения в скетч - программа ошибок не нашла. Загружаю - не работает. Не могу разобраться - почему. Что неправильно сделал, либо чего-то недописал. Ткните пожалуйста. Только начинаю осваивать язык программирования. До этого ничем подобным не занимался, кроме электроники и пайки

 

Dimmm
Dimmm аватар
Offline
Зарегистрирован: 07.11.2016

вот смотри

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

Dimmm пишет:

вот смотри

О_О

evgta
Offline
Зарегистрирован: 02.09.2016

Как бы намек ТС , где скетч?! Ваш кэп

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

evgta пишет:
Как бы намек ТС , где скетч?! Ваш кэп

я запретил.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

извиняюсь, на работе отвлекли 

//Робот с функцией следования по черной  полосе "изоленте".
 
// *********************** Установка выводов моторов ************************
int MotorLeftSpeed = 3; // Левый (А) мотор СКОРОСТЬ — ENA
int MotorLeftForward = 4; // Левый (А) мотор ВПЕРЕД — IN1
int MotorLeftBack = 5; // Левый (А) мотор НАЗАД — IN2
int MotorRightForward = 8; // Правый (В) мотор ВПЕРЕД — IN3
int MotorRightBack = 7; // Правый (В) мотор НАЗАД — IN4
int MotorRightSpeed = 9; // Правый (В) мотор СКОРОСТЬ — ENB
int duration;
 
// ************************установка выводов сонара*****************************
int trigPin = 14; // задание номера вывода trig УЗ датчика
int echoPin = 15; // задание номера вывода echo УЗ датчика
 
// ********************* Установка выводов датчиков линии *******************
const int LineSensorLeft = 19; // вход левого датчика линии
const int LineSensorRight = 18; // вход правого датчика линии
int SL; // статус левого сенсора
int SR; // статус правого сенсора
 
// ************************** Переменная измерение дистанции*****************
long dist; // дистанция, измеренная УЗ датчиком
 
//**************************** Задание параметров*****************************
int MINdist = 10; // минамальная дистанция, меньше которой робот не движется
 
 
// *********************************** SETUP ********************************
void setup ()
{
//*************** Задаем контакты моторов****************
pinMode (MotorRightBack, OUTPUT); // Правый (В) мотор НАЗАД
pinMode (MotorRightForward, OUTPUT); // Правый (В) мотор ВПЕРЕД
pinMode (MotorLeftBack, OUTPUT); // Левый (А) мотор НАЗАД
pinMode (MotorLeftForward, OUTPUT); // Левый (А) мотор ВПЕРЕД
delay(duration);
 
//*************** Задаем контакты датчиков полосы**************
pinMode (LineSensorLeft, INPUT); // определением pin левого датчика линии
pinMode (LineSensorRight, INPUT); // определением pin правого датчика линии
 
// ***************задаем контакты сонара**********************
pinMode(trigPin, OUTPUT); // задание режима работы вывода trig УЗ датчика
pinMode(echoPin, INPUT); // задание режима работы вывода echo УЗ датчика
}
 
// ****************** Основные команды движения ******************
void forward (int a, int sa) // ВПЕРЕД
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sa);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sa);
delay (a);
}
void right (int b, int sb) // ПОВОРОТ ВПРАВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sb);
delay (b);
}
void left (int k, int sk) // ПОВОРОТ ВЛЕВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sk);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (k);
}
void stopp (int f) // СТОП
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (f);
}
// **************************Измерение дистанции*********************
int izmdist() // измерение дистанции УЗ датчиком
{
digitalWrite(trigPin, LOW);
delay(10); // пауза перед измерением расстояния
digitalWrite(trigPin, HIGH);
delay(10);
digitalWrite(trigPin, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
dist = pulseIn(echoPin, HIGH); // считывание расстояния с УЗ датчика
delay(50);
return dist; 
}
// *********************************** LOOP *********************************
// ********************** Режим следования по ЛИНИИ *************************
void loop ()
{
// ************************ Измерение дистанции************************
  izmdist();
if (dist>MINdist) // если измеренная дистанция больше минимальной дистанции едем 
  {   
     SL = digitalRead (LineSensorLeft); // считываем сигнал с левого датчика полосы
     SR = digitalRead (LineSensorRight); // считываем сигнал с правого датичка полосы
 
      // ************************* Следование по черной линии ***********************
      // РОБОТ на полосе — едем прямо
      if (SL == LOW & SR == LOW ) // БЕЛЫЙ — БЕЛЫЙ — едем ПРЯМО
      {
      forward (10, 140);// ПРЯМО (время, скорость)
      }
      // РОБОТ начинает смещаться с полосы — подруливаем
      else if (SL == LOW & SR == HIGH) // ЧЕРНЫЙ - БЕЛЫЙ — поворот ВЛЕВО
      {
      left (10, 170);// поворот ВЛЕВО (время, скорость)
      }
      else if (SL == HIGH & SR == LOW) // БЕЛЫЙ - ЧЕРНЫЙ — поворот ВПРАВО
      {
      right (10, 170);// поворот ВПРАВО (время, скорость)
      }
     // ФИНИШ - РОБОТ видит обоими датчиками полосу
     else if (SL == HIGH & SR == HIGH) // ЧЕРНЫЙ - ЧЕРНЫЙ - СТОП
     {
     stopp (1000);// СТОП
     }
   }
else if (dist<=MINdist) // если измеренная дистанция меньше или равна минимальной - стоим
   {
     stopp (1000); // СТОП
   }
}   
 
 
Клапауций 234
Offline
Зарегистрирован: 24.10.2016

//Робот с функцией следования по черной  полосе "синей изоленте".

slava.ru38
Offline
Зарегистрирован: 28.11.2016

оч. смешно

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

1. Прочитайте и перевыложите скетч. Это не придирка, так как Вы выложили обсуждать невозможно - нет номеров строк.

slava.ru38 пишет:

программа ошибок не нашла.

Открою Вам страшный секрет, - она их и не искала :))) Она лишь проверила синтаксис. А искать ошибки - это дело программиста.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

ЕвгенийП спасибо за конструктивную критику. Сейчас попробую исправить

//Робот с функцией следования по черной  полосе 

// *********************** Установка выводов моторов ************************
int MotorLeftSpeed = 3; // Левый (А) мотор СКОРОСТЬ — ENA
int MotorLeftForward = 4; // Левый (А) мотор ВПЕРЕД — IN1
int MotorLeftBack = 5; // Левый (А) мотор НАЗАД — IN2
int MotorRightForward = 8; // Правый (В) мотор ВПЕРЕД — IN3
int MotorRightBack = 7; // Правый (В) мотор НАЗАД — IN4
int MotorRightSpeed = 9; // Правый (В) мотор СКОРОСТЬ — ENB
int duration;

// ************************установка выводов сонара*****************************
int trigPin = 14; // задание номера вывода trig УЗ датчика
int echoPin = 15; // задание номера вывода echo УЗ датчика

// ********************* Установка выводов датчиков линии *******************
const int LineSensorLeft = 19; // вход левого датчика линии
const int LineSensorRight = 18; // вход правого датчика линии
int SL; // статус левого сенсора
int SR; // статус правого сенсора

// ************************** Переменная измерение дистанции*****************
long dist; // дистанция, измеренная УЗ датчиком

//**************************** Задание параметров*****************************
int MINdist = 10; // минамальная дистанция, меньше которой робот не движется


// *********************************** SETUP ********************************
void setup ()
{
//*************** Задаем контакты моторов****************
pinMode (MotorRightBack, OUTPUT); // Правый (В) мотор НАЗАД
pinMode (MotorRightForward, OUTPUT); // Правый (В) мотор ВПЕРЕД
pinMode (MotorLeftBack, OUTPUT); // Левый (А) мотор НАЗАД
pinMode (MotorLeftForward, OUTPUT); // Левый (А) мотор ВПЕРЕД
delay(duration);

//*************** Задаем контакты датчиков полосы**************
pinMode (LineSensorLeft, INPUT); // определением pin левого датчика линии
pinMode (LineSensorRight, INPUT); // определением pin правого датчика линии

// ***************задаем контакты сонара**********************
pinMode(trigPin, OUTPUT); // задание режима работы вывода trig УЗ датчика
pinMode(echoPin, INPUT); // задание режима работы вывода echo УЗ датчика
}

// ****************** Основные команды движения ******************
void forward (int a, int sa) // ВПЕРЕД
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sa);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sa);
delay (a);
}
void right (int b, int sb) // ПОВОРОТ ВПРАВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sb);
delay (b);
}
void left (int k, int sk) // ПОВОРОТ ВЛЕВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sk);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (k);
}
void stopp (int f) // СТОП
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (f);
}
// **************************Измерение дистанции*********************
int izmdist() // измерение дистанции УЗ датчиком
{
digitalWrite(trigPin, LOW);
delay(10); // пауза перед измерением расстояния
digitalWrite(trigPin, HIGH);
delay(10);
digitalWrite(trigPin, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
dist = pulseIn(echoPin, HIGH); // считывание расстояния с УЗ датчика
delay(50);
return dist; 
}
// *********************************** LOOP *********************************
// ********************** Режим следования по ЛИНИИ *************************
void loop ()
{
// ************************ Измерение дистанции************************
  izmdist();
if (dist>MINdist) // если измеренная дистанция больше минимальной дистанции едем 
  {   
     SL = digitalRead (LineSensorLeft); // считываем сигнал с левого датчика полосы
     SR = digitalRead (LineSensorRight); // считываем сигнал с правого датичка полосы

      // ************************* Следование по черной линии ***********************
      // РОБОТ на полосе — едем прямо
      if (SL == LOW & SR == LOW ) // БЕЛЫЙ — БЕЛЫЙ — едем ПРЯМО
      {
      forward (10, 140);// ПРЯМО (время, скорость)
      }
      // РОБОТ начинает смещаться с полосы — подруливаем
      else if (SL == LOW & SR == HIGH) // ЧЕРНЫЙ - БЕЛЫЙ — поворот ВЛЕВО
      {
      left (10, 170);// поворот ВЛЕВО (время, скорость)
      }
      else if (SL == HIGH & SR == LOW) // БЕЛЫЙ - ЧЕРНЫЙ — поворот ВПРАВО
      {
      right (10, 170);// поворот ВПРАВО (время, скорость)
      }
     // ФИНИШ - РОБОТ видит обоими датчиками полосу
     else if (SL == HIGH & SR == HIGH) // ЧЕРНЫЙ - ЧЕРНЫЙ - СТОП
     {
     stopp (1000);// СТОП
     }
   }
else if (dist<=MINdist) // если измеренная дистанция меньше или равна минимальной - стоим
   {
     stopp (1000); // СТОП
   }
}   


 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

1.
проверка условия в строке 129 лишняя. Обратное условие уже проверялось в строке 103, так что куда оно нафиг денется. Оставьте только else, остальное убирайте.

2.
Зачем Вы пишете "return с;" в строке 95, если в строке 102 Вы этим не пользуетесь? К тому же , делая ненужную вещь, Вы ещё и ошибку внесли - dist у Вас long, а функция izmdist - int. В строке 86 заменяёте int на void, а строку 95 удаляйте вовсе.

А теперь по сути Вашей проблемы.

Откуда Вы взяли значение 10 для MINdist? Вы знаете, что возвращает pulseIn в строке 93? Она вовращает время в микросекундах за которое звук прошёл расстояние от датчика до препятствия и обратно. Если считать скорость звука 330м/с, то 10 соответсвует дистанции в семнадцать миллиметров. Это то, что Вы хотели? Боюсь, что нет.

А теперь общее правило. Общее - не только про эту задачу: Никогда не работайте вслепую!!!

Вот возникла у Вас проблема: переменная сравнивается не так, как Вы ожидали. Первое действие - это не писать в форум. а просто распечатать эту переменную и посмотреть на неё. Просто поставьте перед строкой 103 вывод dist в сериал и посмотрите чему эта самая dist равна. Подносите и отодвигайте препятствие и смотрите как меняется dist. Тогда Вы увидите разумное значение dist на выбранной Вами дистанции останова и вставите его в качестве значения MINdist. После этого у Вас всё нормально заработает. Удачи!

slava.ru38
Offline
Зарегистрирован: 28.11.2016

ЕвгенийП, большое Спасибо за поправки.

Насчет long и int: я пока вникаю в значение всех этих терминов и в процессы, связанные с этими терминами. Поэтому, видимо,не уловив суть определения указанных функций, допустил в программе ошибку.

По значению MINdist: считаю не критичным цифру 10. На функциональность программы это не влияет. Я намеренно занизил расстояние, чтобы проверить работу, пока вплотную не поднесешь препятствие к датчику.

Насчет работы вслепую: пока не приходилось на практике применять Serial. Теперь буду пробовать.

Буду пробовать обновленный с вашей помощью скетч

slava.ru38
Offline
Зарегистрирован: 28.11.2016

только бы вот побольше на доступном мне языке теории как вывести на экран работу функций скетча

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, какая там теория? В сетапе вызываете Serial.begin(115200); а по мере необходимости что-то напечатать пишете Serial.println(dist); Только не забудьте в окне монитора скорость правильную выставить, чтобы была такая же, как и в Serial.begin() (у меня вот выше была 115200).

slava.ru38
Offline
Зарегистрирован: 28.11.2016

тогда вопрос такой. Имеет ли значение - какую я выберу скорость? А то в большинстве (почти во всех, что я видел) скетчей стоит скорость 9600. А вы предлагаете 115200

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Нет, если Вы не собираетесь выводить часто. Если собираетесь, то вывод будет притормаживать.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

загрузил, проверил работу сонара в сериале - все показывает. но в работе робот на препятствие не реагирует, все-равно едет. Но это уже хоть что-то. До этого вообще не было движений. Буду дальше искать, где ошибка. Вот обновленный с учетом советов скетч:

//Робот с функцией следования по черной  полосе 

// *********************** Установка выводов моторов ************************
int MotorLeftSpeed = 3; // Левый (А) мотор СКОРОСТЬ — ENA
int MotorLeftForward = 4; // Левый (А) мотор ВПЕРЕД — IN1
int MotorLeftBack = 5; // Левый (А) мотор НАЗАД — IN2
int MotorRightForward = 8; // Правый (В) мотор ВПЕРЕД — IN3
int MotorRightBack = 7; // Правый (В) мотор НАЗАД — IN4
int MotorRightSpeed = 9; // Правый (В) мотор СКОРОСТЬ — ENB
int duration;

// ************************установка выводов сонара*****************************
int trigPin = 14; // задание номера вывода trig УЗ датчика
int echoPin = 15; // задание номера вывода echo УЗ датчика

// ********************* Установка выводов датчиков линии *******************
const int LineSensorLeft = 19; // вход левого датчика линии
const int LineSensorRight = 18; // вход правого датчика линии
int SL; // статус левого сенсора
int SR; // статус правого сенсора

// ************************** Переменная измерение дистанции*****************
long dist; // дистанция, измеренная УЗ датчиком

//**************************** Задание параметров*****************************
int MINdist = 1000; // минамальная дистанция, меньше которой робот не движется


// *********************************** SETUP ********************************
void setup ()
{
  Serial.begin(9600); // запускаем серийный порт (скорость 9600)
  
//*************** Задаем контакты моторов****************
pinMode (MotorRightBack, OUTPUT); // Правый (В) мотор НАЗАД
pinMode (MotorRightForward, OUTPUT); // Правый (В) мотор ВПЕРЕД
pinMode (MotorLeftBack, OUTPUT); // Левый (А) мотор НАЗАД
pinMode (MotorLeftForward, OUTPUT); // Левый (А) мотор ВПЕРЕД
delay(duration);

//*************** Задаем контакты датчиков полосы**************
pinMode (LineSensorLeft, INPUT); // определением pin левого датчика линии
pinMode (LineSensorRight, INPUT); // определением pin правого датчика линии

// ***************задаем контакты сонара**********************
pinMode(trigPin, OUTPUT); // задание режима работы вывода trig УЗ датчика
pinMode(echoPin, INPUT); // задание режима работы вывода echo УЗ датчика
}

// ****************** Основные команды движения ******************
void forward (int a, int sa) // ВПЕРЕД
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sa);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sa);
delay (a);
}
void right (int b, int sb) // ПОВОРОТ ВПРАВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sb);
delay (b);
}
void left (int k, int sk) // ПОВОРОТ ВЛЕВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sk);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (k);
}
void stopp (int f) // СТОП
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (f);
}
// **************************Измерение дистанции*********************
void izmdist() // измерение дистанции УЗ датчиком
{
digitalWrite(trigPin, LOW);
delay(10); // пауза перед измерением расстояния
digitalWrite(trigPin, HIGH);
delay(10);
digitalWrite(trigPin, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
dist = pulseIn(echoPin, HIGH); // считывание расстояния с УЗ датчика
delay(50);
}
// *********************************** LOOP *********************************
// ********************** Режим следования по ЛИНИИ *************************
void loop ()
{
// ************************ Измерение дистанции************************
  izmdist();
  Serial.println(dist);
  if (dist>MINdist) // если измеренная дистанция больше минимальной дистанции едем 
  {   
     SL = digitalRead (LineSensorLeft); // считываем сигнал с левого датчика полосы
     SR = digitalRead (LineSensorRight); // считываем сигнал с правого датичка полосы

      // ************************* Следование по черной линии ***********************
      // РОБОТ на полосе — едем прямо
      if (SL == LOW & SR == LOW ) // БЕЛЫЙ — БЕЛЫЙ — едем ПРЯМО
      {
      forward (10, 140);// ПРЯМО (время, скорость)
      }
      // РОБОТ начинает смещаться с полосы — подруливаем
      else if (SL == LOW & SR == HIGH) // ЧЕРНЫЙ - БЕЛЫЙ — поворот ВЛЕВО
      {
      left (10, 170);// поворот ВЛЕВО (время, скорость)
      }
      else if (SL == HIGH & SR == LOW) // БЕЛЫЙ - ЧЕРНЫЙ — поворот ВПРАВО
      {
      right (10, 170);// поворот ВПРАВО (время, скорость)
      }
     // ФИНИШ - РОБОТ видит обоими датчиками полосу
     else if (SL == HIGH & SR == HIGH) // ЧЕРНЫЙ - ЧЕРНЫЙ - СТОП
     {
     stopp (1000);// СТОП
     }
   }
else  // если измеренная дистанция меньше или равна минимальной - стоим
   {
     stopp (1000); // СТОП
   }
}   


 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так, а чё печатает-то? Выкладывайте

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Если вы про печать в сериале, то печатает от 200 до 15000 в зависимости от того, как близко подношу ладонь к сонару или совсем убираю и он стену видит

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

И что, при 200 или там 300, она у Вас не останавливается.

Значит возможны два варианта: либо что-то напутано таки в условии, но я пока не вижу что, либо не работает функция stopp.

Чтобы проверить какой вариант имеет место, опять же, принцип тот же (усвойте его наконец!) - не работать вслепую..

1. После строки 132 вставляем печать чего угодно (например, Serial.println("Stroka 133"); )

2. После строки 80 вставляем печать опять же чего угодно (например, Serial.println("Stroka 81"); )

3. После строки 104 вставляет печать переменной MINdist

Таким образом мы точно узнаём попадает она в функцию stopp или нет. Ведь если dist < MINdist, она обязана туда попасть. Вот и посмотрим.

Если попадает, но не останавливается - разбирайтесь почему Вы везде подали LOW, а она едет (это скорее вопрос к схеме, чем к программе). А вот если не попадает, будем думать, почему.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Большое спасибо. Завтра попробую.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

И что, при 200 или там 300, она у Вас не останавливается.

Значит возможны два варианта: либо что-то напутано таки в условии, но я пока не вижу что, либо не работает функция stopp.

Чтобы проверить какой вариант имеет место, опять же, принцип тот же (усвойте его наконец!) - не работать вслепую..

1. После строки 132 вставляем печать чего угодно (например, Serial.println("Stroka 133"); )

2. После строки 80 вставляем печать опять же чего угодно (например, Serial.println("Stroka 81"); )

3. После строки 104 вставляет печать переменной MINdist

Таким образом мы точно узнаём попадает она в функцию stopp или нет. Ведь если dist < MINdist, она обязана туда попасть. Вот и посмотрим.

Если попадает, но не останавливается - разбирайтесь почему Вы везде подали LOW, а она едет (это скорее вопрос к схеме, чем к программе). А вот если не попадает, будем думать, почему.

Вот так - ненавязчиво, шаг за шагом и научите нас правильному тону! Снимаю шляпу!

slava.ru38
Offline
Зарегистрирован: 28.11.2016

схема скорее всего правильная, так как робот встает при сигнале HIGH на обоих датчиках линии. Но не буду, усвоив урок о работе вслепую что-либо утверждать. Надо проверить.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Постаил сериал в указанные строки и результат таков:

монитор порта при сигнале LOW на датчиках линии:

10569

1000

stroka81

10564

1000

stroka81

.......

при сигнале HIGH на датчиках линии:

8234

1000

8156

1000

......

при сигнале HIGH на датчикеах линии и перпятствии меньше установленного минимума:

547

1000

stopp

stroka81

.......

вроде все правильно

Что-то я вообще ничего не понял. Сейчас после введения сериала в указанные строки и мониторинга проверил робота снова - все работает. Странно - ведь толком программу не менял. Я в шоке.

Ну да и ладно. Спасибо ЕвгенийП за помощь.

 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

хотя нет. Кое-какие изменения внес: в строке 128 поставил 50, а в строке 133 - 100

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Добавив некоторые дополнительные возможности своего робота, получился робот, который, используя 2 датчика линии, должен двигатся по светлой линии. При движении мигает светодиод, выполняя функцию световой сигнализации включенного состояния робота. Поставил 3 датчика препятствия HC-SR-04

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

    Проблемы: Робот во время схода одним датчиком линии со светлой линии не успевает среагировать и включить левый( ну или правый) ход. Из-за чего сходит с линии и соответственно встает. Либо если все-таки успевает среагировать на сход с линии и включая левый (ну или правый) ход, то при возврате на линию может не успеть включить ход "вперед" и соответственно поворот продолжается и выводит робота с линии. Что соответственно приводит к полному сходу с линии и его остановке.

    Попробовал оставить один датчик препятствия. Стало получше. Стал успевать реагировать на сход с линии. Но все равно с запаздыванием.

  Вопрос:   - почему такое происходит?

               - можно ли это исправить?

 Я так понимаю, что процесс измерения расстояния отнимает время, во время которого ардуино не принимает информацию от датчиков линии и соответственно не реагирует ни изменение их статуса?

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

Думал исправить это остановкой робота на время, необходимое для измерения расстояния,но желательно, чтобы робот во время измерения расстояния не останавливался. 

Вот скетч с тремя датчиками препятствия:

 

 

slava.ru38
Offline
Зарегистрирован: 28.11.2016
//Робот с функцией следования по белой полосе

// **********************Установка выводов моторов ************************
int MotorLeftSpeed = 5; // Левый (А) мотор СКОРОСТЬ — ENA
int MotorLeftForward = 4; // Левый (А) мотор ВПЕРЕД — IN1
int MotorLeftBack = 3; // Левый (А) мотор НАЗАД — IN2
int MotorRightForward = 8; // Правый (В) мотор ВПЕРЕД — IN3
int MotorRightBack = 7; // Правый (В) мотор НАЗАД — IN4
int MotorRightSpeed = 9; // Правый (В) мотор СКОРОСТЬ — ENB
int duration;

// **********************Установка выводов УЗ датчиков***********************
int trigPinL = 14; // задание номера вывода левого trig УЗ датчика
int echoPinL = 15; // задание номера вывода левого echo УЗ датчика
int trigPinC = 10; // задание номера вывода центрального trig УЗ датчика
int echoPinC = 11; // задание номера вывода центрального echo УЗ дачика
int trigPinR = 12; // задание номера вывода правого trig УЗ датчика
int echoPinR = 13; // задание номера вывода правого echo УЗ датчика

// ********************* Установка выводов датчиков линии *******************
const int LineSensorLeft = 19; // вход левого датчика линии
const int LineSensorRight = 18; // вход правого датчика линии
int SL; // статус левого сенсора
int SR; // статус правого сенсора

// *********************Установка выввода световой и звуковой сигнализации**************
int Light = 2; // задание номера вывода световой сигнализации
int ledState = LOW; // этой переменной устанавливаем состояние светодиода
long previousMillis = 0; // храним время последнего переключения светодиода
long interval = 300; // интервал между включение/выключением светодиода (1 секунда)

// *********************Переменная измерение дистанции датчиками*************

unsigned int impulseTimeL=0;
unsigned int impulseTimeC=0;
unsigned int impulseTimeR=0;
long distL=0; // дистанция, измеренная левым УЗ датчиком
long distC=0; // дистанция, измеренная центральным УЗ датчиком
long distR=0; // дистанция, измеренная правым Уз датчиком


// *********************************** SETUP ********************************
void setup ()
{
Serial.begin(9600); // запускаем серийный порт (скорость 9600)

//*************** Задаем контакты моторов****************
pinMode (MotorRightBack, OUTPUT); // Правый (В) мотор НАЗАД
pinMode (MotorRightForward, OUTPUT); // Правый (В) мотор ВПЕРЕД
pinMode (MotorLeftBack, OUTPUT); // Левый (А) мотор НАЗАД
pinMode (MotorLeftForward, OUTPUT); // Левый (А) мотор ВПЕРЕД
delay(duration);

//*************** Задаем контакты датчиков полосы**************
pinMode (LineSensorLeft, INPUT); // определением pin левого датчика линии
pinMode (LineSensorRight, INPUT); // определением pin правого датчика линии


// ***************Задание режимов выводов УЗ датчиков**********************

pinMode(trigPinL, OUTPUT); // задание режима работы вывода левого trig УЗ датчика
pinMode(echoPinL, INPUT); // задание режима работы вывода левого echo УЗ датчика
pinMode(trigPinC, OUTPUT); // задание режима работы вывода центрального trig УЗ датчика
pinMode(echoPinC, INPUT); // задание режима работы вывода центрального echo УЗ датчика
pinMode(trigPinR, OUTPUT); // задание режима работы вывода правого trig УЗ датчика
pinMode(echoPinR, INPUT); // задание ражима работы вывода правого echo УЗ датчика


// ***************Задаем контакты световой сигнализации********************************

pinMode(Light,OUTPUT); // задание режима работы вывода световой сигнализации
}

// ****************** Основные команды движения ******************
void forward (int a, int sa) // ВПЕРЕД
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sa);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sa);
delay (a);
}
void right (int b, int sb) // ПОВОРОТ ВПРАВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sb);
delay (b);
}
void left (int k, int sk) // ПОВОРОТ ВЛЕВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sk);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (k);
}
void stopp (int f) // СТОП
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (f);
}

// **************************Измерение дистанции*********************

void izmdistL() // измерение дистанции левым УЗ датчиком
{
digitalWrite(trigPinL, HIGH);
delay(10);
digitalWrite(trigPinL, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
impulseTimeL = pulseIn(echoPinL, HIGH); // считывание расстояния с УЗ датчика
distL=impulseTimeL/58; // Пересчитываем в сантиметры
delay(50);
}

void izmdistC() // измерение дистанции центральным УЗ датчиком
{
digitalWrite(trigPinC, HIGH);
delay(10);
digitalWrite(trigPinC, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
impulseTimeC = pulseIn(echoPinC, HIGH); // считывание расстояния с УЗ датчика
distC=impulseTimeC/58; // Пересчитываем в сантиметры
delay(50);
}

void izmdistR() // измерение дистанции центральным УЗ датчиком
{
digitalWrite(trigPinR, HIGH);
delay(10);
digitalWrite(trigPinR, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
impulseTimeR = pulseIn(echoPinR, HIGH); // считывание расстояния с УЗ датчика
distR=impulseTimeR/58; // Пересчитываем в сантиметры
delay(50);
}

// *********************************** LOOP *********************************
// ********************** Режим следования по ЛИНИИ *************************
void loop ()
{
// *********************световая и звуковая сигнализация**************

unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) //проверяем не прошел ли нужный интервал, если прошел то
{
previousMillis = currentMillis; // сохраняем время последнего переключения
if (ledState == LOW) // если светодиод не горит, то зажигаем, и наоборот
ledState = HIGH;
else
ledState = LOW;
digitalWrite(Light, ledState); // устанавливаем состояния выхода, чтобы включить или выключить светодиод
}

// ************************ Измерение дистанции************************
izmdistL();
izmdistC();
izmdistR();
Serial.println(distL);
Serial.println(distC);
Serial.println(distR);
if (distL>50 && distC>50 && distR>50) // если измеренная дистанция больше 50 сантиметров - едем
{
SL = digitalRead (LineSensorLeft); // считываем сигнал с левого датчика полосы
SR = digitalRead (LineSensorRight); // считываем сигнал с правого датичка полосы

// ************************* Следование по черной линии ***********************
// РОБОТ на полосе — едем прямо
if (SL == LOW & SR == LOW ) // БЕЛЫЙ — БЕЛЫЙ — едем ПРЯМО
{
forward (10, 90);// ПРЯМО (время, скорость)
}
// РОБОТ начинает смещаться с полосы — подруливаем
else if (SL == LOW & SR == HIGH) // ЧЕРНЫЙ - БЕЛЫЙ — поворот ВЛЕВО
{
left (10, 90);// поворот ВЛЕВО (время, скорость)
}
else if (SL == HIGH & SR == LOW) // БЕЛЫЙ - ЧЕРНЫЙ — поворот ВПРАВО
{
right (10, 90);// поворот ВПРАВО (время, скорость)
}
// ФИНИШ - РОБОТ видит обоими датчиками полосу
else if (SL == HIGH & SR == HIGH) // ЧЕРНЫЙ - ЧЕРНЫЙ - СТОП
{
stopp (50);// СТОП
}
}
else // если измеренная дистанция меньше или равна минимальной - стоим
{
stopp (100); // СТОП
}
}


 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Вам скорость звука известна?

Прикинтьте, на каком расстоянии Вам нужно обнаруживать препятствие и задавайте таймаут для PulseIn в соответствии с рассчитанным временем.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Скорость звука мне известна. Непонятна ваша мысль про таймаут для PulseIn. Мне нужно будет останавливать робота на время, необходимое процессу PulseIn, высчитавающему заданное мной расстояние? И только после этого продолжать движение? 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

    Где читал, не помню, что во время PulseIn микроконторллер слеп и глух, не воспринимает сигналы внешних датчиков. Так ли это? 

   Если да, то значит ли, что пользуясь тремя датчиками, у которых свой PulseIn, я увеличиваю продолжительность слепоты в 3 раза. Или все 3 процесса происходят в одно время? 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Либо нужно уходить от delay. Везде, где он используется - использовать millis. Кто как думает?

MacSim
Offline
Зарегистрирован: 28.11.2012

http://arduino.ru/Reference/PulseIn

часть делеев вообще можно убрать, а местами без паузы и не обойтись.

Работайте с 3-мя сразу используя прямой доступ к портам. Не разбирался к какому порту они у вас подключены, но лучше повесьте все на один порт. От использования пульсеин естественно придется отказаться. Как вариант возможно использование милис, а можно и другой таймер запускать, что думаю лучше будет (большей точности можно добиться). т.е. посылайте уз сразу с трех, читайте  порт пока не приедет 1,1,1 , а можно только первой. по приходу читайте таймер (или 3 раза), останавливайте и обнуляйте Т. думаю получится быстрее, возможно придется вносит изменения в конструкцию, чтоб не было влияния датчиков друг на друга.

а можно и один датчик использовать, поворачивая его. локатор видели? 

зы: а внизу ссылки "Справочник языка ардуино". Во! оказывается дуиноделы новый язык придумали, а я и не знал. гы-гы :-)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

slava.ru38 пишет:

Либо нужно уходить от delay. Везде, где он используется - использовать millis. Кто как думает?

То что от delay() в серьезных проектах это понятно. Другое дело, не все новички умеют пользоваться millis(),micros(). PulseIn тоже не айс.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

MacSim пишет:

часть делеев вообще можно убрать, а местами без паузы и не обойтись.

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

 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

MacSim пишет:

Работайте с 3-мя сразу используя прямой доступ к портам. Не разбирался к какому порту они у вас подключены, но лучше повесьте все на один порт. От использования пульсеин естественно придется отказаться. Как вариант возможно использование милис, а можно и другой таймер запускать, что думаю лучше будет (большей точности можно добиться). т.е. посылайте уз сразу с трех, читайте  порт пока не приедет 1,1,1 , а можно только первой. по приходу читайте таймер (или 3 раза), останавливайте и обнуляйте Т. думаю получится быстрее, возможно придется вносит изменения в конструкцию, чтоб не было влияния датчиков друг на друга.

а можно и один датчик использовать, поворачивая его. локатор видели? 

зы: а внизу ссылки "Справочник языка ардуино". Во! оказывается дуиноделы новый язык придумали, а я и не знал. гы-гы :-)

1. Правильно ли я понял, что все на один порт  -это соединить разьемы трех датчиков параллельно и посадить на один порт? Не думал, что так можно.

2. через один датчик на серве прошел уже - вариант не сойдет. Все равно 3 раза приходится замерять расстояние , сравнивать с заданным и затем действовать в согласии с измеренным расстоянием. Уж лучше 3 одновременно.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

qwone пишет:

 Другое дело, не все новички умеют пользоваться millis(),micros(). PulseIn тоже не айс.

На а что теперь делать новичкам? Вот и приходится спрашивать совета зрелых и бывалых, просить подсказок и надеяться на помощь.

А чем PulseIn не айс?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

slava.ru38 пишет:

Скорость звука мне известна. Непонятна ваша мысль про таймаут для PulseIn. Мне нужно будет останавливать робота на время, необходимое процессу PulseIn, высчитавающему заданное мной расстояние? И только после этого продолжать движение? 

О-хо-хох...

Т.е. скорость звука Вы знаете, но арифметика Вам неизвестна и читать Вы не умеете.

Ладно, сделаю это за Вас.

1. Внимательно читаем документацию: http://arduino.ru/Reference/PulseIn , где узаем, чьл функцию можно вызвать либо с двумя, либо с тремя параметрами. Последний - таймаут, по умолчанию 1 секунда. Т.е. если мы не задаем таймаут, наша тележка ровно секунду послде вызова команды будет неуправляемо двигаться по инерции. Если, скажем, ее скорость 0.5 м/с, то за это время она может уйти на 0.5 м от линии.

2. За секунду звук успеет дойти до препятствия на расстоянии 170 м, отразиться от него и вернуться обратно. Но у нашего датчика недостаточно чувствительности, чтобы почувствовать препятствие на расстоянии 170 м. Для него предел - где-то около 2 м. А звук проходит 4 метра (туда и обратно) примерно за 12 мс. Стало быть, абсолютно бессмысленно задавать величину таймаута бошлее 12 мс. Кстати, тележка за это время пройдет всего 6 мм, т.е. просто не успеет сойти с линии.

3. Если нам кажется, что и 12 мс слишком ного, можно вообще задаьбся расстоянием, скажем, 40 см - вполне достаточно, чтобы заметить препятствие и отвернуть в сторону. Тогда нам нужнор задавать таймаут всего 2.5 мс. Отклонгение тележки за это время не будет превосходить 1.2 мм.

4. Для того, чтобы это все посчитать вполне достаточно курса средней школы. Но главное - это решение задачи, не выходя за пределы концепции Ардуино. ВЫ протичном случае можно сменить концепцию с Ардуино на AVR: прочитать дэйташит и самому написать неблокирующий аналог PulseIn, как Вам уже советовали ывше.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

   Уважаемый andriano, спасибо, что разжевали. Повторюсь: с ардуино знаком только недавно, с программирование тоже стал знакомиться в связи со знакомством с ардуино. До этого работал только с паяльником и схемами. Следовательно все термины, связанные с программированием слышу впервые и поэтому нужно для их осмысления больше времени, чем например вам. Да и без посторонней помощи это было бы еще дольше. А ссылка http://arduino.ru/Reference/PulseIn у меня закреплена во вкладках - постоянно читаю. Просто там все кратко и без обьяснений. И поэтому не всегда ясно, что там имеется ввиду и как понимать то или иное выражение.

  А вот спасибо вам - немного раскрыли момент при PulseIn. Например только сейчас догнал, что если препятствия не будет ближе, чем способен увидеть датчик, то ожидание сигнала составит 1 сек. Поэтому нужно сразу установить ограничение по времени ожидания сигнала ровно на такую величину, на которой я ожидаю увидеть препятствие.В моем случае это 50 см и соответственно время ожидание 3 мс.

  Надеюсь правильно все понял. Но есть другой вопрос, который еще не осмыслил - если delay стоит не в LOOP, а в SETUP, тормозит ли она программу?

  Если нет, то как определять нужную продолжительность?

  Если да, то ее необходимо тоже заменить в настройках работы мотора forward, left, right?

slava.ru38
Offline
Зарегистрирован: 28.11.2016

И еще: не совсем понятно обьяснение принципа действия датчика препятствия и процесса измерения расстояния. Позвольте я сформулирую так, как понял это я. и если ошибаюсь или чего-то не до сказал - поправьте и дополните.

    Итак: на вывод trigg подается с выхода ардуино сигнал длительностью 10 мс. Этот сигнал в датчике разбивается на пачку из 8 УЗ импульсов 40кГц и посылается вперед.

И в это же самое время, сразу после подачи этих импульсов, на выводе ECHO появляется сигнал HIGH, который у нас подключен ко входу ардуино. И функция PulseIn начинает считать его продолжительность. А продолжаться по времени этот сигнал HIGH будет ровно столько, сколько пачка импульсов 40кГц будет идти до препятствия, отразиться от него и вернется в приемник датчика. И тут же сигнал HIGH c вывода ECHO исчезает. Фунция PulseIn считает это момент концом отсчета.

Т.о это время и есть время которое ультразвук преодолел, начиная свой долгий путь от излучателя датчика до препятствия и обратно домой - в приемник датчика. Но следует учесть, что в данном датчике ультразвук способен вернуться обратно только отразившись  от препятствия, находящегося не больше 5 метров. Если препятствие находится далее 5 метров - датчик их не увидит и соответственно сигнал либо не дойдет до него, либо отразившись - не дойдет обратно из-за недостаточно сильного сигнала.

И тут случится оказия: появившийся на выводе ECHO сигнал HIGH так и не исчезнет. Но оказывается не тут-то было. Разработчики датчика препятствия установили ограничение по времени наличия сигнала HIGH на выводе ECHO, которое равно 1 сек. Т.о. не встретив препятствия, через секунду после излучения пачки импульсов 40кГц сигнал HIGH исчезает с вывода ECHO.Но и получается, что ардуино все это долгое для него время (1сек) ждал ответа, из-за чего вся его другая деятельность, связанная с работой других датчиков была парализована.

Но если в функции PulseIn регламентировать время возврата отразившейся от препятствия пачки импульсов 40кГц с помощью переменной timeout, то ардуино будет ждать не секунду, а столько, сколько мы указали. 

Подскажите, все ли правильно я для себя уяснил. И если да, то хотелось хотя бы примерно вот такого развернутого объяснения терминов.

MacSim
Offline
Зарегистрирован: 28.11.2012

slava.ru38 пишет:

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

 

не делеев, а пауз. с уз излучателя должна уйти волна в течении N-ного времени. у вас это 10 мс. можно конечно и на милис переписать, но не критично.

121,131,141 зачем там пауза?

MacSim
Offline
Зарегистрирован: 28.11.2012

slava.ru38 пишет:

1. Правильно ли я понял, что все на один порт  -это соединить разьемы трех датчиков параллельно и посадить на один порт? Не думал, что так можно.

 

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

у мк есть порты PORT A, PORT B и тд. это 8 битные регистры ввода вывода. в порт можно записать байт и значение получиться сразу на 8 ногах. Так же и читать его можно 8 - ног за раз.

 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

MacSim пишет:

[не делеев, а пауз. с уз излучателя должна уйти волна в течении N-ного времени. у вас это 10 мс. можно конечно и на милис переписать, но не критично.

121,131,141 зачем там пауза?

Про 121, 131, 141 сам не знаю. Исправлю. Меня интересует смысл и необходимая продолжительность 83, 92, 101, 109, 196

slava.ru38
Offline
Зарегистрирован: 28.11.2016

MacSim пишет:

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

у мк есть порты PORT A, PORT B и тд. это 8 битные регистры ввода вывода. в порт можно записать байт и значение получиться сразу на 8 ногах. Так же и читать его можно 8 - ног за раз.

Подскажите пожалуйста , где можно почитать про это

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

не надо пока вам читать про порты. Заставьте двигаться робота, оно и без этого поедет вполне нормально при правильном коде.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

slava.ru38 пишет:

...с ардуино знаком только недавно, с программирование тоже стал знакомиться в связи со знакомством с ардуино. До этого работал только с паяльником и схемами. Следовательно все термины, связанные с программированием слышу впервые и поэтому нужно для их осмысления больше времени, чем например вам. Да и без посторонней помощи это было бы еще дольше. А ссылка http://arduino.ru/Reference/PulseIn у меня закреплена во вкладках - постоянно читаю. Просто там все кратко и без обьяснений. И поэтому не всегда ясно, что там имеется ввиду и как понимать то или иное выражение.

1. То, что я писал, никакого отношения к Ардуино не имеет - исключительно школьный курс физики.

2. Описание http://arduino.ru/Reference/PulseIn действительно не просто излишне краткое, а просто неполное, не описывающее некоторых тонкостей, в результате чего может сложиться просто неверное понимание. Рекомендую англоязычную документацию, по крайней мере, PulseIn там описана лучше. Подозреваю, что и другие тоже.

Цитата:

  Надеюсь правильно все понял. Но есть другой вопрос, который еще не осмыслил - если delay стоит не в LOOP, а в SETUP, тормозит ли она программу?

 

delay предназначена именно для того, чтобы тормозить программу. Соответственно, везде, где мы ее вызываем, она тормозит. Другое дело, что setup выполняется 1 раз, а loop - постоянно. Поэтому delay в setup, как правило, используются, даже если в loop их полностью избегают.

Остальных вопросов в этом сообщении не понял.

По следующему сообщению.

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

Из неточностей: там, где Вы пишете про 10 мс, мне кажется, должно быть 10 мкс.

И то, что Вы понимаете явно неправильно: таймаут - это свойство функции PulseIn, к датчику оно никакого отношения не имеет. Кстати, если бы имело, то Ардуино не могла бы понять, когда принят сигнал, а когда наступил таймаут. Но т.к. таймаут происходит именно внутри Ардуины, она знает, что именно произошло и в случает сигнала - возвращает длительность, а в случае таймаута - 0. Если бы датчик сам срабатывал по таймауту, Ардуина бы возвращала длину импульса датчика, а не 0.

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

1. Давайте для начала таки разберемся с работой узв. датчика. Его алгоритм работы достаточно прост: по сигналу на входе trig он запускает 8 коротких посылок ультразвуком из пищалки, после чего выставляет высокий уровень на выходе echo и как только прилетает обратное эхо он сбрасывает в 0 выход echo. Всё.

Соответственно, управление им это отправка короткого (10 микросекунд) импульса на ногу trig, ожидание установки в 1 ноги echo и замер времени до сброса ноги echo в 0 снова. Или выход по таймауту - "не дождалися". Заметьте что echo может так и остаться в состоянии 1! Соответственно в начальный этап управления надо внести исправление, а именно проверять после отправки сигнала trig перешло ли состояние echo в 0 или "зависло".

Далее. Скорость звука 335 м/сек для Н.У. (760мм.рт.ст., +20 градусов Цельсия, приповерхностная плотность воздуха). Или 335 миллиметров за миллисекунду. Да, ещё он летит "туда и обратно", соответственно можно считать что его скорость в 2 раза ниже, т.е. 167.5 мм/мсек. Предельная дальность по чувствительности этого датчика составляет около 5м, что дает 5000/167.5 = 29,85мсек., как максимальный период ожидания эха или "таймаут". Ждать дольше 30-35мсек - нет никакого смысла.

Ещё надо заметить, что для обратного преобразования в расстояние Вы зачем-то делите вычисленное время на 58 (иногда делят на 59), в то время как операции целочисленного деления у Ардуино нет и в помине, а деления вещественных чисел нет как класса чисел и вовсе. Куда как полезнее делить на такие чиселки, которые являются степенями двойки, чтобы заменить деление сдвигами. Если предварительно умножить нашу скорость в 0.335 мм/мксек на скажем 1024, то получим константу 343.040, что мало отличается от 343 (0,012%!) и, в этом случае мы можем измеренное время в микросекундах домножить на эту константу и поделить на 1024, а поскольку "туда и обратно", то на 2048 что куда как экономичнее и быстрее делается Арудиной! Кто и с какого перепою предложил делить на 58 - ума не приложу, каким надо быть безграмотным программистом.

Да, не забываем проверять "граничные значения": макс. дальность это 5м. или 29850 микросекунд на ожидание. 29850 *343 = 10238550 это меньше чем long, так что в разрядную сетку длинных целых влезает запросто. 10238550/2048 = 4999,29мм или ошибка на коце диапазона из-за целочисленного вычисления составляет около 0,014%. Мне кажется что точность до 0.7мм в конце диапазона - это более чем достаточно. :)

И того, окончательный вариант подпрограммы с использованием pulseIn() может выглядеть примерно так:

/**
 * Функция замера расстояния через wiring::pulseIn() датчиком HCSR-04
 * с максимальным временем ожидания в 30мсек.
 * Для удобства применения имеет одинаковое время исполнения = timeout
 * независимо от времени вычисления расстояния
 * 
 * @param trigPin   -- номер ноги trig датчика
 * @param echoPin -- номер ноги echo датчика
 * @param timeout -- задаваемое время ожидания измерения в микросекундах < 30000!
 *
 * @return int (millimeters 0..5000)
 * @author Arhat109-20161224
 */
int getDistance( uint8_t trigPin, uint8_t echoPin, int timeout)
{
  uint8_t   _isMeasured = 1;
  int       time;

  digitalWrite(trigPin, HIGH);                        // trigPin = 1 на 10мксек
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  for( time = 20; time>0; time--){                    // ждем, если echo ещё не сброшено в 0. Недолго.
    if( digitalRead(echoPin) == 0 ){
      _isMeasured = 0;
      break;
    }
    delayMicroseconds(1);
  }
  if( isMeasured ){                                   // можно измерять, сигнал echo=0

    time = (int)pulseIn( echoPin, timeout+time );     // нет никакого смысла получать long, выравниваем время работы
    timeout -= time;                                  // остаток времени от замера, пригодится.

    if( timeout <= 0 ){ time=5000; }                  // препятствие дальше чем таймаут..
    else{
      time = (int)(343UL * (uint32_t)time / 2048);    // вычисляем в длинных целых с результатом в миллиметрах
    }
  }else{
    time=5000;
  }

  while( timeout>0 ){ delayMicroseconds(1); }         // выравниваем время исполнения до timeout

  return time;
}

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

Для самокатной тележки надо помнить, что во время измерения никаких иных действий оно делать НЕ БУДЕТ, соответственно его надо ставить как можно меньше.

И второе. Если собираетесь измерять расстояния с малым временем, скажем по 4мсек (вполне достаточно для обнаружения препятствий и не сильно мешает управлению), то НЕ ЗАБУДЬТЕ что эхо вполне может прилететь и от предыдущего запуска, ибо оно "гуляет" по полю не менее 30мсек пока не затухнет.. не стоит измерять чаще чем 1 раз в 35мсек. :)

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

P.S. Приведенный код - всего лишь пример как можно измерять расстояния не сильно мешая управлению, и проверяя корректность работы датчика. Он конечно же НЕ проверялся и даже не компилировался. Приведен как демонтсрация идеи и только. Скорее всего, он даже замерять будет неверно, поскольку задержки по 1мксек в циклах, да ещё и с вызовом wiring-функций .. это конечно нонсенс и время работы будет сильно искажено. Для нормальной работы надо скорее всего микроздержки ставить по 3-5-10мксек и соответственно изменять код, чтобы кривизна wiring сказывалась как можно меньше.

Ещё лучше этуработу переложить на прерывание и измерять длительность импульса обработчиком прерываний, скажем PCINT вполне годится. Он, кстати, вполне будет способен измерять дальность хоть от 8-и датчиков и даже одновременно и совершенно не влияя на работу цикла управления... но, это уже иной уровень программирования. :)

slava.ru38
Offline
Зарегистрирован: 28.11.2016

andriano пишет:

delay предназначена именно для того, чтобы тормозить программу. Соответственно, везде, где мы ее вызываем, она тормозит. Другое дело, что setup выполняется 1 раз, а loop - постоянно. Поэтому delay в setup, как правило, используются, даже если в loop их полностью избегают.

Остальных вопросов в этом сообщении не понял.

Насчет того, для чего delay предназначена, чтобы тормозить программу- это я понял. Я не понял смысл этого. Зачем нужно тормозить программу? Нельзя  ли без торможения, операция за операцией?

 

 Насчет остальных вопросов: раз уж и нужна эта delay, хоть я пока не понимаю - зачем, то сколько ей уделять времени? какую продолжительность ставить в конкретных случаях? Есть ли общий принцип, который помогает определять сколько нужно времени для паузы?

slava.ru38
Offline
Зарегистрирован: 28.11.2016

andriano пишет:

Из неточностей: там, где Вы пишете про 10 мс, мне кажется, должно быть 10 мкс.

И то, что Вы понимаете явно неправильно: таймаут - это свойство функции PulseIn, к датчику оно никакого отношения не имеет. Кстати, если бы имело, то Ардуино не могла бы понять, когда принят сигнал, а когда наступил таймаут. Но т.к. таймаут происходит именно внутри Ардуины, она знает, что именно произошло и в случает сигнала - возвращает длительность, а в случае таймаута - 0. Если бы датчик сам срабатывал по таймауту, Ардуина бы возвращала длину импульса датчика, а не 0.

 

Пардон опечатка. Конечно же в данном параметре 10 мкс.

 

Вероятно заговорился. Конечно же, разработчики не датчика, а мк. Таймаут заложен в ардуино, а не в датчике. И одновременно с  началом сигнала HIGH на ECHO,  включается время по таймауту. Если не регламертировно, то 1 сек. Если указано, то установленное.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Arhat109-2 пишет:

Ещё надо заметить, что для обратного преобразования в расстояние Вы зачем-то делите вычисленное время на 58 (иногда делят на 59), в то время как операции целочисленного деления у Ардуино нет и в помине, а деления вещественных чисел нет как класса чисел и вовсе. Куда как полезнее делить на такие чиселки, которые являются степенями двойки, чтобы заменить деление сдвигами. Если предварительно умножить нашу скорость в 0.335 мм/мксек на скажем 1024, то получим константу 343.040, что мало отличается от 343 (0,012%!) и, в этом случае мы можем измеренное время в микросекундах домножить на эту константу и поделить на 1024, а поскольку "туда и обратно", то на 2048 что куда как экономичнее и быстрее делается Арудиной! Кто и с какого перепою предложил делить на 58 - ума не приложу, каким надо быть безграмотным программистом.

Уважаемый Arhat109-2, спасибо за подробности и глубинные нюансы. Насчет деления - согласен, что умножение ардуино выполнит быстрее. А деление на 58 - это образец на разных сторонних сайта, где приводили примеры перевода времени в сантиметры. Вот я и воспользовался. Другого способа не знал. Сечас постараюсь по вашему совету исправить.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

slava.ru38 пишет:

Есть ли общий принцип, который помогает определять сколько нужно времени для паузы?

Диалог из фильма Кин-дза-дза:

- Ну, это на глаз.
- Дикари!