Всегда был интересен процесс интеграции тех или иных роботов в социальную, городскую сферу.Возникает очень много вопросов, как технического, юридического так и этического характера.
Что будет например если ваша поделка весом под 60 кг сломает, например, кому то ногу.Или собьется GPS-трек и робот спровоцирует ДТП на оживленном пешеходном переходе-перекрестке? Или подарит цветы не той, "незапрограммированной" девушке, ошибется цветом кожи клиента или доставит до адресата пиво теплым а шаурму холодной? Задавшись в один прекрасный момент идеей создания робота своей мечты можно получить ответы на некоторые эти вопросы, заодно, в очередной раз, попробовать перевернуть мир.Собственно под катом описан процесс создания некого универсального робота.Конкретно шасси.
Первые роботы были скорее "пробой пера"
Был такой, 2-х колесный
И такая модификация:
Ну и такая:
После изучения с полсотни вариантов конструкций, как заводских так и самодельных решено было взять за основу простую и изящную конструкцию типа «Краб» от тайландских мастеров газонокошения. Были визуально определены конструкция, механика и кинематика.
Итак, для создания нам понадобится:
- Кучка металлолома:
-
Колеса.Желательно выбрать с ярко выраженным протектором, параллельным оси колеса, чтобы реализовать грунто-зацеп и танковый разворот.В данном случае используются колеса от мотоблока.
-
Ведомые звезды.От мотоциклов, мокиков и прочей велосипедятины.
-
Электродвигатели с редуктором модели MY1016Z2 на 12 вольт.Как выяснилось позже запас магнитного насыщения сердечника и толщина изоляции обмоток такого двигателя позволяют запросто их перегружать напряжением в 24 вольта, повышая ток и мощность.
-
Мотоциклетная цепь. Была выбрана мотоциклетная цепь под номером 428, для пущей совместимости с большинством зубчатых колес.
-
Пульт дистанцинного управления.Использовать можно любой, был взят китайский для авиамоделизма, с радиусом действия до 400м.
-
Микроконтоллер Atmega 8a.
-
Парочка сборок Дарлингтона для управления электромагнитными реле.К примеру ULN2803AFWG.
-
Электромагнитные реле и постели для них, применяющиеся преимущественно на автомобилях.
![image](https://habrastorage.org/webt/ud/i3/8p/udi38psgbjxvm9qomjdj9nfwyww.jpeg" size=2560x189)
- Свинцовая аккумуляторная батарея.
Спустя пару месяцев махания диском болгарки, росчерка электродами и конструкция из пота, крови и металла была готова.
Ступицы, оси, шайбы и прочие запчасти.Не обошлось без токарных работ по вытачиванию упоров, натяжных роликов для цепей.
Кусок металла и куча проводов:
Электронная начинка для теста всей конструкции предельная проста:
Atmega напрямую прикрученная к транзисторной сборке, которая напрямую управляет реле.Реле, надо отметить, коммутируют нагрузку через самодельные дросселя, чтобы немного сгладить якорные токи при пуске двигателей.
Переполюсовка питания двигателей также осуществляется по команде с Atmeg`и через отдельные реле.
Проведя процедуру привязки приемника к пульту, замкнув сервисной перемычкой контакты на приемнике, на сленге "Bind" — можно приступить к программированию управления пультом.
Посмотрим на выходные сигналы с приемника осциллографом:
Ага, в взависимости от положения стика меняется длительность импульса.Можно обработать это микроконтроллером, считывая уровни сигналов, считая такты-длительность.
Пару-десятков тестов для калибровки и код был написан.
Так выглядит исходник по приему сигналов с приемника и управлением роботом.
;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)
edmus
20.10.2021 20:55+1Что будет например если ваша поделка весом под 60 кг сломает, например, кому то ногу.Или собьется GPS-трек и робот спровоцирует ДТП на оживленном пешеходном переходе-перекрестке?
Для этого существуют стандарты. Например для автомобилей: ISO 26262 — международный стандарт по функциональной безопасности дорожных транспортных средств.
Wesha
21.10.2021 02:33залипание контактной части реле, вследствии возрастания тока.
История учит, что она ничему не учит...
vakhramov
21.10.2021 11:26+2>Что будет например если ваша поделка весом под 60 кг сломает, например, кому то ногу
Тут надо определиться, бага это или фича)
Cubus
22.10.2021 13:35Кусок металла и куча проводов:
А почему у колёс направление протектора разное? Слева "наружу", а справа "внутрь"?
COKPOWEHEU
22.10.2021 17:52Данная телега легко справляется с большинством препятствий, значительными уклонами до 40 ‰
40 ‰ это 4 %, то есть 2,2º, если я правильно посчитал.
TimID
29.10.2021 13:33У вас же коллекторный электромотор, какое ещё векторное управление?
И задумайтесь лучше о двигателе без редуктора. Одно дело - крутить колесо велосипеда с постоянной скорость, а другое - испытывать постоянные толчки при "танковом" управлении.
В вашем случае даже может не BLDC нужен, а чистопородный асинхронник.
ophil
пока что не робот, а игрушка с пультом. Робот должен сам кататься. И пжлст, спрячьте ассемблер под кат, листать скучно
Areso
Существует две точки зрения. Одна чётко говорит об автономности, в то время как вторая разрешает роботам быть управляемыми. В частности, такое определение приведено в русской Википедии и на это указывает один из примеров в толковом словаре Кузнецова.