| Форум РадиоКот https://radiokot.ru/forum/ |
|
| Емкостной сенсор на МК + светодиод (ШИМ) https://radiokot.ru/forum/viewtopic.php?f=61&t=83068 |
Страница 1 из 2 |
| Автор: | DerMeister [ Сб янв 05, 2013 18:48:32 ] | ||
| Заголовок сообщения: | Емкостной сенсор на МК + светодиод (ШИМ) | ||
Здравствуйте, уважаемые Коты. Опять хочу обратиться за помощью к вам. По сути: Написал я код в CVAVR. Суть его такова: При прикосновению к сенсору (реализован программно), контроллер (Attiny13a) меняет яркость светодиода с помошью своего аппаратного ШИМ. Точнее при длительном прикосновении - начинает меняться яркость от нуля до максимума и наоборот. А при коротком прикосновении (менее 1с) - просто включает или выключает этот светодиод без всяких ШИМ. Так как я не программист, а еще только учусь - писал долго и упорно. В итоге в отладчике AVR Studio все работает как надо. А вот в железе ересь какая-то получается. Вот собственно и вопрос к профессионалам - в чем ошибка? Код с комментариями в приложении. Спасибо заранее за ответы!
|
|||
| Автор: | vitalik_1984 [ Сб янв 05, 2013 23:05:28 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Можно еще в протеусе попробовать, если есть желание, подозреваю, что там тоже не будет работать. Сомневаюсь, что в студии вы смогли бы правильно сымитировать работу сенсора.Скорее всего тут и кроется подвох. Для нормальной работы нужно делать калибровку сенсоров, чтобы неточности аппаратной части компенсировать.Она, конечно есть, но я бы повторил несколько раз и усреднил значения. И вообще можно еще экспериментировать с различной емкостью на контактах сенсора. Еще есть некоторые замечания насчет оформления кода, например функцию check можно запускать и из калибровки и из рабочего состояния.Таким образом экономится флеш память Мк. Просто возвращать time после выполнения, тогда работа с усреднением Код: unsigned int sredn; for(i=0;i<8;i++){ sredn=check(); } sredn= sredn/8; f=1; и так далее. |
|
| Автор: | blackx [ Сб янв 05, 2013 23:29:16 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Разбейте код на части - и отдельно тестируйте работу с сенсором, отдельно - ШИМ, отдельно - задержки и т. д. Найти ошибку в трехстраничном коде не так просто. Особенно, если код написан новичком. К тому же "железо" - у вас, может вы там что не так собрали. |
|
| Автор: | DerMeister [ Вс янв 06, 2013 15:42:51 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Спасибо Вам за ответы. Дело в том, что я это и собирал, так сказать "по отдельности". Т.е. сперва был придуман сенсор. В интернете я прочитал только принцип их пстроения на контроллере, а программу писал сам. В этом и интерес для меня. Кстати, пробовал усреднять, но как выяснилось и с однократной калибровкой работает стабильно. Потом решил наконец-таки разобраться с ШИМ. Долго он мне покоя не давал. Вобщем по отделиности все работает. Совместил ШИМ и сенсор - получилось. А вот прикрутить распознование длительного и короткого нажатия на сенсор не удалось. Вот от того я и решил, что где-то у меня какой-то незначительный косяк в коде. Который я по глупости своей не вижу. Полагаю, что проблема с счетчиком. Нужно и считать им емкость сенсора, и управлять ШИМ. Было бы их два.... Ну будем думать значит. Спасибо за подсказки по оптимизации кода! Кстати скажите пожалуйста еще: когда контроллер отрабатывает команду delay он "зависает" на время этой задержки. Это значит что и таймер-счетчик не считает в этот момент? А то мне тут такое подсказали, но мне в это что-то с трудом верится... |
|
| Автор: | a_skr [ Вс янв 06, 2013 17:10:10 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
у контроллера нет команды delay. delay_ms и delay_us - это функции-циклы отсчета заданной задержки. во время выполнения этих функций таймер-счетчик никто не останавливает |
|
| Автор: | vitalik_1984 [ Вс янв 06, 2013 22:02:55 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Вот накидал схемку Вложение: Функция используется довольно таки прозрачно здесь pressed это ваша функция сенсора, которая при нажатой кнопке возвращает 1 А time_of_button ()это функция из моего алгоритма. Код: status = time_of_button ((pressed()); switch(status){ 1: {short_pressing(); break;} 2: {long_pressing(); break;} default break; } как то так Можно еще добавить проверку флага запуска обработки нажатия перед этим и в конце очистку флага, если выполнили обработку. за ошибки просьба не пинать, ночь все таки накладывает свой отпечаток. С Рождеством! PS, только сейчас осенило- нельзя для полноценной работы шим сбрасывать или останавливать таймер, особенно если он один как в тини13! А это у вас делается регулярно при опросе сенсора!!! Код: TCNT0=0; //счетчик в 0 TCCR0B=0x01; //таймер запустили отсюда совет- при разработкой устройства нужно первоначально распределить ресурсы, а уже из этого складывать алгоритм. |
|
| Автор: | vitalik_1984 [ Пн янв 07, 2013 07:43:17 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Продолжим:Распределим ресурсы. Для работы шим нужно, чтобы таймер тикал всегда отсюда делаем вывод, что нужно перестроить процедуру считывания сенсора. Настроим физический шим на вывод ноги шим. Дальше определим дискретность шим.пусть будет 255 значений- считать будет легче. Процедура сенсора: зарядили, сбросили глобальную переменную счета переполнений таймера считали значение таймера разряжаем считали таймер считали глобальную. Сравнили со значением сработки если нажато- вернули 1 если не нажато- вернули 0. позже напишу как избавиться от повтора обработки сенсора. |
|
| Автор: | vitalik_1984 [ Вт янв 08, 2013 21:21:05 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Че это похоже только мне интересно? Где развитие проекта? |
|
| Автор: | Alexeyslav [ Ср янв 09, 2013 17:14:22 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
На тини13 два таймера, один пусть работает на ШИМ, другой на измерение емкости сенсора. Да вообще, измерить емкость сенсора можно в подпрограмме реализующей задержку - чего зря ресурсам пропадать. |
|
| Автор: | a_skr [ Ср янв 09, 2013 17:57:35 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
на tiny13 всего один 8-битный таймер с двумя ШИМ-каналами: Peripheral Features – One 8-bit Timer/Counter with Prescaler and Two PWM Channels – 4-channel, 10-bit ADC with Internal Voltage Reference – Programmable Watchdog Timer with Separate On-chip Oscillator – On-chip Analog Comparator |
|
| Автор: | vitalik_1984 [ Ср янв 09, 2013 20:22:58 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Alexeyslav писал(а): Да вообще, измерить емкость сенсора можно в подпрограмме реализующей задержку - чего зря ресурсам пропадать. Вы вообще как это себе представляете? И что это за подпрограмма такая задержки? |
|
| Автор: | Alexeyslav [ Ср янв 09, 2013 20:46:31 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
я так понял, алгоритм прост - ШИМ работает сам по себе, а в основном цикле производится измерение емкости сенсора и задержка. например, проверять каждые 100мс то если 20 последовательных проверок покажут "нажата" - значит нажатие длинное. Вот во время этой задержки, измерять емкость сенсора и усреднять значение. Программно измерять, без использования таймера. |
|
| Автор: | vitalik_1984 [ Ср янв 09, 2013 21:30:10 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Шим и так должен работать сам по себе Alexeyslav писал(а): а в основном цикле производится измерение емкости сенсора и задержка. И так в основном цикле Alexeyslav писал(а): например, проверять каждые 100мс Я про это и говорил тут vitalik_1984 писал(а): Можно еще добавить проверку флага запуска обработки нажатия перед этим и в конце очистку флага, если выполнили обработку. В обработке таймера считаем ~100мс, ставим флаг. В основном: Если флаг, то это Код: status = time_of_button ((pressed()); switch(status){ 1:{short_pressing(); break;} 2:{long_pressing(); break;} default break; } и очистили флаг Alexeyslav писал(а): если 20 последовательных проверок покажут "нажата" - значит нажатие длинное. Определением этого занимается функция time_of_button () блок схему алгоритма которой я привел. Alexeyslav писал(а): Вот во время этой задержки, измерять емкость сенсора и усреднять значение. Программно измерять, без использования таймера. Вот это поясните тут не понятноЯ полагаю, что измерять без таймера просто нецелесообразно-он все равно молотит. Просто добавляется еще одна переменная для подсчета переполнений. |
|
| Автор: | DerMeister [ Ср янв 09, 2013 21:34:27 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Простите, что долго не объявлялся. Праздники закончились - работы по горло. Некогда заниматься пока этим сенсором.... Спасибо огромное всем за дельные советы и предложения! Особенно конечно же vitalik_1984!!! Вы мне очень помогли! Вот в том-то и проблема, что таймер останавливать нельзя - ШИМ выключается, естесственно. Я его выключал периодически всего на пару тактов, мне кажется светодиод не должен от этого моргать. Всего-то 0,9*10^-6 секунды vitalik_1984 Ваш алгоритм натокнул меня на определенные мысли... Даже кое что улучшить можно. Но пока, по своей программистской неграмотности не могу это сформулировать При первой же возможности попытаюсь воплотить ваши советы и идеи в жизнь. Обязательно отпишусь что да как! Еще раз спасибо большое всем! |
|
| Автор: | Alexeyslav [ Ср янв 09, 2013 23:00:07 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Таймер работает на ШИМ, его трогать нельзя. Остается крутится в программе, измеряя интервал(время заряда емкости сенсора) в циклах, подобных той же подпрограмме DELAY_MS. Только новая DELAY будет состоять из непрерывного измерения и усреднения, а по окончанию задержки около 100мс анализируется усредненное значение. Так одновременно измеряем сенсор и реализуем задержку. Любые помехи будут "съедены" постоянным усреднением. |
|
| Автор: | vitalik_1984 [ Ср янв 09, 2013 23:15:08 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
DerMeister писал(а): Я его выключал периодически всего на пару тактов, мне кажется светодиод не должен от этого моргать. Всего-то 0,9*10^-6 секунды Это возможно, но зачем вообще моргать? DerMeister писал(а): Ваш алгоритм натолкнул меня на определенные мысли... Даже кое что улучшить можно. Я бы пересмотрел функцию void PWM(void) как то мутно все выглядит там. Примерный алгоритм чтения кнопок check() используется для инициализации и для самой работы кнопок. вход в функцию принимаемые данные(указатель на массив unsigned int buffer) 1 заряжаем или разряжаем обнуляем глобальную переменную temp читаем значение таймера в temp2 тупим пока на разрядится или пока не зарядится. читаем значение таймера temp3 читаем переменную temp возвращаем *buffer=((temp<<8)|temp3) -temp2; как из этого сделать чтение и инициализацию позже напишу. Цитата: в циклах, подобных той же подпрограмме DELAY_MS. не нужно делей никакой
|
|
| Автор: | DerMeister [ Чт янв 10, 2013 14:52:55 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Цитата: Я бы пересмотрел функцию void PWM(void) как то мутно все выглядит там. А что там мутного-то? По-моему все стандартно - увеличиваем число в регистре совпадения от 0 до 255 и обратно. От этого светодиод то плавно разгарается, то гаснет. Delay нужен чтоб не сильно быстро это все происходило. Я пробовал не останавливать таймер, а записывать в одну переменную его значение на момент начала зарядки сенсора, в другую переменную - значение на момент конца зарядки. Потом вычитать из второго первое. Типа так: DDRB=0x09; #asm("nop") #asm("nop") temp1=TCNT0; DDRB=0x01; while(PINB.3==0){}; temp2=TCNT0; temp=(temp2-temp1) if(бла, бла, бла...) Т.е. если в temp получается значение больше чем контрольное - сенсор сработал. Но так ваще ерунда какая-то получается. Это связано с переполнением таймера. И temp2-temp1 получается ошибочным. Я так думаю... |
|
| Автор: | vitalik_1984 [ Чт янв 10, 2013 15:58:19 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
ошибочным, потому что между этими считываниями может произойти переполнение Так вот в переполнении добавляется 1к еще одной переменной. Так как таймер 8 бит, это как раз переменная чар складываем (temp3<<8)|temp2 это будет то число, которое общее отнимаем temp1 это будет как раз число тиков между зарядкой -разрядкой. Его нужно вернуть в вызывающую процедуру. забыл case вписать Код: status = time_of_button ((pressed()); switch(status){ case 1:{short_pressing(); break;} case 2:{long_pressing(); break;} default break; } Всю прогу переделал, осталось дописать функции long_pressing() и short_pressing(). |
|
| Автор: | vitalik_1984 [ Вс янв 13, 2013 19:17:26 ] |
| Заголовок сообщения: | Re: Не работает в железе код |
Дописал весь код, осталось проверить как будет работать и убрать неточности. Где схема в протеусе, которую тестировали с первоначальной прошивкой? |
|
| Автор: | DerMeister [ Вт янв 15, 2013 19:49:02 ] |
| Заголовок сообщения: | Re: Емкостной сенсор на МК + светодиод (ШИМ) |
Схемы в протеусе нет. Так как я не очень-то ему доверяю - приврать он любитель, надо сказать. Все тестировал в железе. Но в принципе могу накидать и схемку. Щас попробую.... |
|
| Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|


