Мой колесный аппарат на Ардуино Мега

zhenious
Offline
Зарегистрирован: 03.07.2014

Состав аппарата:
1. Ардуино Мега
2. Сенсор шилд
3. Мотор-драйвер
4. Четыре двигателя/колеса
5. Два сервопривода
6. Два УЗ датчика
7. Приемник 433МГц
8. Детский металлический конструктор

Состав пульта:
1. Макетная плата
2. Ардуино Нано
3. Передатчик 433МГц
4. Джойстик

С самого начала решил, что лучший вариант для сборки прототипа - металлический конструктор на болтиках и гаечках. Стоит всего 600+ руб. и предоставляет волю в конструировании.
Ардуино Мега - большое количество выводов для подключения датчиков и исполнительных устройств (в перспективе)
Сенсор шилд - для подключения питания к датчикам. Сервоприводы тоже подключены через него.
Брал два мотор-драйвера, но один не захотел работать. Поэтому подключил 4 движка к одному драйверу, левая сторона к одному выходу, правая - к другому.
После долгих попыток и раздумий, поворот колес решил сделать на сервоприводах. Просто к каждому сервоприводу приклеил редуктор с колесом.
Два УЗ датчика - задумка такая: например, левый датчик видит препятствие, правый - свободно, значит объезд справа.
Приемник 433МГц - дешевая односторонняя связь, передача данных с аппарата на пульт пока не предполагается.

С пультом все понятно - пояснений не требуется. В дальнейшем будет еще клавиатура на 5 кнопок, для выбора каких-нибудь режимов/команд работы аппарата.

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

С УЗ датчиками пока отработал такой алгоритм: если объект приблизился ближе 15см, то едем назад. Если свободно - вперед.

Концепция развития проекта такая: постепенное внедрение различных датчиков для регистрации критических состояний/опасностей. Например, ИК датчиков для определения отсутствия пола под колесами.

Моя страница с разработками:
https://vk.com/myrobotics

zhenious
Offline
Зарегистрирован: 03.07.2014

Несколько фоток:

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а такие контсрукторы разве еще продают?

помню был такой у меня  в детстве

zhenious
Offline
Зарегистрирован: 03.07.2014

Да, еще продают) Сам подобным игрался в 90е

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

как со стабильностью связи на таких модулях?

art100
Offline
Зарегистрирован: 09.03.2014

продают

есть даже очень нафаршированные 893 детали ~36$

а вам уже больше 7 лет?

вам можно?

http://oz.by/constructors/more10186443.html

http://minsk.deal.by/Metallicheskie-konstruktory.html Выбирайте из 42 предложений

думаю для катающегося робота хватит за глаза в 300 деталей 30$ 

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

так что за "вечные иглы" деньги смешные

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

мне можно. мама разрешила

вот чем нужно баловаться))) металл, а не китайский пластик

 

art100
Offline
Зарегистрирован: 09.03.2014

jeka_tm пишет:

мне можно. мама разрешила

вот чем нужно баловаться))) металл, а не китайский пластик

 

нет

нужно комбинировать

у каждого материала есть плюсы и минусы

комбинация дает лучшие результаты

колесо лучше из пластмассы

выключатели лучше из пластмассы

каркас из метала

оси из металла

так что достаю конструктор и ищу колеса и стойки чтоб arduino mega прикрутить?

кодом поделитесь?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

по максимому из металла. только хардкор. шимом рулите))

zhenious
Offline
Зарегистрирован: 03.07.2014

jeka_tm пишет:

как со стабильностью связи на таких модулях?

В пределах комнаты работают, дальше не проверял

zhenious
Offline
Зарегистрирован: 03.07.2014

в моем случае такой http://market.yandex.ru/model.xml?modelid=10553453&hid=10470548

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

платы крепятся к металлу на нейлоновых стойках с нейлоновыми болтиками

по скетчу покажу позже

igsru
Offline
Зарегистрирован: 20.06.2014

А можно увидеть ваши скетчи?

Интересует кусок работы с приемником и  передатчиком

 

zhenious
Offline
Зарегистрирован: 03.07.2014

Схема подключения модулей аппарата к Ардуино.

zhenious
Offline
Зарегистрирован: 03.07.2014

Программирование аппарата-робота.
Два основных момента проекта:
1. Модульность. Для каждого устройства робота пишется свой модуль - отдельный класс/библиотека. Для удобства и читабельности скетча, а также использования в дальнейшем проектировании любых других роботов.
2. Частота работы скетча 10Гц. Для данного проекта достаточно опрашивать датчики и реагировать на окружающий мир 10 раз в секунду.

Текущая версия скетча для Ардуино Мега самого аппарата:

#include <KemaUS.h>
#include <KemaState.h>
#include <KemaDrive.h>
#include <VirtualWire.h>  //pin 11

  KemaDrive myDrive(2,3,4,5,6,7);
  KemaState curState;
  KemaState prevState;
  KemaUS ultraSonic(22,23,24,25);  
    
  long prevTime = 0;  //для алгоритма работы цикла loop() 10р/с
  long deltaTime = 0; //для алгоритма работы цикла loop() 10р/с
  int incomingByte = 0;  //для тестирования через сериал-порт
  boolean rfCtrl = true; // запрет/разрешение раидоуправления
  char passRfCtrl[4] = {'*', '*', '*', '*'};  //кодовое слово для проверки приходящего сообщения
  char act = '?';  //текущая команда
  
void setup()
{
  Serial.begin(9600);
  
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(2000);	 // Bits per sec
    vw_rx_start();  
    myDrive.turn(curState.turnAng());
}

void loop()
{
   
   prevTime = millis();
   uint8_t buf[VW_MAX_MESSAGE_LEN];
   uint8_t buflen = VW_MAX_MESSAGE_LEN;
   rfCtrl = true;
    
  // ---------------------------------------------------- Sensor Section
  curState.setEchoR(ultraSonic.pingR());
  curState.setEchoL(ultraSonic.pingL());
  
  //----------------------------------------------------- RF control
    if (vw_get_message(buf, &buflen)) // Non-blocking
    {
	int i;
        char letter;
        rfCtrl = true;
        for (i = 0; i < buflen-1; i++)
	{
	    letter = buf[i];
            if(letter != passRfCtrl[i])	 
            {
                rfCtrl = false;
                break;
            }   
	}
	if(rfCtrl)
        {
            letter = buf[buflen-1];
            Serial.println(letter);
            switch (letter)
            {
              case 'S':  
              curState.setAct('S'); 
              curState.setSpeed(0); 
              act = 'S';
              break;
              case 'B':   
              curState.setAct('B');
              curState.setSpeed(curState.speed()-1); 
              act = 'B';
              break;
              case 'F':
              curState.setAct('F');    
              curState.setSpeed(curState.speed()+1);
              act = 'F';
              break;
              case 'R':
              curState.setAct('R');
              curState.setTurnAng(curState.turnAng() + 10);
              act = 'R';
              break;
              case 'L':
              curState.setAct('L');
              curState.setTurnAng(curState.turnAng() - 10);
              act = 'L';
              break;
              case 'W':
              curState.setAct('W');
              curState.setTurnAng(0);
              act = 'W';
              break;
     
            }
           
        }
    }   
  // ---------------------------------------------------- Smart Section
  
  if(!rfCtrl)
  {
    if((curState.echoR() < 300) && (curState.echoL() < 300)) //stop
    {
      curState.setAct('S');
      curState.setSpeed(0);
      act = 'S';
    }
    
    if((curState.echoR() < 150) && (curState.echoL() < 150)) //back
    {
        curState.setAct('B');
        curState.setSpeed(curState.speed()-1);  
        act = 'B';
    }
  
    if((curState.echoR() == 0) && (curState.echoL() == 0)) //forward
    {
       curState.setAct('F');    
       curState.setSpeed(curState.speed()+1);
       act = 'F';
    }
  }
   
     if (Serial.available() > 0)
  {
     incomingByte = Serial.read();
     Serial.println("command");
     if (incomingByte == 52)
     {
       curState.setAct('L');
       curState.setTurnAng(curState.turnAng() - 10);
       act = 'L';
       Serial.println("left");
     }
     if (incomingByte == 53)
     {
        curState.setAct('W');
        curState.setTurnAng(0);
        act = 'W';
        Serial.println("stop");
     }
     if (incomingByte == 54)
     {
          curState.setAct('R');
          curState.setTurnAng(curState.turnAng() + 10);
          act = 'R';
          Serial.println("right");
     }

  }
  // ---------------------------------------------------- Drive Section
    switch (act)
    {
      case 'S':
        myDrive.move(curState.speed());  
      break;
      case 'B':
        myDrive.move(curState.speed());
      break;
      case 'F':
        myDrive.move(curState.speed());
      break;
      case 'R':
        myDrive.turn(curState.turnAng());
        
      break;
      case 'L':
        myDrive.turn(curState.turnAng());
        
      break;
      case 'W':
        myDrive.turn(curState.turnAng());
        
      break;
     
    }
    
  // --------------------------------------------------- Final Section
  act = '?';
  prevState = curState;
  deltaTime = millis() -  prevTime;
  if(deltaTime < 100)
       delay(100 - deltaTime);
 // Serial.println(curState.act());
  
}

Модуль KemaUS - библиотека для работы с ультра-звуковыми датчиками.
Модуль KemaState - библиотека для сохранения состояния аппарата (скорости, показания дачткиов и т.д.).
Модуль KemaDrive - библиотека для движения робота (управление двигателями, сервами для поворотов).
VirtualWire - библиотека для работы с радио-передатчиком.

Sensor Section - секция скетча для снятия показаний с датчиков.
RF control - секция для радиоуправления. С пульта приходят сообщения из 5 символов, 4 первых - кодовое слово, 5-ый - команда.
Smart Section - "умная" секция для принятия решений по показаниям датчиков. Также в этом месте скетча код для тестирования с консоли через сериал порт.
Drive Section - исполнительная часть программы. Выполняет команды для управления двигателями и сервами. набор команд:
S - стоп
B - назад
F - вперед
R - право
L - лево
Final Section - конец скетча. Сбрасывается команда, сохраняется текущее состояние аппарата, выполняется алгоритм для поддержки частоты 10гц.

zhenious
Offline
Зарегистрирован: 03.07.2014

Скетч для Ардуино Нано пульта радиоуправления:

#include <VirtualWire.h>
 
       int VRx; //ось х джойстика
       int VRy; //ось у джойстика
       int SW;
       unsigned long curTime;
       char act, prevAct;  //команда
       char *msg = "****"; //кодовое слово
void setup() {                

  Serial.begin(9600);  
   vw_set_ptt_inverted(true); 
   vw_setup(2000);	 // Bits per sec

}

void loop()
{
       
       VRx = analogRead(0);
       if(VRx < 100) 
       {
          act = 'L';
          msg = "****L";
          curTime = millis();
       }   
       if(VRx > 900) 
       {
          act = 'R';
          msg = "****R";
          curTime = millis();
       }
       VRy = analogRead(1);
       if(VRy < 100) 
       {
          act = 'F';
          msg = "****F";
          curTime = millis();
       }   
       if(VRy > 900) 
       {
          act = 'B';
          msg = "****B";
          curTime = millis();
       }
       if(prevAct != act)  
       {     
           Serial.println(act);  
           vw_send((uint8_t *)msg, strlen(msg));
           vw_wait_tx(); 
       }    
       if(( millis() - curTime) > 500)
            act = '?';
      
       prevAct = act;
       delay(200);
}

Описание и ссылки библиотеки VirtualWire брал с arduino.cc.
С джойстиком все просто: считываем analogRead() с оси х и оси у, значения меняются от 0 до 1000+.

zhenious
Offline
Зарегистрирован: 03.07.2014

Выкладываю видео - демонстрация работы УЗ датчиков. Радиоуправление отключено.

http://vk.com/video-73778892_169217223

копия на http://youtu.be/KQMuNkswav4

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

art100
Offline
Зарегистрирован: 09.03.2014

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

1.а где брать это?

#include <KemaUS.h>
#include <KemaState.h>
#include <KemaDrive.h>
#include <VirtualWire.h>  //pin 11
KemaDrive myDrive(2,3,4,5,6,7);
KemaState curState;
KemaState prevState;
KemaUS ultraSonic(22,23,24,25);

заказал верно?

2.УльтроЗвук вроде такой http://ru.aliexpress.com/item/1pcs-Ultrasonic-Module-HC-SR04-Distance-Measuring-Transducer-Sensor-for-Arduino-HC-SR04-HCSR04/558618295.html?productId=558618295

3.Радио вроде такое http://ru.aliexpress.com/item/Lowest-Price-433Mhz-RF-transmitter-and-receiver-kit-for-Arduino-Project-Drop-Shipping-TK0460/1754885635.html?productId=1754885635

4.Моторы вроде такие http://ru.aliexpress.com/item/Free-shiping-4Lot-package-Deceleration-DC-motor-supporting-wheels-smart-car-chassis-motor-robot-car/1880306880.html?productId=1880306880

5.Моторный щиток какой похоже на L298 один корпус на два задних мотора? этого добра не попалил еще ни одной

а серво какие? может ссылка есть? по слухам SG90 с качалкой чтоб приклеить

6.с качалками дешевле чем за 5 штук не нашел Такие вроде? http://ru.aliexpress.com/item/Hot-sell-5X-SG90-9g-Mini-Micro-Servo-for-RC-for-RC-250-450-Helicopter-Airplane/1766910256.html

щас попробую рассмотреть

 

 

art100
Offline
Зарегистрирован: 09.03.2014

...

zhenious
Offline
Зарегистрирован: 03.07.2014
#include <KemaUS.h>
#include <KemaState.h>
#include <KemaDrive.h>

Это собственноручно написанные классы https://yadi.sk/d/dpl6VfuRWSZoC

Все верно HC-SR04, 433RF, обычные желтые двигатели (1:48), драйвер на L298 и маленькие SG90.

все это добро брал здесь http://www.miniinthebox.com/arduino_c5028

синие колеса и нейлоновые стойки здесь http://dvrobot.ru/shop/i441.Koleso_sinee.htm и http://dvrobot.ru/shop/i666.stoyka_papa_korotkaya.htm

 

zhenious
Offline
Зарегистрирован: 03.07.2014

Видео - поворот колес на сервоприводах. Управление с РУ пульта.

http://vk.com/video-73778892_169237848

http://youtu.be/ls2U3A_UEn8

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

art100
Offline
Зарегистрирован: 09.03.2014


sender01.ino: в функции " void setup()':
sender01:12: ошибка: 'vw_set_ptt_inverted " не был объявлен в этой области
sender01:13: ошибка: 'vw_setup " не был объявлен в этой области
sender01.ino: в функции " void loop()':
sender01:49: ошибка: 'vw_send " не был объявлен в этой области
sender01:50: ошибка: 'vw_wait_tx " не был объявлен в этой области

 

это какой библиотеки нехватает ?

в приемнике тоже нехватает

reciver01.ino: в функции " void setup()':
reciver01:22: ошибка: 'vw_set_ptt_inverted " не был объявлен в этой области
reciver01:23: ошибка: 'vw_setup " не был объявлен в этой области
reciver01:24: ошибка: 'vw_rx_start " не был объявлен в этой области
reciver01.ino: в функции " void loop()':
reciver01:32: ошибка: 'VW_MAX_MESSAGE_LEN " не был объявлен в этой области
reciver01:41: ошибка: 'buf' не был объявлен в этой области
reciver01:41: ошибка: 'vw_get_message " не был объявлен в этой области

это у на что

void setup()
{
Serial.begin(9600);

vw_set_ptt_inverted(true); // требуется для DR3100
vw_setup(2000); // бит в сек
vw_rx_start(); 

а для радио ничего не надо добавлять?

не знаю такая версия подходит от 26.05.2013 ?

26.05.2013  10:37    <DIR>          examples
26.05.2013  15:38    <DIR>          util
26.05.2013  10:59            18 616 VirtualWire.cpp
21.03.2013  16:32            12 066 VirtualWire.h
               6 файлов         32 003 байт

компиляцию вроде и передатчик и приемник прошли, что там на выходе получится не представляю

пробежал по коду вроде все аккуратно

только поверхностно один лишний оператор глаз выцепил

насколько я понял сходу выбор из строки командного символа

  //----------------------------------------------------- RF control
  if (vw_get_message(buf, &buflen)){ // Non-blocking
    int i;
    char letter;
    rfCtrl = true;
    for(i=0; i<buflen-1; i++){
      letter = buf[i];
      if(letter!=passRfCtrl[i]){   rfCtrl=false;  }//               break;            }   
    }
    if(rfCtrl)        {
      letter = buf[buflen-1];
      Serial.println(letter);

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

  VRx = analogRead(0);
  if(VRx<100){          act='L'; msg="****L"; curTime=millis(); }   
  if(VRx>900){          act='R'; msg="****R"; curTime=millis(); }
  VRy = analogRead(1);
  if(VRy<100){          act='F'; msg="****F"; curTime=millis(); }   
  if(VRy>900){          act='B'; msg="****B"; curTime=millis(); }
и слушаем
switch (letter){
  case 'S': curState.setAct('S'); curState.setSpeed(0);                       act = 'S'; break;
  case 'B': curState.setAct('B'); curState.setSpeed(curState.speed()-1);      act = 'B'; break;
  case 'F': curState.setAct('F'); curState.setSpeed(curState.speed()+1);      act = 'F'; break;
  case 'R': curState.setAct('R'); curState.setTurnAng(curState.turnAng()+10); act = 'R'; break;
  case 'L': curState.setAct('L'); curState.setTurnAng(curState.turnAng()-10); act = 'L'; break;
  case 'W': curState.setAct('W'); curState.setTurnAng(0);                     act = 'W'; break;
}

глаз еще лишнее вроде выцепил

кнопочек добавить повидимому

не ясно W это просто лишнее или с умыслом?

вроде решение трапеции

что там дальше будет пока не знаю

точно пойду посплю

стил мне твой нравится

 

zhenious
Offline
Зарегистрирован: 03.07.2014

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

по своему коду:

да, достаем последний символ из строки послания - управляющий.

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

zhenious
Offline
Зарегистрирован: 03.07.2014

Прикрутил полноцветный LED модуль для сигнализации состояния робота.

Написал такую библиотеку для этого модуля:

#include "Arduino.h"
#include "KemaLED.h"

KemaLED::KemaLED(int rPin, int gPin, int bPin)
{
 	_rPin = rPin;
	_gPin = gPin;
	_bPin = bPin;
	
  pinMode(_rPin, OUTPUT); 
  pinMode(_gPin, OUTPUT);
  pinMode(_bPin, OUTPUT);
	
  analogWrite(_rPin, 0);
  analogWrite(_gPin, 0);
  analogWrite(_bPin, 0);
 
}

void KemaLED::led(char color)
{
    switch (color)
    {
      case 'R':
  	  	 analogWrite(_rPin, 0);
  		 analogWrite(_gPin, 255);
  		 analogWrite(_bPin, 255);
      break;
	  
      case 'G':
  	  	 analogWrite(_rPin, 255);
  		 analogWrite(_gPin, 0);
  		 analogWrite(_bPin, 255);
      break;
	  
      case 'B':
  	  	 analogWrite(_rPin, 255);
  		 analogWrite(_gPin, 255);
  		 analogWrite(_bPin, 0);
	  break; 
	  
      case 'Y':
  	  	 analogWrite(_rPin, 0);
  		 analogWrite(_gPin, 75);
  		 analogWrite(_bPin, 255);
      break;
	  
      case 'W':
  	  	 analogWrite(_rPin, 0);
  		 analogWrite(_gPin, 0);
  		 analogWrite(_bPin, 0);
      break;
	  
     
    }
}

В конструкторе задаются пины R, G, B (красный, зеленый, синий).

При подаче на соответствующий пин 0 - цвет на максимум, 255 - отсутствие цвета.

В метод led() передается цвет в виде char. Используются R G B Y W.  (Красный, зеленый, синий, желтый). W - типа белый, но на самом деле отключение LED всех цветов.

Модуль такой: http://www.miniinthebox.com/ru/5050-rgb-led-modules-full-color-display-module-red_p991018.html

 

zhenious
Offline
Зарегистрирован: 03.07.2014

Видео по использованию полноцветного LED модуля:

http://vk.com/video-73778892_169324157

http://youtu.be/wIxC7eGpphM

zhenious
Offline
Зарегистрирован: 03.07.2014

Прицепил спереди на платформу робота ИК датчики для обнаружения пола (его отсутствия) перед передними колесами.

Пара фоток:

Получилась простая библиотека:

#include "Arduino.h"
#include "KemaIR.h"

KemaIR::KemaIR(int ir1, int irr)
{
 	_ir1 = ir1;
	_irr = irr;
  pinMode(_ir1, INPUT);  
  pinMode(_irr, INPUT);
 
}

int KemaIR::pingL()
{
	  return digitalRead(_ir1);
}

int KemaIR::pingR()
{
	  return digitalRead(_irr);
}

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

zhenious
Offline
Зарегистрирован: 03.07.2014

Видео - Заезды на столе - используются ИК датчики для обнаружения края стола.

http://vk.com/video-73778892_169370651

http://youtu.be/hcbRNRprRSw

zhenious
Offline
Зарегистрирован: 03.07.2014

Поставил сзади платформы робота контактные датчики:

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

Библиотека для контактных датчиков:

#include "Arduino.h"
#include "KemaCrash.h"

KemaCrash::KemaCrash(int crashL, int crashR)
{
 	_crashL = crashL;
	_crashR = crashR;
  pinMode(_crashL, INPUT);  
  pinMode(_crashR, INPUT);
 
}

int KemaCrash::pingL()
{
	  return digitalRead(_crashL);
}

int KemaCrash::pingR()
{
	  return digitalRead(_crashR);
}

Два метода для правого и левого колеса. Видео - http://youtu.be/NUNYtZlqDgI

zhenious
Offline
Зарегистрирован: 03.07.2014

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

http://youtu.be/6t9xD_McWX0

http://vk.com/video-73778892_169419767

Полная библиотека по управлению двигателями и сервами:

KemaDrive::KemaDrive(int in1,int in2,int in3,int in4,int lpin, int rpin)
{
 	_in11 = in1; //левый передний двигатель
	_in12 = in2; //правый передений
	_in21 = in3; //левый задний
	_in22 = in4; //правый задний
	_lpin = lpin; //левая серва
	_rpin = rpin; //правая
	_rDefault = 51; //угол прямого положения правого колеса
	_lDefault = 51; //левого колеса
	_minSpeed = 150; //ШИМ минимальной скорости
	
  pinMode(_in11, OUTPUT); 
  pinMode(_in12, OUTPUT);
  pinMode(_in21, OUTPUT); 
  pinMode(_in22, OUTPUT);
  pinMode(_lpin, OUTPUT);
  pinMode(_rpin, OUTPUT);
  
  digitalWrite(_in11, LOW);
  digitalWrite(_in12, LOW); 
  digitalWrite(_in21, LOW);
  digitalWrite(_in22, LOW); 
  
  
}

void KemaDrive::move(int speed)
{
  if(speed == 0)
     stop();
  int curSpeed = _minSpeed - abs(speed)*int(_minSpeed/10);
  if(curSpeed < 0)
     curSpeed = 0;
  if(speed > 0)
     movFwd(curSpeed);
  if(speed < 0)
     movBck(curSpeed);
  
}

void KemaDrive::stop()
{
  digitalWrite(_in11, LOW);
  digitalWrite(_in12, LOW); 
  digitalWrite(_in21, LOW);
  digitalWrite(_in22, LOW); 
  
}

void KemaDrive::movBck(int speed)
{
    analogWrite(_in12, speed);
    digitalWrite(_in11, HIGH);
    digitalWrite(_in22, HIGH);
    analogWrite(_in21, speed);
}

void KemaDrive::movFwd(int speed)
{
    digitalWrite(_in12, HIGH);
    analogWrite(_in11, speed);
    analogWrite(_in22, speed);
    digitalWrite(_in21, HIGH);
     
}

void KemaDrive::turn(int ang)
{
  	if (ang == 0)
	   turnReset();
	if(ang < 0)
	   movL(abs(ang));
	if(ang > 0)
	   movR(ang);
}

void KemaDrive::movL(int ang)
{
        writeToServo(_lDefault - ang, _rDefault - correctAng(ang));
		
}

void KemaDrive::movR(int ang)
{
 	 	writeToServo(_lDefault + correctAng(ang), _rDefault + ang);
	 
}

void KemaDrive::turnReset()
{
 	 	writeToServo(_lDefault, _rDefault);
	     
}

void KemaDrive::writeToServo(int posL, int posR)
{
    for(int i=0; i<10; i++)
    {
        digitalWrite(_lpin, HIGH);
        delayMicroseconds(map(posL,0,180,544,2300)); 
        digitalWrite(_lpin, LOW);
        digitalWrite(_rpin, HIGH);
        delayMicroseconds(map(posR,0,180,544,2300)); 
        digitalWrite(_rpin, LOW);
        delay(5);
     }
}

int KemaDrive::correctAng(int ang)
{
   double B = 100.0 + 155.0/(tan(ang*3.14159265/180.0));
   double beta = atan(155.0/B);
   return int(beta*(180.0/3.14159265));
}

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да вы неутомимый. скоро в нем электроники будет больше чем  в бмв

zhenious
Offline
Зарегистрирован: 03.07.2014

Пояснения по методам:

move(int speed) - публичный метод для вызова из основного скетча. Скорость задается в единицах: +-1 до +-10 (- назад). 0 - стоп.  Высчитывает ШИМ и вызывает приватные методы: стоп, вперед, назад.

turn(int ang) - метод для поворота колес. Угол:- налево, + направо, 0 колеса прямо. Вызывает приватные методы: налево, направо и прямо.

writeToServo(int posL, int posR) - метод, подающий сигналы на сервы.

correctAng(int ang) - метод для корректировки разности углов поворота колес. (по этой теме моя статейка http://vk.com/wall-73778892_5)

zhenious
Offline
Зарегистрирован: 03.07.2014

jeka_tm пишет:

да вы неутомимый. скоро в нем электроники будет больше чем  в бмв

По плану еще всего 3 вещи: датчик скорости, компас и СД карта.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

например так

http://www.youtube.com/watch?v=3aaO30BLatM

а дальше так например

http://www.youtube.com/watch?v=kyPA6NQlucQ

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Главное что бы саб был посерьезней и спойлер.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

главное чтобы не получилось

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

А на самом деле пофигу что получится. Главное что бы самому разработчику нравилось.

zhenious
Offline
Зарегистрирован: 03.07.2014

Puhlyaviy пишет:
А на самом деле пофигу что получится. Главное что бы самому разработчику нравилось.

Все правильно, пусть это будет комок проводов с колесами, но свой родной )

zhenious
Offline
Зарегистрирован: 03.07.2014

Поставил датчик скорости:

Библиотека для модуля:

#include "Arduino.h"
#include "KemaSpeed.h"

KemaSpeed::KemaSpeed(int spd)
{
 	_spd = spd;
	_duration = 0;
	_speedMM = 0;
	_speedRPS= 0;	
  pinMode(_spd, INPUT);  
 
}

int KemaSpeed::getSpeed()
{
       if(digitalRead(_spd) == 1) 
          _duration = pulseIn(_spd, LOW, 50000);
       else
          _duration = pulseIn(_spd, HIGH, 50000);
       
       _speedRPS = (1000000.0/_duration)/43.96;
	   _speedMM = _speedRPS*204.1;
	   return int(_speedMM);
}

С помощью функции  pulseIn() считывается время прокрутки одной прорези в колесике датчика. Затем высчитывается скорость, на основе диаметров колеса робота и колесика датчика. На выходе getSpeed() - скорость в миллиметрах.

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

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

zhenious
Offline
Зарегистрирован: 03.07.2014

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

Сейчас один образ памяти весит около 40 байт, т.е. 1 сек = 400 байт.  В ардуино мега 8 кб ОЗУ - много не запомнишь...

Впрочем, для этих целей планировал модуль SD карты использовать, но пока попробую ОЗУ контроллера.

Как только потестирую, опубликую

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Puhlyaviy пишет:

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

 не могли бы вы помочь мне с написанием фуфельной библиотеки ? :) ТС их плодит одну за одной, а моя и одну ещё не родил..... извините, что сюда написал - за вами не угнацца :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

неееееееее ! не написать - понять чё не так !

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

сюда ушёл... чёбы не мешать :)

http://arduino.ru/forum/programmirovanie/biblioteka-ili-ya-glyuchyu-pomoshch

zhenious
Offline
Зарегистрирован: 03.07.2014

Прикрутил к пульту радиоуправления клавиатуру на 5 кнопок:

Поправил скетч для пульта:

 #include <VirtualWire.h>
 
       int VRx;
       int VRy;
       int SW;
       int adc_key_val [5] = {0, 141, 327, 501, 739};
       int key = -1;
       unsigned long curTime;
       char act, prevAct;
       char *msg = "kema";
void setup() {                

  Serial.begin(9600);  
   vw_set_ptt_inverted(true); // Required for DR3100
   vw_setup(2000);	 // Bits per sec

}

// the loop routine runs over and over again forever:
void loop()
{
       
       VRx = analogRead(0);
       if(VRx < 100) 
       {
          act = 'L';
          msg = "kemaL";
          curTime = millis();
       }   
       if(VRx > 900) 
       {
          act = 'R';
          msg = "kemaR";
          curTime = millis();
       }
       VRy = analogRead(1);
       if(VRy < 100) 
       {
          act = 'F';
          msg = "kemaF";
          curTime = millis();
       }   
       if(VRy > 900) 
       {
          act = 'B';
          msg = "kemaB";
          curTime = millis();
       }
       
       key = get_key (analogRead (3));
       switch (key)
       {
          case 0: 
            act = 'P';
            msg = "kemaP";
            curTime = millis();
          break;
          case 1: 
            
          break;
          case 2: 
             
          break;
          case 3: 
            
          break;
          case 4: 
            act = 'M';
            msg = "kemaM";
            curTime = millis();
          break;
      }
                
       if(prevAct != act)  
       {     
           Serial.println(act);  
           vw_send((uint8_t *)msg, strlen(msg));
           vw_wait_tx(); 
       }    
       if(( millis() - curTime) > 500)
            act = '?';
      
       prevAct = act;
       delay(200);
}

int get_key (unsigned int input)
{
   int k;
   int delta;
   for (k = 0; k < 5; k++)
   {
      delta = input - adc_key_val [k];
      if (abs(delta) < 5)
             return k;
       
   }
   if (k >= 5) k = -1; // No valid key pressed
   return k;
}

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

int adc_key_val [5] = {0, 141, 327, 501, 739} - в массиве значения для каждой кнопки.

int get_key (unsigned int input) - функция выбирает кнопку по значениям из массива.

Оператор switch в строках 051-072 выбирает команду по нажатой кнопке. 

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

zhenious
Offline
Зарегистрирован: 03.07.2014

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

zhenious
Offline
Зарегистрирован: 03.07.2014

Первые тесты памяти до 3 сек.

http://youtu.be/flpF5y9pQIs

Откат по памяти в исходную позицию. В начале движение по РУ, а потом откат по записанной памяти (3 сек). Мерцание диода - РУ режим, синий цвет - режим движения по памяти.

SLOM
Offline
Зарегистрирован: 06.11.2014

что нового? или проект помер? 

zhenious
Offline
Зарегистрирован: 03.07.2014

Проект живет, но показывать нового нечего.

Недавно делал первый небольшой ремонт - заели шестеренки в редукторе. Разобрал, построгал ножом.

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

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

SLOM
Offline
Зарегистрирован: 06.11.2014

компас на борту с электроникой, тем более где моторы и провода под большим током, работать как надо -не будет! 

поэтому ставят гироскопы. 

zhenious
Offline
Зарегистрирован: 03.07.2014

SLOM пишет:

компас на борту с электроникой, тем более где моторы и провода под большим током, работать как надо -не будет! 

Ну так ведь нельзя... Все удовольствие и есть в "творческих муках" !

arduinonovice
Offline
Зарегистрирован: 02.02.2016

Подскажите как колеса от конструктора с отверстием около 5 мм насадить на сервопривод?

http://ru.aliexpress.com/item/Practical-SG90-9g-Mini-Micro-Servo-For-RC-...

https://market.yandex.ru/product/11865474?hid=10470548&show-uid=54435858...

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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