Обсуждаем контроллеры компании Atmel.
Ответить

Led-глобус, проблема

Чт ноя 30, 2017 09:19:26

Здравствуйте, уважаемые.
Давно хотел сделать для себя устройство с механической разверткой. Собрал статор, ротор. Светодиодов не очень много, всего 24, но мне достаточно. Используемый МК - Atmega328p на 16МГц, регистры 74HC595. Программирую на CodeVision 3.12. С железом проблем нет. Есть трудности с программной частью. И именно по ней требуется помощь. Для начала сделал вывод по столбцам и тупой задержкой с помощью delay_us. Конкретно в моем случае задержка после выводка каждого столбца была 850мкс. Все работало. Потом решил сделать расчет времени задержки на таймерах и без delay_us. Задумка была такая - по INT0 начинается отсчет 16-битного таймера Т1 до следующего срабатывания INT0. На ноге с INT0 сидит ИК-диод и дает "ноль" в определенной точке вращение ротора, как в большинстве подобных схем. При каждом срабатывании INT0 делается расчет времени необходимого для вывода ОДНОГО столбца изображения. Всего 48 столбцов. Результат расчета помещается в 8-битный таймер Т2 и при его переполнении выводится очередной столбец изображения. Для Т1 выбран предделитель 64 (250кГц), для Т2 - 256 (62,5кГц). И вот где-то на этапе вычислений я либо не замечаю ошибки, либо не учитываю какую-то тонкость программирования МК. Ротор делает 10-12 оборотов в секунду, поэтому переполнения Т1 быть не должно. В результате получаю следующее - вывод всего изображения происходит где-то за 2-3 "предполагаемых" переполнения таймера2, т.е. примерно за 20 градусов от полного круга. Привожу полный код программы с подробными комментариями. Надеюсь на вашу помощь.

Re: Led-глобус, проблема

Чт ноя 30, 2017 23:52:33

И вот где-то на этапе вычислений я либо не замечаю ошибки, либо не учитываю какую-то тонкость программирования МК.
А как ты можешь заметить ошибку, если не видишь значений?
Что конкретно у тебя насчитывает таймер-1, что он вычисляет как значение для таймера-2?
Заведи массив на все 48 строк, чтобы за время "рисования" запомнить все значения TCNT1 в момент INT0 и вычисленного kw_t2 для каждой строки.
И выведи эти значения по окончанию всего цикла рисования, хотя бы через UART на консоль.
Потребуется 48 * (2 + 1 ) = 144 байта памяти для массива.
поэтому переполнения Т1 быть не должно.
Не должно или их точно нет?
Прерывание по переполнению вижу - добавь туда какое-нить диагностическое мигание.

Переменные, которые используются/изменяются как в основном цикле, так и в прерывании объяви volatible.

Re: Led-глобус, проблема

Пт дек 01, 2017 06:03:52

mas123, спасибо что откликнулся на зов помощи.
Проблематично вывести на консоль что-то с вращающейся штуковины, а если остановить, то и расчетов никаких не будет. Можно разве что в EEPROM записать и потом глянуть.
"отсутствие" переполнения Т1 я предполагал потому что частота вращения не менее 10 оборотов в секунду, а максимальное значение Т1 достигнет только при оборотах меньше 4 в секунду.
Проведу рекомендованные мероприятия и отпишусь по результатам.

P.S. Расчет kw_t2 делается один раз за оборот и используется для вывода каждого столбца изображения.

Re: Led-глобус, проблема

Пт дек 01, 2017 13:45:58

Проблематично вывести на консоль что-то с вращающейся штуковины, а если остановить, то и расчетов никаких не будет.
Эммммм, не вижу НИКАКОЙ проблемы даже по двум причинам:
- вывод стоит делать после прохождения одного круга.
Выполнен один проход, буфер заполнен - всё, можно выводить цифры и пофигу уже на дальнейшее кручение.

- вывод в UART на прерываниях.
Тут-то что мешать будет "кручению"? Если только не намудрить в функции обработки прерывания передатчика UART...

Re: Led-глобус, проблема

Пт дек 01, 2017 16:49:21

а если сделать проще - по переполнению (или по любому другому событию) зажигать определённый светодиод в глобусе, тогда будет виден не только факт, но и момент события.

Re: Led-глобус, проблема

Пт дек 01, 2017 20:10:14

В общем я сделал так. В своей "тупой" (которая использует delay) выводилке изображения подобрал задержку и по ней выставил скорость двигателя 15 оборотов в секунду. Было 27. Затем в программе, листинг которой я опубликовал тут, добавил запись в EEPROM МК 20 значений подряд TCNT1 и kw_t2, но сначала выжидал 4 секунды для стабилизации скорости вращения. И был удивлен тем, что всегда старший байт счетчика в EEPROM был нулевым, а kw_t2 всегда был больше 2. Косяк мой был в том, что я читал сначала старший байт счетчика, а потом младший. А надо строго наоборот. После этого цифирки стали соответствовать друг другу. И тут я предположил, что компилятор не учитывает правила работы при чтении регистров счетчика. И заменил строку:
kw_t2=((TCNT1H<<8) + TCNT1L)/192;

на вот такую комбинацию:
kw_t2=TCNT1L;
kw_t2=((TCNT1H<<8) + kw_t2)/192;

и заработало, блин. Я неделю бился с этой проблемой. Это уже второй косяк на который я напоролся понадеевшись на корректность CVAVR. Первый был связан с кривым генератором начального кода для инициализации ватчдога на atmege328.
Только изредка почему-то пропускает INT0. Не могу пока понять почему.

Re: Led-глобус, проблема

Пт дек 01, 2017 20:46:28

добавил запись в EEPROM МК 20 значений подряд TCNT1 и kw_t2,
Хм, а время записи данных в EEPROM не мешало и не сбивало показания?
я читал сначала старший байт счетчика, а потом младший. А надо...
kw_t2=((TCNT1H<<8) + kw_t2)/192;
А почему было не написать в стиле вот так:
Код:
unsigned int nValue = TCNT1;
nValue /= 192;
kw_t2 = nValue;
Специально пишу через отдельную переменную для наглядности. Можно и kw_t2 = TCNT1 / 192;
Компиляторы умеют правильно вычитывать двухбайтные значения из TCNTх, ADC,...
Только изредка почему-то пропускает INT0. Не могу пока понять почему.
В смысле "пропускает"? Либо на входе сигнал "плохой", либо в этот момент прерывания запрещены. Повесь отдалочный светодиод и мигай им при входе в обработчик INT0.

Re: Led-глобус, проблема

Вс дек 03, 2017 08:45:10

Хм, а время записи данных в EEPROM не мешало и не сбивало показания?

Я сначала заполнял массив, а после этого уже писал его EEPROM.
А почему было не написать в стиле вот так:
Код:
unsigned int nValue = TCNT1;
nValue /= 192;
kw_t2 = nValue;
Специально пишу через отдельную переменную для наглядности. Можно и kw_t2 = TCNT1 / 192;

Я пробовал. Выяснилось, что cvavr не знает такого регистра :)
В смысле "пропускает"? Либо на входе сигнал "плохой", либо в этот момент прерывания запрещены. Повесь отдалочный светодиод и мигай им при входе в обработчик INT0.

Прерывания у меня вообще не запрещаются в этом коде, ну разве что аппаратно в переполнении счетчика Т2. Происходит следующее, если нет сработки INT0, то все светодиоды гаснут и я фиксирую "моргание". Буду с этим разбираться.
Спасибо за участие в топике :beer:

Re: Led-глобус, проблема

Вс дек 03, 2017 09:55:59

Я пробовал. Выяснилось, что cvavr не знает такого регистра :)
их можно и познакомить :) : в папке inc найди файл от своего МК и допиши про TCNT1W (по аналогии с ADCW) должно прокатить я к меге 8 так дописывал, правда там он описан был в верхней части (не через дефайны)
Ответить