Работа с резистивным сенсорным экраном

Хоть резистивный touchscreen и является устаревшим и активно вытесняется емкостными сенсорами, но тем не менее он еще не скоро канет в Лету. Во первых из-за простоты и дешевизны, а во вторых из-за элементарной работы с ним.

Конструктив
Итак, как он устроен. Там все очень и очень просто. Есть две пленки, сделанные из проводящего материала, а между ними гранулы диэлектрика. Когда касаемся пальцем, то продавливаем зазор между пленками и контачим верхнюю на нижнюю. Ну, а определить координаты касания уже дело несложное.

Для этого на каждую пленку нанесено по два электрода. Слева-справа на одной и сверху-снизу на другой. Крест на крест, в общем. Поскольку сопротивление пленки довольно большое, под сотни ом, то образуются как бы два перпендикулярных резистора, висящие друг над другом.

В точке касания они замыкаются между собой и вуаля, получается такая схема:

Теперь достаточно концы одной пленки подтащить к шинам питания (банально заведя туда лог 0 и лог 1), чтобы она образовала обычный резистивный делитель. А с другой пленки снять получившееся напряжение. Которое будет пропорционально координате. Так как сопротивления входа АЦП огромно, то жалкие сотни ом, что составляет остаток пленки (R1) нам никак не помешает. Также не помешает и болтающийся конец (R2).
Теперь меняем положение, растягивая между шинами питания уже другую пленку и снимаем вторую координату. Элементарно!

Вилы в стогу
Но при попытке взять схему в лоб, то получаем первые вилы в бок. Дело в том, что если мы будем тупо менять по очереди пленки и сканировать значения, то много мы не намеряем. Т.к. когда касания нет, то пленки не перескаются, а значит каналы АЦП во время измерения висят в воздухе, ловя всякий мусор. И как их отличить от нажатия? Да никак! АЦП без разницы, что на вход пришло.
Так что нам надо замер координат делать не непрерывно, а тогда и только тогда, когда есть касание. До этого на тачскрин даже не отвлекаться.
Делается это просто — мы одну пленку подтягиваем к земле. А вторую вешаем на вход с pullup. Был тачскрин, стала обычная кнопка.

Ее мы лениво опрашиваем, в ожидании нажатия. Но тут прячутся вторые вилы, на которые мы будем нарываться еще не раз и не два. Дело в том, что тачскрин это две проводящие пленки. Большие плоские пленки, находящиеся очень близко друг от друга. Ничего не напоминает? Правильно — конденсатор, мать его. А значит у него нефиговая емкость. И если ты его переключишь в режим отслеживания нажатия и тут же проверишь — получишь нажатие. Т.к. емкость еще не успела зарядиться, а значит коротит. Так что после перевода порта в режим опроса надо подождать около миллисекунды. А только потом начинать щупать. То же касается, кстати, и режима смены замеров координат. Начнешь быстро переключать пленки с координаты на координату — получишь полную херню на выходе. Переключил, подождал, замерил. Переключил, подождал, замерил. Только так.

Под это дело я набросал небольшой пример кода для ATMega16 на Pinboard.

Код
Код в виде обычного конечного автомата. Правда он разнесен на процедуру и прерывание.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//=========================================
//Область задач
//=========================================
void ScanTouch(void)
{
switch(TouchState)
	{
	case 0: // Ожидание нажатия. Подготовка.
		{
		DDRA  &=0xF0;
		PORTA &=0xF0;
 
		DDRA  |=1<<XA | 1<<XB;		// XA и XB гонят землю
		PORTA |=1<<YA | 1<<YB;		// YA и YB слушают уровень на входе с подтяжкой
 
		TouchState = 1;			// Переход к стадии  проверки.
 
		SetTimerTask(ScanTouch,10);	// Выдержка для установления состояния и зарядки емкости.
 
		break;
		}
	case 1:	// Проверка нет ли нажатия
		{
		if(PINA & 1<<YA)			// Если на входе 1, т.е. нажатия нет 
			{
			TouchState = 0;			// Возврат на прошлый шаг. 
			SetTimerTask(ScanTouch,10);
			}
		else					// Если 0, т.е. нажатие. Готовим замер!			
			{
			PORTA &=0xF0;			// Зануляем четыре бита, чтобы с чистого листа.
			DDRA &=0xF0;
							// Сейчас Y пленка гонит потенциал, Х считывает. 
			PORTA |=1<<YA;			// YА на Vcc  YB на GND остальные в HiZ нюхают АЦП
			DDRA |=1<<YA|1<<YB;		// -
 
			TouchState=2;			// Переход на другую стадию.
			SetTimerTask(ScanTouch,10);	// Выдержка на переходный процесс.
			}
		break;
		}
 
	case 2:	// Запускаем АЦП для снятия координат
		{
		TouchState = 3;
		ADMUX = 1<<REFS0 | 1<<ADLAR | 2<<MUX0;			//Меняем канал АЦП на чтение Х 
		ADCSRA = 1<<ADEN | 1<<ADIE | 1<<ADSC | 3<<ADPS0;	// Запускаем преобразование. 
		break;							// До встречи в обработчике прерывания.
		}
 
	case 5: // Координаты сняты. Можно обрабатывать. 
		{
		TouchState = 0;
		if (!UDR_Busy)			// Если UART не занят
			{
			UDR_Busy = 1;		// Занимаем его
 
			OutBuff[0] = 'Y';	// Пишем в буфер мессагу
			OutBuff[1] = '=';
 
			BIN8toASCII3(OutBuff[2],OutBuff[3],OutBuff[4],coord_Y);	// Вписываем координаты
 
			OutBuff[5] = ' ';
			OutBuff[6] = 'X';
			OutBuff[7] = '=';
 
			BIN8toASCII3(OutBuff[8],OutBuff[9],OutBuff[10],coord_X);
 
			OutBuff[11] = 10;		//CR - не забываем перевод каретки
			Buff_index = 0;			// Обнуляем индекс
			UDR = OutBuff[Buff_index];	// Поехали!
			}
 
			SetTimerTask(ScanTouch,100);	// Повтор сканирования. Не торопимся
			break;
			}
	default:
		{
		TouchState = 0;
		}
	}
}
 
// Продолжаем веселиться в обработчике прерывания от АЦП
ISR(ADC_vect)
{
PORTA &=0xF0;		// Зануляем четыре бита, чтобы с чистого листа.
DDRA &=0xF0;
 
if(TouchState == 3)
	{
	coord_X = ADCH;		// Прошлый замер дал X
 
	// Сейчас уже X пленка гонит потенциал, Y считывает
	PORTA |=1<<XA;		// ХА на Vcc  XB на GND остальные в HiZ нюхают АЦП
	DDRA |=1<<XA|1<<XB;		// -
 
	ADMUX = 1<<REFS0 | 1<<ADLAR | 3<<MUX0;		// Перебрасываем канал АЦП на другую пленку
	TouchState = 4;					// Перекидываем автомат
 
	ADCSRA = 1<<ADEN | 1<<ADIE | 1<<ADSC | 3<<ADPS0;	// Запускаем конверсию и до встречи тут же.
	}
else if (TouchState == 4)		// Второй вход в прерывание
	{
	coord_Y = ADCH;			// Прошлый замер дал Y
 
	TouchState = 5;			// Стадия обработки
	SetTask(ScanTouch);		// Обе координаты считаны. Готово. Вызваем задачу готовности.
	}
}

Выброс данных в UART идет следующим образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
ISR(USART_TXC_vect)
{
Buff_index++;		// Увеличили индекс
if(Buff_index != 12) 	// Если мессадж не ушел 
	{
	UDR = OutBuff[Buff_index];	// Шлем дальше
	}
else
	{
	Buff_index = 0;			// Иначе все зануляем.
	UDR_Busy = 0;
	}
}

Все очень и очень просто, без задержек и тормозов. Все на конечных автоматах и диспетчере. Но диспетчер тут не принципиален, может быть что угодно. Хоть тот же флаговый автомат. Главное, чтобы была служба таймеров. Весь проект в архиве в конце статьи.

BIN8toASCII3 это макрос переводящий бинарное значение в три разряда ASCII символов, пригодных к выводу в терминалку.

Выглядит оно так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Bin to ASCII 
// IN = value 
// A B C = ascii code of digits
#define BIN8toASCII3(a_,b_,c_,in_) 						\
do										\
{										\
asm volatile(									\
		"LDI %A[RA],-1+'0'" 				"\n\t" 		\
"bcd1%=:"	"INC %A[RA]"					"\n\t"		\
         	"SUBI %A[RC],100"				"\n\t"		\
         	"BRCC bcd1%="					"\n\t"		\
         	"LDI %A[RB],10+'0'"				"\n\t"		\
"bcd2%=:"   	"DEC %A[RB]"					"\n\t"		\
         	"SUBI %A[RC],-10"				"\n\t"		\
         	"BRCS bcd2%="					"\n\t"		\
         	"SBCI %A[RC],-'0'"				"\n\t"		\
										\
		 : [RA]"=a" (a_), [RB]"=a" (b_), [RC]"=a" (c_)			\
		 : "[RC]" (in_)							\
	 );									\
										\
}										\
while(0)

Нет, это не УЖОСНАХ, а GCCшная ассемблерная вставка. Я корячил алгоритм BIN2ASCII и так и эдак, потом решил, что красивей, короче и быстрей чем на ассемблере не получится и воткнул его в код так. О том как писать такие вставки в GCC неплохо написал Alatar в нашем сообществе. Если кто не читал, то рекомендую. Также, если будут желающие, то я дополнительно постараюсь разжевать эту тему до состояния манной каши.

В железе
Сам touchscreen надыбал в Китае, на Dealextrem. Обошелся он мне в пару баксов. Можно еще не очень дорого купить у всяких ремонтников сотовых. Конкретно этот от Nintendo DS, но там множество вариантов с разной диагональю и по различной цене.

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

Да подключил все лапшой к контроллеру. Данные традиционно вывожу на терминалку.

42 thoughts on “Работа с резистивным сенсорным экраном”

  1. Чтобы безопасно припаяться к таким пленочкам можно сделать небольшую печатную платку, с одной стороны которой будут площадки, соответствующие плащадкам на пленке, с другой стороны платы — что угодно. Так можно подпаиваться к другим шлейфам с меньшим шагом между площадками.

  2. Я бы не стал говорить про скорый конец резистивных (р.) экранов. Дело в том, что емкостные очень плохо (читай — почти совсем не) реагируют на руки/пальцы в перчатках, что почти начисто убирает их из списка вариантов для многих промышленных систем. Можно ввернуть им чувствительность, но тогда они начинают ловить кучу помех. Старые р. экраны имели две этих пленки, но вот что я вам скажу — неделю назад на Freescale Technology Forum видел р. экран, который на ощупь не продавливался, но прекрасно работал, в том числе через футболку (ну этот фокус надо было видеть).

  3. > Нет, это не УЖОСНАХ, а GCCшная ассемблерная вставка.

    До кучи познай дао раздельной компиляции и ты сможешь вызывать ассемблерные функции из С как родные. Делов-то вспомнить про calling converntion вообще и про abi в частности.

    1. Пробовал, не очень понравилось. Оптимизатор на ней спотыкается и начинает спешно тасовать регистры. Лучше уж дать ему выбор самому определить что куда ныкать.

  4. На многох платах контроллеров жестких дисков (старые Seagate, например)
    очень часто стоят разъёмы мотора привода шпинделя,
    которые ИДЕАЛЬНО подходят для сенсорных экранов.
    Можно даже вырезать кусочек платы с разъёмом, чтобы не выпаивать его,
    и припаять провода к плате

  5. >> ADCSRA = 1<<ADEN | 1<<ADIE | 1<<ADSC | 3<<ADPS0;
    .. имхо естетичней выглядит: ADCSRA |= 1<<ADSC; // запуск единичного преобразования
    .. но разницы никакой, если только где-то по пути не отключается АЦП, что не очень хорошо, так как первое преобразование самое долгое и неточное

  6. у меня пара вопросов:
    — в коде 2 переменные XA и YA не могу найти где задается их значение.
    — у меня есть тачскрин + экран от видеокамеры Sony DCR-H26 — вроде бы он там резистивный, но информации 0ю Омметром мерял — ерунда получается. Можно как-то определить тип тачскрина?
    — какая скорость терминала 115200?
    — прошил откомпиленный hex в mega32 — по уарту летят нули бесконечно, правда у меня экран хз как подключен, может быть дело в этом. Как бы еще распиновку шлейфа узнать — метод тыка не помог. тоже 4 контакта. Но есть одна особенность — 2 крайних теряются на схеме контролера экрана, а вот 2 центральных выходят на главный шлейф и идут к мозгам, но как я их не крутил — ничего не вышло. может что подскажите?

    1. Резистивный его видно. Он тупой как валенок. В том смысле что там нет контроллера или какой либо электроники. Ну и звонится он омметром.

      Прога написана для мега16 для мега32 надо все зависимые места перекомпилить

      1. ну да, все верно, шлейф и больше ничего нет.
        но даже на 200М не звонится… при подключении шлет постоянно мусор. Он может вообще неисправен :)) кто его знает…
        Перебрал все 16 комбинаций — нашел 5 при которых как-то работает. С остальными нули. что странно ибо комбинаций должно быть четкое кол-во, без разницы же как резисторы подключать. Думаю дальше. матуалов нет вообще никаких :(

        А может бть проблема в несоответствии напряжений? у меня подсветка экрана (отдельная) заработала от 8,5-9,5в… может и тачскрину мало?

        1. На напряжение ему должно быть пофигу — делителю все равно какое делить. А какие контакты где должно быть видно. И не надо ничего перебирать. Вообще чтоль ни одна пара не звонится на какое либо сопротивление? Если нет, то либо дисплей не резистивный, либо он неисправен.

          1. аа черт! после еще пары часов ковыряния но уже по забугорным сайтам выяснилось что экран все таки емкостной :(( ну и замеры емкости это подтвердили :( пошел читать про емкостные экраны :)

    1. если в отзывах к телефону народ говорит что на морозе от рук не пашет — то емкостной.

      судя по этому
      http://ezinearticles.com/?LG-KM900-Arena-Vs-LG-KC910-Renoir&id=2100753
      The Capacitive touch screen technology utilized by the LG KM900 Arena provides superior tactile responsiveness than the resistive touch screen technology used by the LG Renoir.

      там резистивный, но черт его знает на самом деле :)

      1. По фотографии тача видно что он резистивный. Емкостные имеют или шлейф с большим количеством контактов ( посмотрите на тач айфона ) , или контроллер на шлейфе. На этом же явно видны 4 дорожки и видно на какую боковину тача они идут.

        1. Не обязательно. Для емкостного тача достаточно и четырех проводов. У ифона больше изза мультитача — нужно больше сканирующих выводов. Контроллер сразу же на шлейфе делают чтобы повысить точность за счет снижения паразитных емкостей, но и без этого он может вполне годно работать.

    1. Как пользователь LG KM900 Arena могу сказать — сенсор реагирует только на касание пальцем. Стилус он не понимает. Кроме того, в описаниии сказано, что экран защищён каленым стеклом. Интересно — через каленку резистивник срабатывал бы ?

      1. Один разок сработает… Если по приложенному к экрану шилу молотом хорошенько долбануть. Потом не будет уже.
        Все резистивные, что я видел, довольно заметно прогибались при нажатии.

  7. Проблема еще в том что патенты на изготовление емкостных дисплеев имеет ограниченный круг компаний (чужаков туда не пускаю). Не Китайцы конечно могут выпускать что и сколько угодно но крупным компаниям если не договорились не получить емкостных дисплеев.

    Поэтому резистивные еще не скоро уйдут с рынков.

  8. Приветствую того, от кого только NMI c RESET-ом вылечат)! Респект и уважуха за столь содержательные статьи, сайт рулит — почерпнул много полезной в практике информации, возбудмвшей желание поделиться собственными наработками, что уже само по себе — весьма позитивный момент). Ежели будет интерес к тому, что я смогу предложить — то как-нибудь попробую затариться духом святым дабы осилить высечение скрижалей из кремния..) Но об этом в другой раз.
    Теперь — к вопросу на тему. Есть задача сделать стекло (3 стекла из плексигласса) интерактивным, можно заменить таковыми или сварганить из них (плекс+тач) бутерброд — не важно(прочность должна соответствовать приблизительно, критична прозрачность). Точность обработки никакая не требуется, а нужно достаточно произвольно задать несколько областей (прямоугольных, скажем, тоже не суть важно пока) для реагирования на прикосновенмя к оным. Размеры стекла, конечно, не стандартные (одно около 1200x900mm, и два размером 600×900, точно не помню, пока не суть важно, хотя если есть смысл — то можно попробовать подогнать к ближайшему большему габариту). Прогуглмв тему ничего подходящего пока не нашёл(((. Все решения охренительно дороги, цены, правда включают электронику и софт, всё заточено под писюки. Плёнка, как я понял прозрачностью отметается, точнее отсутствием нормального наличмя оной))). Вот бы кто подсказал, где можно купить/заказать стекло такое, технология не инетересует — иультитач не нужен. Буду весьма признателен за любую наводочку, системник пивом залью под завязку.)))

  9. Приветствую того, от кого только NMI c RESET-ом вылечат)! Респект и уважуха за столь содержательные статьи, сайт рулит — почерпнул много полезной в практике информации, возбудившей желание поделиться собственными наработками, что уже само по себе — весьма позитивный момент). Ежели будет интерес к тому, что я смогу предложить — то как-нибудь попробую затариться духом святым дабы осилить высечение скрижалей из кремния..) Но об этом в другой раз.
    Теперь — к вопросу на тему. Есть задача сделать стекло (3 стекла из плексигласса) интерактивным, можно заменить таковыми или сварганить из них (плекс+тач) бутерброд — не важно(прочность должна соответствовать приблизительно, критична прозрачность). Точность обработки никакая не требуется, а нужно достаточно произвольно задать несколько областей (прямоугольных, скажем, тоже не суть важно пока) для реагирования на прикосновенмя к оным. Размеры стекла, конечно, не стандартные (одно около 1200x900mm, и два размером 600×900, точно не помню, пока не суть важно, хотя если есть смысл — то можно попробовать подогнать к ближайшему большему габариту). Прогуглмв тему ничего подходящего пока не нашёл(((. Все решения охренительно дороги, цены, правда включают электронику и софт, всё заточено под писюки. Плёнка, как я понял прозрачностью отметается, точнее отсутствием нормального наличмя оной))). Вот бы кто подсказал, где можно купить/заказать стекло такое, технология не инетересует — иультитач не нужен. Буду весьма признателен за любую наводочку, системник пивом залью под завязку.)))

    1. Несколько лет назад работал со штукой под названием k-glass это обычное стекло ,но с токопроводящим напылением. Мы это напыление резали лазером и получали стеклянные обогреватели, снимая по киловатту с квадратного метра. Может вам что полезное будет из этой серии будет. А вот как превратить его в тач… тут нужно будет думать. Может удастся и индуктивный сделать.

      1. Киловатт с квадратного метра? нехилое напыление. какова его толщина, и каким лазером его можно резать — обычным, типа как у рекламщиков? следов не остаётся? а вариант интересненький, спасибо…

        1. Толщину не знаю, но на вид стекло как стекло, ну может чуть чуть более темное чем оконное. Толщина стекла 5мм. Резали его лазером в 3кВт. Им металл режут, но думаю рекламный тоже сдюжит. Главное чтобы он мог на него сфокусироваться (наш лазер фокусировался на проводящие поверхности и ловил хорошо напыление). Следы остаются естественно. Бороздки будто стеклорез прошел. Но мы не особо много экспериментировали с мощностью и толщиной луча. Не до того было.

  10. Скажите, а терминалка, это как бы к вашему Pinboard идет. Или же совим терминалом можно координаты узнать? И что получается, когда нажатия нет — порт молчит, как коснулся — потекли данные?

  11. Доброе время суток!
    Подскажите как быть в такой вот ситуации?
    Куплен резистивный touch screen на замену вышедшему из строя и сотовый его видит как сдвинутый в лево на пол экрана, т.е. я нажимаю на правый край экрана, а нажатие происходит по середине, если нажимать в середине, то нажимается слева экрана. Калибровка не помогает, т.к. она видит его точно также.

Добавить комментарий