Нужна идея (распараллеливание процессов)
- Войдите на сайт для отправки комментариев
Делаю вот такую штуку (уже текущее состояние): http://www.youtube.com/watch?v=2uaoDtSHL4Y
Все работает... почти.
Работа с дисплеем построена достаточно просто - есть массив, описывающий текущее состояние каждого "пиксела" и есть прерывания - по прерыванию считывается инфомрация о следующей строке и она отображается и т.п.
Чтобы с дисплеем было удобно работать - написал библиотекчку и несколько "простых" функций. К примеру, вывод "бегущей строки" делается одной строчкой:
matrix.printRunningString(string, color, font6x8, FAST);
Девайс оснащен ИК-приемником и модулем RF24L01 и вот тут "подкрался незаметно".
Когда на экране что-то статичное (отображение часов на видео) - тут все происходит быстро - функция "статичной" печати быстренько правильно заполняет массив и МК спокойно получает и обрабатывает команды от ИК и принимает от RF24, а вот когда работает функция бегущей строки - мы из основного цикла уходим в обработку функции "сдвигов" и пока вся анимация не пройдет - в основной цикл не возвращаемся и, соответственно, пропускаем все, что только можно.
Чтобы было более понятно - приведу структуру "базовой" функции, которая занимается "печатью" строки и анимацией:
// печатаем строку void Matrix::printString(String s, byte pos, byte color, unsigned char *Font, char effect, int speed) { // .............. // инициаизация и подготовка // .............. if (effect==1) { // сдвижка вверх for (i=0; i<8; i++){ // .............. // что-то тут делаем // .............. } ready=millis()+speed; while(millis()<ready); } else if (effect==2) { // сдвижка вниз for (i=0; i<8; i++){ // .............. // что-то тут делаем // .............. } ready=millis()+speed; while(millis()<ready); } else if (effect==3) { // сдвиг влево for(k=0; k<(32-empty*longStringFlag); k++){ // проходим 32 шага - чтобы самый крайний правый пиксель уехал влево до конца // .............. // что-то тут делаем // .............. } ready=millis()+speed; while(millis()<ready); } }
Очевидно, что проблема в том, что когда ждем следующую итерацию для сдвига - крутимся в пустом цикле (и сюда бы как раз включить "прослушивание" ИК и RF24), но вот как это корректно сделать, особенно с учетом того, что управление экраном вынесено в библиотеку и эта библиотека о своем "окружении" вообще ничего не знает?
Или как вместо этого "пустого цикла" возвращаться на время в loop, а потом - снова вернуться в "анимационную" функцию да еще и в нужном состоянии?
P.S. пример blink без delay освоен, но вот как его применить конкретно тут - ума не приложу :(
P.P.S. RF24 я могу повесить на прерывание и это закроет часть проблемы.. с ИК я так сделать точно не смогу.
Почему с ИК не сможете? библиотеку маленько покурите на второе прерывание сожайте и все будет работать.
как я понял, вы получаете строку и пока она вся не выведется, у вас контроллер тупит с ИК...
тогда напрашивается все красивости не сразу делать, а разбить на отдельные шаги, т.е сдвигать не все 8 строк или 32 столбца в цикле, а за раз на 1 строку/столбец(уменьшится время прерывания, больше отойдет на выполнение основной программы)
с прерываниями тоже не все так гладко, как ожидалось.
При "отрисовке" прерывание предельно короткое и работаем вообще с минимальным "квантом" изображения - одной строкой.
По срабатыванию прерывания вызывается функция, которая гасит текущую строку, записывает в регистры состояние следующей строки, зажигает новую строку и возврат. Еще больше укоротить это прерывание - не представляется возможным :(
Оппа.. взлетело.
Сделал так.. в основном скетче создал функцию:
В соответствующих функциях как раз работа с ИК и RF
Эта же функция включена в основном цикле.
В файл объявления библиотеки (lib.h) тоже добавил описание этой функции
чтобы можно было ее вызывать, и дальше в базовой функции, что упоминалась выше, "пустые" циклы поправил на:
И это сработало...
Теперь и радио работает, и ик-команды принимаются, даже если строка движется. Результат достигнут, но, конечно, это "костыль".
И никаких "визуальных эффектов".
Я шел более простым путем, без прерываний
Все действия с датчиками, матрицами, радио, экраном и т.п. описал отдельными функциями и каждой позволяю выполнять по одному действию не менее чем через ххх миллисекунд (конечно никаких delay нигде). Например бегущая строка, если есть что показывать, то выполняет по одному действию каждые 60 мс (),не чаще,датчики и радио по пол секунды, и т.п.
ну для распараллеливания(запарился выписывать :) ) можно вообще прикрутить RTOS какой нить, вроде как для мег есть куцая версия
Я делал табло на двух мк. Один работал с матрицей и принимал команды и данные через последовательный порт,
пока отображались данные из одного буфера, второй заполнялся данными.
Второй мк обрабатывал сигналы от датчиков, пульта д.у. и т.д. и передаавл данные первому.
Я делал табло на двух мк. Один работал с матрицей и принимал команды и данные через последовательный порт,
пока отображались данные из одного буфера, второй заполнялся данными.
Второй мк обрабатывал сигналы от датчиков, пульта д.у. и т.д. и передаавл данные первому.
Это было бы уже просто.
Сейчас есть желание обойтись одним МК и вроде как мега должна справиться (и, как оказалось, это правда, но я узнал много нового и выкрутился "костылями"), но дальше потенциально подключение LAN-модуля (или даже WiFi) - чувствую, что это еще не все "грабли" на которые я наступил...
Теперь буду знать, что динамическая индикация - это задача для отдельного МК, и если задачи только этим не ограничиваются - лучше использовать специализированый контроллер (чтобы этот контроллер "рулил" матрицами) и для остальных задач - мега (или что-то там, что есть в наличии).
С одним можно, но надо всё правильно разрулить. И работать через прерывания, основной приоритет матрице.
Сделать вывод для неё в прерывании и с минимальным числом команд, используя или "чистый C" или asm.
А остальные пп разделить по приоритету и минимизировать время их выполнения.
Или как вариант табло со статической индикацией.
Для работы с отображением на матрице используется вот такая функция (обработчик прерывания):
Вот как этой фукнции назначить максимальный приоритет? "Визуальные эффекты" начинаются из-за того, что другое прерывание "смещает" по времени исполенине этой функции. А сделать это другое прерывание "короче" - уже тоже не получается - упираюсь в модуль RF24
В Mega невозможно назначить приоритет событию, как в XMega или 51. Поэтому
лучше или не использовать прерывания с большим приоритетом или в какие то
моменты их запрещать. Сколько ещё и какие прерывания используете?
>> сделать это другое прерывание "короче" - уже тоже не получается - упираюсь в модуль RF24
ustas, вероятно, можно в обработчике прерывания только поставить флаг, типа "радио модуль просит обратить на него внимание"=true.
А чуть позже, в основном loop, если true сделать listenRF24();
ustas, вероятно, можно в обработчике прерывания только поставить флаг, типа "радио модуль просит обратить на него внимание"=true.
Супер, спасибо! Это тоже сработало (возвращаюсь к работе на прерываниях - ничего не пропускаем через RF и зазря не используем машинное время). Еще раз спасибо!