РОБОТ ИССЛЕДОВАТЕЛЬ 3Pi

В книге по беспроводной связи приведено описание bluetooth микросхемы WT12 для управления роботом с компьютера. Микросхема вместе со стабилизатором питания на 3.3 вольта умещается в коробочку от телефонной розетки

К плате припаивается розетка и первые четыре провода (земля, питание VCC и UART PD0, PD1) идут к WT12. Оптопара подключается туда же с помощью трехжильного JSR-кабеля: на рисунке красным проводом подключено питание, средний провод - земля, а белый отвечает информационному сигналу ADC7. Джампер подключения ADC7 к триммерному потенциометру вытягивается.

Для плавности движения скорость работы двигателей 3Pi задается как можно меньше, причем направления вращения колес у него одинаковое при одинаковых по знаку управляющих воздействиях. Добавление оптопары разнообразит поведение, программа беспроводного управления и адаптации помещена ниже. Тележка видит кота и ведет себя неагрессивно, она несколько мала, чтобы кот на ней катался.

Буфер UART закольцован, при выявлении 'C'-'O'-'M' последовательности символов следующий байт (COM) управляет моторами: 0 - стоп, 1 и 2 - повороты, 3 - адаптивное движение с анализом сигналов от сенсора расстояния, 4 - реверс (задний ход). Ответная передача данных датчика производится по принятии кода перевода каретки.


#include <pololu/3pi.h> 



char send_buffer[32];   

char receive_buffer[32];

unsigned char receive_buffer_position = 0;   

int TUART=0; char S1,S2,S3; int COM=3; int S=0;



void check_for_new_bytes_received(){    

char byte=0;   

while(serial_get_received_bytes()!=receive_buffer_position){   

    // Process the new byte that has just been received

    byte=receive_buffer[receive_buffer_position];   

    switch(byte){   

    case 'C': green_led(1); break;   

    case 13 : while(!serial_send_buffer_empty());   

    send_buffer[0] = S;   

    serial_send(send_buffer,1);   

    break;   

    }   

    if (byte) { TUART++;

      switch (TUART) {

      case 1: S1=byte; break; 

      case 2: S2=byte; break; 

      case 3: S3=byte; break; 

      default: 

      if (S1=='C') if (S2=='O') if (S3=='M') COM=byte-48; 

       S1=S2; S2=S3; S3=byte; TUART--; break; 

    }}

    if (receive_buffer_position == sizeof(receive_buffer)-1){   

    receive_buffer_position = 0;}else{receive_buffer_position++;}   

}}   



int main() {

// BLUETOOTH

serial_set_baud_rate(115200);

serial_receive_ring(receive_buffer,sizeof(receive_buffer));

// OPTICAL SENSOR

int T=0; int sum=0; int samples=0; 

set_analog_mode(MODE_8_BIT); start_analog_conversion(7);  

// MECHANICAL EFFECTOR

int motorSpeed1=0; int motorSpeed2=0; int V=30; 



while(1) {

//ADC 7

if (!analog_is_converting()){ 

  sum += analog_conversion_result();     

  start_analog_conversion(7);     

  if (++samples == 10){ 

  S = sum/10; samples = 0; sum = 0;

  }     

}

// CONTROL MODE

check_for_new_bytes_received();

switch(COM){

  case 0 : motorSpeed1=0; motorSpeed2=0; break;

  case 1 : motorSpeed1=-V; motorSpeed2=V; break;

  case 2 : motorSpeed1=V; motorSpeed2=-V; break;

  default: motorSpeed1=V; motorSpeed2=V;

  // TURN BY SENSOR

  if (T==0){ if (S>100) T=1; }else{

  if (++T == 80) T=0; motorSpeed2=-V; }

  break;

  // REVERSE

  case 4 : motorSpeed1=-V; motorSpeed2=-V; break;

}

set_motors(motorSpeed1,motorSpeed2); 

delay_ms(10);

}//while

}

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

Учет края стола

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


#include <pololu/3pi.h> 



char send_buffer[32];   

char receive_buffer[32];

unsigned char receive_buffer_position = 0;   

int T=0; int TUART=0; char S1,S2,S3; int COM=3; 

int A=7; int sum=0; int samples=0; int S=0; int U=0;

unsigned int sensor_values[5]; int n; int D=0; int K=0;    



void init_ADC(int N){

sum=0; samples=0; A=N; start_analog_conversion(A);

}



void check_ADC(int M){

if (!analog_is_converting()){ 

  sum += analog_conversion_result();     

  start_analog_conversion(A);     

  if (++samples == M){ 

  S = sum/M; samples = 0; sum = 0;

  }     

}}



int check_SNS(){

int i,n; n=0; D=sensor_values[n];

for (i=1;i<5;i++) if (D<sensor_values[i]) { 

D=sensor_values[i]; n=i; }

return n;

}



void GetPower() {    

  init_ADC(6); samples=1; 

  while (samples>0) check_ADC(10); U=100*S/155; 

  S=0; init_ADC(7); check_ADC(10);

}



void check_for_new_bytes_received(){    

char byte=0; int SS=0; int COMM; 

while(serial_get_received_bytes()!=receive_buffer_position){   

    byte=receive_buffer[receive_buffer_position];   

    switch(byte){  

    case 6 : GetPower();

    while(!serial_send_buffer_empty());

    send_buffer[0] = 123;

    send_buffer[1] = U; 

    serial_send(send_buffer,2);

    break;     

    case 7  : S=0; init_ADC(7); break;      

    case 13 : while(!serial_send_buffer_empty());

    send_buffer[0] = 123; 

    SS=4000/S; 

    send_buffer[1] = SS; 

    n=check_SNS(); SS=D/20;

    send_buffer[2] = SS;

    serial_send(send_buffer,3);   

    break;   

    }   

    if (byte) { TUART++;

      switch (TUART) {

      case 1: S1=byte; break; 

      case 2: S2=byte; break; 

      case 3: S3=byte; break; 

      default: COMM=COM;

      if (S1=='C') if (S2=='O') if (S3=='M') 

      { T=0; COM=byte-48; 

      if (COM==4)  if (COMM==4) COM=0; 

      }

       S1=S2; S2=S3; S3=byte; TUART--; break; 

    }}

    if (receive_buffer_position == sizeof(receive_buffer)-1){   

    receive_buffer_position = 0;}else{receive_buffer_position++;}   

}}   



int main() {

//print("Hello"); 

// SENSORS

pololu_3pi_init(2000);

set_analog_mode(MODE_8_BIT); GetPower(); 

// BLUETOOTH

serial_set_baud_rate(115200);

serial_receive_ring(receive_buffer,sizeof(receive_buffer));

// WAITING BUTTON

int W=1; while(W) { check_ADC(10); 

read_line_sensors(sensor_values,IR_EMITTERS_ON);

check_for_new_bytes_received();

unsigned char button = button_is_pressed(MIDDLE_BUTTON);

if (button==MIDDLE_BUTTON) W=0;

}

// MECHANICAL EFFECTOR

int motorSpeed1=0; int motorSpeed2=0;  

while(1) {

check_ADC(10);

read_line_sensors(sensor_values,IR_EMITTERS_ON);

check_for_new_bytes_received();

// CONTROL MODE

int V=40;

switch(COM){

  case 0 : motorSpeed1=0; motorSpeed2=0; break;

  case 1 : motorSpeed1=0; motorSpeed2=0;  

  if (T<30) { T++; motorSpeed1=-V; motorSpeed2=V;}

  break;

  case 2 : motorSpeed1=0; motorSpeed2=0; 

  if (T<30) { T++; motorSpeed1=V; motorSpeed2=-V;}

  break;

  default: // TURN BY SENSOR  

  if (T==0){ n=check_SNS(); 

  if (D>1500) { T=1; V=30; K=90;

   if (n>2) {

   motorSpeed1=V/4-V; motorSpeed2=V/2-2*V;

   }else{

   motorSpeed2=V/4-V; motorSpeed1=V/2-2*V;

   }

  }else{ 

  if (S>100) { T=1; K=60; 

  motorSpeed1=V; motorSpeed2=-V; 

  }else{

  motorSpeed1=V; motorSpeed2=V; 

  }}

  }else{ if (++T > K) T=0;}

  break;

  // REVERSE

  case 4 : motorSpeed1=-V; motorSpeed2=-V; break;

}

set_motors(motorSpeed1,motorSpeed2); 

delay_ms(10);

}//while

}

Со стороны компьютера робот управляется Visual MatLab, система формирует интерфейс, обработывает сигналы и, главное, взаимодействует с интернет.


y=-1, u=0, 

C=0, w=0, x=1, a=0, b=0, c=0, d=0, g=0 

open panel, getcamera, open mouse support



getpower, do, C=server, control(C),  pause 1, end



function: control(C)

if w=0, % управление роботом,

   if a>0, S=[67;79;77;48;13], s=command(S), a=0, end

   if b>0, S=[67;79;77;49;13], s=command(S), b=0, end

   if c>0, S=[67;79;77;51;13], s=command(S), c=0, end

   if d>0, S=[67;79;77;50;13], s=command(S), d=0, end

   if g>0, S=[67;79;77;52;13], s=command(S), g=0, end

   getgraph 

   % if C<123, if d>0, y=read(2), else, y=read(0), end end 

else if C<123, 

   if C>9 then C=C+65-10 else C=C+48 end

   e=write(119,'com9'), e=write(C,'com'), e=write(13,'com')

   end 

end



function: getpower

% запрос питания робота по виртуальному порту,

if w=0, e=read('com4'), e=write(6,'com'), pause 1

s=0, do 3,  if s<>123, s=read('com'), end, end, 

if s=123, s=read('com'), e=write(7,'com'), pause 1

e=read('com'), s=?_POWER; else e=write(7,'com')

pause 1, s=?_NO_SIGNAL; 

end end



function: s=command(S)

for i=1:size(S) do, e=write(S(i),'com'), end, 

s=read('com'), s=read('com'), s=read('com')



function: getgraph

e=write(13,'com'), 

s=0, do 3,  if s<>123, s=read('com'), end, end,

if s=123, s=read('com'), e=read('com'), 

if s>0, e=?, if y<0, y=[s e], else, y=[y;s e], y=?? 

end end end



function: click

  play click.wav

  if near Button1 then Button1 lights, a=1-a, else

  if near Button2 then Button2 lights, b=2-b, else

  if near Button3 then Button3 lights, c=4-c, else

  if near Button4 then Button4 lights, d=8-d, else

  if near Button5 then Button5 lights, g=16-g, getcamera 

  end, end, end, end, end

  C=a+b+c+d, control(C)



function: lights

subject Lamp paints red. pause 0.2

subject Lamp paints green.



function: C=server

C=123, if w>0, 

C=read('http://mathscinet.ru/.../command.xml')

pause 0.5,  if C>0, h=123,  

h=read('http://mathscinet.ru/.../image.xml')

pause 0.5,  if h>0, getcamera

e=write(0,'http://mathscinet.ru_folder=.../data/_file=image.xml')

pause 0.5

e=write(0,'http://mathscinet.ru_folder=.../data/_file=image.jpg')

pause 0.5

end end end



function: getcamera

if x=0, open background panel.jpg [:] else

X=read('camera.bmp:2'), e=write(0,'camera:file=image.jpg')

open background image.jpg [:] end

X=read('maxX'), Y=read('maxY'), X=X/2

Scene moves at [X;Y-20] position. 

Стандартное обеспечение

Pololu 3Pi robot это мобильная, высокопроизводительная платформа обладающая двумя металлическими мотор-редукторами, пятью отражающими сенсорами, один LCD дисплеем, зуммером, тремя кнопками, и все это соединяется с C/C++ програмируемым ATmega168 или ATmega328 микроконтроллером. С ипользованием навесной платы сверху это основа для построения роботов-кукол (ноги куклы).

Начиная с серийного номера 0J5840, 3Pi роботы поставляются с новым ATmega328P микроконтроллером, различия по отношению к прежнему варианту составляют 32 KB flash, 2 KB RAM, and 1 KB of EEPROM, так что код, написанный для младшей версии процессора, должен работать с минимальными модификациями и на ATmega328. Возможная скорость может достигать 1м/с.

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

Робот оснащен по бордюру датчиками, позволяющими на высокой скорости ощущать гоночную трассу. Вызов подпрограммы pololu_3pi_init(2000) устанавливает интервал опроса в линейке датчиков 2000*0.4 us = 0.8 ms.

Вводная информация от фирмы

Возможности к развитию

Навесное оборудование цепляется по UART (PD0 и PD1). Удалением джамперов высвобождаются два аналоговых входа и один аналоговый/дискретный вход/выход, которые не вполне свободны функционально. Через PC5 в библиотеке управления роботом подпитываются эмиттеры инфракрасных датчиков, поэтому помимо джампера нужно делать поправки в софте. Аналоговые входы ADC6 и ADC7 ориентированы на контроль напряжения питания и положения триммерного потенциометра. Удаление LCD-экрана полностью освобождает три пина (PB0, PD2, and PD4). Также PB1, PB4, PB5 и PD7 доступны для ограниченного использования. Ножки PB1, PB4, and PB5 соединены с тремя пользовательскими кнопками, а к PD7 подпаян зеленый светодиод LED пользователя.

Подведем итоги. Пины PD0 и PD1 полностью свободны (для TTL-коммуникации включая). Ножки PC5, ADC6 и ADC7 высвобождаются удалением джамперов. PC5 может использоваться как аналоговый вход или в роли дискретного входа-выхода, тогда как ADC6 и ADC7 рассматриваются исключительно как входы. Ножки PB0, PD2 и PD4 становятся полностью свободными дискретными I/O линиями при удалении LCD, тогда как такие же функционально PB1, PB4, PB5 и PD7 частично свободны, если внимательно следить, чтобы не было альтернативного использования. Важно отметить, что PB4 и PB5 задествованы программатором.

ОПИСАНИЕ

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

БИБЛИОТЕЧНЫЙ СЭТ



Rambler's Top100