Недавно кое кто жаловался, что на ардуйне на mega1280 можно шевелить малым количеством серв по USB (пан и тилт для нескольких камер).
Решив сварганить подобное на спор, я взял мк, у которого не было ни аппаратного USB для связи с ПК, ни 13ти хардварных каналов сравнения (attiny2313), далее сварганил платку, написал пару сотен строк кода и вуоля:
Attiny2313 рулит 13 сервомашинками 16-битным ШИМом по USB при практически отсутствующих внешних компонентах. Опция выставлять все каналы в Z-состояние из командной строки расслабляя сервомашинку в комплекте.
Как оно работает?
Тупо. Я заюзал единственный 16-битный таймер, заставил его считать до ICR1, и дергать прерывание при оверфлоу. ICR1 давал как раз 50Hz. Вся output-compare логика делается программно, пока мы не выполняем усб трансферов. То есть погрешность некоторая есть, но на нее серве плевать. Со всеми плюшками влезло в 1918 байт, да еще сотенка осталась!
Результат поначалу выглядел хреново. С 12Mhz кварцем все было очень дергано для реального применения. С 16Mhz разницы между аппаратным и полупрограммным ШИМом уже увидть было нельзя, лишь небольшие скачки при передаче данных по усб. На 18Mhz или 20Mhz это даст еще более годные результаты, но таких кварцев рядом не валялось. (Хотя в проше я их задефайнил.).
Клиентское ПО я написал (опять) на луа, лежит вместе с lunartool на github. (servo-ctl аплет)
Схематика, плата и прошивка так же на github’е
Больше фотографий тут
Существует ли какой нибудь способ сделать так, чтобы AVR с программной реализацией юсб мог достаточно быстро выполнять что-то кроме «я слушаю линии d+ d- и жду сигнала»?
А то в голову приходит только вариант «После получения команды ‘фас’ не выполнять usbpool()(и вообще выставить через на ноге отвечающей за int0 состояние 0). Потом сосредоточиться на выполнении полезной подпрограммы. После окончания выполнения, выполнять usbpool() и по факту получения какой либо команды, сбрасывать на компьютер накопленный результат если таковой есть».
Есть ли какие-нибудь иные варианты? И какие косяки можно поймать пытаясь сотворить доброе, разумное и вечное?
Разве что влепить кварц на 20Mhz. Ну и можно конечно замаскировать прерывание от int0, не вызывать usbpoll. Это не вызовет дисконнекта девайса. Но при попытке обращения софта в момент «недоступности» хостовый усб стек сконфузится. Проще для таких целей STM32 заюзать.