Запись данных с сонора при разных положениях сервы.

trunker
Offline
Зарегистрирован: 05.05.2012
#include <Ultrasonic.h>
Ultrasonic ultrasonic(2, 13);
#include <Servo.h>
Servo  servoMain;
#include <AFMotor.h>
 int LeftStat(0);
 int FrontStat(0);
 int RightStat(0);
 float Stat(0);
 int servotime(1000);
 void setup()
  {
    servoMain.attach(9);
     Serial.begin(9600);
    
  }

void servoLeft(){
 servoMain.write(0);
}
void servoFront(){
 servoMain.write(90);
 }
void servoRight(){
 servoMain.write(180);}
void loop(){
   
{Stat=ultrasonic.Ranging(CM);
Serial.println(LeftStat);
{servoLeft(); // считываем значение сонора слева
delay(servotime);}

{servoRight();// считываем значение справа
delay(servotime);
}
{servoFront(); //считываем значение сонора в переди

delay(servotime);
}
{if (Stat==0)
{(Stat=LeftStat);}
if (Stat==90)
{(Stat=FrontStat);}
if (Stat==180)
{(Stat=RightStat);}}}
}

В общем попытался сделать так что бы при каждом положение сервы данные заносились в отдельные переменные, но что то не выходит, я не очень хорошо знаю программирование, но смысл понял, в общем при печате какой либо из переменных они все раны нулю. ну кроме Stat.
Подскажите пожалуйста как добиться нужного результата? 
rusel6
Offline
Зарегистрирован: 07.02.2012

Поддержую! так как самому нунжно такое делать скоро

trunker
Offline
Зарегистрирован: 05.05.2012

В общем та это чась кода от задуманного робота.

Смысл такой.

Записываем переменные со всех сторон,

Возврашаем сонар в положение прямо,

Выбираем переменную с максимальным значением,

Если это справа(или слева), то разворачиваемся в право(лево), до тех пор пока не получим входное значение с сонора равное или +- какой то процент, 
 

Движемся Вперед, до тех пор пока показание с сонора не достигнут минимума (определенное значение),

Повторяем цикл.

В общем что то такое хотелось бы

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Не совсем понял смысл.

Но ничего сложного не вижу.

Поворачиваете серву на заданый угол - опрашиваете датчик - присваиваете его показания переменной

соотсветствующей этому положению.  И так для всех трех положений.

Далее (исходя из имеющихся данных) производите вычисление оптимальной траектории движения бота.

trunker
Offline
Зарегистрирован: 05.05.2012

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

а можно пример, кусок кода?

я вот как то так попробовал но не получается(

{servoRight();
(Stat=RightStat);
delay(servotime);

 

Вроде бы должно быть все правильно? но с RightStat идут нули Stat - это переменная с данными сонора.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

 

#include <Servo.h> 

Servo myservo;

void setup() 
{ 
  myservo.attach(9);
   
} 

void loop() 
{

myservo.write(0);//поворачиваем серву вправо
right=analogRead(14);//читаете ваш датчик
delay(1000);

myservo.write(90);//поворачиваем серву по центру
center=analogRead(14);//читаете ваш датчик
delay(1000);


myservo.write(180);//поворачиваем серву влево
left=analogRead(14);//читаете ваш датчик
delay(1000);



}

 

 

 

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

А вообще так извращаться смысла особо нет.

Мой робот и без того находил "куда ехать" и не застревал. 

leshak
Offline
Зарегистрирован: 29.09.2011
  1.  А что значит конструкция вида "int RightStat(0);"? Что вы хотели этим нулем сказать?
  2.  Переменную RightStat вы только читаете, но нигде, никода в нее ничего не записываете. Логично что она всегда равна нулю.
  3.  Показание сонара, вы читаете в переменную Stat, но потом нигде не используете, тут же заменяете это значение данными из других переменных
  4. Такое впечатление, что фигурные и круглые скобки вы расставляете случайно. Подбираете такую комбинацию лиш бы компилятор не ругался. http://arduino.ru/Reference/Braces

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Да и еще.

Логичней было-бы действовать

  1. Дал команду на поворот сервы
  2.  Подождал какое-то время (что-бы успела повернутся)
  3. Прочитали показания  сонара

Вы же, похоже, пыталсиь

  1.  Дать команду сервер
  2. Прочитать значение сонара
  3. Ждать  (только теперь непонятно чего).
trunker
Offline
Зарегистрирован: 05.05.2012

leshak пишет:

  1.  А что значит конструкция вида "int RightStat(0);"? Что вы хотели этим нулем сказать?
  2.  Переменную RightStat вы только читаете, но нигде, никода в нее ничего не записываете. Логично что она всегда равна нулю.
  3.  Показание сонара, вы читаете в переменную Stat, но потом нигде не используете, тут же заменяете это значение данными из других переменных
  4. Такое впечатление, что фигурные и круглые скобки вы расставляете случайно. Подбираете такую комбинацию лиш бы компилятор не ругался. http://arduino.ru/Reference/Braces

 


 

1. Это начальное значение переменной. Не правильно?

2. Все, понял основную ошибку, надо местами поменять переменные...

leshak
Offline
Зарегистрирован: 29.09.2011

trunker пишет:

 

1. Это начальное значение переменной. Не правильно?

http://arduino.ru/Tutorial/Variables

trunker
Offline
Зарегистрирован: 05.05.2012
#include <Ultrasonic.h>
Ultrasonic ultrasonic(2, 13);
#include <Servo.h>
Servo  servoMain;
#include <AFMotor.h>
 AF_DCMotor motor(1);
 AF_DCMotor motor2(2);
 AF_DCMotor motor3(3);
 AF_DCMotor motor4(4);
 float LeftStat=0;
 float FrontStat=0;
 float RightStat=0;
 float Stat=0;
 int servotime=1000;
 void setup()
  {
    servoMain.attach(9);
     Serial.begin(9600);
   
  }
void Forvard()
{motor.run(FORWARD);
motor.setSpeed(255);
motor2.run(FORWARD);
motor2.setSpeed(255);
motor3.run(FORWARD);
motor3.setSpeed(255);
motor4.run(FORWARD);
motor4.setSpeed(255);}
void Back()
{motor.run(BACKWARD);
motor.setSpeed(255);
motor2.run(BACKWARD);
motor2.setSpeed(255);
motor3.run(BACKWARD);
motor3.setSpeed(255);
motor4.run(BACKWARD);
motor4.setSpeed(255);}
void Left()
{
motor.run(BACKWARD);
motor.setSpeed(255);
motor2.run(BACKWARD);
motor2.setSpeed(255);
motor3.run(FORWARD);
motor3.setSpeed(255);
motor4.run(FORWARD);
motor4.setSpeed(255);}
void Right()
{motor.run(FORWARD);
motor.setSpeed(255);
motor2.run(FORWARD);
motor2.setSpeed(255);
motor3.run(BACKWARD);
motor3.setSpeed(255);
motor4.run(BACKWARD);
motor4.setSpeed(255);}
void Stop()
{motor.run(RELEASE);
motor2.run(RELEASE);
motor3.run(RELEASE);
motor4.run(RELEASE);}

void servoLeft(){
 servoMain.write(0);
}
void servoFront(){
 servoMain.write(90);
 }
void servoRight(){
 servoMain.write(180);}
void loop(){
    
{
Stat=ultrasonic.Ranging(CM);
servoLeft();// считываем значение сонора слева
delay(servotime);
LeftStat=Stat;
delay(servotime);
servoFront(); //считываем значение сонора в переди
delay(servotime);
FrontStat=Stat;
delay(servotime);
servoRight();
delay(servotime);
RightStat=Stat;
delay(servotime);

if (LeftStat>RightStat&&LeftStat>FrontStat)
{Left();}
else if (Stat>(LeftStat-5))
{Forvard();}
else
{Stop();}
}
}

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

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

Подскажите пожалуйста, уж очень хочется довести до конца задуманное.

leshak
Offline
Зарегистрирован: 29.09.2011

Скажите, что, по вашему, происходит в строчках 75, 78 и 82?

trunker
Offline
Зарегистрирован: 05.05.2012

ну как я понимаю

75 присваевается значение с далномера переменной Stat

78 записывается и сохраняется показание дальномера слева

82 то же самое только справа

 

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

leshak
Offline
Зарегистрирован: 29.09.2011

Вообщем вот что вы сделали.

в строке 75 датчика, сохранили ее в переменную Stat (зачем она вообщем вам?)

Дальше поехали вращать сервой в разные стороны, и время от времени присваивать значение хранящееся в Stat (которое не меняется само по себе) переменным FrontStat, LeftStat, RightStat

В итоге, к концу Loop все переменные у вас имеют одинаковое значение. То что было считаннно в начале Loop.

Поэтому условия их сравнения я уже не вычитывал, они бессмыслены

leshak
Offline
Зарегистрирован: 29.09.2011

trunker пишет:

78 записывается и сохраняется показание дальномера слева

 

Где  в этой строчке вы видите чтения датчика? Там одна переменная присваивается другой.

trunker
Offline
Зарегистрирован: 05.05.2012

Ну Stat я использовал для удобства, что бы дальше меньше писать.
 Это же не меняет смысл? или для этого надо писать функцию? или я не так что то понимаю?

А скажите пожалуйста как сделать так что бы данные записывались?  

leshak
Offline
Зарегистрирован: 29.09.2011

 Попробую еще раз ( я не даю готовый ответ, потому что хочу что-бы сами поняли).

Представте что у вас есть блокнот с четырьмя листиками. И вас есть часы. Находитесь вы дома. На каждый листик вы можете записать только одно значение "который час". 

Вам сказали: Пойди в магазин и запиши "который час" на второй листик, потом пойди на почту и запиши когда ты пришел туда на третий, пойди дай в табло васе и запиши время события на четвертый листик.

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

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

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

------------

Возвращаесь с скетчу: часы- это сонар , "который час" -  показания сонара, листики - ваши переменные.

 

trunker
Offline
Зарегистрирован: 05.05.2012

Спасибо вам большое за интересный пример и старания, в общем я понял так:

void loop(){
    
servoLeft();// считываем значение сонора слева
delay(servotime);
LeftStat=ultrasonic.Ranging(CM);
delay(servotime);
servoFront(); //считываем значение сонора в переди
delay(servotime);
FrontStat=ultrasonic.Ranging(CM);
delay(servotime);
servoRight();
delay(servotime);
RightStat=ultrasonic.Ranging(CM);
delay(servotime);
{if (LeftStat>RightStat&&LeftStat>FrontStat)
{servoFront();
Left();}
else if (ultrasonic.Ranging(CM)>(LeftStat-5))
{Forvard();}
else
{Stop();}}
}

Вроде уже лучше) 
leshak
Offline
Зарегистрирован: 29.09.2011

 Ну да. Так уже больше похоже на правду.

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

Теперь с условиями разбирайтесь. Что с чем вы сравниваете и что по этому поводу нужно делать.Как минимум, я вижу, внутри условий вы опять, в строке 18 зачем-то опрашиваете сонар (может это нужно, но я не понял этой логики).

trunker
Offline
Зарегистрирован: 05.05.2012

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

trunker
Offline
Зарегистрирован: 05.05.2012
void loop(){
    
servoLeft();// считываем значение сонора слева
delay(servotime);
LeftStat=ultrasonic.Ranging(CM);
delay(servotime);

servoFront(); // считываем значение сонора спереди
delay(servotime);
FrontStat=ultrasonic.Ranging(CM);
delay(servotime);

servoRight(); // считывание значения сонора справа
delay(servotime);
RightStat=ultrasonic.Ranging(CM);
delay(servotime);


if (LeftStat>RightStat&&LeftStat>FrontStat)
{Left();
servoFront();}
else if (ultrasonic.Ranging(CM)>(LeftStat-5))
{Forvard();}
else
{Stop();}
}

по задумке если первое условие верно серва становится прямо а платформа поварачивает на лево, но серва не хочет стоять на месте, тут что не так? 
trunker
Offline
Зарегистрирован: 05.05.2012

Ну чего, подсказать кто может? 

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну вы мысленно прокрутите что ваш скетч делает. Или на бумажке алгоритм нарисуте. 

Вот оно же и делает ровно то что вы в скетче написали:

  1. Сработало услвои в строчке 19
  2. Выполнились команды в строчке 20,21  (повернули налево, и поставили серву прямо).
  3. Все. Loop закончился. И начал выполнятся заново (серву влево, замерили, прямомо замерили...)

Условия в строчке 22 - даже не проверяется если стработало условие в строчке 19. Почитайте как работает if-else 

Заодно и с while познакомтесь раз хотите реализовать что-то типа "до тех пор пока"

 

trunker
Offline
Зарегистрирован: 05.05.2012

По поводу while вроде все ясно но есть одно НО, в описание пишется будет выполняться до тех порка пока выражение не будет  ложью а мне надо наоборот, до тех пор пока не будет истина. как этого добиться?

leshak
Offline
Зарегистрирован: 29.09.2011
trunker
Offline
Зарегистрирован: 05.05.2012
void loop()

{Stop();
  servoLeft();// считываем значение сонора слева
  delay(servotime);
  LeftStat=ultrasonic.Ranging(CM);
  delay(servotime);

  servoFront(); // считываем значение сонора спереди
  delay(servotime);
  FrontStat=ultrasonic.Ranging(CM);
  delay(servotime);

  servoRight(); // считывание значения сонора справа
  delay(servotime);
  RightStat=ultrasonic.Ranging(CM);


  if (LeftStat>RightStat&&LeftStat>FrontStat)
  {
    servoFront();
    delay(servotime);
    while (!(ultrasonic.Ranging(CM)>(LeftStat-5))){


      Left();
    }
    servoFront();
    delay(servotime);
    while (ultrasonic.Ranging(CM)>=10){


      Forvard();
    }
  }
}

Получилось как то так, но почему то вперед не едет, точнее едет на 1 рывок и все, и начинается по новой, а надо что бы ехал до тех пор пока растояние до препятствия не будет >= 10

trunker
Offline
Зарегистрирован: 05.05.2012

вот откуда он получает значение меньше или равное 10 (когда до препятсьвия гаразда больше) ? с кодом же все правильно? 

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну, по скетчу вроде выглядит именно как "ехал до тех пор пока растояние до препятствия не будет >= 10".

Попробуйте сделать вывод в serial.Print что там ваш датчик возвращает. Может он в миллиметрах возврат дает. Или наоборот. Или ловит свои собственные посылки. 

МОжете даже отдельный скетч написать что-то типа 

void loop(){
  Serial.println(ultrasonic.Ranging(CM));
  delay(200);
}

Откройте сериал монитор, помашите перед ним рукой. Посмотрите какие значения с него идут.

И еще. Строчки 28,29 зачем? Ну то есть они не помешают. Просто не нужную задержку дают. У нас же и так серва уже повернута во front в строчках 21,22 и с тех пор мы ее не крутили. Значит 28 вообще не даст никакого видимого эффекта. А 29 - будет просто "стоять тупить".

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

А еще.... возможно есть какое-то ограничение, с какой скоростью датчик данные возвращать умеет. Ему же нужно послать импульс и дождатся ответа.А это время. Или ловит эхо от предыдущего замера. Возможно слишком быстро читаете. Попробуйте после  forward, delay какой-нить втыкнуть небольшой (внутри while).