Code does not work without delay

Hello all,

I need some help with my code.
Basically I have to read out a touchscreen and detect wrong measurements.
When the values of coords are above 100 and 150 the measurement is correct and the value of the touchscreen is accepted. (Thus, the if-condition is fullfilled)
However, when it’s not above those values, it has to just remember the previous values and do nothing actually.
My code does work and I get correct values.
However when I remove the delay and the values are under the minimum (i.e. measurement error), the value I get is not the previous one (it’s always around -0,07, no matter what previous one is).
It works good when the delay is above 100ms…
Can anyone explain to me why this is? Or is the code correct and does it have to do with the serial.print?

Thanks!

 #include <TouchScreen.h>

TouchScreen ts(0,1,2,3,4); 
  int coords[2];
  double coords_double[2];

void setup()
{
  Serial.begin(38400);
}

void loop()
{
  ts.read(coords);
  
  if(coords[0] > 100 && coords[1] > 150) {
  coords_double[0] =  map((double)coords[0], 153, 793, -108, 108); //(double) map(coords[0], 124, 783, -108, 108);
  coords_double[0]  =  coords_double[0]/1000;
  coords_double[1] =  map((double)coords[1], 208, 799, -84, 84); //(double) map(coords[0], 124, 783, -108, 108);
  coords_double[1]  =  coords_double[1]/1000;
  }
  else {
    }
  
  Serial.print(coords_double[0]);
  Serial.print(",");
  Serial.println(coords_double[1]);
  delay(1000);
}

Probably has to do with the touchscreen read.

Yikes! The library uses the second and third pin numbers for BOTH pinMode()/digitalWrite() AND analogRead(). Since you can't use Pin 0 and Serial at the same time I assume the '0' was intended to refer to A0. I further assume that you used analog pins for all four I/O pins. You should change:

TouchScreen ts(0,1,2,3,4);

to

TouchScreen ts(A0, A1, A2, A3, 4);

That way the pinMode()/digitalWrite() AND analogRead() will be going TO THE SAME PIN.

Note: the 5th value is NOT a pin number. It's a multiplier called 'rxplate' used in calculating the touch pressure on some types of touch screens. The library example used 300. If the value 4 works for you then keep it.

Thanks for the replies :slight_smile:
The touchscreen read is actually an adjusted version of the library, because I have a 5-wire touchscreen
I'll add the code I used here:

TouchScreen::TouchScreen(int pinLL, int pinLT,int pinSG, int pinRL, int pinRT)

{
  _pinLL = pinLL;
  _pinLT = pinLT;
  _pinSG = pinSG;
  _pinRL = pinRL;
  _pinRT = pinRT;

}
/* ================  Public methods ================ */

/**
 * Reads the X and Y coordinates from a touchscreen
 */
void TouchScreen::read(int *coordinates)
{
  pinMode( _pinRT + DIGITAL_OFFSET, OUTPUT );    
  pinMode( _pinLL + DIGITAL_OFFSET, OUTPUT );  

  digitalWrite( _pinRT + DIGITAL_OFFSET, LOW );     // Point RL is 0V or GND for both x and y measurement
  digitalWrite( _pinLL + DIGITAL_OFFSET, HIGH );    // Point LL is 5V for both x and y measurement
  pinMode( _pinSG + DIGITAL_OFFSET, INPUT );     // SG pin is always used to read out the data

  // Read the X coordinate
  pinMode( _pinLT + DIGITAL_OFFSET, OUTPUT );    
  digitalWrite( _pinLT + DIGITAL_OFFSET, HIGH );    // point LT is HIGH to measure the x-coordinate
  pinMode( _pinRL + DIGITAL_OFFSET, OUTPUT );    
  digitalWrite( _pinRL + DIGITAL_OFFSET, LOW );    // point RL is LOW to measure the x-coordinate
  _xVal = analogRead( _pinSG );      // Read the X value from the sense pin


  // Read the Y coordinate
  pinMode( _pinLT + DIGITAL_OFFSET, OUTPUT );    
  digitalWrite( _pinLT + DIGITAL_OFFSET, LOW );    // point LT is LOW to measure the y-coordinate
  pinMode( _pinRL + DIGITAL_OFFSET, OUTPUT );    
  digitalWrite( _pinRL + DIGITAL_OFFSET, HIGH );    // point RL is HIGH to measure the y-coordinate
  _yVal = analogRead( _pinSG );      // Read the Y value from the sense pin
  

  // Update the array we were pointed to by the calling function
  coordinates[0] = _xVal;
  coordinates[1] = _yVal;
}

The pins do refer to the analog pins a0 - a4
So I should change

TouchScreen myTouchScreen(0,1,2,3,4)

to
So I should change

TouchScreen myTouchScreen(A0,A1,A2,A3,A4)

?

WimBPM:
At least on an Uno, analogRead() works the same whether you use 0 or A0, 1 or A1, etc.
We had a thread with that in it last week and an example using constants and variables to give pin numbers showed it working.

But that’s analogRead() and your library code uses the values for pinMode() as well, not the same.

If you ever want to read only on timed intervals then there’s a technique for that.

 #include <TouchScreen.h>

TouchScreen ts(0,1,2,3,4);
  int coords[2];
  double coords_double[2];

unsigned long readStartMs, readWaitMs = 10; // wait of 10ms is for 100 reads/sec… 1000 seems way too long

void setup()
{
  Serial.begin(38400);
}

void loop()
{
  if ( millis() - readStartMs >= readWaitMs ) // unsigned subtraction has no problem with rollover
  {
    readStartMs += readStartMs;  // new start time set where it should be

ts.read(coords);
 
  if(coords[0] > 100 && coords[1] > 150) {
  coords_double[0] =  map((double)coords[0], 153, 793, -108, 108); //(double) map(coords[0], 124, 783, -108, 108);
  coords_double[0]  =  coords_double[0]/1000;
  coords_double[1] =  map((double)coords[1], 208, 799, -84, 84); //(double) map(coords[0], 124, 783, -108, 108);
  coords_double[1]  =  coords_double[1]/1000;
  }
  else {
    }
 
  Serial.print(coords_double[0]);
  Serial.print(",");
  Serial.println(coords_double[1]);

} // end of timed interval action

}

Also note that Arduino float and double are the same 32-bit IEEE floating point.

Arduino floating point is 100x slower than Arduino 32 bit integers which are less than half as fast as 16 bit.

Analog read returns 16 bit integer values 0 to 1023. If you can work to use that int directly, your code will run faster and use less RAM.

Why does method set the pinmode each time you try to read the pin? I'm under the impression that that's actually not a good idea.

There's no harm to it.

Capacitive touch and using leds as light detectors use fast mode change as does some multiplexing, all Charlieplexing and my blinking while twinkling leds wedding display sketch.

Using pinMode() instead of manipulating a port DDR (data direction register) is slower but not a bad idea.'

Here's from the Atmel 328 datasheet (my highlighting):

14.2.1 Configuring the Pin
Each port pin consists of three register bits: DDxn, PORTxn, and PINxn. As shown in ”Register Description” on
page 92, the DDxn bits are accessed at the DDRx I/O address, the PORTxn bits at the PORTx I/O address, and
the PINxn bits at the PINx I/O address.
The DDxn bit in the DDRx Register selects the direction of this pin. If DDxn is written logic one, Pxn is configured
as an output pin. If DDxn is written logic zero, Pxn is configured as an input pin.
If PORTxn is written logic one when the pin is configured as an input pin, the pull-up resistor is activated. To switch
the pull-up resistor off, PORTxn has to be written logic zero or the pin has to be configured as an output pin. The
port pins are tri-stated when reset condition becomes active, even if no clocks are running.
If PORTxn is written logic one when the pin is configured as an output pin, the port pin is driven high (one). If
PORTxn is written logic zero when the pin is configured as an output pin, the port pin is driven low (zero).

14.2.2 Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the SBI
instruction can be used to toggle one single bit in a port.

14.2.3 Switching Between Input and Output
When switching between tri-state ({DDxn, PORTxn} = 0b00) and output high ({DDxn, PORTxn} = 0b11), an intermediate
state with either pull-up enabled {DDxn, PORTxn} = 0b01) or output low ({DDxn, PORTxn} = 0b10) must
occur. Normally, the pull-up enabled state is fully acceptable, as a high-impedance environment will not notice the
difference between a strong high driver and a pull-up. If this is not the case, the PUD bit in the MCUCR Register
can be set to disable all pull-ups in all ports.
Switching between input with pull-up and output low generates the same problem. The user must use either the tristate
({DDxn, PORTxn} = 0b00) or the output high state ({DDxn, PORTxn} = 0b11) as an intermediate step.

Tri-state is INPUT LOW. The pin is LOW but has a high impedance, it won't drain current except for a tiny bit when the pin is read. I've used this after learning the led as a light detector and some cap sense techniques, it can be used to detect tiny currents and measure trapped charge in a wire.

The only time a problem can occur is if the circuit connected to the pin can't stand the transitions shown in 14.2.3 and then that comes down to the order you change the PORTxn and the DDRxn bits.

Using pinMode() safeties that at a cost in speed.