Touch Screen Library: Unterschied zwischen den Versionen

Aus ProjectWiki
Wechseln zu:Navigation, Suche
K (Electrical Connection)
K (API)
 
(11 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 2: Zeile 2:
 
Based on the Appnote [http://www.atmel.com/Images/doc8091.pdf AVR341 - Four and five-wire Touch Screen Controller] by Atmel, this library handles everything needed to use a 4-wire resistive touchscreen in Bascom.
 
Based on the Appnote [http://www.atmel.com/Images/doc8091.pdf AVR341 - Four and five-wire Touch Screen Controller] by Atmel, this library handles everything needed to use a 4-wire resistive touchscreen in Bascom.
  
Features:
+
[https://youtu.be/eGcUwT6J5nE?t=2m47s Demo Video]
 +
 
 +
[http://www.mcselec.com/index2.php?option=com_forum&Itemid=59&page=viewtopic&t=12623 Forum Thread]
 +
 
 +
'''Features:'''
 
* Interrupt-controlled sampling
 
* Interrupt-controlled sampling
* Touch contact pressure measurement
+
* Touch contact resistance measurement
 
* Adjustable sampling rate
 
* Adjustable sampling rate
 
* Filtering
 
* Filtering
Zeile 10: Zeile 14:
 
* Screen rotation
 
* Screen rotation
 
* Click/Drag detection
 
* Click/Drag detection
* AtXMega, AtMega (untested)
+
* ATXmega, ATmega (untested)
 +
 
  
 
==How to use==
 
==How to use==
 +
Before including the library, a display has to be set up (for the calibration routine draw functions) and the settings (below) need to be done.
 +
<pre>Config Graphlcd =
 +
 +
Const Touch_updaterate = 200
 +
$include "4wireResistiveTouch.inc"</pre>
 +
 +
The application could look like:
 +
<pre>Dim Status As Byte
 +
 +
Touch_init
 +
Do
 +
  Status = Touch_get_sample()
 +
  If Status = True Then
 +
      ' new coordinates are available in Touch_x and Touch_y (and Touch_r if enabled)
 +
 +
  End If
 +
 +
  ' ... more code
 +
Loop</pre>
 +
  
 
===Options===
 
===Options===
Options and settings need to be set before the $include-statement, every setting has a default value that will be used if not specified otherwise.
+
Options and settings need to be set before the ''$include''-statement, every setting has a default value that will be used if not specified otherwise.
 
(in the list below the default values are shown)
 
(in the list below the default values are shown)
  
Zeile 31: Zeile 56:
 
* 1: Method 1 (needs one additional sample cycle)
 
* 1: Method 1 (needs one additional sample cycle)
 
* 2: Method 2 (needs two additional sample cycles)
 
* 2: Method 2 (needs two additional sample cycles)
<pre>Touch_read_resistance = False</pre>
+
<pre>Const Touch_read_resistance = False</pre>
  
 
If the contact resistance measurement is enabled, the touch ITO layer resistances need to be known (in Ohms, measured between + and - contact of the unconnected touch layers, Y-resistance is only needed for Method 1, X for both):
 
If the contact resistance measurement is enabled, the touch ITO layer resistances need to be known (in Ohms, measured between + and - contact of the unconnected touch layers, Y-resistance is only needed for Method 1, X for both):
Zeile 37: Zeile 62:
 
Const Touch_resistance_y = 600</pre>
 
Const Touch_resistance_y = 600</pre>
  
Control port for touch screen (standard I/O port):
+
If the contact resistance measurement is enabled, an additional sanity check is performed, coordinates are only valid if the resistance is below this value (in Ohms):
<pre>Touch_ctrl_port Alias Porta</pre>
+
<pre>Const Touch_max_resistance = 1000</pre>
 +
 
 +
Control port for touch screen (ATXmega: I/O port, ATmega: Port of X+ INT, other wires connected to PortA):
 +
<pre>Const Touch_ctrl_port = Varptr( "Portb") </pre>
  
 
Control port pin connections:
 
Control port pin connections:
Zeile 46: Zeile 74:
 
Const Touch_pin_yn = 3</pre>
 
Const Touch_pin_yn = 3</pre>
  
ADC port pin connections (XMega: Adca is used, AtMega: can be the same as the control port pins if control port is also the ADC port):
+
(ATXmega only) ADC port pin connections (Adca is used):
 
<pre>Const Touch_pin_xn_adc = 4
 
<pre>Const Touch_pin_xn_adc = 4
 
Const Touch_pin_yn_adc = 5
 
Const Touch_pin_yn_adc = 5
Zeile 74: Zeile 102:
  
 
===API===
 
===API===
Status Flags:
+
'''Status Flags:'''
 
<pre>Dim Touch_touched As Bit
 
<pre>Dim Touch_touched As Bit
 
Dim Touch_newsample As Byte
 
Dim Touch_newsample As Byte
 
Dim Touch_sample_invalid As Bit
 
Dim Touch_sample_invalid As Bit
Dim Touch_clicked As Byte
+
Dim Touch_clicked As Bit
 
Dim Touch_dragging As Bit
 
Dim Touch_dragging As Bit
 
Dim Touch_calibrated As Bit</pre>
 
Dim Touch_calibrated As Bit</pre>
  
Coordinates:
+
'''Coordinates:'''
 
<pre>Dim Touch_x As Word , Touch_y As Word
 
<pre>Dim Touch_x As Word , Touch_y As Word
#if Touch_measure_resistance >= 1
+
Dim Touch_r As Word         ' only available if contact resistance measurement is enabled</pre>
  Dim Touch_r As Word
 
#endif</pre>
 
  
Display rotation:
+
'''Display rotation:'''
 
* 0: 0°
 
* 0: 0°
 
* 1: 90°
 
* 1: 90°
 
* 2: 180°
 
* 2: 180°
 
* 3: 270°
 
* 3: 270°
If the touch screen supports rotation, the transformed screen coordinates need to be rotated to. The rotation information needs to be provided with this variable. It can be declared in the main application, above the $include statement (for example as an overlay to the display driver's rotation variable), if not set, it is declared automatically.
+
If the touch screen supports rotation, the transformed screen coordinates need to be rotated too. The rotation information needs to be provided with this variable. It can be declared in the main application, above the ''$include'' statement (for example as an overlay to the display driver's rotation variable), if not set, it is declared automatically.
 
<pre>Dim Touch_rotation As Byte</pre>
 
<pre>Dim Touch_rotation As Byte</pre>
  
Sub routines:
+
'''Sub routines:'''
 +
 
 +
Initializes the hardware modules (Timer, ADC, Pin Interrupt) and enters standby mode
 
<pre>Sub Touch_init()</pre>
 
<pre>Sub Touch_init()</pre>
Initializes the hardware modules (Timer, ADC, Pin Interrupt) and enters standby mode
 
  
 +
Starts the calibration procedure, calculates the coefficients and stores the calibration values in EEPROM
 
<pre>Sub Touch_calibrate()</pre>
 
<pre>Sub Touch_calibrate()</pre>
Starts the calibration procedure, calculates the coefficients and stores the calibration values in EEPROM
 
  
 +
Loads the calibration values from EEPROM. If they are not set, the calibration procedure is started. This sub routine is called from ''Touch_init()'', no need to call again after init.
 
<pre>Sub Touch_load_calibration()</pre>
 
<pre>Sub Touch_load_calibration()</pre>
Loads the calibration values from EEPROM. If they are not set, the calibration procedure is started. This sub routine is called from Touch_init, no need to call again after init.
 
  
 +
Resets the stored calibration values
 
<pre>Sub Touch_reset_calibration()</pre>
 
<pre>Sub Touch_reset_calibration()</pre>
Resets the stored calibration values
 
  
 +
Returns ''True'' (1) if new valid coordinate data is available, otherwise returns ''False'' (0). The coordinate data is transformed into screen coordinates if calibration values are available. The coordinate variables are updated.
 
<pre>Function Touch_getsample() As Byte</pre>
 
<pre>Function Touch_getsample() As Byte</pre>
Returns True (1) if new valid coordinate data is available, otherwise returns False (0). The coordinate data is transformed into screen coordinates if calibration values are available. The coordinate variables are updated.
 
  
 +
Returns ''True'' (1) if the touch screen has been clicked (delta between first and last point below threshold and touch screen released), otherwise returns ''False'' (0). The coordinate variables are updated.
 
<pre>Function Touch_click() As Byte</pre>
 
<pre>Function Touch_click() As Byte</pre>
Returns True (1) if the touch screen has been clicked (delta between first and last point below threshold and touch screen released). The coordinate variables are updated.
 
  
 
===Other Display Types===
 
===Other Display Types===
 +
The calibration function uses some graphic functions (Cls, Circle and Rotate, if supported by the display) to draw the reference points. LCDs configured via Bascom (''Config Graphlcd ='' ) do not need any changes in the code, as well as for my ILI9341 library (which supports rotation). Other display types could be used as well with small changes, the corresponding lines in the ''Touch_calibrate()'' sub routine are marked with ''# DISPLAY CLS #'', ''# DISPLAY CIRCLE #'' and ''# DISPLAY ROTATE #''.
  
  
 
===Change Timer-, ADC-Hardware-Module and Pin Interrupt===
 
===Change Timer-, ADC-Hardware-Module and Pin Interrupt===
 +
To simplify modifications, all hardware-related functions and settings are kept at a single location, for both ATmega and ATXmega, in section ''Portability'', marked with ''# XMEGA #'' and ''# ATMEGA #''.
 +
 +
For the ATmega, ''TIMER0'', the ''ADC'' module and ''INT0'' are used, the ATxmega is set up to use ''TCC1'', ''ADCA.CH0'', and ''PORT.INT0''.
  
  
 
===Electrical Connection===
 
===Electrical Connection===
 +
[[File:lcd-connections.jpg|thumb|frameless|LCD connection schematic]]
 +
To connect to an ATmega controller, simply connect the pins of the ADC port straight to the sense lines (X-, Y+, Y-; hard coded to PortA), no additional components are needed. X+ has to be connected to an external interrupt pin (''INT0'', to use another, see above).
 +
 +
The ADC module of the ATXmega controllers can't sample at the CPU's voltage level, therefore a few additional components are needed to interface to the touch screen. The reference voltage for the ADC module is set to VCC/1,6 (VCC 3,3V: 2,06V), the resistor network yields a maximum voltage of about 1,98V (VCC 3,3V). Other resistor combinations should work as well, the calibration routine does the rest, but the overall impedance should be a few hundred kiloohms. To ensure correct measurements, the sample & hold circuit of the ADC module needs a low signal impedance, that is the job of the operational amplifier (any standard opamp should do, here it is a ''TL274'').
 +
 +
The schematic also shows the connections of the display controller I've used and the backlight control circuit.
  
[[File:lcd-connections.jpg|thumb|frameless|LCD connection schematic]]
 
  
 
==Sample==
 
==Sample==
 +
This sample works for both ATXmega and ATmega controllers, just change the ''$regfile'' statement. Every time, at the initialization, the screen calibration is performed (for demonstration purposes, normally the values ares stored in EEPROM and loaded automatically). In the main loop, it draws a consecutive line between measured coordinates.
 +
<pre>$regfile = "xm128a1def.dat"
 +
'$regfile = "m128def.dat"
 +
$hwstack = 64
 +
$swstack = 48
 +
$framesize = 64
 +
 +
#if _xmega = 1
 +
  $crystal = 32000000
 +
  ' use the internal 32 MHz oscillator as system clock and calibrate with the 32 KHz oscillator
 +
  Config Osc = Enabled , 32mhzosc = Enabled , 32khzosc = Enabled
 +
  Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
 +
  Osc_dfllctrl.0 = 1
 +
  Dfllrc32m_ctrl.0 = 1
 +
#else
 +
  $crystal = 16000000
 +
#endif
 +
 +
Config Submode = New
 +
 +
' Graphic LCD driver
 +
Config Graphlcd = 240 * 128 , Dataport = Portd , Controlport = Portc , Ce = 2 , Cd = 3 , Wr = 0 , Rd = 1 , Reset = 4 , Fs = 5 , Mode = 8
 +
 +
' Touch screen library and settings
 +
Const Touch_screen_width = 240
 +
Const Touch_screen_height = 128 
 +
#if _xmega = True
 +
  Const Touch_ctrl_port = Varptr( "Porta")
 +
#else
 +
  Const Touch_ctrl_port = Varptr( "Portd")                                    ' INT0 of mega128
 +
#endif
 +
$include "4WireResistiveTouch.inc"
 +
 +
Dim Status As Byte , Firstsample As Byte
 +
Dim X2 As Word , Y2 As Word                                                    ' previous coordinates
 +
 +
' initializations
 +
Enable Interrupts
 +
Touch_reset_calibration                                                        ' for demonstration, the stored data is deleted to force recalibration
 +
Touch_init
 +
 +
' main loop
 +
Do
 +
  If Touch_touched = True Then                                                ' touch screen active
 +
      Status = Touch_get_sample()
 +
      If Status = True Then                                                    ' new sample available
 +
        If Firstsample = True Then                                            ' is first sample, set previous coordinates to same location
 +
            X2 = Touch_x
 +
            Y2 = Touch_y
 +
            Firstsample = False
 +
        End If
 +
        Line(touch_x , Touch_y) -(x2 , Y2 ) , 1                                ' draw a line from the previous to the actual coordinates
 +
        X2 = Touch_x                                                          ' remember previous coordinates
 +
        Y2 = Touch_y
 +
      End If
 +
  Else
 +
      Firstsample = True                                                        ' not touched, the next sample is the first
 +
  End If
 +
Loop</pre>
 +
 +
== Donate ==
 +
This Software is [http://en.wikipedia.org/wiki/Donationware Donationware].
 +
<paypal>1</paypal>
 +
[[About|See here]] for more informations
 +
 +
 +
== Changelog ==
 +
=== 1.1 ===
 +
* Increased max. delta to 5000 pixels/sec to match handwriting speed
 +
* Fixed a little bug in calculating the rotated coordinates
 +
 +
 +
== Download ==
 +
* [http://www.braunecker.at/downloads/touch/4WireResistiveTouch.zip 4-wire Resistive Touch Screen Library 1.1]
  
  
==Download==
+
Old versions:
 +
* [http://www.braunecker.at/downloads/touch/4WireResistiveTouch-1-0.zip 4-wire Resistive Touch Screen Library 1.0]

Aktuelle Version vom 6. Juli 2019, 17:34 Uhr

Overview

Based on the Appnote AVR341 - Four and five-wire Touch Screen Controller by Atmel, this library handles everything needed to use a 4-wire resistive touchscreen in Bascom.

Demo Video

Forum Thread

Features:

  • Interrupt-controlled sampling
  • Touch contact resistance measurement
  • Adjustable sampling rate
  • Filtering
  • Screen coordinate calibration (stored in EEPROM)
  • Screen rotation
  • Click/Drag detection
  • ATXmega, ATmega (untested)


How to use

Before including the library, a display has to be set up (for the calibration routine draw functions) and the settings (below) need to be done.

Config Graphlcd = 

Const Touch_updaterate = 200
$include "4wireResistiveTouch.inc"

The application could look like:

Dim Status As Byte

Touch_init
Do
   Status = Touch_get_sample()
   If Status = True Then
      ' new coordinates are available in Touch_x and Touch_y (and Touch_r if enabled)

   End If

   ' ... more code
Loop


Options

Options and settings need to be set before the $include-statement, every setting has a default value that will be used if not specified otherwise. (in the list below the default values are shown)

Width of the underlying screen in pixels:

Const Touch_screen_width = 240

Height of the underlying screen in pixels:

Const Touch_screen_height = 320

If the display supports rotation, then the touch coordinates need to be rotated too. To enable this function, set to true:

Const Touch_enable_rotation = False

Measure the touch contact resistance:

  • False: Off
  • 1: Method 1 (needs one additional sample cycle)
  • 2: Method 2 (needs two additional sample cycles)
Const Touch_read_resistance = False

If the contact resistance measurement is enabled, the touch ITO layer resistances need to be known (in Ohms, measured between + and - contact of the unconnected touch layers, Y-resistance is only needed for Method 1, X for both):

Const Touch_resistance_x = 200
Const Touch_resistance_y = 600

If the contact resistance measurement is enabled, an additional sanity check is performed, coordinates are only valid if the resistance is below this value (in Ohms):

Const Touch_max_resistance = 1000

Control port for touch screen (ATXmega: I/O port, ATmega: Port of X+ INT, other wires connected to PortA):

Const Touch_ctrl_port = Varptr( "Portb") 

Control port pin connections:

Const Touch_pin_xp = 0
Const Touch_pin_xn = 1
Const Touch_pin_yp = 2
Const Touch_pin_yn = 3

(ATXmega only) ADC port pin connections (Adca is used):

Const Touch_pin_xn_adc = 4
Const Touch_pin_yn_adc = 5
Const Touch_pin_yp_adc = 6

Measurements per sample (The median value is taken as coordinate sample):

Const Touch_samples = 5

Coordinate update rate (coordinates generated per second)

Const Touch_updaterate = 100

No. of invalid coordinate samples to be sure the touch screen has been released

Const Touch_release_count = 5

Debounce time in seconds (touch screen tend to bounce badly, during this time, invalid samples are ignored and the state will not switch to released):

Const Touch_time_debounce = 0.05

After changing the type of sample to be measured, the screen needs some time for the voltages to settle, this depends on RC time constant of touch screen, 0.2ms should work for most (in seconds):

Const Touch_time_switch_measurement = 0.0002

Click/Drag detection delta in pixels (Drag: first and actual coordinate delta above threshold, Click: first and last coordinate below threshold and not dragging, applied on the raw ADC values, may not be 100% pixel-correct):

Const Touch_click_delta = 15

Maximum speed in pixels/sec (delta between last and actual coordinates, also applied on the raw ADC values, same as for Click/Drag detection):

Const Touch_max_delta = 3000


API

Status Flags:

Dim Touch_touched As Bit
Dim Touch_newsample As Byte
Dim Touch_sample_invalid As Bit
Dim Touch_clicked As Bit
Dim Touch_dragging As Bit
Dim Touch_calibrated As Bit

Coordinates:

Dim Touch_x As Word , Touch_y As Word
Dim Touch_r As Word          ' only available if contact resistance measurement is enabled

Display rotation:

  • 0: 0°
  • 1: 90°
  • 2: 180°
  • 3: 270°

If the touch screen supports rotation, the transformed screen coordinates need to be rotated too. The rotation information needs to be provided with this variable. It can be declared in the main application, above the $include statement (for example as an overlay to the display driver's rotation variable), if not set, it is declared automatically.

Dim Touch_rotation As Byte

Sub routines:

Initializes the hardware modules (Timer, ADC, Pin Interrupt) and enters standby mode

Sub Touch_init()

Starts the calibration procedure, calculates the coefficients and stores the calibration values in EEPROM

Sub Touch_calibrate()

Loads the calibration values from EEPROM. If they are not set, the calibration procedure is started. This sub routine is called from Touch_init(), no need to call again after init.

Sub Touch_load_calibration()

Resets the stored calibration values

Sub Touch_reset_calibration()

Returns True (1) if new valid coordinate data is available, otherwise returns False (0). The coordinate data is transformed into screen coordinates if calibration values are available. The coordinate variables are updated.

Function Touch_getsample() As Byte

Returns True (1) if the touch screen has been clicked (delta between first and last point below threshold and touch screen released), otherwise returns False (0). The coordinate variables are updated.

Function Touch_click() As Byte

Other Display Types

The calibration function uses some graphic functions (Cls, Circle and Rotate, if supported by the display) to draw the reference points. LCDs configured via Bascom (Config Graphlcd = ) do not need any changes in the code, as well as for my ILI9341 library (which supports rotation). Other display types could be used as well with small changes, the corresponding lines in the Touch_calibrate() sub routine are marked with # DISPLAY CLS #, # DISPLAY CIRCLE # and # DISPLAY ROTATE #.


Change Timer-, ADC-Hardware-Module and Pin Interrupt

To simplify modifications, all hardware-related functions and settings are kept at a single location, for both ATmega and ATXmega, in section Portability, marked with # XMEGA # and # ATMEGA #.

For the ATmega, TIMER0, the ADC module and INT0 are used, the ATxmega is set up to use TCC1, ADCA.CH0, and PORT.INT0.


Electrical Connection

LCD connection schematic

To connect to an ATmega controller, simply connect the pins of the ADC port straight to the sense lines (X-, Y+, Y-; hard coded to PortA), no additional components are needed. X+ has to be connected to an external interrupt pin (INT0, to use another, see above).

The ADC module of the ATXmega controllers can't sample at the CPU's voltage level, therefore a few additional components are needed to interface to the touch screen. The reference voltage for the ADC module is set to VCC/1,6 (VCC 3,3V: 2,06V), the resistor network yields a maximum voltage of about 1,98V (VCC 3,3V). Other resistor combinations should work as well, the calibration routine does the rest, but the overall impedance should be a few hundred kiloohms. To ensure correct measurements, the sample & hold circuit of the ADC module needs a low signal impedance, that is the job of the operational amplifier (any standard opamp should do, here it is a TL274).

The schematic also shows the connections of the display controller I've used and the backlight control circuit.


Sample

This sample works for both ATXmega and ATmega controllers, just change the $regfile statement. Every time, at the initialization, the screen calibration is performed (for demonstration purposes, normally the values ares stored in EEPROM and loaded automatically). In the main loop, it draws a consecutive line between measured coordinates.

$regfile = "xm128a1def.dat"
'$regfile = "m128def.dat"
$hwstack = 64
$swstack = 48
$framesize = 64

#if _xmega = 1
   $crystal = 32000000
   ' use the internal 32 MHz oscillator as system clock and calibrate with the 32 KHz oscillator
   Config Osc = Enabled , 32mhzosc = Enabled , 32khzosc = Enabled
   Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
   Osc_dfllctrl.0 = 1
   Dfllrc32m_ctrl.0 = 1
#else
   $crystal = 16000000
#endif

Config Submode = New

' Graphic LCD driver
Config Graphlcd = 240 * 128 , Dataport = Portd , Controlport = Portc , Ce = 2 , Cd = 3 , Wr = 0 , Rd = 1 , Reset = 4 , Fs = 5 , Mode = 8

' Touch screen library and settings
Const Touch_screen_width = 240
Const Touch_screen_height = 128  
#if _xmega = True
   Const Touch_ctrl_port = Varptr( "Porta")
#else
   Const Touch_ctrl_port = Varptr( "Portd")                                     ' INT0 of mega128
#endif
$include "4WireResistiveTouch.inc"

Dim Status As Byte , Firstsample As Byte
Dim X2 As Word , Y2 As Word                                                     ' previous coordinates

' initializations
Enable Interrupts
Touch_reset_calibration                                                         ' for demonstration, the stored data is deleted to force recalibration
Touch_init

' main loop
Do
   If Touch_touched = True Then                                                 ' touch screen active
      Status = Touch_get_sample()
      If Status = True Then                                                     ' new sample available
         If Firstsample = True Then                                             ' is first sample, set previous coordinates to same location
            X2 = Touch_x
            Y2 = Touch_y
            Firstsample = False
         End If
         Line(touch_x , Touch_y) -(x2 , Y2 ) , 1                                ' draw a line from the previous to the actual coordinates
         X2 = Touch_x                                                           ' remember previous coordinates
         Y2 = Touch_y
      End If
   Else
      Firstsample = True                                                        ' not touched, the next sample is the first
   End If
Loop

This Software is Donationware. <paypal>1</paypal> See here for more informations


Changelog

1.1

  • Increased max. delta to 5000 pixels/sec to match handwriting speed
  • Fixed a little bug in calculating the rotated coordinates


Download


Old versions: