image


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


Что будет например если ваша поделка весом под 60 кг сломает, например, кому то ногу.Или собьется GPS-трек и робот спровоцирует ДТП на оживленном пешеходном переходе-перекрестке? Или подарит цветы не той, "незапрограммированной" девушке, ошибется цветом кожи клиента или доставит до адресата пиво теплым а шаурму холодной? Задавшись в один прекрасный момент идеей создания робота своей мечты можно получить ответы на некоторые эти вопросы, заодно, в очередной раз, попробовать перевернуть мир.Собственно под катом описан процесс создания некого универсального робота.Конкретно шасси.


Первые роботы были скорее "пробой пера"
Был такой, 2-х колесный





И такая модификация:



Ну и такая:



После изучения с полсотни вариантов конструкций, как заводских так и самодельных решено было взять за основу простую и изящную конструкцию типа «Краб» от тайландских мастеров газонокошения. Были визуально определены конструкция, механика и кинематика.
Итак, для создания нам понадобится:


  1. Кучка металлолома:

image


  1. Колеса.Желательно выбрать с ярко выраженным протектором, параллельным оси колеса, чтобы реализовать грунто-зацеп и танковый разворот.В данном случае используются колеса от мотоблока.


  2. Ведомые звезды.От мотоциклов, мокиков и прочей велосипедятины.


  3. Электродвигатели с редуктором модели MY1016Z2 на 12 вольт.Как выяснилось позже запас магнитного насыщения сердечника и толщина изоляции обмоток такого двигателя позволяют запросто их перегружать напряжением в 24 вольта, повышая ток и мощность.



image


  1. Мотоциклетная цепь. Была выбрана мотоциклетная цепь под номером 428, для пущей совместимости с большинством зубчатых колес.


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



image


  1. Микроконтоллер Atmega 8a.


  2. Парочка сборок Дарлингтона для управления электромагнитными реле.К примеру ULN2803AFWG.


  3. Электромагнитные реле и постели для них, применяющиеся преимущественно на автомобилях.



![image](https://habrastorage.org/webt/ud/i3/8p/udi38psgbjxvm9qomjdj9nfwyww.jpeg" size=2560x189)


  1. Свинцовая аккумуляторная батарея.

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


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


image


Кусок металла и куча проводов:


image


Электронная начинка для теста всей конструкции предельная проста:
Atmega напрямую прикрученная к транзисторной сборке, которая напрямую управляет реле.Реле, надо отметить, коммутируют нагрузку через самодельные дросселя, чтобы немного сгладить якорные токи при пуске двигателей.


Переполюсовка питания двигателей также осуществляется по команде с Atmeg`и через отдельные реле.


image


Проведя процедуру привязки приемника к пульту, замкнув сервисной перемычкой контакты на приемнике, на сленге "Bind" — можно приступить к программированию управления пультом.


Посмотрим на выходные сигналы с приемника осциллографом:


image


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


Пару-десятков тестов для калибровки и код был написан.


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


;by IC
;GK1
;PC5-муфта
;pc4-контакт 4- реверс правый борт (ВЫХОДНОЙ СИГНАЛ)
;pc3-контакт 3 -реверс левый борт (ВЫХОДНОЙ СИГНАЛ)
;pc2-контакт 2 -мотор-редуктор правый борт (ВЫХОДНОЙ СИГНАЛ)
;pc1-контакт 1 -мотор-редуктор левый борт (ВЫХОДНОЙ СИГНАЛ)
;pc0-ДВС (ВЫХОДНОЙ СИГНАЛ)G
;pb-ВХОДНОЙ СИГНАЛ ПДУ
;ПДУ - канал 4 - левый стик, лево-право
;ПДУ - канал 3 - левый стик, вверх-вниз
;ПДУ - канал 2 - правый стик, вверх-вниз (вниз-скважность уменьшается, вверх- скважность увеличивается)
;ПДУ - канал 1 - правый стик, лево- право (лево-скважность уменьшается, право- скважность увеличивается)
;d7-d8 -нейтраль
;0116h - высоко
;91 - низко
rjmp RESET ; Reset Handler
rjmp EXT_INT0 ; IRQ0 Handler
rjmp EXT_INT1 ; IRQ1 Handler
;rjmp TIM2_COMP ; Timer2 Compare Handler
;rjmp TIM2_OVF ; Timer2 Overflow Handler
;rjmp TIM1_CAPT ; Timer1 Capture Handler
;rjmp TIM1_COMPA ; Timer1 CompareA Handler
;rjmp TIM1_COMPB ; Timer1 CompareB Handler
;rjmp TIM1_OVF ; Timer1 Overflow Handler
;rjmp TIM0_OVF ; Timer0 Overflow Handler
;rjmp SPI_STC ; SPI Transfer Complete Handler
;rjmp USART_RXC ; USART RX Complete Handler
;rjmp USART_UDRE ; UDR Empty Handler
;rjmp USART_TXC ; USART TX Complete Handler
;rjmp ADC ; ADC Conversion Complete Handler
;rjmp EE_RDY ; EEPROM Ready Handler
;rjmp ANA_COMP ; Analog Comparator Handler
;rjmp TWSI ; Two-wire Serial Interface Handler
;rjmp SPM_RDY ; Store Program Memory Ready Handler
RESET:
cli
ldi r17, 0xff     
out 0x3D, r17                ;инициализация стэка
ldi R16, 0b00111111     ;порт С как выход
out 0x14, r16           ;настройка через регистр DDRC\
ldi R16, 0x0            ;порт B как вход
out 0x17, r16           ;настройка через регистр DDRB
ldi R16, 0x0            ;порт D как вход
out 0x11, r16           ;настройка через регистр DDRD
sbi 0x12, 0         ;устанавливаем бит активации Pull-up в PORTD для пина PD0
sbi 0x12, 1         ;устанавливаем бит активации Pull-up в PORTD для пина PD1
sbi 0x12, 2         ;устанавливаем бит активации Pull-up в PORTD для пина PD2
jmp PDU_mode
U_turn_right_PDU:
nop
CALL R1__LEFT_ON
CALL latency_relay_switch
CALL M1__LEFT_ON
CALL M2__RIGHT_ON
nop
jmp chanel3
U_turn_left_PDU:
nop
CALL R2__RIGHT_ON
CALL latency_relay_switch
CALL M1__LEFT_ON
CALL M2__RIGHT_ON
nop
jmp chanel3
PDU_mode:
chanel1:
ldi r21, 0
ldi r22, 0
ldi r23, 1
ldi r24, 0
nop
get_low:
nop
sbic 0x10, 0
jmp get_low            ;дождались нуля на PD0
get_rising:
nop
sbis 0x10, 0
jmp get_rising            ;дождались HIGH сигнала на PD0
get_falling:
nop
add r21, r23               ;основной бит
adc r22, r24               ;дополнительный
sbic 0x10, 0
jmp get_falling            ;Сигнал HIGH закончился
cpi r22, 1
breq U_turn_right_PDU
cpi r21, 0x9f   ;a0
brlo U_turn_left_PDU
chanel2:
ldi r21, 0
ldi r22, 0
ldi r23, 1
ldi r24, 0
nop
get_low2:
nop
sbic 0x10, 1
jmp get_low2            ;дождались нуля на PD0
get_rising2:
nop
sbis 0x10, 1
jmp get_rising2            ;дождались HIGH сигнала на PD0
get_falling2:
nop
add r21, r23               ;основной бит
adc r22, r24               ;дополнительный
sbic 0x10, 1
jmp get_falling2            ;Сигнал HIGH закончился
cpi r22, 1
breq Motion_forward_PDU
cpi r21, 0x9f   ;a0
brlo Motion_backward_PDU
nop
CALL M1__LEFT_OFF
CALL M2__RIGHT_OFF
CALL latency_relay_switch
CALL R1__LEFT_OFF
CALL R2__RIGHT_OFF
nop
chanel3:
ldi r21, 0
ldi r22, 0
ldi r23, 1
ldi r24, 0
get_low3:
sbic 0x10, 2
jmp get_low3            ;дождались нуля на PD0
get_rising3:
sbis 0x10, 2
jmp get_rising3            ;дождались HIGH сигнала на PD0
get_falling3:
add r21, r23               ;основной бит
adc r22, r24               ;дополнительный
sbic 0x10, 2
jmp get_falling3            ;Сигнал HIGH закончился
cpi r22, 1
breq Clutch_ON_PDU
CALL Clutch_OFF
nop
jmp PDU_mode
Clutch_ON_PDU:
CALL Clutch_ON
jmp PDU_mode
Motion_forward_PDU:
CALL R2__RIGHT_ON
CALL latency_relay_switch
CALL R1__LEFT_ON
CALL latency_relay_switch
CALL M1__LEFT_ON
CALL M2__RIGHT_ON
nop
jmp chanel3
Motion_backward_PDU:
CALL M1__LEFT_ON
CALL M2__RIGHT_ON
nop
jmp chanel3
LDI     R16,2       ; Загружаем адрес нулевой ячейки
LDI     R17,0       ; EEPROM 
;LDI    R21, 0x33       ; и хотим записать в нее число cc
RCALL   EEWrite     ; вызываем процедуру записи.
LDI     R16,1       ; Загружаем адрес нулевой ячейки
LDI     R17,0       ; EEPROM 
mov r21, r22
RCALL   EEWrite     ; вызываем процедуру записи.
ldi r25, 1               ;флаг записи епромки
LDI     R16,3       ; Загружаем адрес нулевой ячейки
LDI     R17,0       ; EEPROM 
mov r21, r25
RCALL   EEWrite     ; вызываем процедуру записи.
skip:
nop
jmp idle
EEWrite:    
SBIC    EECR,EEWE       ; Ждем готовности памяти к записи. Крутимся в цикле
RJMP    EEWrite         ; до тех пор пока не очистится флаг EEWE
CLI             ; Затем запрещаем прерывания.
OUT     EEARL,R16       ; Загружаем адрес нужной ячейки
OUT     EEARH,R17       ; старший и младший байт адреса
OUT     EEDR,R21        ; и сами данные, которые нам нужно загрузить
SBI     EECR,EEMWE      ; взводим предохранитель
SBI     EECR,EEWE       ; записываем байт
SEI                 ; разрешаем прерывания
RET                 ; возврат из процедуры
EERead: 
SBIC    EECR,EEWE       ; Ждем пока будет завершена прошлая запись.
RJMP    EERead          ; также крутимся в цикле.
OUT     EEARL, R16      ; загружаем адрес нужной ячейки
OUT     EEARH, R17      ; его старшие и младшие байты
SBI     EECR,EERE       ; Выставляем бит чтения
IN  R25, EEDR       ; Забираем из регистра данных результат
RET
Motion_forward:
CALL latency_relay_switch
CALL R2__RIGHT_ON
CALL latency_relay_switch
CALL R1__LEFT_ON
CALL latency_relay_switch
CALL M1__LEFT_ON
CALL M2__RIGHT_ON
CALL latency
CALL M1__LEFT_OFF
CALL M2__RIGHT_OFF
CALL latency_relay_switch
CALL R1__LEFT_OFF
CALL R2__RIGHT_OFF
Motion_backward:
CALL latency_relay_switch
CALL M1__LEFT_ON
CALL M2__RIGHT_ON
CALL latency
CALL M1__LEFT_OFF
CALL M2__RIGHT_OFF
U_turn_right:
CALL latency_relay_switch
CALL R1__LEFT_ON
CALL latency_relay_switch
CALL M1__LEFT_ON
CALL M2__RIGHT_ON
CALL latency
CALL M1__LEFT_OFF
CALL M2__RIGHT_OFF
CALL latency_relay_switch
CALL R1__LEFT_OFF
;ret
U_turn_left:
CALL latency_relay_switch
CALL R2__RIGHT_ON
CALL latency_relay_switch
CALL M1__LEFT_ON
CALL M2__RIGHT_ON
CALL latency
CALL M1__LEFT_OFF
CALL M2__RIGHT_OFF
CALL latency_relay_switch
CALL R2__RIGHT_OFF
;ret
jmp Motion_forward
TEST1:
CALL ICE_Start
CALL latency
CALL ICE_Stop
CALL latency
CALL M1__LEFT_ON
CALL latency
CALL M1__LEFT_OFF
CALL latency
CALL M2__RIGHT_ON
CALL latency
CALL M2__RIGHT_OFF
CALL latency
CALL R1__LEFT_ON
CALL latency
CALL R1__LEFT_OFF
CALL latency
CALL R2__RIGHT_ON
CALL latency
CALL R2__RIGHT_OFF
CALL latency
CALL Clutch_ON
CALL latency
CALL Clutch_OFF
jmp TEST1
idle:
;sbi 0x15, 5           ;PortC, бит 5
nop
jmp idle
EXT_INT0:
sbi 0x15, 5           ;PortC, бит 5
reti
EXT_INT1:
sbi 0x15, 4           ;PortC, бит 5
reti
;Задержка
latency_relay_switch:                 ;калиброванная задержка для переключения реле
ldi r20, 255
ldi r21, 100
;ldi r22, 1
delay2:
subi r20, 1
sbci r21, 0
;sbci r22, 0
brne delay2
nop
ret
;Задержка
latency:
ldi r20, 255
ldi r21, 255
ldi r22, 12
delay1:
subi r20, 1
sbci r21, 0
sbci r22, 0
brne delay1
nop
ret
ICE_Start:
sbi 0x15, 0           ;PortC, бит 0
RET
ICE_Stop:
cbi 0x15, 0           ;PortC, бит 0
ret
M1__LEFT_ON:
sbi 0x15, 1           ;PortC, бит 1
ret
M1__LEFT_OFF:
cbi 0x15, 1           ;PortC, бит 1
ret
M2__RIGHT_ON:
sbi 0x15, 2           ;PortC, бит 2
ret
M2__RIGHT_OFF:
cbi 0x15, 2           ;PortC, бит 2
ret
R1__LEFT_ON:
sbi 0x15, 3           ;PortC, бит 3
ret
R1__LEFT_OFF:
cbi 0x15, 3           ;PortC, бит 3
ret
R2__RIGHT_ON:
sbi 0x15, 4           ;PortC, бит 4
ret
R2__RIGHT_OFF:
cbi 0x15, 4           ;PortC, бит 4
ret
Clutch_ON:
sbi 0x15, 5           ;PortC, бит 5
ret

Clutch_OFF:
cbi 0x15, 5           ;PortC, бит 5
ret

После окончательной сборки и с полсотни выездов стало ясно что механика робота работает отлично.Данная телега легко справляется с большинством препятствий, значительными уклонами до 40 ‰, обладает запасом мощности, достаточной маневренностью.



Как видно на видео на некоторых участках местности крутящего момента двигателей явно не хватает.
Не беда — они легко выдерживают 2-х кратную перегрузку с повышением момента и оборотов.Достаточно установить в силовой цепи последовательно еще 1 аккумулятор, но при этом появляется другая большая проблема — залипание контактной части реле, вследствии возрастания тока.Что собственно и произошло — вдруг 60000 грамовая машина потеряв управление понеслась в недопустимую сторону.



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


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


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


На робота будут установлены более-менее профессиональные контроллеры электродвигателей с векторным управлением крутящего момента, различными программными функциями типа hard-stop, выполнено дублирование сигналов, установлена датчиковая аппаратура и литиевые аккумуляторы, будет заменен, на более интересный, микропроцессор.


Запись теплового следа и поиск отклонений для фиксаций нарушений охранного периметра и локальных техногенных дефектов.


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


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


P.S. Новые законы робототехники не за горами.
P.S.S. Рабочее название проекта "Grass-killer".

Комментарии (10)


  1. ophil
    20.10.2021 20:06
    +12

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


    1. Areso
      20.10.2021 23:48
      +2

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


  1. edmus
    20.10.2021 20:55
    +1

    Что будет например если ваша поделка весом под 60 кг сломает, например, кому то ногу.Или собьется GPS-трек и робот спровоцирует ДТП на оживленном пешеходном переходе-перекрестке?

    Для этого существуют стандарты. Например для автомобилей: ISO 26262 — международный стандарт по функциональной безопасности дорожных транспортных средств.


  1. maxwolf
    20.10.2021 23:38

    Ну наконец-то! Хоть кто-нибудь уже сделает приличную автономную газонокосилку.


    1. Wesha
      21.10.2021 02:29
      +1

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


  1. Wesha
    21.10.2021 02:33

    залипание контактной части реле, вследствии возрастания тока.

    История учит, что она ничему не учит...


  1. vakhramov
    21.10.2021 11:26
    +2

    >Что будет например если ваша поделка весом под 60 кг сломает, например, кому то ногу

    Тут надо определиться, бага это или фича)


  1. Cubus
    22.10.2021 13:35

    Кусок металла и куча проводов:

    А почему у колёс направление протектора разное? Слева "наружу", а справа "внутрь"?


  1. COKPOWEHEU
    22.10.2021 17:52

    Данная телега легко справляется с большинством препятствий, значительными уклонами до 40 ‰
    40 ‰ это 4 %, то есть 2,2º, если я правильно посчитал.


  1. TimID
    29.10.2021 13:33

    У вас же коллекторный электромотор, какое ещё векторное управление?
    И задумайтесь лучше о двигателе без редуктора. Одно дело - крутить колесо велосипеда с постоянной скорость, а другое - испытывать постоянные толчки при "танковом" управлении.
    В вашем случае даже может не BLDC нужен, а чистопородный асинхронник.