Na primeira parte vimos como é a interface com o controlador do display. E a detecção de toque? Esta parte não é tratada pelo controlador, porém utiliza alguns pinos em comum com ele. Quais pinos e como implementar a detecção de toque deu um pouco de trabalho.
De forma resumida, quando realizamos um toque, é feito o contato entre duas linhas resistivas ortogonais (em formato de cruz). Dois pino estão ligados ao extremo da linha X e dois pinos estão ligados ao extremo da linha Y. Para conseguirmos detectar a posição do toque é preciso que pelo menos um extremo de cada linha esteja ligado a uma entrada analógica:
- Detectar se temos um toque: colocamos em nível baixo os dois extremos de uma linha (por exemplo X), ligamos uma ponta da outra linha à alimentação via um pullup (basta configurar este pino como entrada com pullup) e examinamos a tensão na outra ponta. Se tiver toque, a tensão será próxima de zero (devido ao contato com a linha aterrada), caso contrário será alguma tensão positiva (devido ao pullup).
- Determinar a posição no eixo X: Colocamos uma ponta do Y em nível alto e a outra em nível baixo e medimos a tensão na ponta do X ligada à entrada analógica.
- Determinar a posição no eixo Y: Colocamos uma ponta do X em nível alto e a outra em nível baixo e medimos a tensão na ponta do Y ligada à entrada analógica.
Como descobrir quais os pinos usados? Basta desconectar o shield do Arduino e usar um multímetro para medir a resistência entre os pinos analógicos e os demais. A maioria das combinações vai ser indicada pelo multímetro como "aberto" (sem conexão). Dois pares vão indicar resistência, são os extremos das linhas. No meu caso foram (6, A1) e (7, A8). Você pode fazer um teste colocando o multímetro para medir a resistência entre uma ponta de uma linha e uma ponta da outra: sem toque fica em aberto, com toque resulta numa resistência que muda conforme onde você toca.
O programa abaixo mostra a detecção de toque e a determinação da posição:
- // Conexões do display
- const int lcdRST = A4;
- const int lcdCS = A3;
- const int lcdRS = A2;
- const int lcdWR = A1;
- const int lcdRD = A0;
- const int lcdDATA[] = {8, 9, 2, 3, 4, 5, 6, 7 };
- // Conexões do sensor de toque
- const int touchY1 = A1;
- const int touchY2 = 7;
- const int touchX1 = A2;
- const int touchX2 = 6;
- // Iniciação
- void setup() {
- // Inicia o controlador do display
- // (para ter certeza que não vai interferir)
- for (int i = 0; i < 8; i++) {
- pinMode(lcdDATA[i], INPUT);
- }
- pinMode(lcdRST, OUTPUT);
- digitalWrite (lcdRST, HIGH);
- delay(10);
- digitalWrite (lcdRST, LOW);
- delay(10);
- digitalWrite (lcdRST, HIGH);
- delay(10);
- pinMode(lcdCS, OUTPUT);
- digitalWrite (lcdCS, HIGH);
- pinMode(lcdRS, OUTPUT);
- digitalWrite (lcdRS, HIGH);
- pinMode(lcdRD, OUTPUT);
- digitalWrite (lcdRD, HIGH);
- pinMode(lcdWR, OUTPUT);
- digitalWrite (lcdWR, HIGH);
- // Inicia a serial
- Serial.begin(115200);
- }
- // Laço perpétuo
- void loop() {
- static int maxX = 0, maxY = 0;
- static int minX = 1024, minY = 1024;
- int x, y;
- if (temToque()) {
- // Lê a posição
- x = toqueX();
- y = toqueY();
- // Atualiza mínimo e máximo
- if (x < minX) {
- minX = x;
- }
- if (x > maxX) {
- maxX = x;
- }
- if (y < minY) {
- minY = y;
- }
- if (y > maxY) {
- maxY = y;
- }
- // Mostra o resultado
- Serial.print ("X = ");
- Serial.print (x);
- Serial.print (" [");
- Serial.print (minX);
- Serial.print (":");
- Serial.print (maxX);
- Serial.print ("] Y = ");
- Serial.print (y);
- Serial.print (" [");
- Serial.print (minY);
- Serial.print (":");
- Serial.print (maxY);
- Serial.println ("]");
- }
- delay (1000);
- }
- // Verifica se tem toque
- bool temToque() {
- pinMode (touchY1, INPUT);
- pinMode (touchY2, INPUT_PULLUP);
- pinMode (touchX1, OUTPUT);
- pinMode (touchX2, OUTPUT);
- digitalWrite (touchX1, LOW);
- digitalWrite (touchX2, LOW);
- delay(5);
- Serial.print ("Teste de toque: ");
- Serial.println (analogRead(touchY1));
- return analogRead(touchY1) < 30;
- }
- // Le a coordenada X do toque (sem escala)
- int toqueX() {
- pinMode (touchX1, OUTPUT);
- pinMode (touchX2, OUTPUT);
- pinMode (touchY1, INPUT);
- pinMode (touchY2, INPUT);
- digitalWrite (touchX1, LOW);
- digitalWrite (touchX2, HIGH);
- delay(1);
- int soma = 0;
- for (int i = 0; i < 5; i++) {
- soma += analogRead(touchY1);
- }
- return soma/5;
- }
- // Le a coordenada Y do toque (sem escala)
- int toqueY() {
- pinMode (touchX1, INPUT);
- pinMode (touchX2, INPUT);
- pinMode (touchY1, OUTPUT);
- pinMode (touchY2, OUTPUT);
- digitalWrite (touchY1, LOW);
- digitalWrite (touchY2, HIGH);
- delay(1);
- int soma = 0;
- for (int i = 0; i < 5; i++) {
- soma += analogRead(touchX1);
- }
- return soma/5;
- }
Experimentando um pouco você vai ver que a variação da leitura fica apenas numa parte da faixa de 0 a 1023 do ADC. Você precisa fazer um processo de calibração para determinar os valores para os limites (pode variar de display para display); os valores intermediários são deduzidos supondo que a resistência varia linearmente.
Partes das informações aqui eu peguei em https://www.hackster.io/calogerus/arduino-uno-2-4-tft-lcd-display-shield-touch-panel-ili9341-576b1b. Notar que o display deste artigo tem a detecção de toque ligada em pinos diferentes.
Nenhum comentário:
Postar um comentário