2.8 ILI9341 restive touch miso not connected ?

Status
Not open for further replies.
Edited copy of the included "ILI9341Test.ino".

Reads touch and maps to pixels and draws crosshairs and an 'X' mostly to a bounding box. Resistive report goes beyond pixel limits. Use a stylus tip to see, mostly tracks with hardcoded edges on my screen. No dynamic calibration points.

View attachment ILI9341Test_Oct22.ino
 
On the PJRC - assume the same as OP Frank's display: For pressure calc per the data sheet p#73 the main factor is the z2/z1. Supposing we had a steady accurate X position multiplying that by x/4096 is supposed to fix the drift as it crosses the screen. it does no correction for y.

Working with that I see similar or greater variability to the pressure # as in the initial PJRC lib code that is wholly different, but relies on z1 and z2. Removed the x-term as it just adds another random term to what didn't look good.

Just looking at (z2/z-1) and expecting it to reflect on the x position I don't see that. It changes on my display at the lightest touch seen or a firm touch - finger or spring stylus. Not only at the same point by a factor of 2 - but across the display both x and y.

If you don't move your finger it is fairly accurate, the Adafruit code which i copy/pasted basically uses that formula in a different order, the outcome is the same. For my testing its very apparent when your touching the screen regardless of where you touch it, the touch values are vastly different. Based on my screwing around using uint32_t shows 0-10000(very light touch) values are only seen if the screen is being touched, the touch values from noise are 30K - 500K values. Im not using any averaging at the moment and only using 1 read per output.

The point of the math is to determine if the screen is being touched. Remember your calculating the resistance of 5 resistors that can very based on temp, position and pressure of touch and your only using 3 points at most to do it.

They do list a second formula that uses Y also. So you could make it more accurate. On my screen the Y resistance is 524 and R resistance is 288. Really accuracy with this part is not really needed, if you can determine the screen is being touched then its good enough. For me I just need to know when to ignore the x/y pos values since Y seems to be all over the place due to noise from the LCD.

ZTZpRbw.jpg







z1 and z2 are read up front and may be weak after power on? - so I read them a second time midway through the xyxyxy reads - and the (z1/z2) value is no better.

I should be right on x.vs.y - as they are bits in the SPI commands - and printed in the debug spew. But it varies across both axis as well. Lowest x,y has highest z tendency on the lightest touch and it is lowest z at the highest x,y.

The pressure value from the original calculation is more suggestive:: int z = z1 + 4095 - z2;
> I don't see a reason to change it for the data sheet version - wherever it came from

This is with my working #2 display - up for days. As long as it has been on #1 was off - did a power off swap and it came up white on repowering. Did a reprogram and the color is back [for 10 minutes] - but the touch works in either case - and #1 maybe better than #2,

The accuracy of the XPT2046 vref is based mainly on the circuit. Looking at the datasheet page 12 shows that with no capacitor it will take 42uS for Vref to rise and 124uS with a 1uF capacitor. So if your turning it on and off then you need to wait a while before reading.

Also your values will very based on the amount of noise your screen is putting out. If you look at the first O-scope image I posted you will see alot of noise with the CH1 and CH2 pins. Its a 15KHz square/sin wave that is coming from the display itself and much's up the x voltages throwing the Y return values all over the place.



Im so glad I spent money on an O-scope, it makes figuring things out so much easier.
 
O-scopes are way cool - never had one though in my line of work. I have DVM's I can turn on - but all those terms are ~constants and when primary term was flakey knowing the resistance seemed futile.

Indeed - no problem detecting touch - I was expecting the system would provide a more stable value - even re-reading it after x,y when looking good as noted showed no real improvement worth extra cpu cycles from what PJRC started with that I could see over just reading the z values up front as is.

The sample included stability wise seems +/- a pixel (or two) generally with the crosshair under a pointer. With a box of text big enough to read and a couple pixels border and gap - hitting the right spot should be easy. Fingers have un-calibrated hard and soft spots and even lifting off registers touch for some time shifting the mass even if it is a straight lift.
 

My Tetris-clone ("T3TRIS")
Some things are still to do.
Sound (sorry for the quiet volume level ) is a AAC file, stored in on-board flash, played with my codecs-lib.
 
I'll guess it's a controller for an electric car or gocart... Very impressive


This intrigues me!? mercury switches or lamps in Bondo??
Capture1212.JPG
 
Last edited:
I'll guess it's a controller for an electric car or gocart... Very impressive


This intrigues me!? mercury switches or lamps in Bondo??
View attachment 5358

Light bulbs in a tacky material used to hold posters to the wall. Cheap and dirty light load, I test motor controllers for a living so I have learned the hard way to Light test before running a motor. Basically limits/prevents damage since there is a higher resistance in light bulbs compared to a motor.
 
Is there anyone following - other than Frank who wrote a really cool T3TRIS implementation?

If so the Beta 1 version of 1.26 shipped with a version of XPT2046_Touchscreen that I modified. I put in a PULL request PJRC will hopefully validate as good next week.

If you want to try my updated "I:\Teensy165\hardware\teensy\avr\libraries\XPT2046_Touchscreen\XPT2046_Touchscreen.cpp" on your 1.26 Beta 1 install file I'll attach it. I think what I changed is noted in a prior post. Turns out one of the nits I picked made things work better for Frank in a specific case and otherwise perfectly well.

View attachment XPT2046_Touchscreen.cpp
 
Second that... a simple widget library with a few different (simple) controls, specifically round-rect buttons, radio buttons, and check boxes, together with a touchscreen event handler, would go a long way towards helping a lot of users.
 
Last edited:
++
and sprites, like on the old C64
with collision-detection (and alphablending between the sprites? sprite/screen is not possible,not enough ram)
 
Last edited:
cartere or epicycloid : have you tested with the update p#88 XPT2046_Touchscreen.cpp?

I did a sample button and made it DRAW and HIT test from a STRUCT. I was to have generalized this from an ARRAY - but didn't yet. The sample is ugly as I hacked it into to the Lib Sample. Cartere sample is a cleaner start and I'm going to put my struct solution in place of that hardcoded one as time allows. It also lets me know what added elements I should include.

Then I'm hoping to do an interrupt LIB version to stop SPI polling for Touch. But I've been wondering how you attachInterrupt(TS_Pin, onTouch, FALLING); then onTouch(){ PIN___disable_irq()(TS_PIN) ... PIN___enable_irq(TS_PIN) }

That is in the ISR entry clear ONLY the PIN interrupt on TS_PIN and exit restart the interrupt? Stopping all interrupts is crazy, and it doesn't seem that doing a detachInterrupt/attachInterrupt cycle should be needed on each touch.

"pins_teensy.c", line 138 shows how those things work and it may be simple enough to just call them, but resetting the vector function seems like unneeded overhead - but I have a less than ReadOnly understanding of that code and how the vector is stored and if it would persist if it were just hardcoded to drop these (and any other) lines:
intFunc[pin] = NULL; // detachInterrupt :; NULL the function pointer
and
intFunc[pin] = function; // attachInterrupt :: set the function pointer
 
@defragster -- No I didn't try your version yet. It sounded like it was still very much a work in progress. If you post (or PM) your sample button code using the STRUCT I'll try to test it later today/tonight.

For compatibility, portability and debugging purposes, it would be my preference that you didn't pursue an interrupt-based approach. I have a lot of different HW hooked up to a bunch of pins, and anything that ends up being pin-specific, like interrupts, means I'll be spending a ton of time chasing layers of issues if things don't work. Just one person's opinion.

At a bare minimum, an approach like Paul's Encoder library, which gives users the option to #define a flag to use or not use interrupts, is a very elegant way to do what you're wanting to do.
 
@epicycloid : That version is posted for a PULL 6 days back - last edit was a compiler warning I saw when compiling for T3TRIS testing - Paul will do it 11/3 hopefully - just looking to get some run time on it so he can trust it.
I'll get on the STRUCT recoding of @cartere sample shortly.
 
Last edited:
cartere or epicycloid : have you tested with the update p#88 XPT2046_Touchscreen.cpp?

I did a sample button and made it DRAW and HIT test from a STRUCT. I was to have generalized this from an ARRAY - but didn't yet. The sample is ugly as I hacked it into to the Lib Sample. Cartere sample is a cleaner start and I'm going to put my struct solution in place of that hardcoded one as time allows. It also lets me know what added elements I should include.

Then I'm hoping to do an interrupt LIB version to stop SPI polling for Touch. But I've been wondering how you attachInterrupt(TS_Pin, onTouch, FALLING); then onTouch(){ PIN___disable_irq()(TS_PIN) ... PIN___enable_irq(TS_PIN) }

That is in the ISR entry clear ONLY the PIN interrupt on TS_PIN and exit restart the interrupt? Stopping all interrupts is crazy, and it doesn't seem that doing a detachInterrupt/attachInterrupt cycle should be needed on each touch.

"pins_teensy.c", line 138 shows how those things work and it may be simple enough to just call them, but resetting the vector function seems like unneeded overhead - but I have a less than ReadOnly understanding of that code and how the vector is stored and if it would persist if it were just hardcoded to drop these (and any other) lines:
intFunc[pin] = NULL; // detachInterrupt :; NULL the function pointer
and
intFunc[pin] = function; // attachInterrupt :: set the function pointer

@defragster:
No, you don't need to switch off interrupts or deTach them.
I think it is sufficiant to call attachInterrupt in begin() of your Library, and detachInterrupt only at end().
You can treat the corresponding ISR() almost like a normal function, but declare global variables as volatile. Don't make them larger as "int" (for example arrays, structs or such), otherwise you could run intro problems with non-atomic accesses.
32 BIT read/writes are atomic.
I think, taking an Ardiuno-example for Pin-Interrupts and modify it for your needs schould work.
 
Finally getting to the BUTTON struct array . . . trying to add general some case coverage . . .

@FrankB: - there is a note about the touch hardware interrupt that says interrupts are not that straightforward for the touch display:

However, inside your interrupt function, if the display is no longer being touched, any attempt to read the touch position will cause the interrupt pin to create another falling edge. This can lead to an infinite loop of falsely triggered interrupts. Special care is needed to avoid triggering more interrupts on the low signal due to reading the touch position.

As I read this:: This is a problem in that on TOUCH the isr triggers - then the ISR gets control to query the device it will then 'read the touch position'. If at any point it does that - if the TOUCH is removed it triggers yet another interrupt while still within the prior interrupt. I suppose while contact it held the INT PIN is not reset - but at the point touch is lost and it does reset - any ISR call to update() will itself trigger yet another INT - which would then call update() ... repeat until touched.
 
@epicycloid : interrupt would be on any specified pin - and would be an optional feature needing to be requested. Normal polling method would be the always available default.
 
Here is an update - almost cool - whenever you touch 'off' it rotates the screen and redraws. This just allows your code to pick or change orientation on the fly and properly maps the touch data to the relevant x,y pixels. It won't clip or re-arrange things outside the pixels that are in the common 0,239 area that is in the 4 rotations. Rotations 1,3 and 2,4 work on the same constraints so that adds yet another variable to my pondering:: if buttons were tagged as such they could be duplicated for use in alternate views at updated locations, and hidden as appropriate.

>setup waits a bit for Serial to connect so USB data isn't lost
>I debounced the touch jitter, hitting the line between off/on would commonly/rapidly alternate the states
>when the screen rotates the map to x,y goes with it using a TS_Rotate global you update, and could be wrapped in a function.
>I slowed the touch polling with an elapsedMillis

I didn't generalize the drawing code yet - everything marked '// INCORPORATE' should be go. The unique nature of this touch/toggle button needs to be incorporated as it seems cool, but wasn't a button behavior I forsaw. But the rotate tracking uses a struct of the screen dimensions in the 4 orientations - this is similar to how buttons/frames will be defined.

I edited code and notes just writing this - and now it seems this could/should work on a non-touch ILI9341 with hardcoded buttons: View attachment onoffbutton_ts.ino

Snippet:
Code:
TS_MAP tsMap[4] = {   { 0, 319, 0, 239 }, { 319, 0, 0, 239 }, { 319, 0, 239, 0 }, { 0, 319, 239, 0 } };

boolean TS_GetMap( int16_t &xx, int16_t &yy )
{
  static int16_t xxo = 500, yyo = 500;  // Store old/last returned x,y point
  if (!ts.touched()) return false;
  pp = ts.getPoint();
  xx = map(pp.x, TS_MINX, TS_MAXX, tsMap[TS_Rotate].xt, tsMap[TS_Rotate].xb);
  yy = map(pp.y, TS_MINY, TS_MAXY, tsMap[TS_Rotate].yl, tsMap[TS_Rotate].yr);
  if (TS_Rotate % 2) {
    int16_t swap = xx;
    xx = yy;
    yy = swap;
  }
  // Debounce by +/-# pixel to minimize point jitter
  if ( ((xxo - TS_DEBOUNCE) <= xx) && ((xxo + TS_DEBOUNCE) >= xx) ) xx = xxo; else xxo = xx;
  if ( ((yyo - TS_DEBOUNCE) <= yy) && ((yyo + TS_DEBOUNCE) >= yy) ) yy = yyo; else yyo = yy;
  return true;
}
 
Touchpaint works with x & y swapped

yup, something like that. Or
x &= ~0x7;

Then, increasing the Z_THRESHOLD gives better results (at least for my display).


@paul:
The touchpaint example is ok with these lines changed in XPT2046_Touchscreen.cpp
Code:
    if (z >= Z_THRESHOLD) {
        xraw = 4096-y;
        yraw = x;
    }

That's not the "correct" solution, but gives a hint what to change.

With the patch to the library to swap x & y Touchpaint works pretty well. It needs to have its x & y code fixed, and then it would make a useful example addition to the XPT2046_Touchscreen library. I'll take a crack at that.
 
Status
Not open for further replies.
Back
Top