Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
Отлично! Можно оставить в разделе модов - другим может пригодится! viewforum.php?f=24
Отлично! Можно оставить в разделе модов - другим может пригодится! http://www.forum.getchip.net/viewforum.php?f=24
|
|
|
 |
Добавлено: 25 апр 2016, 22:28 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
Собрал модификацию устройства: выбросил индикацию (как звук, так и светодиоды), за счёт этих выводов увеличил количество линий до 16. Пришлось убрать даже ввод UART, теперь нет сохранения в память значений чувствительности линий. И остался только вывод символа нажатой линии, ну и отладочная информация при старте. Увеличил счётчик повторов, чтобы второе срабатывание не мешалось. Заодно развёл плату под SMD. Правда, получилось совместно с говорилкой из 87-го проекта.
Собрал модификацию устройства: выбросил индикацию (как звук, так и светодиоды), за счёт этих выводов увеличил количество линий до 16. Пришлось убрать даже ввод UART, теперь нет сохранения в память значений чувствительности линий. И остался только вывод символа нажатой линии, ну и отладочная информация при старте. Увеличил счётчик повторов, чтобы второе срабатывание не мешалось. Заодно развёл плату под SMD. Правда, получилось совместно с говорилкой из 87-го проекта.
|
|
|
 |
Добавлено: 24 апр 2016, 22:48 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
всех с наступившим! не поверите - оказывается на точность измерения и работу алгоритма в целом сильно влиял код буфера для уарта! сейча только, после перерыва и работой над другой железкой, понял что то код для буфера уарта что я использовал сильно косячен. сейчас разбираюсь в подробностях и отпишу о результатах по завершению.
всех с наступившим! не поверите - оказывается на точность измерения и работу алгоритма в целом сильно влиял код буфера для уарта! сейча только, после перерыва и работой над другой железкой, понял что то код для буфера уарта что я использовал сильно косячен. сейчас разбираюсь в подробностях и отпишу о результатах по завершению.
|
|
|
 |
Добавлено: 01 янв 2016, 21:35 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
[quote="GetChiper"]Да, все правильно. Усреднений можно и 8 сделать - уже будет лучше.
Какие все таки значения с сенсоров?[/quote] их нет(( какпробовал снять но не получается - код отсылающий значения по уарту через кольцевой буфер шлёт фигню. а так - наверняка больше FF. а поскольку счётчик переполняется то регистрируется нажатие
|
|
|
 |
Добавлено: 12 дек 2015, 20:10 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
Да, все правильно. Усреднений можно и 8 сделать - уже будет лучше.
Какие все таки значения с сенсоров?
Да, все правильно. Усреднений можно и 8 сделать - уже будет лучше.
Какие все таки значения с сенсоров?
|
|
|
 |
Добавлено: 12 дек 2015, 19:33 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
измеряется всё один раз при инициализации. измеряется в количестве тактов цикла while и и сохраняется в оперативной памяти. в отладке эти значения отправляются по уарту. большинство из них больше байта - FF. видимо опрос слишком быстрый. значения при прикосновении больше FF стабильно. видимо надо "загрубить" цикл while - чтобы точки замера разнести во времени. усреднения нет - не могу сообазить как сделат чобы не вылезти из объёмов оперативной памяти.
а так что нужно будет сделать - цикл for от 0 до 32 для каждой клавиши, каждый раз суммировать значение замера и потом сумму разделить на 32. сам цикл замера увеличить во времени чтобы не был слишком шустрым... поправьте меня если не прав.
измеряется всё один раз при инициализации. измеряется в количестве тактов цикла while и и сохраняется в оперативной памяти. в отладке эти значения отправляются по уарту. большинство из них больше байта - FF. видимо опрос слишком быстрый. значения при прикосновении больше FF стабильно. видимо надо "загрубить" цикл while - чтобы точки замера разнести во времени. усреднения нет - не могу сообазить как сделат чобы не вылезти из объёмов оперативной памяти.
а так что нужно будет сделать - цикл for от 0 до 32 для каждой клавиши, каждый раз суммировать значение замера и потом сумму разделить на 32. сам цикл замера увеличить во времени чтобы не был слишком шустрым... поправьте меня если не прав.
|
|
|
 |
Добавлено: 12 дек 2015, 18:30 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
Какие эталонные значения сенсоров выходят? Какие значения при прикосновении?
Я не вижу в программе, что сенсоры для каждого замера опрашиваются по несколько раз, а значения усредняется
Какие эталонные значения сенсоров выходят? Какие значения при прикосновении?
Я не вижу в программе, что сенсоры для каждого замера опрашиваются по несколько раз, а значения усредняется
|
|
|
 |
Добавлено: 12 дек 2015, 00:42 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
Благодарю! Честно. я уже две неделю воюю с этим. не даётся. я сделал автокалибровку: при запуске опрашивается каждая кнопка и потом нажатие сверяется с этим значением. и всё равно какие-то кнопки не реагируют на нажатие а какие-то черезчур чувствительны. сделал проверку нажатия кнопки(триггер) и не работает. про отсылку символов вообще молчу. шлётся всё что угодно кроме символа нажатой клавиши. может подскажете что не так с логикой? пожалуйста. очень обино за две убитых впустую недели((( [code]#include <avr/io.h> #include <avr/interrupt.h> #include "usart.h" #include "usart.c"
//макросы для работы с битами #define InvBit(reg, bit) reg ^= (1<<(bit)) #define ClearBit(reg, bit) reg &= (~(1<<(bit))) #define SetBit(reg, bit) reg |= (1<<(bit)) #define BitIsSet(reg, bit) ((reg & (1<<bit)) != 0)
/* //переменные для подсчета количества переполнений volatile unsigned char sub_time_pin0 = 0;
unsigned char CountDreb; //сколько циклов опроса кнопка должна удерживаться
*/ // количество сенсоров #define SENSOR 10 //10. // переменная счётчик сенсорных площадок volatile unsigned char _iSens; // переменная счётчик volatile unsigned char _Counter; // массив данных калибровки выводов volatile unsigned char Kalibrovka[SENSOR]; //переменная для антидребезга //volatile unsigned char _DrebComp = 0; //#define _Drebezg 20 // перемменная нажатия клавиши volatile unsigned char _PressedSensor[SENSOR]; //проверка нажатия кнопки через структуру где numb - переменная цикла #define Clear_DDR(numb) ( *(VirtPIN[numb].DDR_BUT) &= (~(1<<VirtPIN[numb].BUT)) ) // вывод работает как ВХОД. при PORT = 0 = HI-Z #define Set_DDR(numb) ( *(VirtPIN[numb].DDR_BUT) |= (1<<VirtPIN[numb].BUT) ) // вывод работает на ВЫХОД. PORT = 0 = pin = 0 #define Check_PIN(numb) ( (*(VirtPIN[numb].PIN_BUT)&(1<<VirtPIN[numb].BUT))!=0 ) #define UART_PIN(numb) (VirtPIN[numb].Symbol) // структура/массив пинов сенсорных площадок struct _STRUCT_PIN { volatile unsigned char *DDR_BUT; //порт кнопки (DDRD, DDRA...) volatile unsigned char *PIN_BUT; //порт кнопки (PIND, PINA...) volatile unsigned char BUT; //пин кнопки (PD0, PA1...) volatile unsigned char Symbol; // символ по уарту };
struct _STRUCT_PIN VirtPIN[SENSOR] = { {&DDRD,&PIND,PD6,'0'},//9 {&DDRD,&PIND,PD3,'1'},//7 {&DDRB,&PINB,PB1,'2'},//1 {&DDRB,&PINB,PB4,'3'},//4 {&DDRD,&PIND,PD2,'4'},//6 {&DDRB,&PINB,PB0,'5'},//0 {&DDRB,&PINB,PB3,'6'},//3 {&DDRD,&PIND,PD4,'7'},//8 {&DDRB,&PINB,PB2,'8'},//2 {&DDRB,&PINB,PB5,'9'},//5 // {&DDRD,&PIND,PD5,'L'},//10 //<--- нет 1Мом резистора на выводе // {&DDRB,&PINB,PB6,'R'} //11 //<--- нет 1Мом резистора на выводе };
int main( void ) { // инициализация пинов контроллера для работы с сенсорными площадками // устанавливаем выводы на выход (DDR = 1) и в устанавливаем ноль (PORT = 0) DDRD |= (1<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD6); PORTD &= (1<<PD2)&(1<<PD3)&(1<<PD4)&(1<<PD6); DDRB |= (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5); PORTB &= (1<<PB0)&(1<<PB1)&(1<<PB2)&(1<<PB3)&(1<<PB4)&(1<<PB5); USART_Init();
// USART_SendStr("Button: "); // калибровочная часть НАЧАЛО // выполняется один раз после инициализации периферии sei(); //++++++++++++++++++++++++++++++++++++++++++++++++++ for (_iSens=0; _iSens<SENSOR; _iSens++) { Set_DDR(_iSens); // сбросили ёмкость на сенсоре _Counter = 0; // обнулили счётчик Clear_DDR(_iSens); // начали заряжать ёмкость сенсорной площадки while(!Check_PIN(_iSens) && (_Counter < 0xFF) ) // инкременировать счётчик до тех пор пока не выйдет из нуля в единицу. значит ёмкость зарядилась { _Counter++; // проверка счётчика. если счётчик равен ff значит пин контроллера и ёмкость сенсорной площадки калибровку не прошли. а значит бида-бида. } Set_DDR(_iSens); // сбросили ёмкость на сенсоре и переходим к следующему сенсору Kalibrovka[_iSens]=_Counter++; // сохранили показание счётчика в массиве калибровки. с этими значениями будет проверяться нажата "кнопка или нет" USART_SendStr(_Counter); } //++++++++++++++++++++++++++++++++++++++++++++++++++ // калибровочная часть КОНЕЦ //разрешаем прерывания
while(1) { // рабочая часть НАЧАЛО //++++++++++++++++++++++++++++++++++++++++++++++++++
for (_iSens=0; _iSens<SENSOR; _iSens++) { cli(); if (Kalibrovka[_iSens]<0xFF) // проверка массива калибровки на 0xFF. если равно то пин не фурычит { Set_DDR(_iSens); // сбросили ёмкость на сенсоре _Counter = 0; // обнулили счётчик Clear_DDR(_iSens); // начали заряжать ёмкость сенсорной площадки while(!Check_PIN(_iSens) && (_Counter < 0xFF)) // инкременировать счётчик до тех пор пока не выйдет из нуля в единицу. значит ёмкость зарядилась { _Counter++; // проверка счётчика. если счётчик равен ff значит пин контроллера и ёмкость сенсорной площадки калибровку не прошли. а значит бида-бида. } if ( (_Counter > Kalibrovka[_iSens]) && !( _PressedSensor[_iSens] ) ) // сравниваем счётчик со значениями из массива калибровки. { // если значение калибровки меньше то (1) _PressedSensor[_iSens] = 1; //переменная нажатия кнопки = НАЖАТА USART_SendStr(UART_PIN(_iSens)); // (1) то отсылаем код кнопки по уарту. } if ( (_Counter <= Kalibrovka[_iSens]) && ( _PressedSensor[_iSens] ) ) // сравниваем счётчик со значениями из массива калибровки. { _PressedSensor[_iSens] = 0; }
Set_DDR(_iSens); // сбросили ёмкость на сенсоре. он больше нам не нужен //шагаем на следующий пин } sei(); } //++++++++++++++++++++++++++++++++++++++++++++++++++ // рабочая часть КОНЕЦ }
return 0; }
[/code]
|
|
|
 |
Добавлено: 11 дек 2015, 01:38 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
Антидребезга, как токового, у сенсоров нет, но нужно игнорировать единичные сработки (могут появляться от электрических или электромагнитных помех). Отвязаться от таких помех легко - достаточно делать несколько замеров и если они все показываю что сенсор сработал, значит он сработал. А если из серии замеров только один или два сработавших остальные нет - это помехи.
Что значит антиповтор? Чтобы когда клавиша нажата не шли ее коды при каждом опросе? Тоже просто заведи переменную в которой храни номер предыдущей нажатой клавиши (или ноль если ничего не нажато) и сравнивай это значение после каждого опроса. Если новое значение равно предыдущему - значит клавиша еще не отпускалась.
Про антимультитач. Сенсоры ты опрашиваешь последовательно. Какой первый сработал тот и нажат - остальные просто игнорируй.
Антидребезга, как токового, у сенсоров нет, но нужно игнорировать единичные сработки (могут появляться от электрических или электромагнитных помех). Отвязаться от таких помех легко - достаточно делать несколько замеров и если они все показываю что сенсор сработал, значит он сработал. А если из серии замеров только один или два сработавших остальные нет - это помехи.
Что значит антиповтор? Чтобы когда клавиша нажата не шли ее коды при каждом опросе? Тоже просто заведи переменную в которой храни номер предыдущей нажатой клавиши (или ноль если ничего не нажато) и сравнивай это значение после каждого опроса. Если новое значение равно предыдущему - значит клавиша еще не отпускалась.
Про антимультитач. Сенсоры ты опрашиваешь последовательно. Какой первый сработал тот и нажат - остальные просто игнорируй.
|
|
|
 |
Добавлено: 08 дек 2015, 19:14 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Простая сенсорная панель (Keypad). |
Цитата |
|
за пару вечеров мозгования родилось вот это: [code]#include <avr/io.h> #include <avr/interrupt.h> #include "usart.h" #include "usart.c"
//макросы для работы с битами #define InvBit(reg, bit) reg ^= (1<<(bit)) #define ClearBit(reg, bit) reg &= (~(1<<(bit))) #define SetBit(reg, bit) reg |= (1<<(bit)) #define BitIsSet(reg, bit) ((reg & (1<<bit)) != 0)
/* //переменные для подсчета количества переполнений volatile unsigned char sub_time_pin0 = 0;
unsigned char CountDreb; //сколько циклов опроса кнопка должна удерживаться
*/ // количество сенсоров #define SENSOR 10 //10. // переменная счётчик сенсорных площадок volatile unsigned char _iSens; // переменная счётчик volatile unsigned char _Counter; // массив данных калибровки выводов volatile unsigned char Kalibrovka[SENSOR]; //переменная для антидребезга //volatile unsigned char _DrebComp = 0; //#define _Drebezg 20 // перемменная предыдущей клавиши volatile unsigned char _PreviousSensor = 0xFF; //проверка нажатия кнопки через структуру где numb - переменная цикла #define Clear_DDR(numb) ( *(VirtPIN[numb].DDR_BUT) &= (~(1<<VirtPIN[numb].BUT)) ) // вывод работает как ВХОД. при PORT = 0 = HI-Z #define Set_DDR(numb) ( *(VirtPIN[numb].DDR_BUT) |= (1<<VirtPIN[numb].BUT) ) // вывод работает на ВЫХОД. PORT = 0 = pin = 0 #define Check_PIN(numb) ( (*(VirtPIN[numb].PIN_BUT)&(1<<VirtPIN[numb].BUT))!=0 ) #define UART_PIN(numb) (VirtPIN[numb].Symbol) // структура/массив пинов сенсорных площадок struct _STRUCT_PIN { volatile unsigned char *DDR_BUT; //порт кнопки (DDRD, DDRA...) volatile unsigned char *PIN_BUT; //порт кнопки (PIND, PINA...) volatile unsigned char BUT; //пин кнопки (PD0, PA1...) volatile unsigned char Symbol; // символ по уарту };
struct _STRUCT_PIN VirtPIN[SENSOR] = { {&DDRD,&PIND,PD6,'0'},//9 {&DDRD,&PIND,PD3,'1'},//7 {&DDRB,&PINB,PB1,'2'},//1 {&DDRB,&PINB,PB4,'3'},//4 {&DDRD,&PIND,PD2,'4'},//6 {&DDRB,&PINB,PB0,'5'},//0 {&DDRB,&PINB,PB3,'6'},//3 {&DDRD,&PIND,PD4,'7'},//8 {&DDRB,&PINB,PB2,'8'},//2 {&DDRB,&PINB,PB5,'9'},//5 // {&DDRD,&PIND,PD5,'L'},//10 //<--- нет 1Мом резистора на выводе // {&DDRB,&PINB,PB6,'R'} //11 //<--- нет 1Мом резистора на выводе };
int main( void ) { // инициализация пинов контроллера для работы с сенсорными площадками // устанавливаем выводы на выход (DDR = 1) и в устанавливаем ноль (PORT = 0) DDRD |= (1<<PD2)|(1<<PD3)|(1<<PD4)|(1<<PD6); PORTD &= (1<<PD2)&(1<<PD3)&(1<<PD4)&(1<<PD6); DDRB |= (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5); PORTB &= (1<<PB0)&(1<<PB1)&(1<<PB2)&(1<<PB3)&(1<<PB4)&(1<<PB5); USART_Init();
// USART_SendStr("Button: "); // калибровочная часть НАЧАЛО // выполняется один раз после инициализации периферии //++++++++++++++++++++++++++++++++++++++++++++++++++ for (_iSens=0; _iSens<SENSOR; _iSens++) { Set_DDR(_iSens); // сбросили ёмкость на сенсоре _Counter = 0; // обнулили счётчик Clear_DDR(_iSens); // начали заряжать ёмкость сенсорной площадки while(!Check_PIN(_iSens) && (_Counter < 0xFF) ) // инкременировать счётчик до тех пор пока не выйдет из нуля в единицу. значит ёмкость зарядилась { _Counter++; // проверка счётчика. если счётчик равен ff значит пин контроллера и ёмкость сенсорной площадки калибровку не прошли. а значит бида-бида. } Set_DDR(_iSens); // сбросили ёмкость на сенсоре и переходим к следующему сенсору Kalibrovka[_iSens]=_Counter++; // сохранили показание счётчика в массиве калибровки. с этими значениями будет проверяться нажата "кнопка или нет" //USART_SendStr(_Counter); } //++++++++++++++++++++++++++++++++++++++++++++++++++ // калибровочная часть КОНЕЦ //разрешаем прерывания sei();
while(1) { // рабочая часть НАЧАЛО //++++++++++++++++++++++++++++++++++++++++++++++++++
for (_iSens=0; _iSens<SENSOR; _iSens++) { cli(); if (Kalibrovka[_iSens]<0xFF) // проверка массива калибровки на 0xFF. если равно то пин не фурычит { Set_DDR(_iSens); // сбросили ёмкость на сенсоре _Counter = 0; // обнулили счётчик Clear_DDR(_iSens); // начали заряжать ёмкость сенсорной площадки while(!Check_PIN(_iSens) && (_Counter < 0xFF)) // инкременировать счётчик до тех пор пока не выйдет из нуля в единицу. значит ёмкость зарядилась { _Counter++; // проверка счётчика. если счётчик равен ff значит пин контроллера и ёмкость сенсорной площадки калибровку не прошли. а значит бида-бида. } if ( (_Counter > Kalibrovka[_iSens]) && (_PreviousSensor != _iSens) ) // сравниваем счётчик со значениями из массива калибровки. { // если значение калибровки меньше то (1) _PreviousSensor = _iSens; //делаем нынешнюю кнопку предыдущей USART_SendStr(_iSens++); // (1) то отсылаем код кнопки по уарту. } Set_DDR(_iSens); // сбросили ёмкость на сенсоре. он больше нам не нужен //шагаем на следующий пин } sei(); } //++++++++++++++++++++++++++++++++++++++++++++++++++ // рабочая часть КОНЕЦ }
return 0; }
[/code] что делает: 1) определяет в цикле от 1 до 10 для каждой кнопки предел чвствительности. я назвал это автокалибровкой. запустился мк, прогнал каждую кнопку на время заряда до 1. сохранил знаение в массиве для каждой кнопки. 2) в теле цикла while идёт постоянная проверка каждой клавиши со значением из массива калибровки. если бльше то отсылаем код клавиши. вопросы: как примерно реализовать антидребезг? как реализовать антиповтор клавиши(антизалипание)? как реализовать антимультитач? я много времени убил безвозвратно пытаясь разобрать каракули исходника для алгоритм билдера. можно ли просто на словах объяснить алгоритм?
|
|
|
 |
Добавлено: 08 дек 2015, 01:48 |
|
|
 |
|