Емкостной сенсор на МК + светодиод (ШИМ)

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
DerMeister
Встал на лапы
Сообщения: 85
Зарегистрирован: Вт июл 17, 2012 17:45:46
Откуда: Тольятти

Емкостной сенсор на МК + светодиод (ШИМ)

Сообщение DerMeister »

Здравствуйте, уважаемые Коты.
Опять хочу обратиться за помощью к вам.
По сути:
Написал я код в CVAVR. Суть его такова:
При прикосновению к сенсору (реализован программно), контроллер (Attiny13a) меняет яркость светодиода с помошью своего аппаратного ШИМ. Точнее при длительном прикосновении - начинает меняться яркость от нуля до максимума и наоборот. А при коротком прикосновении (менее 1с) - просто включает или выключает этот светодиод без всяких ШИМ.
Так как я не программист, а еще только учусь - писал долго и упорно. В итоге в отладчике AVR Studio все работает как надо. А вот в железе ересь какая-то получается.
Вот собственно и вопрос к профессионалам - в чем ошибка?
Код с комментариями в приложении.
Спасибо заранее за ответы!
Вложения
sens.txt
(4.29 КБ) 366 скачиваний
Боишься? Сиди дома!
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

Можно еще в протеусе попробовать, если есть желание, подозреваю, что там тоже не будет работать.
Сомневаюсь, что в студии вы смогли бы правильно сымитировать работу сенсора.Скорее всего тут и кроется подвох. Для нормальной работы нужно делать калибровку сенсоров, чтобы неточности аппаратной части компенсировать.Она, конечно есть, но я бы повторил несколько раз и усреднил значения.
И вообще можно еще экспериментировать с различной емкостью на контактах сенсора.

Еще есть некоторые замечания насчет оформления кода, например функцию check можно запускать и из калибровки и из рабочего состояния.Таким образом экономится флеш память Мк.
Просто возвращать time после выполнения, тогда работа с усреднением

Код: Выделить всё

unsigned int sredn; 
for(i=0;i<8;i++){
   sredn=check();
}
sredn= sredn/8;
f=1; 

и так далее.
Последний раз редактировалось ploop Ср янв 09, 2013 21:44:33, всего редактировалось 3 раза.
Причина: Отредактировано по просьбе автора.
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

Re: Не работает в железе код

Сообщение blackx »

Разбейте код на части - и отдельно тестируйте работу с сенсором, отдельно - ШИМ, отдельно - задержки и т. д. Найти ошибку в трехстраничном коде не так просто. Особенно, если код написан новичком. К тому же "железо" - у вас, может вы там что не так собрали.
Изображение only pure true norwegian blackx Изображение
DerMeister
Встал на лапы
Сообщения: 85
Зарегистрирован: Вт июл 17, 2012 17:45:46
Откуда: Тольятти

Re: Не работает в железе код

Сообщение DerMeister »

Спасибо Вам за ответы.
Дело в том, что я это и собирал, так сказать "по отдельности". Т.е. сперва был придуман сенсор. В интернете я прочитал только принцип их пстроения на контроллере, а программу писал сам. В этом и интерес для меня. Кстати, пробовал усреднять, но как выяснилось и с однократной калибровкой работает стабильно.
Потом решил наконец-таки разобраться с ШИМ. Долго он мне покоя не давал. Вобщем по отделиности все работает. Совместил ШИМ и сенсор - получилось. А вот прикрутить распознование длительного и короткого нажатия на сенсор не удалось. Вот от того я и решил, что где-то у меня какой-то незначительный косяк в коде. Который я по глупости своей не вижу.
Полагаю, что проблема с счетчиком. Нужно и считать им емкость сенсора, и управлять ШИМ. Было бы их два.... :)
Ну будем думать значит.
Спасибо за подсказки по оптимизации кода!
Кстати скажите пожалуйста еще: когда контроллер отрабатывает команду delay он "зависает" на время этой задержки. Это значит что и таймер-счетчик не считает в этот момент? А то мне тут такое подсказали, но мне в это что-то с трудом верится...
Боишься? Сиди дома!
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Не работает в железе код

Сообщение a_skr »

у контроллера нет команды delay. delay_ms и delay_us - это функции-циклы отсчета заданной задержки. во время выполнения этих функций таймер-счетчик никто не останавливает :) . кроме того, если интересно, в CodeVisionAVR в этих функциях сбрасывается сторожевой таймер, как мы выяснили в этой теме.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

Вот накидал схемку
Длительность нажатия.pdf
(27.02 КБ) 363 скачивания

Функция используется довольно таки прозрачно здесь 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
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

Продолжим:Распределим ресурсы.
Для работы шим нужно, чтобы таймер тикал всегда отсюда делаем вывод, что нужно перестроить процедуру считывания сенсора.
Настроим физический шим на вывод ноги шим.
Дальше определим дискретность шим.пусть будет 255 значений- считать будет легче.


Процедура сенсора:
зарядили,
сбросили глобальную переменную счета переполнений таймера
считали значение таймера
разряжаем
считали таймер
считали глобальную.
Сравнили со значением сработки если нажато- вернули 1
если не нажато- вернули 0.

позже напишу как избавиться от повтора обработки сенсора.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

Че это похоже только мне интересно? Где развитие проекта?
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Не работает в железе код

Сообщение Alexeyslav »

На тини13 два таймера, один пусть работает на ШИМ, другой на измерение емкости сенсора. Да вообще, измерить емкость сенсора можно в подпрограмме реализующей задержку - чего зря ресурсам пропадать.
a_skr
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Re: Не работает в железе код

Сообщение a_skr »

на 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
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

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

Вы вообще как это себе представляете? И что это за подпрограмма такая задержки?
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Не работает в железе код

Сообщение Alexeyslav »

я так понял, алгоритм прост - ШИМ работает сам по себе, а в основном цикле производится измерение емкости сенсора и задержка. например, проверять каждые 100мс то если 20 последовательных проверок покажут "нажата" - значит нажатие длинное.
Вот во время этой задержки, измерять емкость сенсора и усреднять значение. Программно измерять, без использования таймера.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

Шим и так должен работать сам по себе
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
Встал на лапы
Сообщения: 85
Зарегистрирован: Вт июл 17, 2012 17:45:46
Откуда: Тольятти

Re: Не работает в железе код

Сообщение DerMeister »

Простите, что долго не объявлялся. Праздники закончились - работы по горло. Некогда заниматься пока этим сенсором....
Спасибо огромное всем за дельные советы и предложения! Особенно конечно же vitalik_1984!!! Вы мне очень помогли!
Вот в том-то и проблема, что таймер останавливать нельзя - ШИМ выключается, естесственно. Я его выключал периодически всего на пару тактов, мне кажется светодиод не должен от этого моргать. Всего-то 0,9*10^-6 секунды :)
vitalik_1984 Ваш алгоритм натокнул меня на определенные мысли... Даже кое что улучшить можно. Но пока, по своей программистской неграмотности не могу это сформулировать :)
При первой же возможности попытаюсь воплотить ваши советы и идеи в жизнь. Обязательно отпишусь что да как!
Еще раз спасибо большое всем!
Боишься? Сиди дома!
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Не работает в железе код

Сообщение Alexeyslav »

Таймер работает на ШИМ, его трогать нельзя. Остается крутится в программе, измеряя интервал(время заряда емкости сенсора) в циклах, подобных той же подпрограмме DELAY_MS. Только новая DELAY будет состоять из непрерывного измерения и усреднения, а по окончанию задержки около 100мс анализируется усредненное значение. Так одновременно измеряем сенсор и реализуем задержку. Любые помехи будут "съедены" постоянным усреднением.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

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
Встал на лапы
Сообщения: 85
Зарегистрирован: Вт июл 17, 2012 17:45:46
Откуда: Тольятти

Re: Не работает в железе код

Сообщение DerMeister »

Я бы пересмотрел функцию 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
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

ошибочным, потому что между этими считываниями может произойти переполнение
Так вот в переполнении добавляется 1к еще одной переменной.
Так как таймер 8 бит, это как раз переменная чар складываем (temp3<<8)|temp2 это будет то число, которое общее отнимаем temp1 это будет как раз число тиков между зарядкой -разрядкой.
Его нужно вернуть в вызывающую процедуру.

забыл case вписать :shock:

Код: Выделить всё

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
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: Не работает в железе код

Сообщение vitalik_1984 »

Дописал весь код, осталось проверить как будет работать и убрать неточности.
Где схема в протеусе, которую тестировали с первоначальной прошивкой?
DerMeister
Встал на лапы
Сообщения: 85
Зарегистрирован: Вт июл 17, 2012 17:45:46
Откуда: Тольятти

Re: Емкостной сенсор на МК + светодиод (ШИМ)

Сообщение DerMeister »

Схемы в протеусе нет. Так как я не очень-то ему доверяю - приврать он любитель, надо сказать. Все тестировал в железе.
Но в принципе могу накидать и схемку. Щас попробую....
Боишься? Сиди дома!
Ответить

Вернуться в «Периферия»