terça-feira, maio 25, 2021

Examinando um Shield Arduino com Display LCD TTF de 2,4" Sensível ao Toque - Parte 2

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:
  1. // Conexões do display  
  2. const int lcdRST = A4;  
  3. const int lcdCS = A3;  
  4. const int lcdRS = A2;  
  5. const int lcdWR = A1;  
  6. const int lcdRD = A0;  
  7.   
  8. const int lcdDATA[] = {8, 9, 2, 3, 4, 5, 6, 7 };  
  9.   
  10. // Conexões do sensor de toque  
  11. const int touchY1 = A1;  
  12. const int touchY2 = 7;  
  13. const int touchX1 = A2;  
  14. const int touchX2 = 6;  
  15.   
  16. // Iniciação  
  17. void setup() {  
  18.   // Inicia o controlador do display  
  19.   // (para ter certeza que não vai interferir)  
  20.   for (int i = 0; i < 8; i++) {  
  21.     pinMode(lcdDATA[i], INPUT);  
  22.   }  
  23.   pinMode(lcdRST, OUTPUT);  
  24.   digitalWrite (lcdRST, HIGH);  
  25.   delay(10);  
  26.   digitalWrite (lcdRST, LOW);  
  27.   delay(10);  
  28.   digitalWrite (lcdRST, HIGH);  
  29.   delay(10);  
  30.   pinMode(lcdCS, OUTPUT);  
  31.   digitalWrite (lcdCS, HIGH);  
  32.   pinMode(lcdRS, OUTPUT);  
  33.   digitalWrite (lcdRS, HIGH);  
  34.   pinMode(lcdRD, OUTPUT);  
  35.   digitalWrite (lcdRD, HIGH);  
  36.   pinMode(lcdWR, OUTPUT);  
  37.   digitalWrite (lcdWR, HIGH);  
  38.   
  39.   // Inicia a serial  
  40.   Serial.begin(115200);  
  41. }  
  42.   
  43. // Laço perpétuo  
  44. void loop() {  
  45.   static int maxX = 0, maxY = 0;  
  46.   static int minX = 1024, minY = 1024;  
  47.   int x, y;  
  48.     
  49.   if (temToque()) {  
  50.     // Lê a posição  
  51.     x = toqueX();  
  52.     y = toqueY();  
  53.   
  54.     // Atualiza mínimo e máximo  
  55.     if (x < minX) {  
  56.       minX = x;  
  57.     }  
  58.     if (x > maxX) {  
  59.       maxX = x;  
  60.     }  
  61.     if (y < minY) {  
  62.       minY = y;  
  63.     }  
  64.     if (y > maxY) {  
  65.       maxY = y;  
  66.     }  
  67.   
  68.     // Mostra o resultado  
  69.     Serial.print ("X = ");  
  70.     Serial.print (x);  
  71.     Serial.print (" [");  
  72.     Serial.print (minX);  
  73.     Serial.print (":");  
  74.     Serial.print (maxX);  
  75.     Serial.print ("] Y = ");  
  76.     Serial.print (y);  
  77.     Serial.print (" [");  
  78.     Serial.print (minY);  
  79.     Serial.print (":");  
  80.     Serial.print (maxY);  
  81.     Serial.println ("]");  
  82.   }  
  83.   delay (1000);  
  84. }  
  85.   
  86. // Verifica se tem toque  
  87. bool temToque() {  
  88.   pinMode (touchY1, INPUT);  
  89.   pinMode (touchY2, INPUT_PULLUP);  
  90.   pinMode (touchX1, OUTPUT);  
  91.   pinMode (touchX2, OUTPUT);  
  92.   digitalWrite (touchX1, LOW);  
  93.   digitalWrite (touchX2, LOW);  
  94.   delay(5);  
  95.   Serial.print ("Teste de toque: ");  
  96.   Serial.println (analogRead(touchY1));  
  97.   return analogRead(touchY1) < 30;  
  98. }  
  99.   
  100. // Le a coordenada X do toque (sem escala)  
  101. int toqueX() {  
  102.   pinMode (touchX1, OUTPUT);  
  103.   pinMode (touchX2, OUTPUT);  
  104.   pinMode (touchY1, INPUT);  
  105.   pinMode (touchY2, INPUT);  
  106.   digitalWrite (touchX1, LOW);  
  107.   digitalWrite (touchX2, HIGH);  
  108.   delay(1);  
  109.   int soma = 0;  
  110.   for (int i = 0; i < 5; i++) {  
  111.     soma += analogRead(touchY1);  
  112.   }  
  113.   return soma/5;  
  114. }  
  115.   
  116. // Le a coordenada Y do toque (sem escala)  
  117. int toqueY() {  
  118.   pinMode (touchX1, INPUT);  
  119.   pinMode (touchX2, INPUT);  
  120.   pinMode (touchY1, OUTPUT);  
  121.   pinMode (touchY2, OUTPUT);  
  122.   digitalWrite (touchY1, LOW);  
  123.   digitalWrite (touchY2, HIGH);  
  124.   delay(1);  
  125.   int soma = 0;  
  126.   for (int i = 0; i < 5; i++) {  
  127.     soma += analogRead(touchX1);  
  128.   }  
  129.   return soma/5;  
  130. }  
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: