Pages: [1] 2   Go Down
Author Topic: Controller con Touch Screen  (Read 1322 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao,
Dopo aver fatto qualche esperienza con tastiere, display 16x2 e led vari, mi sto cimentando nella realizzazione di un controller per varie funzioni che dovrà essere installato nel cruscotto di un automobile da show.
Mi sono procurato una shield seeed con touch screen 2.8 pollici ed installato tutte le librerie del caso.
Ho disegnato 4 rettangoli sul display ed ho calibrato le coordinate del touch per utilizzare questi rettangoli come pulsanti.
Con la pressione di ogni singolo tasto provvedo ad attivare o disattivare 4 rele (su schedina autocostruita).

Il problema:
Ho provveduto a far evidenziare il tasto mediante inversione dei colori quando lo stesso viene premuto, tornando ai colori normali dopo mezzo secondo (questo mi permette di avere anche una sorta di ritardo ed evitare che il touch rilevi più pressioni del tasto).
Ora vorrei fare in modo che quando premo uno dei tasti, questo rimanga "evidenziato" (invertendo i colori), e quando lo premo nuovamente ritorni allo stato originale, per segnalarmi che il relativo rele' collegato è acceso o spento.

Purtroppo non sono riuscito a venirne a capo...

Video: http://www.youtube.com/watch?v=XosVaYu6NoY&feature=youtu.be

Qui di seguito metto lo sketch
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <stdint.h>
#include <SeeedTouchScreen.h>
#include <TFTv2.h>
#include <SPI.h>

TouchScreen ts = TouchScreen(XP, YP, XM, YM);
int rele1 = 22;
int rele2 = 24;
int rele3 = 26;
int rele4 = 28;

void setup()
{
  TFT_BL_ON;      // turn on the background light
  Tft.TFTinit();  // init TFT library  
  Tft.drawRectangle(5,5,70,48,RED);
  Tft.drawRectangle(5,65,70,48,RED);
  Tft.drawRectangle(5,125,70,48,RED);
  Tft.drawRectangle(5,185,70,48,RED);
  Tft.drawString("OUT 1",10,24,2,RED);
  Tft.drawString("OUT 2",10,84,2,RED);
  Tft.drawString("OUT 3",10,144,2,RED);
  Tft.drawString("OUT 4",10,204,2,RED);
  pinMode(rele1, OUTPUT);
  pinMode(30, OUTPUT);
  pinMode(rele2, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(rele3, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(rele4, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(53, OUTPUT);
}
int on1 = 0;
int on2 = 0;
int on3 = 0;
int on4 = 0;

void loop()
{
  Point p = ts.getPoint();
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);

  if ( p.x > 5 && p.x < 70 && p.y > 5 && p.y <48) {
    if (p.z > __PRESURE) {
      Tft.fillRectangle(5,5,70,48,RED);
      Tft.drawString("OUT 1",10,24,2,BLACK);
      delay(500);
      Tft.fillRectangle(5,5,70,48,BLACK);
      Tft.drawString("OUT 1",10,24,2,RED);
      Tft.drawRectangle(5,5,70,48,RED);
      on1 = !on1;
      digitalWrite(rele1, on1 ? HIGH : LOW);
      digitalWrite(30, on1 ? HIGH : LOW);
    }
  }
  else if ( p.x > 5 && p.x < 70 && p.y > 70 && p.y <118) {
    if (p.z > __PRESURE) {
      Tft.fillRectangle(5,65,70,48,RED);
      Tft.drawString("OUT 2",10,84,2,BLACK);
      delay(500);
      Tft.fillRectangle(5,65,70,48,BLACK);
      Tft.drawString("OUT 2",10,84,2,RED);
      Tft.drawRectangle(5,65,70,48,RED);
      on2 = !on2;
      digitalWrite(rele2, on2 ? HIGH : LOW);
      digitalWrite(32, on2 ? HIGH : LOW);
    }
  }
  else if ( p.x > 5 && p.x < 70 && p.y > 130 && p.y <178) {
    if (p.z > __PRESURE) {
      Tft.fillRectangle(5,125,70,48,RED);
      Tft.drawString("OUT 3",10,144,2,BLACK);
      delay(500);
      Tft.fillRectangle(5,125,70,48,BLACK);
      Tft.drawString("OUT 3",10,144,2,RED);
      Tft.drawRectangle(5,125,70,48,RED);
      on3 = !on3;
      digitalWrite(rele3, on3 ? HIGH : LOW);
      digitalWrite(34, on3 ? HIGH : LOW);
    }
  }
  else if ( p.x > 5 && p.x < 70 && p.y > 190 && p.y <238) {
    if (p.z > __PRESURE) {
      Tft.fillRectangle(5,185,70,48,RED);
      Tft.drawString("OUT 4",10,204,2,BLACK);
      delay(500);
      Tft.fillRectangle(5,185,70,48,BLACK);
      Tft.drawString("OUT 4",10,204,2,RED);
      Tft.drawRectangle(5,185,70,48,RED);
      on4 = !on4;
      digitalWrite(rele4, on4 ? HIGH : LOW);
      digitalWrite(36, on4 ? HIGH : LOW);
    }
  }
}
edit by mod: il codice va incluso con gli appositi tag
« Last Edit: May 20, 2013, 03:00:24 am by leo72 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Risolto questo dovrò poi aggiungere dei controlli temperatura, pressione aria, ecc
Logged

Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Non conosco la libreria che usi, ma non è difficile capire cosa fanno le righe del codice da te inviato.

Due domande, prima di proporti un'idea per la soluzione.
Come mai per on1, on2, ... hai usato intero invece che booleano?
Per quale motivo non hai messo il controllo if p.z>_... (che presumo verifichi il tocco sullo schermo) prima di tutti gli altri if in modo da nidificali all'interno e far controllare al programma coordinate e tutto il resto solo nel caso di un clic?

Ora vediamo alla mia idea, sperando che possa esserti utile.
Consideriamo il blocco di codice inerente ad out1

Code:
if ( p.x > 5 && p.x < 70 && p.y > 5 && p.y <48) {
    if (p.z > __PRESURE) {
      Tft.fillRectangle(5,5,70,48,RED);
      Tft.drawString("OUT 1",10,24,2,BLACK);
      delay(500);
      Tft.fillRectangle(5,5,70,48,BLACK);
      Tft.drawString("OUT 1",10,24,2,RED);
      Tft.drawRectangle(5,5,70,48,RED);
      on1 = !on1;
      digitalWrite(rele1, on1 ? HIGH : LOW);
      digitalWrite(30, on1 ? HIGH : LOW);
    }
  }


Elimina tutto il blocco prima di on1=...
quindi togli il pezzo
Code:
      Tft.fillRectangle(5,5,70,48,RED);
      Tft.drawString("OUT 1",10,24,2,BLACK);
      delay(500);
      Tft.fillRectangle(5,5,70,48,BLACK);
      Tft.drawString("OUT 1",10,24,2,RED);
      Tft.drawRectangle(5,5,70,48,RED);
un piccolo delay come antibounching lo lascerei, ma lo vedrai con l'uso pratico se e quanto sia utile...
dopo on1=!on1 hai lo stato attuale del parametro on1, attivi il rele e - presumo - il led corrispondente, a questo punto potresti aggiornare lo stato del rettangolo corrispondente sullo schermo con qualcosa come:

Code:
      Tft.fillRectangle(5,5,70,48,BKGR1);
      Tft.drawString("OUT 1",10,24,2,TXTR1);
      Tft.drawRectangle(5,5,70,48,BORDR1);

dove alle variabili bkgr1, txtr1, bordr1 fai assumere i valori che vuoi a seconda che lo stato on1 sia 1 oppure 0.
Ancora meglio, crei una bella funzione alla quale passi numero del rettangolo e stato on corrispondente e la funzione ti disegna il rettangolo, così scrivi il codice una volta sola e lo usi per tutti i rettangoli presenti e che vorrai in seguito aggiungere.

Spero di esserti stato utile...
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Questo thread è stato aperto nella sezione sbagliata.
Al momento non riesco a spostarlo nella sezione corretta per problemi legati agli ultimi aggiornamenti del forum per cui:
1) lo chiudo;
2) chiedo al suo autore di riaprirlo in una sezione più appropriata;

3) leggere il regolamento

edit:
spostato in "generale" (anche se non è la più appropriata)
« Last Edit: May 20, 2013, 03:01:54 am by leo72 » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ Mod
Chiedo scusa per gli errori... Non lo faccio più  smiley-red

@ paulus1969
Grazie per l'interessamento...
Il pezzo di codice on = !on proviene da un precedente tutorial che avevo seguito sull'accensione e spegnimento di rele con telecomando IR, che poi ho prelevato e riadattato per questo nuovo progetto.
Francamente non saprei dirti il perchè sia stato utilizzato un operatore piuttosto che un altro (non sono ancora abbastanza esperto per scrivere da zero completo un programma e utilizzo arduino principalmente come laboratorio per apprendere qualche fondamento di linguaggio C).
Riguardo al controllo  "if p.z>_..." in effetti l'esempio presente all'interno della libreria lo riportava una sola volta a monte di tutto il listato. Poi io pasticciando con il codice avevo fatto delle prove e mi è rimasto scritto così (provvedo comunque a ripristinare il codice originale).

Appena arrivo a casa provo quanto da te suggerito... In effetti io prima andavo a ridisegnare sopra un altro rettangolo non creando una vera e propria inversione di stato ma solo di colori.

Il problema è che non riesco ad associare gli stati "on ?" ai comandi della libreria "Tft.draw_xxx" probabilmente a causa di di sintassi sbagliate...
Stesso problema nel caso volessi scrivere lo stato del rele in un testo a parte di fianco al tasto (tipo on off). Non riesco ad associare gli stati "on?"

Saluti,
Davide
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho trovato la sintassi giusta ed ora funziona come mi serviva  smiley

Posto il codice:
Code:
#include <stdint.h>
#include <SeeedTouchScreen.h>
#include <TFTv2.h>
#include <SPI.h>

TouchScreen ts = TouchScreen(XP, YP, XM, YM);
int rele1 = 22;
int rele2 = 24;
int rele3 = 26;
int rele4 = 28;

void setup()
{
  TFT_BL_ON;      // turn on the background light
  Tft.TFTinit();  // init TFT library 
  Tft.drawRectangle(5,5,70,48,RED);
  Tft.drawRectangle(5,65,70,48,RED);
  Tft.drawRectangle(5,125,70,48,RED);
  Tft.drawRectangle(5,185,70,48,RED);
  Tft.drawString("OUT 1",10,24,2,RED);
  Tft.drawString("OUT 2",10,84,2,RED);
  Tft.drawString("OUT 3",10,144,2,RED);
  Tft.drawString("OUT 4",10,204,2,RED);
  pinMode(rele1, OUTPUT);
  pinMode(30, OUTPUT);
  pinMode(rele2, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(rele3, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(rele4, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(53, OUTPUT);
}
int on1 = 0;
int on2 = 0;
int on3 = 0;
int on4 = 0;

void loop()
{
  Point p = ts.getPoint();
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
 
if (p.z > __PRESURE) {
  if ( p.x > 5 && p.x < 70 && p.y > 5 && p.y <48) {
      on1 = !on1;
      delay(500);
      digitalWrite(rele1, on1 ? HIGH : LOW);
      digitalWrite(30, on1 ? HIGH : LOW);
      on1 ? Tft.fillRectangle(5,5,70,48,RED) : Tft.fillRectangle(5,5,70,48,BLACK);
      on1 ? Tft.drawString("OUT 1",10,24,2,BLACK) : Tft.drawString("OUT 1",10,24,2,RED);
      on1 ? Tft.drawRectangle(5,5,70,48,RED) : Tft.drawRectangle(5,5,70,48,RED);
    }
  }
  else if ( p.x > 5 && p.x < 70 && p.y > 70 && p.y <118) {
      on2 = !on2;
      delay(500);
      digitalWrite(rele2, on2 ? HIGH : LOW);
      digitalWrite(32, on2 ? HIGH : LOW);
      on2 ? Tft.fillRectangle(5,65,70,48,RED) : Tft.fillRectangle(5,65,70,48,BLACK);
      on2 ? Tft.drawString("OUT 2",10,84,2,BLACK) : Tft.drawString("OUT 2",10,84,2,RED);
      on2 ? Tft.drawRectangle(5,65,70,48,RED) : Tft.drawRectangle(5,65,70,48,RED);
  }
  else if ( p.x > 5 && p.x < 70 && p.y > 130 && p.y <178) {
      on3 = !on3;
      delay(500);
      digitalWrite(rele3, on3 ? HIGH : LOW);
      digitalWrite(34, on3 ? HIGH : LOW);
      on3 ? Tft.fillRectangle(5,125,70,48,RED) : Tft.fillRectangle(5,125,70,48,BLACK);
      on3 ? Tft.drawString("OUT 3",10,144,2,BLACK) : Tft.drawString("OUT 3",10,144,2,RED);
      on3 ? Tft.drawRectangle(5,125,70,48,RED) : Tft.drawRectangle(5,125,70,48,RED);
  }
  else if ( p.x > 5 && p.x < 70 && p.y > 190 && p.y <238) {
      on4 = !on4;
      delay(500);
      digitalWrite(rele4, on4 ? HIGH : LOW);
      digitalWrite(36, on4 ? HIGH : LOW);
      on4 ? Tft.fillRectangle(5,185,70,48,RED) : Tft.fillRectangle(5,185,70,48,BLACK);
      on4 ? Tft.drawString("OUT 4",10,204,2,BLACK) : Tft.drawString("OUT 4",10,204,2,RED);
      on4 ? Tft.drawRectangle(5,185,70,48,RED) : Tft.drawRectangle(5,185,70,48,RED);
  }
}

Ora provo ad infilare dentro altre funzionalità...

Grazie paulus1969  smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Logged

Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bene, mi rimane un dubbio su quel delay di 500 ms, forse è un po' troppo lungo... ma l'importante è che adesso il programma faccia quello per cui è stato concepito.

Si potrebbe migliorare spostando in una funzione il codice che è ripetuto diverse volte.

Fatto questo, sarai pronto per scrivere un piccolo tutorial sul tuo lavoro, quindi schema del collegamento del display, dove lo hai comprato, quanto costa, schema della scheda... e software. Magari finisce nuovamente sul forum megatopic dal quale è stato spostato!  smiley-lol
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao,
Il delay è necessario perchè altrimenti quando tieni il dito sul touch prende delle "letture continue" facendo attaccare e staccare continuamente il relè alla frequenza di clock dell'arduino (o del display, non saprei).
Ora sto cercando un sistema per fare 4 piccole schedine "voltage divider" per far leggere all'arduino delle tensioni a mo' di voltmetro, e visualizzare le 4 tensioni sempre sul display.
Inoltre il progetto dovrebbe prevedere il controllo anche delle sospensioni pneumetiche dell'automobile da show, pertanto poi dovrò ingegnarmi con pressostati, elettrovalvole e quant'altro necessario.
Un passo alla volta  smiley-lol
Ho cominciato solo un paio di mesi fa con Arduino, avendo solo una piccolissima esperienza di programmazione html...
Fortunatamente maneggio plc (ladder) e tastiere industriali per mestiere, quindi perlomeno non sono completamente a digiuno sulla logica di funzionamento di queste elettroniche  smiley-wink Ma sul C non avevo mai lavorato.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi dai qualche dritta sulla funzione?
Il mio problema è che le coordinate dei tasti sono diverse, quindi anche se faccio le funzioni tipo "evidenziato rosso" e "evidenziato nero" come lo associo poi alle coordinate giuste di ogni singolo tasto?

Saluti,
Davide
Logged

Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Passi il numero di tasto o di relè come parametro alla funzione.

Puoi agire con funzioni come colora (tasto, colore)
oppure tastrosso (tasto)
tastnero (tasto)
accendi(rele)
spegni(rele)
inverti(rele)
...
e così via

Così - oltre ad un codice più elegante e riutilizzabile - hai il vantaggio di poter aggiungere e togliere pulsanti ed attuatori in modo molto semplice e puoi anche facilmente mettere degli "effetti speciali" (visto l'uso al quale mi par di capire è destinato il sistema) con cicli for o con il generatore di numeri casuali.

EDIT:
Le coordinate le metti in uno o più array, guarda qui:
http://arduino.cc/en/Reference/Array
« Last Edit: May 21, 2013, 01:04:23 pm by paulus1969 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Azz... Penso che su questo dovrò lavorare parecchio  smiley-lol
Siamo già molto più avanti delle mie reali capacità nella programmazione...
Se ho ben capito dovrei creare una funzione tipo "void xxx" ed elencare all'interno tutti gli stati possibili, per poi richiamarla al bisogno?

Al momento sto provando ad aggiungere 4 misure di tensione tramite un semplice "voltage divider". Ho già realizzato la schedina (2 semplici resistenze per ogni voltmetro) e codice scopiazzato da qui: http://www.clarenceho.net:8123/blog/articles/2009/05/17/arduino-test-voltmeter

Quel codice funziona benissimo se usato così com'è (visualizzando il risultato su monitor seriale). Sto provando ad adattarlo per visualizzare i risultati delle misure sul display e non riesco ancora a fare il refresh del video. In pratica viene scritto il risultato nuovo sopra a quello vecchio sul display rendendo il tutto ovviamente illeggibile.

Mah... stiamo a vedere...  smiley-mr-green
Logged

Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Questo è un "classico"  smiley-lol
Diversi i sistemi per rimediare...
te ne elenco un paio

Mettiti nelle coordinate su cui scrivere il valore corrente e

- Stampa prima un "                " , vuota, solo spazi, e poi ti rimetti sulle coordinate e stampa il valore corrente

- Stampa il valore corrente seguito da "    ", solo spazi

- Se sei sul grafico ed il valore lo rappresenti in un rettangolo, ridisegna lo sfondo del rettangolo e poi il valore corrente

insomma il trucco consiste nel coprire il valore precedente con le cifre del nuovo valore e con degli spazi. Se il display grafico che usi (non so come funziona) non ti copre i caratteri con gli spazi ma ti sovrappone nuovi a vecchi caratteri, vedi se puoi impostare un background color per i caratteri o al limite usa il rettangolo.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Con il metodo degli spazi non va. Con il metodo del rettangolo del colore di sfondo invece si.
Sono però sorti 2 effetti collaterali:
  • Non funzionano più i tasti correttamente
  • La misura di tensione aumenta a seconda di quanti tasti vengono attivati

Con il ciclo di base già postato in precedenza (con delay di 500ms), se tengo il dito appoggiato su uno qualsiasi dei tasti questo cambia stato "on/off" ogni 500ms. Inserendo il codice del "voltmetro" all'interno del ciclo questo mi disturba la ciclica dei tasti. Il tasto numero 1 funziona correttamente, mentre gli altri 3 si attivano e disattivano a tratti (apparentemente random).

A mia interpretazione il problema potrebbe essere causato dal fatto che il ciclo è composto da:
void loop ()
- "if" pulsate premuto
  - "if" pulsante 1
  - "else if" pulsante 2
  - "else if" pulsante 3
  - "else if" pulsante 4
- ciclo voltmero
In pratica essendo il ciclo voltmetro ad un livello "più alto" nella gerarchia del ciclo rispetto ai singoli tasti, l'arduino sembra mettere sullo stesso piano gli "if" e il "ciclo voltmetro" lasciando indietro gli "else if". Scusate se l'ho detto in modo un po spartano ma sto provando a interpretare...

Poi ho notato che misurando ad esempio una sempice batteria tipo AAA (1,5V) quando attivo uno dei tasti la misura sale un po. poi attivando progressivamente anche gli altri tasti la misura sale progressivamente fino a 2 Volt.

Mah...
Logged

Pages: [1] 2   Go Up
Jump to: