Tank-bot

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

Представляю вам своего робота .

Робот умеет обходить препятствия (ИК датчик радарного типа).

Не падать со стола /лестницы и т.д. (датчик поверхности).

Включать/выключать фары автоматически (фоторезистор).

Так же на борту есть индикатор заряда аккумов - три светодиода.

Когда уровень заряда выше 60% - горит зеленый , когда ниже - горит желтый , когда ниже 15% - горит

красный , когда ниже 5% - красный мигает , отключаются маршевые двигатели , головня серва устанавливается по центру.

В таком состоянии логика и светодиоды будут работать около 3часов.

Так же реализовано управление по  ИК  (пульт от телека) , правда программа ИК на отдельном МК  ,

но скоро я совмещу две программы .

 

 

 

 

 

 

 

 

 

 

Остальные фото здесь foto.mail.ru/mail/heruvim219/Tank-bot

Видео здесь video.mail.ru/mail/heruvim219/Tank-Bot

Если кому интересно , схему и программу выложу позже.

 участник конкурса "Arduino 2012"

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

 >Если кому интересно

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

Конечно интерестно. 

А аккумы заряжаются где-то снаружи или могут "прямо на месте"?

А по поводу проекта: однозначно "браво"!

 

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

 Аккумы заряжаются внешним зарядником (потому сверху и стоят).

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

А прогу выложу позже (откоментирую и выложу).

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

 

"Arduino 2012"

Zaliv
Offline
Зарегистрирован: 05.03.2011

Это очень очень круто! Даже немного завидно (по хорошему) прямоте рук.

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

Я правильно понял, что ИК датчик закреплен на поворачивающейся платформе?

Alexander
Offline
Зарегистрирован: 25.04.2010

Класс! Вы не против если я помещу краткое резюме, одну из фоток и ссылку на эту ветку в раздел проекты?

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

>Я правильно понял, что ИК датчик закреплен на поворачивающейся платформе?< 

Датчик вращается на серве.

И по положению сервы определяет с  какой стороны препятствие , если препятствие прямо перед ним - сдает назад и разворачивается.

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

>Вы не против если я помещу краткое резюме, одну из фоток и ссылку на эту ветку в раздел проекты? <

Нет , не против .

Только я , немного , не понял  где именно вы хотите ее поместить ?

Alexander
Offline
Зарегистрирован: 25.04.2010

Спасибо. Сюда http://arduino.ru/projects

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

Почему то в сети мало проектов роботов на дуино. 

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

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

 

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

Вот программа робота.

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

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

Дело в том что машина с "жесткой" программой движения часто , надолго , зависала 

в неудобных местах - узких проходах и т.д.

 

 

#include <Servo.h> //библиотека для серво
Servo myservo;//объект серво
volatile int state = LOW;//пременная обрабатываемая прерыванием


 int pos=0;//угол поворота сервы
 int val=0;//время маневра в зависимости от заряда аккума
 int  napravlenie=0;//направление для разворота назад
 int povorot=0;//задержка поворота
 int servospeed=0;//скорость движения сервы
 
 
 
void setup ()
{  pinMode(3,INPUT);//датчик поверхности
   pinMode(1,OUTPUT);//сигнальный светодиод
   pinMode(13,OUTPUT);//мотор1
   pinMode(12,OUTPUT);//мотор1
   pinMode(11,OUTPUT);//мотор2
   pinMode(10,OUTPUT);//мотор2
   pinMode(9,OUTPUT);//частота на ИК светодиоды
   pinMode(6,OUTPUT);//индикатор заряда аккума желтый
   pinMode(7,OUTPUT);//индикатор заряда аккума красный
   pinMode(8,OUTPUT);//индикатор заряда аккума зеленый
   pinMode(2,INPUT);//головной TSOP
   pinMode(19,INPUT);//вход аккума - измерение уровня заряда
   pinMode(17,INPUT);//вход фоторезистора - включение фар
   pinMode(18,OUTPUT);//фары
   attachInterrupt(0, blink, CHANGE);//инициализация нулевого прерывания
    
   randomSeed(analogRead(0));//выбор случайного значения
   myservo.attach(5);//инициализация сервы
}
void loop ()

{
  
  
      if(analogRead(17)<11)//если на фоторезисторе меньше 9 то...
 {
   digitalWrite(18,HIGH);//включаем фары
   
 }
 else//если на фоторезисторе больше 9 то...
 {
   digitalWrite(18,LOW);//выключаем фары
   
 }

 //************АККУМУЛЯТОР*************************//
  
  
   if(analogRead(19)>615)//Если напруга выше 50%(3в на АЦП и выше) то...
  {
     digitalWrite(6,LOW); 
     digitalWrite(7,LOW); 
     digitalWrite(8,HIGH); //включаем зеленый светодиод
      val=0; //время маневра + 0 мс
  }
  
   if(analogRead(19)<615)//Если напруга ниже 50%(от3 до 2.5в на АЦП) то...
  {
     digitalWrite(6,HIGH); //включаем желтай светодиод
     digitalWrite(7,LOW); 
     digitalWrite(8,LOW); 
      val=150; //время маневра + 150 мс
      
      
      
      if(analogRead(19)<512)//Если напруга ниже 15%(от2.5 до 2.37в на АЦП) то...
  {
     digitalWrite(6,LOW); 
     digitalWrite(7,HIGH); //включаем красный светодиод
     digitalWrite(8,LOW);
    val=500; //время маневра + 500 мс
  }
   
  }
  //*****************МИНИМАЛЬНЫЙ ЗАРЯД**********************//
       if(analogRead(19)<=490)//если напруга ниже 5% (2.35в и ниже)
  {
     digitalWrite(6,LOW); 
     digitalWrite(7,HIGH);//мигаем красным светодиодом 
     digitalWrite(8,LOW);
     
  digitalWrite(13,LOW);
  digitalWrite(12,LOW);//отключаем маршевые 
  digitalWrite(11,LOW);//двигатели
  digitalWrite(10,LOW);
  
     delay(500);
     digitalWrite(6,LOW); 
     digitalWrite(7,LOW); //мигаем красным светодиодом 
     digitalWrite(8,LOW); 
     delay(500);  
     
      myservo.write(90);//устанавливаем головной сервопривод 
                       //в среднее положение
  }
  else
  {
   tone(9,38000);//генерируем частоту для TSOPов 36Кгц
   digitalWrite(1,LOW);//сигнальный светодиод выключен
   
   
     if(analogRead(17)<11)//если на фоторезисторе меньше 9 то...
 {
   digitalWrite(18,HIGH);//включаем фары
   
 }
 else//если на фоторезисторе больше 9 то...
 {
   digitalWrite(18,LOW);//выключаем фары
   
 }
   
   
   
 //***********************ДВИЖЕНИЕ************************//
   
  digitalWrite(13,HIGH);//едем вперед
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,HIGH);
  
 
  //********************************************************************************//
 //*******************ДВИЖЕНИЕ СЕРВЫ С ПРАВА НА ЛЕВО*******************************//
 //*******************************************************************************//
 
  servospeed=random(10,17);//случайно выбираем скорость движения головной сервы
  for(pos = 30; pos < 150; pos +=3)  // с права на лево
  {                                 
    myservo.write(pos);//установка сервы на заданный угол              
    delay(servospeed);//движение головной сервы    


 
   
   if(digitalRead(3)==HIGH)//если датчик поверхности не видит поверхности то ...
{
  digitalWrite(1,HIGH);//включаем сигнальный светодиод
 
 
  digitalWrite(13,LOW);//едем назад 500мс
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(500+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
    
        
    napravlenie=random(0,6);//случайно выбираем направление поворота
    if( napravlenie>3)//если больше 3 то...
    {
  digitalWrite(13,HIGH);//поворачиваем влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(500+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
    }
    else//если меньше 3 то...
    {
   digitalWrite(13,LOW);//поворачиваем вправо
   digitalWrite(12,HIGH);
   digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
   delay(500+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
    }
 
      
}
   
   
   
   
   
if(state==HIGH&&(pos>=30&&pos<=85))//если сработал TSOP и угол сервы от 30 до 85град. то...
{
  
   povorot=random(0,100);//случайно выбираем время завершения поворота
   digitalWrite(13,LOW);//поворачиваем вправо
   digitalWrite(12,HIGH);
   digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
   delay(povorot);//время поворота
      
}

if(state==HIGH&&(pos>=85&&pos<=95))//если сработал TSOP и угол сервы от 85 до 95град. то...

{
 
 
  digitalWrite(13,LOW);//сдаем назад
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(1000+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
    
        
  digitalWrite(13,HIGH);//поворачиваем влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(500+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
    
      
}

if(state==HIGH&&(pos>=95&&pos<=150))//если сработал TSOP и угол сервы от 95 до 150град. то...

{
  povorot=random(0,100);//случайно выбираем время завершения поворота
  digitalWrite(13,HIGH);//поворачиваем влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(povorot);//время поворота влево
}



}  
    
    
 
    
 //********************************************************************************//
 //*******************ДВИЖЕНИЕ СЕРВЫ С ЛЕВА НА ПРАВО*******************************//
 //*******************************************************************************//
   
 
 
 servospeed=random(10,17);//случайно выбираем скорость движения сервы
  for(pos = 150; pos >30; pos -=3)  // с лева на право
  {              
    myservo.write(pos); //угол поворота сервы              
    delay(servospeed);  //время поворота сервы


 
   if(digitalRead(3)==HIGH)//если датчик поверхности не видит поверхности то ...
{
  digitalWrite(1,HIGH);//включаем сигнальный светодиод
 
 
  digitalWrite(13,LOW);//едем назад 500мс
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(500+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
    
        
    napravlenie=random(0,6);//случайно выбираем направление поворота
    if( napravlenie>3)//если больше 3 то...
    {
  digitalWrite(13,HIGH);//поворачиваем влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(500+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
    }
    else//если меньше 3 то...
    {
   digitalWrite(13,LOW);//поворачиваем вправо
   digitalWrite(12,HIGH);
   digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
   delay(500+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
    }
 
      
}
   








 if(state==HIGH&&(pos>=95&&pos<=150))//если сработал TSOP и угол сервы от 150 до 95град. то...
{
  
  povorot=random(0,100);//случайно выбираем время завершения поворота
  digitalWrite(13,HIGH);//поворачиваем влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(povorot);//время поворота
}

if(state==HIGH&&(pos>=85&&pos<=95))//если сработал TSOP и угол сервы от 95 до 85град. то...

{
  
 
  digitalWrite(13,LOW);//сдаем назад
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(1000+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
     
      
        
  
  digitalWrite(13,LOW);//поворачиваем вправо
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW);
  digitalWrite(10,HIGH);
  delay(500+val);//если уровень заряда аккума ниже 50% едем назад 650мс ,  если ниже 15% - 1000мс
     
      
}

if(state==HIGH&&(pos>=30&&pos<=85))//если сработал TSOP и угол сервы от 85 до 30град. то...

{
  
  povorot=random(0,100);//случайно выбираем время завершения поворота
  digitalWrite(13,LOW);//поворачиваем вправо
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW);
  digitalWrite(10,HIGH);
  delay(povorot);//время завершения поворота
}   
}
}
}
void blink()//функция внешнего прерывания 
//обработка сигнала с головного TSOРа


{
  state = !state;//меняем значение переменной на противоположное
  digitalWrite(1,HIGH);//включаем сигнальный светодиод
}





 

Nikita1
Offline
Зарегистрирован: 19.10.2011

Клево! а для чего нужны прерывания? 

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

 >а для чего нужны прерывания?

Уточните вопрос: вас интересует зачем вообще нужны прерывания, или зачем они используются в данном скетче?

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

 >Вот программа робота.

Спасибо за прекрасно откоментированный код. 

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

Nikita1
Offline
Зарегистрирован: 19.10.2011

leshak пишет:

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

именно в этом

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

>а для чего нужны прерывания?<

Действительно , можно и без прерывания , просто опрашивать цифровой пин.

Но , спрерыванием он как то интереснее себя ведет. 

Серва несколько задерживается в том положении , в которм обнаружила препятствие .

>Для себя "подсмотрел" идею увеличивать время включения движков когда "просаживается" аккамулятор.<
 

Это довольно таки условно.

Аккум просаживается нелинейно.

 

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

Сейчас работаю над модуляцией частоты ИК т.к. датчик , иногда , срабатывает на энергосберегающие лампы и яркое солнце. 

Fenrir
Offline
Зарегистрирован: 03.07.2011

видео бы еще для полного счастья =)

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

Ссылка на видео стоит в первом сообщении. 

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

 > зачем они используются в данном скетче?

Так в комментариях же написанно:"//обработка сигнала с головного TSOРа". TSOP, как я понимаю это датчик препятствия. Вот для того что-бы ловить его "срабатывание" и использовано прерывание.

Почему прерывание, а не просто опрос пина? Читаем документацию arduino.ru/Reference/AttachInterrupt, раздел ""Использование перерываний", там расписано в чем преимущества "через прерывание", по сравнению в простым чтением пина.

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

> Это довольно таки условно. Аккум просаживается нелинейно.

Ну это уже детали. Подобрать "приемлемые параметры", увеличить частоту дискретизации и т.п. всегда можно. Главное "идея", "подход". А идея увеличивать время реакции при просаживании, лично для меня, была нова. Честно говоря вообще не приходило в голову "что-то с этим делать", просто принимал как неизбежность.

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

>>Так в комментариях же написанно:"//обработка сигнала с головного TSOРа". TSOP, как я понимаю это датчик препятствия. Вот для того что-бы ловить его "срабатывание" и использовано прерывание.<<<

 

На самом деле можно и без прерывания.

Прерывание лишь изменяет состояние переменной , а она опрашивается в строго определенные моменты программы.

На первый взгляд , действительно , не видно разницы (в данном роботе)  в поведении машины , но потестив ее пару дней 

становится ясно что с прерыванием она ведет себя ... умнее , что ли.

Nikita1
Offline
Зарегистрирован: 19.10.2011

nestandart пишет:

Если кому интересно , схему и программу выложу позже.

Схемку можно глянуть, пажалуйста

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

>> Схемку можно глянуть, пажалуйста<<

Позже.

Скорее всего я полностью изменю прграмму.

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

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

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

Народ , я в тупике.

Дело вот в чем.

Вот это програма управления , тем же , роботом с ИК пульта  (одна она прекрасно работает).

unsigned long val=0;
unsigned long val2=0;
unsigned long val3=0;
unsigned long val4=0;
unsigned long val5=0;
unsigned long val6=0;
unsigned long val7=0;
unsigned long val8=0;


#include <Servo.h> 
Servo myservo;

void setup()

{
  pinMode(19,INPUT);
 
   pinMode(9,OUTPUT);
   pinMode(10,OUTPUT);
   pinMode(11,OUTPUT);
   pinMode(12,OUTPUT);
    pinMode(13,OUTPUT);
    
     pinMode(6,OUTPUT);
     pinMode(7,OUTPUT);
     pinMode(8,OUTPUT);
 myservo.attach(5);
}
void loop()

{
  
  //**************************АККУМУЛЯТОР********************//
    if(analogRead(19)<615)
  {
     digitalWrite(6,HIGH); 
     digitalWrite(7,LOW); 
     digitalWrite(8,LOW); 
     
      if(analogRead(19)<512)
  {
     digitalWrite(6,LOW); 
     digitalWrite(7,HIGH); 
     digitalWrite(8,LOW); 
  }
     
  }
  
   if(analogRead(19)>615)
  {
     digitalWrite(6,LOW); 
     digitalWrite(7,LOW); 
     digitalWrite(8,HIGH); 
  }
 //**********************МИНИМАЛЬНЫЙ ЗАРЯД*****************//
        if(analogRead(19)<=485)
  {
     digitalWrite(6,LOW); 
     digitalWrite(7,HIGH); 
     digitalWrite(8,LOW);
  digitalWrite(13,LOW);//вперд
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
     delay(500);
     digitalWrite(6,LOW); 
     digitalWrite(7,LOW); 
     digitalWrite(8,LOW); 
     delay(500);  
      myservo.write(90);
  }
  //******************************************************//
  else
  {
  myservo.write(90);
  
  if(pulseIn(2,LOW)<1)
  {
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
  digitalWrite(13,LOW);
 
  }
  
  
  
  
val=pulseIn(2,LOW);
 val=(val/1000);
 
 
 
 if(val==2)
 {
 val2=pulseIn(2,LOW); 
 val3=pulseIn(2,LOW); 
 val4=pulseIn(2,LOW); 
 val5=pulseIn(2,LOW);
 val6=pulseIn(2,LOW);
  val7=pulseIn(2,LOW);
  val8=pulseIn(2,LOW);
  
 
 
 if((val2/1000)==0&&(val3/1000)==0&&(val4/1000)==1&&(val5/1000)==0&&
 (val6/1000)==1&&(val7/1000)==1&&(val8/1000)==1)
 {
 
   
 digitalWrite(13,HIGH);//вперд
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
  
  
  
  
  
  
 }
 

  
 
 
 
 
 if((val2/1000)==0&&(val3/1000)==0&&(val4/1000)==1&&
 (val5/1000)==0&&(val6/1000)==1&&(val7/1000)==1&&(val8/1000)==0)
 {
 
 
 digitalWrite(13,LOW);//вправо
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
  
 }

 
 
 
 
 if((val2/1000)==1&&(val3/1000)==1&&(val4/1000)==0&&
 (val5/1000)==0&&(val6/1000)==1&&(val7/1000)==1&&(val8/1000)==0)
 {
 
  
  
  digitalWrite(13,HIGH);//лево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
   digitalWrite(10,LOW);
 
 
 }
 

 
 if((val2/1000)==1&&(val3/1000)==0&&(val4/1000)==1&&
 (val5/1000)==0&&(val6/1000)==1&&(val7/1000)==1&&(val8/1000)==1)
 {
 
 
   
  digitalWrite(13,LOW);//назад
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
   digitalWrite(10,LOW);
   
 }
  }
 
 
 
 
 

  }
 
 }

 

Но , я не могу совместить ее с вышеописаной (автономной ) программой.
Чтобы с кнопки пульта программа переключалась между автономной и ручной.
Что я только не делал и два TSOPA через два прерывания , и последовательный опрос и т.д.
Программы вместе не работают вообще.

У кого какие мысли ?  

 


 
  

 

 

 

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

>У кого какие мысли ?

Мысли:

  1. Через прерывания все-таки "кошерней".
  2. В обоих скетчах переменная "val" используется с разным смыслом. возможно на этом "интерферирует".
  3. IK-пульт дает "засветку" на TSOP.
  4. " не работают вообще" это "вообще никакие команды не выполняются" или "выполняются хаотично"?
  5. Вместо команд на сервы сделать вывод в Serial и посмотреть какие оно решения принимает (вообщем сделать вывод debug информации).
  6. Не забываем что пульт выдает сигналы "не четко", длительность импульсов может немного плавать.
  7. Посмотрел бы на библиотеку IRRemote, возможно что-то оттуда "выдрать" кусок захвата-декодинга сигналов, а может и целиком заюзать ее заюзать (если место позволяет).
  8. Возможно "вместе" уже памяти не хватает. Попробовать добавить банальное мограние диодом. Узнать у нас цикл loop крутится вообще или где-то зависает.

 

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

1.Не работает

2. Названия переменных я , конечно же , меняю.

3.Не совсем понял. Пульт и TSOP работают на одной частоте .

Датчик препятствий распознает пульт как препятствие.

У меня стоят два TSOPа (по одному на каждое прерывание).

4.При разных вариантах "неработает" по разному.

Но чаще всего пульт вообще не работает , а автономная программа постоянно фиксирует препятствие и бесконечно совершает 

маневр.

5.Попробую

6.Только в пределах микросекунд , а я счатываю милисекунды.

Ложных срабатываний пульта нет .Несрабатываний ( в прграмме ручного управления )тоже не было.

7.Думал об этом.Наверное попробую.

8.Памяти хватает . ATmega 328  на борту.

 

Максимум что я , пока , придумал  это переключать режимы не командой с пульта а кнопкой на цифровом пине.

Мне кажется что конструкция "считывания импульсов в переменные" (если она крутится в автономной программе)

сильно забивает цикл и мешает работе сервы.

 

Вот один из примеров.

Вот так работает (вкл/выкл фар)

прерывание (само собой ) не работает.

unsigned long val=0;
unsigned long val2=0;
unsigned long val3=0;
unsigned long val4=0;
unsigned long val5=0;
unsigned long val6=0;
unsigned long val7=0;
unsigned long val8=0;
volatile int state = LOW;

#include <Servo.h> 
Servo myservo;

void setup()

{  
   pinMode(4,INPUT);
   pinMode(1,OUTPUT);
   pinMode(13,OUTPUT);
   pinMode(11,OUTPUT);
   pinMode(12,OUTPUT);
   pinMode(10,OUTPUT);
   pinMode(9,OUTPUT);
   pinMode(6,OUTPUT);
   pinMode(7,OUTPUT);
   pinMode(8,OUTPUT);
   pinMode(2,INPUT);
   pinMode(19,INPUT);
   pinMode(17,INPUT);
    pinMode(18,OUTPUT);
   attachInterrupt(0, blink, CHANGE);
}
void loop()

{
  
  
if(state==HIGH)
{
  digitalWrite(1,HIGH);
}
else
{
  digitalWrite(1,LOW);
}
  
 
 if(pulseIn(4,LOW)<1)
  {
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
  digitalWrite(13,LOW);
 
  }
  
val=pulseIn(4,LOW);
 val=(val/1000);
 
 if(val==2)
 {
 val2=pulseIn(4,LOW); 
 val3=pulseIn(4,LOW); 
 val4=pulseIn(4,LOW); 
 val5=pulseIn(4,LOW);
 val6=pulseIn(4,LOW);
  val7=pulseIn(4,LOW);
  val8=pulseIn(4,LOW);
  
 
 
 if((val2/1000)==0&&(val3/1000)==0&&(val4/1000)==1&&(val5/1000)==0&&
 (val6/1000)==1&&(val7/1000)==1&&(val8/1000)==1)
 {
 digitalWrite(18,!digitalRead(18));
 delay(500);
 }
 }
 }

 
 void blink()
{
  state = !state;
 
}

 

А вот так не работает (включил частоту на ИК светодиоде).

На пкльт не реагирует , на датчик реагирует с большим опозданием.

unsigned long val=0;
unsigned long val2=0;
unsigned long val3=0;
unsigned long val4=0;
unsigned long val5=0;
unsigned long val6=0;
unsigned long val7=0;
unsigned long val8=0;
volatile int state = LOW;

#include <Servo.h> 
Servo myservo;

void setup()

{  
   pinMode(4,INPUT);
   pinMode(1,OUTPUT);
   pinMode(13,OUTPUT);
   pinMode(11,OUTPUT);
   pinMode(12,OUTPUT);
   pinMode(10,OUTPUT);
   pinMode(9,OUTPUT);
   pinMode(6,OUTPUT);
   pinMode(7,OUTPUT);
   pinMode(8,OUTPUT);
   pinMode(2,INPUT);
   pinMode(19,INPUT);
   pinMode(17,INPUT);
    pinMode(18,OUTPUT);
   attachInterrupt(0, blink, CHANGE);
}
void loop()

{
   tone(9,36000);
 
  
if(state==HIGH)
{
  digitalWrite(1,HIGH);
}
else
{
  digitalWrite(1,LOW);
}
  
 
 if(pulseIn(4,LOW)<1)
  {
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
  digitalWrite(13,LOW);
 
  }
  
val=pulseIn(4,LOW);
 val=(val/1000);
 
 if(val==2)
 {
 val2=pulseIn(4,LOW); 
 val3=pulseIn(4,LOW); 
 val4=pulseIn(4,LOW); 
 val5=pulseIn(4,LOW);
 val6=pulseIn(4,LOW);
  val7=pulseIn(4,LOW);
  val8=pulseIn(4,LOW);
  
 if((val2/1000)==0&&(val3/1000)==0&&(val4/1000)==1&&(val5/1000)==0&&
 (val6/1000)==1&&(val7/1000)==1&&(val8/1000)==1)
 { 
 digitalWrite(18,!digitalRead(18));
 delay(500);
 
 }
 }
 }

 
 void blink()
{
  state = !state;
 
}

Может , и правда , забивает ? Завтра проверю.

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

 Попробуйте сделать  так  (выключив tone, естественно при нем работать не будет)

if(state==HIGH)
{
  digitalWrite(1,HIGH);
  delay(500);
  state=LOW;
}

else
{
  digitalWrite(1,LOW);
}

....

void blink(){
  state=HIGH;
}

 Что-бы он включал на заметное время фары при любом импульсе на IR приемнике. Тогда, если при включенном TSOP и, не трогая пульт, фары будут гореть или мограть, вы будете знать что IR-приемник ловит ваш TSOP.

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

>>IR-приемник ловит ваш TSOP.<<

TSOP это и есть IR приемник. 

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

Так и есть частота светодиодов создает устойчивую помеху .

При включиеных ИК светодиодах робот на пульт не реагирует.

Но .

1.Даже если на TSOPах нет отраженного (или еще какого либо) сигнала - то же самое , на пульт не реагирует.

2.У меня два TSOPa  один -датчик препятствий (впереди) , второй я делал специально для пульта , он смотрит вверх .

Эти TSOPы подклчены к разным ногам МК (прерываниям) и опрашиваются раздельно.

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

>второй я делал специально для пульта , он смотрит вверх

Боюсь что этого "мало", все это излучение хорошо отражается-переотражается от стен/потолка. Попробуйте сделать такой финт ушами:

1. Выключаете несколько раз в секунду излучатель головного TSOP-a.

2. В этот момент делаете включаете "опрос пульта" и выключаете "опрос головного", если "там тихо" , опять включаете головной. 

Вообщем работаете с ними "попеременно". Возможно, в итоге, вообще одним TSOP-пом обойдется, играясь только включением-выключением излучателя и по разному интерпретирую его срабатывания. Естественно опрашивать пульт прийдется, все-таки через прерывания. pulseIn тут уже не подойдет никак. На нем программа будет "останавливаться и ждать".

Ну и посмотрите все-таки еще раз в сторону IRRemote. Там именно через прерывания и сделано. Объявлен  массив rawbuf в него, при обработке прерывания, закидывают временные интервалы между пойманными тиками, а потом уже анализируются и пытаются декодировать в код клавиши (если известен протокол пульта). 

 Плюс есть еще есть нюанс, что с пульта первый импульс, как правило, идет более длинный чем остальные. Стартовый. Что-бы определить "начало передачи" и не "зависать" если вы услышали команду "с середины".

Ну и еще подводным камнем может быть как пульт шлет "удержание кнопки". Просто повторяет ее, повторяет сменив один бит, шлет специальный код "повторение" и т.п. В IRRemote есть семпл IRrecvDump им можно посмотреть-сдампить что-же именно шлет ваш пульт.

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

>>1. Выключаете несколько раз в секунду излучатель головного TSOP-a.

2. В этот момент делаете включаете "опрос пульта" и выключаете "опрос головного", если "там тихо" , опять включаете головной.<<

Вы читаете мои мысли.

Я придумал вот что.

Сделать генератор частоты на внешней микросхеме (что бы он совершенно не зависил от МК).

Сделать импульсную модуляцию этого генератора.

У меня длинна пакета импульсов с пульта составляет 9мс.

Так вот сделать модуляцию - 10мс горит , 10мс не горит .

Вот в эти самые "не горит" ловить пакет с пульта.

Теоретически все гладко , посмотрим что будет на практике.

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

Дело ваше. Но IMHO, это гиморней. Если не считать того что "нужно еще одну железку вкорячить", то вылезет еще куча вопросов: а как синхронизировать эту железку с МК? и т.п. Помоему "программно" все-таки намного проще будет и гибче будет. Можно подбирать соотношение времени  опросов пульта/головного. Можно делать что-то типа "выключили головной на 2 мкс." если на "пульте" тишина, включили обратно головной, если "что-то есть на пульте", то "послушаем дополнительное время, что-бы наверняка". Такой гибкости "в железе" вы вряд ли добъетесь.

>Так вот сделать модуляцию - 10мс горит , 10мс не горит

Зачем? Вы сможете давить пульт с такой частотой? IMHO "прислушиваться к пульту" несколько раз в секунду будет вполне достаточно. А остальное время отдать на "голову", что-бы "не разбить свое лицо о камни" :)

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

 К тому же "длинна пакета импульсов с пульта составляет 9мс" и "10мс не горит". А если начало пакета не совпадет по времени с периодом "10 мс не горит", что будет? Пульт-то вы нажимать будете "когда в голову взбредет", а не "в строгом соотвествии".

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

Получается такая логика (и возможно на одном TSOP-е):

  1. "Головной что-то поймал".
  2. Выключаем излучатель
  3. Если сигнал "продолжает поступать", обрабатываем его как пульт, если "исчез" - обрабатываем его как препятсвие.
  4. Включаем излучатель.

В этом случае даже не прийдется решать "как делить между ними время".

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

Не очень хороший вариант.

Дело в том что солнце и энергосберегающие лампы дают постоянную засветку на несущей частоте TSOPа (36-38КГц).

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

Функция pulseIn  отказывается работать вместе сфункцией tone.

Определять сигнал свой/чужой лучше всего по длинне , заранее сгенерированого , импульса.

Допустим .

1.пришел сигнал - меряем длинну импульса .

2.Если длинна равна 3мс (собственная ИК модуляция) - препятствие.

3.Если 2мс (начальный импульс в пачке пульта) - пульт.

4. Если больше/меньше - фоновая засветка.

 

 

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

 >Дело в том что солнце и энергосберегающие лампы дают постоянную засветку на несущей частоте TSOPа

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

Да и я какое-то время назад, монстрячил IR-приемник для управления компом - люстра из 6-сти сберегаек по 25ват никак не мешала. Ну да ладно, примем на веру. Раз у вас "засвечивает", значит так и есть.

>Функция pulseIn отказывается работать вместе сфункцией tone.

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

Ну даже если бы "работала", то лучше было-бы отказатся от нее. Она фактически "останавливает программу и ждет", лучше избегать этого. 

>лучше всего по длинне , заранее сгенерированого , импульса

Лучше всего то что "заработает" :)  Описанная вами логика, выглядит здраво. Я бы попробовал.

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

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

leshak , я тут , как оказалось , легко и просто решил проблему с энергосберегающими лампами.

Проанализировал что с них идет , так вот : частота от 34 КГц до 40КГц , беспорядочные импульсы от 1до 100 мс 

(в среднем около 7-20мс).

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

 (когда сигнала нет , на выходе TSOPа лог1 , когда сигнал появляется - лог0).

Осталась проблема с лонцем , но ее отложим .

В ближайшие пол года солнца не предвидится.

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

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

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

Видел я подобные проекты ИК бамперов .  Можно и на отдельном МК датчик соорудить.

Вобщем посмотрим. Если и буду делать то только в следующем роботе. 

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

>>Да и я какое-то время назад, монстрячил IR-приемник для управления компом - люстра из 6-сти сберегаек по 25ват никак не мешала. Ну да ладно, примем на веру. Раз у вас "засвечивает", значит так и есть. <<

 

Моя автономная программа просто выдает частоту 36КГц , TSOP реагирует на эту частоту

(хот на импульсы , хоть на постоянный сигнал).

А в пультах идет импульсная кодировка.

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

Потому лампы пультам и не мешают.

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

 Спасибо за разъяснение.

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

А вот что пришло в голову: а может для головного, взять TSOP с другой частотой? Есть же, вроде и с несущей на 50Кгц.

Кстати, раскажите а от чего вы шасси (колеса, гусеницы) брали?

Nikita1
Offline
Зарегистрирован: 19.10.2011

Гусеницы от Tamiya похоже 

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

>> Кстати, раскажите а от чего вы шасси (колеса, гусеницы) брали?<<

Шасси полностью самодельное , выточил из текстолита , фурнитура и некоторые детали из детского (металического) конструктора.

Гусеницы  , звезды , катки - Tamiya.

Моторы - переделаные сервы.

Выкусил ограничитель на ведущей шестерне , снял всю электронику.

Так что теперь это просто мотор-редукторы.

Позже выложу отдельные фото деталей платформы.

MAFia
Offline
Зарегистрирован: 26.10.2011

 Браво! А не скажешь, что за двигатели там стоят? Мотор-редуктора, если я понял?

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

>>Браво! А не скажешь, что за двигатели там стоят? Мотор-редуктора, если я понял? <<

Я же писал , это переделаные (под постоянное вращение) сервоприводы Tower pro sg5010.

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

Попробовал совместить программу пульта и автономную , но и здесь грабли.

Программа состоит из двух больших подпрограмм .

Переключение между ними происходит посредством нажатия кнопки с фиксированым положением.

Программа нормально переходит из ручной в автономную , но при переходе из автономной в ручную - ручная не работает 

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

 

#include <Servo.h> 
Servo myservo;
volatile int state = LOW;
int val=0;
 int val2=0;
 int val3=0;
 int val4=0;
 int val5=0;
 int  val6=0;
 int  val7=0;
 int val8=0;

 int pos=0;
 int val11=0;
 int val22=0;
 int val33=0;
 int val44=0;
 
 
void setup ()

{ 
   pinMode(4,INPUT);
   pinMode(3,INPUT);
    pinMode(7,OUTPUT);
    
   pinMode(1,OUTPUT);
   pinMode(13,OUTPUT);
   pinMode(11,OUTPUT);
   pinMode(12,OUTPUT);
   pinMode(10,OUTPUT);
   pinMode(9,OUTPUT);
   pinMode(6,OUTPUT);
   pinMode(7,OUTPUT);
   pinMode(8,OUTPUT);
   pinMode(2,INPUT);
   pinMode(19,INPUT);
   pinMode(17,INPUT);
    pinMode(18,OUTPUT);
  
    
   randomSeed(analogRead(0));
   myservo.attach(5);
}
void loop ()

{
  
  
  if(digitalRead(4)==HIGH)
  
  {
    digitalWrite(7,HIGH);
    
    if(pulseIn(2,LOW)==0)
   {
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,LOW);
  digitalWrite(13,LOW);
  digitalWrite(18,LOW);
  }
  
  
  
 
 
 
 
   
val=pulseIn(2,LOW);
 val=(val/1000);
 if(val==2)
 {
 val2=pulseIn(2,LOW); 
 val3=pulseIn(2,LOW); 
 val4=pulseIn(2,LOW); 
 val5=pulseIn(2,LOW);
 val6=pulseIn(2,LOW);
  val7=pulseIn(2,LOW);
  val8=pulseIn(2,LOW);
  
 
 
 
 
 if((val2/1000)==0&&(val3/1000)==0&&(val4/1000)==0&&(val5/1000)==0&&
 (val6/1000)==0&&(val7/1000)==0&&(val8/1000)==0)
 {
 
   
 digitalWrite(18,HIGH);
 
  
 }
 
 
 if((val2/1000)==1&&(val3/1000)==0&&(val4/1000)==0&&(val5/1000)==0&&
 (val6/1000)==0&&(val7/1000)==0&&(val8/1000)==0)
 {
 
   
 digitalWrite(1,!digitalRead(1));
 delay(500);
 
  
 }
 
 
 
 
 
 
 if((val2/1000)==0&&(val3/1000)==0&&(val4/1000)==1&&(val5/1000)==0&&
 (val6/1000)==1&&(val7/1000)==1&&(val8/1000)==1)
 {
 
   
 digitalWrite(13,HIGH);//вперд
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
  
 
  
  
  
  
 }
 

  
 
 
 
 
 if((val2/1000)==0&&(val3/1000)==0&&(val4/1000)==1&&
 (val5/1000)==0&&(val6/1000)==1&&(val7/1000)==1&&(val8/1000)==0)
 {
 
  digitalWrite(13,HIGH);//лево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
   digitalWrite(10,LOW);

 }

 
 
 
 
 if((val2/1000)==1&&(val3/1000)==1&&(val4/1000)==0&&
 (val5/1000)==0&&(val6/1000)==1&&(val7/1000)==1&&(val8/1000)==0)
 {
 
  
  digitalWrite(13,LOW);//вправо
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
  
 
 
 
 }
 

 
 if((val2/1000)==1&&(val3/1000)==0&&(val4/1000)==1&&
 (val5/1000)==0&&(val6/1000)==1&&(val7/1000)==1&&(val8/1000)==1)
 {
 
 
   
  digitalWrite(13,LOW);//назад
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
   digitalWrite(10,LOW);
  
 }
  }
 
 
    
    
    
    
  }
  else
  
  {
  digitalWrite(7,LOW);
  
   tone(9,36000);
   
   
   
     if(analogRead(17)<11)//если на фоторезисторе меньше 9 то...
 {
   digitalWrite(18,HIGH);//включаем фары
   
 }
 else//если на фоторезисторе больше 9 то...
 {
   digitalWrite(18,LOW);//выключаем фары
   
 }
   
   
   
 //***********************ДВИЖЕНИЕ************************//
   
  digitalWrite(13,HIGH);//вперед
  digitalWrite(12,LOW);
  digitalWrite(11,LOW);
  digitalWrite(10,HIGH);
  
 

 
  val33=random(12,17);
  for(pos = 30; pos < 150; pos +=3)  // с права на лево
  {                                 
    myservo.write(pos);              
    delay(val33);    


 
   
   if(digitalRead(3)==HIGH)
{

 
 
  digitalWrite(13,LOW);//назад
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(500+val44);
    
        
    
  digitalWrite(13,HIGH);//влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(1000+val44);
     
 
      
}
   
   
   
   
   
if(digitalRead(2)==LOW&&(pos>=30&&pos<=85))
{
  
   val22=random(0,100);
   digitalWrite(13,LOW);//вправо
   digitalWrite(12,HIGH);
   digitalWrite(11,LOW);
   digitalWrite(10,HIGH);
   delay(val22);
      
}

if(digitalRead(2)==LOW&&(pos>=88&&pos<=95))

{
 
 
  digitalWrite(13,LOW);//назад
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(1000+val44);
    
        
  digitalWrite(13,HIGH);//влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(1000+val44);
    
      
}

if(digitalRead(2)==LOW&&(pos>=95&&pos<=150))

{
  val22=random(0,100);
  digitalWrite(13,HIGH);//влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(val22);
}



}  
    
    
 
    
//2************************************************************// 
    
   
 
 
 val33=random(12,17);
  for(pos = 150; pos >30; pos -=3)  // с лева на право
  {              
    myservo.write(pos);               
    delay(val33);  


 
  if(digitalRead(3)==HIGH)
{
 
  
  digitalWrite(13,LOW);//назад
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(500+val44);
    
        
    
  digitalWrite(13,HIGH);//влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(1000+val44);
  

}
   









 if(digitalRead(2)==LOW&&(pos>=95&&pos<=150))
{
  
  val22=random(0,100);
  digitalWrite(13,HIGH);//влево
  digitalWrite(12,LOW);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(val22);
}

if(digitalRead(2)==LOW&&(pos>=85&&pos<=95))

{
  
 
  digitalWrite(13,LOW);//назад
  digitalWrite(12,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(10,LOW);
  delay(1000+val44);
     
      
        
  
  digitalWrite(13,LOW);//вправо
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW);
  digitalWrite(10,HIGH);
  delay(1000+val44);
     
      
}

if(digitalRead(2)==LOW&&(pos>=30&&pos<=85))

{
  
  val22=random(0,100);
  digitalWrite(13,LOW);//вправо
  digitalWrite(12,HIGH);
  digitalWrite(11,LOW);
  digitalWrite(10,HIGH);
  delay(val22);
}   
}
}
}





 

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

 Честно горя скетч такого объема трудно "прокрутить в голове". Попробуйте сделать "рефакторинг кода", глядишь и сами увидите "где что-то не так". 

Разделите "принятие решения" и "выполнение решение". Сделайте для команда константы 

#define cmdRigh=1
#define cmdLeft=2
#define cmdStop=3

Объявите две функции getAutoCommand (в которой будет автономная логика) и getManualCommand (в которой будет логика из пульта). Вызываете ту функцию "какой режим сейчас включен", примерно так

if(manualMode) cmd=getManualCommand() else cmd=getAutoCommand()

switch(cmd) {
  case CMD_RIGHT:
    //... включаем пины для поворота влево
    break;
  case CMD_LFFT
    //... включаем пины для поворота вправо
    ....
   break;
  //  ....
}

  Все эти серии из digitalWrite тоже можно "причесать", посмотрите ветку arduino.ru/forum/apparatnye-voprosy/binarnye-chasy, как там человек  хранит в коде "какие леды нужно включить, какие выключить". Немного расточительно на каждый пин, по целому байту отводить, но все равно "намного читабельный".

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

Сейчас же скет изобилует кучей "магических цифр", дублированием кода. Код "не читается". Ну хотя-бы эти все "влево", "вправо" в отдельные функции повыносить. val22, val33 какие-то более осмысленные имена дать и т.п.

 

 

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

 Вот эти

(val2/1000)==1&&(val3/1000)==0&&(val4/1000)==1&&
170
 (val5/1000)==0&&(val6/1000)==1&&(val7/1000)==1&&(val8/1000)==1

тоже можно упрятать в какие-то константы, и оформить в виде функции которая возвращает "код клавиши".

Да и сами val2,val3, val4 не нужны. Можно объявить массив byte vals[7], тогда и вычивать их можно будет не кучей pulseIn, а

циклом

for(i=0;i<7;i++)vals[i]=pulseIn(2,LOW).

И "сравнивать" потом тоже будет удобней (сделать массив в котором "ожидаемые значение", пробежались по двум массивам, сравнили каждый элемент, а не выписывать "длинющие условие if-a").

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

 >>>Объявите две функции getAutoCommand (в которой будет автономная логика) и getManualCommand (в которой будет логика из пульта). Вызываете ту функцию "какой режим сейчас включен", примерно так<<<

Думал об этом - попробую.

А то я тут уже в такие дебри полез ...

"При переходе на ручное управление опрашивать ячейку ипрома и если там 1 то пишем туда 0 , включаем релюшку 

(сброс питания с МК).

А при входе в автономную программу пишем в ячейку 1."

Спаял попробовал -работает , но в готовое устройство я такое , конечно же , не поставлю.

 

>>val22, val33 какие-то более осмысленные имена дать и т.п.<<

Это все в порядке эксперимента , лоск буду наводить когда функционал будет нормально работать.

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

 >(сброс питания с МК)

Да жесткач. Но за умение добиватся цели любыми средствами - уважение :)

>Это все в порядке эксперимента

Это понятно. Все мы знаем откуда это возникает. Более того, на начальных этапах именно так и нужно. Криво-косо, абы живо. Пока "идея не протухла".

>лоск буду наводить когда функционал будет нормально работать

Подходы к программированию типа XP, говорят что так нельзя. Когда "код большой", вы уже не сможете его нормально отрефакторить (тем более с ArduinoIDE которое практически не имеет инструментов для "работы с кодом"). Велик страх "что-то поломать" (и довольно обоснованный), да и "работает - не трогай". Но развивать такой кодом все "трудней и трудней" (вот даже сейчас, ошибка скорее всего где-то в логика, а "увидеть" ее не получается). Поэтому обычно рекомендую идти "маленькими шагами".

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

И они "не разрывны", хотя конечно, это все, в довольно большой степени "религиозные" подходы к написанию кода. Дело вкуса. Но лично мне такая парадигма очень помогает (плюс Unit Tesiting, но в ардуине на него "ресурсов не хватит").

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

Кажется нашел проблему .

Щас еще поковыряю - посмотрим.

Дело в том что при запуске автономной программы включается выдача частоты (ИК светодиоды).

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

А , как я уже писал выше , pulseIn напрочь отказывается работать когда работает частота (то же самое и с сервами).

Даже вот такой , простенький , таймер , вместе с pulseIn работает крайне некорректно (да и pulseIn в это время тоже)

 

 long previousMillis = 0;
 void setup()

{
  pinMode(13,OUTPUT);
}


void loop()

{
 if (millis() -previousMillis >1000) 
 {  
   previousMillis = millis();  
   digitalWrite(13, !digitalRead(13));
 }
 
}

 

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

 

На досуге надо заняться изысканием замены pulseIn , пусть менее элеганттным зато более функциональным.

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

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

Все !

Это последняя версия этого робота - Tankbot v7 (седьмая версия платы !).

Я так и не смог сделать переключение между режимами с ИК пульта .

Сделал переключение на кнопке.

Сделал два нижних датчика (впереди).

Один датчик работал плохо , теперь если и упадет , то только при движении назад. 

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

Поставил подстроечный резистор на ИК свотодиоды , теперь можно регулировать дальность от 5см до 40см.

В конце видео фотик сдох , так что других фото/видео материалов , в ближайшее время ,не будет.

Видео

video.mail.ru/mail/heruvim219/Tank-Bot/21.html