Hydra + CP7 display touch + Serial Port reading problem

Hi,

I’m working on GUI project using Hydra and CP7. It has become pretty big project and looks really nice with this display. Now I have to add monitoring of data sent by Arduino board connected to serial port (COM1). Arduino sends 174 bytes each second.

After adding the serial port reading I have a problem with CP7 touch starting to read invalid X/Y coordinates at some point and becoming unusable.

The project is big, but I managed to reproduce with simple example. Here is zip or check the code below:
https://drive.google.com/file/d/0B1zHz__652kNaW1ORXlrMXVkb3c/edit?usp=sharing

It’s easy to reproduce by holding finger on the LCD for 1-2s, then releasing and holding on different spot, repeating this several times. Or just touch fast many times.

using System;
using System.Collections;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;

using System.IO.Ports;

namespace CP7_UART_Test
{
    public partial class Program
    {
        SerialPort uart;
        Thread uartReceiveThread;

        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            display_CP7.ScreenPressed += new Display_CP7.TouchEventHandler(display_CP7_ScreenPressed);
            display_CP7.ScreenReleased += new Display_CP7.TouchEventHandlerTouchReleased(display_CP7_ScreenReleased);

            uart = new SerialPort("COM1", 115200, Parity.None, 8, StopBits.One);
            uart.Open();

            uartReceiveThread = new Thread(new ThreadStart(UartReceiveThreadMethod));
            uartReceiveThread.Start();

            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");
        }

        void display_CP7_ScreenReleased(Display_CP7 sender)
        {
            Debug.Print("Screen released");
        }

        void display_CP7_ScreenPressed(Display_CP7 sender, Display_CP7.TouchStatus touchStatus)
        {
            Debug.Print("Screen pressed, num points: " + touchStatus.numTouches + ", x: " + touchStatus.touchPos[0].xPos + ", y: " + touchStatus.touchPos[0].yPos);
        }

        void UartReceiveThreadMethod()
        {
            while (true)
            {
                while (uart.BytesToRead == 0)
                    Thread.Sleep(10);

                Debug.Print("Serial port bytes: " + uart.BytesToRead);

                while (uart.BytesToRead > 0)
                    uart.ReadByte();
            }
        }

    }
}

Check also the log from VS Output window:
https://drive.google.com/file/d/0B1zHz__652kNekFXdF94a3NtdVk/edit?usp=sharing

See lines after 341.

[quote]Screen pressed, num points: 1, x: 129, y: 2560
Screen released
Screen released
Serial port bytes: 174
Screen released

Screen released
Screen pressed, num points: 1, x: 65, y: 3328
Screen pressed, num points: 7, x: 65, y: 3328
Screen pressed, num points: 15, x: 65, y: 3328
Screen pressed, num points: 15, x: 65, y: 3328
Screen pressed, num points: 15, x: 65, y: 3328
Screen released[/quote]

After the problem happens I start to get a lot of screen released events while holding finger on the LCD (instead of screen pressed event). I very rarely get screen pressed event anymore and if I do get it, then it’s with wrong coordinates and many touch points.

In the full project I tried several things. Like reading from serial port using event, but it made touch unresponsive and also I often get “Buffer OverFLW” message in upper left screen corner in this case. I tried opening, reading and closing the com port when I expect data - still breaks touch. Tried adding and removing the screenPressed/Released event handlers dynamically (with += and -=) - didn’t help. It happens even if I just discard the incoming data with uart.DiscardInBuffer() instead of reading it.

Maybe a clue - when problem happens project restart from inside Visual Studio does not fix it (with CTRL+SHIFT+F5).

Hydra is with Ethernet firmware v4.2.6.1 and TinyBooter v4.2.6.1.
Tried to power it from PC usb and from usb power adapter 5v/1A.

Please, how can I avoid this problem? Any idea is appreciated.

edit:

  • it happens also with uart baudrate of 9600.
  • tested with arduino sending only 9-10 bytes per second - still happens.
  • no problem if Arduino does not send any data (without change to Hydra side code).

We are able to reproduce the problem. We will let you know when we find out more.

Thanks! Glad it’s reproducible.

I have noticed that if I send fewer bytes, less than 16, and changed your inner loop in the UartReceiveThreadMethod function to the below code, the problem does not appear to happen, or at least as quickly as it does otherwise. In the mean time, as a work around, you can try that code and to try and send very little data to see if it helps you at all. Alternatively, you can look into using software serial since you are sending so little data.


void UartReceiveThreadMethod()
{
    byte[] buffer = new byte[4096];
    int ready;

    while (true)
    {
        ready = uart.BytesToRead;

        if (ready > 0)
        {
            uart.Read(buffer, 0, ready);
            Debug.Print("Serial port bytes: " + ready);
        }

        Thread.Sleep(5);
    }
} 

I used your code, although I have tried reading into a buffer instead of byte by byte.

I confirm that with less bytes it is harder to reproduce. With 10 bytes it still happens in 1-2 minutes of fast screen touching. With 174 bytes it’s very easy - always less than 1 minute, sometimes even after the first 5-6 touches. With 3 bytes it took me ~3 min the first time I triled, 2nd time less than 1 min (seems random). I could not reproduce it with 1 byte - at least I didn’t have the patience.

I’m not familiar with software serial, but read here under “Software UART”:
https://www.ghielectronics.com/docs/15/uart
that it requires very precise timing and something like the SignalGenerator class can be used, which is part of premium library not available on Hydra.

edit:

  • I cannot reproduce it on COM2 (socket 7)! Trying for over 5 min with 174 bytes. WIll test the other 2 coms now.
  • it is OK also on COM3 (s4) and COM4 (s6). For COM4 I connected the CP7 touch to socket 5.

Nice, I’ll keep CP7 i2c touch on socket 5 (COM1) and will use sockets 6 and 7 for the 2 Arduinos that I need to monitor (socket 4 is used by Flash module). I should have tried this earlier. Will report any problems, but seems OK :slight_smile:

Has anyone experienced a problem where ScreenPressed event is continuously triggered with coordinates x=839 and y=73 without touching the screen?

It usually doesn’t stop unless I slide finger over the CP7 capacitive buttons on its right side. If I don’t do that then the event continues to trigger I get out of memory exception after a while.

I have seen this in the past, but it was extremely rare, so I ignored it then. Now it’s very often after connecting CP7 touch to socket 5 and 2 arduinos to sockets 6 and 7.

Here is example project:
https://drive.google.com/file/d/0B1zHz__652kNQ3hwTmVGeTQtYms/edit?usp=sharing

VS Output log when this happens and leads to exception:
https://drive.google.com/file/d/0B1zHz__652kNWXVMYVRLeDdNZUU/edit?usp=sharing

It’s harder to reproduce than the previous problem with COM1 data breaking CP7 touch. But you don’t even need to touch the screen, it happens after some time. Usually I press several times at start and just leave it running.

Thanks for any help with this, I’m at a dead end again :frowning:

About how long does it take the problem to manifest? Are you sending the same ~140 bytes as before? Does it happen with only one UART running instead of two?

Each Arduino is sending 174 bytes (1 by 1 in a loop). In the log you see them as ~120 because they get split between multiple readings I guess.

Just tried again - 3 minutes until x=839 touch starts to trigger, after another 2 minutes I get exception. Here is the log:
https://drive.google.com/file/d/0B1zHz__652kNNlFVUFZmXzVZZ3M/edit?usp=sharing
I touched the screen only 3 times at start.

Will test now both uart ports separately.

edit:

It’s confusing. First I tested only COM4 and reproduced easily. Then COM2 and I stopped it after 11 min without problems. I connected again both ports and for now running over 30 min and still OK. I’ll leave it running during the night.

If this is a problem only at my end, I’ll try an ugly change to the CP7 driver (had a look at its code) - make it return only 1 point, ignoring all outside the screen area - I don’t need multi-touch, gestures or the android style buttons.

Night test did not pass, but it ran much longer. I don’t know when it started triggering x=839 point and crashed, but I see that my previous VS Output logs were between 30k-50k lines long and the night log is 2800000 lines (probably around 5-6 hours):
https://drive.google.com/file/d/0B1zHz__652kNRmpPU2FlTlBKMTQ/edit?usp=sharing

Will test with 12v/2A power adapter. Also I’ll try workaround with CP7 driver returning only single point, just int x and y coords.

Probably the x=839 problem is cable or power related. I took the boards home to test during the weekend and it’s running for over 36 hours. Using release build and showing debug messages on LCD (only on ScreenPressed).

Btw the first problem I reported didn’t happen again after I stopped using COM1 (s5) and connected the CP7 touch there instead.

Glad to hear it seems to be working after using better cables, they can cause a lot of weird issues if they’ve gone bad. We will let you know once we figure out the issue with COM1.

Actually I’m using the same cables, but I thought that maybe something changed after disconnecting/reconnecting them at home. Probably it’s the power adapter. Anyway glad to be able to continue with the project :slight_smile:

Hi,

a question unrelated to uart - is there a way to reliably use touch cable longer than 20cm?

Colleagues who use 30cm cable report that the project sometimes hangs. Previously they tried 50cm and it was very unstable - they switched to 30cm and say that it’s much better, but not fully ok. They cannot use the standard 20cm.

I tried to reproduce. I don’t have 30cm cable, so I first used 10cm and 20cm cables connected together with the extender module. Tested with the very simple example at the end. Took me almost 5 min of quickly touching the screen to reproduce. After that for faster reproduce I used 2x20cm cables - then the problem happens in less than 1 min pressing.

Seems that touch events stop coming. Often I get “Failed to perform I2C transaction” message:

[quote]Screen pressed, num points: 1, x: 543, y: 104
Screen pressed, num points: 1, x: 543, y: 104
Screen released
Screen pressed, num points: 1, x: 531, y: 117
Screen pressed, num points: 1, x: 531, y: 117
Screen pressed, num points: 1, x: 531, y: 117
Screen pressed, num points: 1, x: 531, y: 117
Screen pressed, num points: 1, x: 531, y: 118
Screen pressed, num points: 1, x: 531, y: 118
Failed to perform I2C transaction
Failed to perform I2C transaction
Failed to perform I2C transaction
Screen pressed, num points: 1, x: 512, y: 0
Failed to perform I2C transaction
Screen released
Failed to perform I2C transaction
Failed to perform I2C transaction
[/quote]and it continues to appear. Sometimes there is no such message - simply nothing happens on touch anymore. Very often pressing the Hydra reset button and restarting the project from visual studio does not fix it - in such case only power off/on restores touch.

It works with the standard 20cm cable.

I saw “Raptor + CP7 : Failed to perform I2C transaction errors” forum topic, but the CP7 module driver modification by Dat does not avoid it in this case.

A colleague tried to measure with scope what is happening on pins 3, 8 and 9 of the touch socket - we use socket 5. I have no hardware knowledge at all, so just forwarding his findings (he even tried some hardware modification):

[quote] When touch stops responding the CP7 lcd pulls down the i2c_SDA line (pin 8 ) - verified that lcd holds the line, not the Hydra. i2c_SCL (pin 9) remains High. i2c_INT line (pin 3) continues to react on display touching and goes Low for around 8ms on every touch.

The pull-up resistors on i2c_SDA and i2c_SCL lines are 2.2K on Hydra board and 10K on CP7. On CP7 we also tested with resistors 2.37K, 4,7K, infinity (desoldered resistors)[/quote]
In my tests no resistors are changed.

Are we trying something that is not possible?

Hydra is powered with USB DP module and 12v/2A adapter. I tried ethernet firmwares 4.2.6.1 and latest 4.2.6.2.

namespace CP7_Test
{
    public partial class Program
    {
        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            display_CP7.ScreenPressed += new Display_CP7.TouchEventHandler(display_CP7_ScreenPressed);
            display_CP7.ScreenReleased += new Display_CP7.TouchEventHandlerTouchReleased(display_CP7_ScreenReleased);

            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");
        }

        void display_CP7_ScreenReleased(Display_CP7 sender)
        {
            Debug.Print("Screen released");
        }

        void display_CP7_ScreenPressed(Display_CP7 sender, Display_CP7.TouchStatus touchStatus)
        {
            Debug.Print("Screen pressed, num points: " + touchStatus.numTouches + ", x: " + touchStatus.touchPos[0].xPos + ", y: " + touchStatus.touchPos[0].yPos);
        }
    }
}

Using a Hydra with a 50cm cable, we were unable to reproduce any issue within a few minutes. Have you tried a variety of cables and extenders? Do you have other CP7s and Hydras to test with?

I have 2nd Hydra - will try it tomorrow. Only one CP7, several 10cm cables, two 20cm and one extender. The colleagues are using different Hydra/CP7 - I don’t have access to theirs.

In our setups connected to Hydra are USB DP module, CP7 (touch to socket 5), flash module and ENC28 lan. We use different power adapters.They use long R/G/B cables also, while I use 10cm for those.

It is same with the 2nd Hydra. Also tried socket 6 for touch - same. I see that sometimes it is ok for up to 4-5 minutes, but rarely. Btw I touch pretty fast when testing - maybe 4-5 times/sec. Too bad I don’t have another CP7. If it matters - its revision is 1.2.

Could you take all the other modules except the CP7 out of the designer so that you just have the CP7 and the test program you sent earlier? Does it still happen then?

Other modules were never added to designer, they are just connected to Hydra. Here is the full example:
https://drive.google.com/file/d/0B1zHz__652kNLWtGVmZCb3JXNXM/edit?usp=sharing

We were able to reproduce the problem. We will let you know when we have something more.

Something else (not testing long cables) and possible workaround for it.

With same example as before - if I hold finger (or put coin) over the LCD for 1 min and 30 seconds I always get out of memory exception. Time to reproduce is always the same.

[quote]Screen pressed, num points: 1, x: 319, y: 479
Screen pressed, num points: 1, x: 319, y: 479
Screen pressed, num points: 1, x: 319, y: 479
GC: 39msec 1287672 bytes used, 5003460 bytes available
Type 0F (STRING ): 684 bytes
Type 11 (CLASS ): 550608 bytes
Type 12 (VALUETYPE ): 99456 bytes
Type 13 (SZARRAY ): 248772 bytes
Type 03 (U1 ): 204 bytes
Type 04 (CHAR ): 672 bytes
Type 07 (I4 ): 1044 bytes
Type 0F (STRING ): 36 bytes
Type 11 (CLASS ): 246816 bytes
Type 15 (FREEBLOCK ): 5003460 bytes
Type 16 (CACHEDBLOCK ): 48 bytes
Type 17 (ASSEMBLY ): 28092 bytes
Type 18 (WEAKCLASS ): 96 bytes
Type 19 (REFLECTION ): 180 bytes
Type 1B (DELEGATE_HEAD ): 468 bytes
Type 1D (OBJECT_TO_EVENT ): 216 bytes
Type 1E (BINARY_BLOB_HEAD ): 349836 bytes
Type 1F (THREAD ): 1152 bytes
Type 20 (SUBTHREAD ): 96 bytes
Type 21 (STACK_FRAME ): 4200 bytes
Type 23 (LOCK_HEAD ): 60 bytes
Type 24 (LOCK_OWNER_HEAD ): 24 bytes
Type 27 (FINALIZER_HEAD ): 144 bytes
Type 31 (IO_PORT ): 144 bytes
Type 33 (I2C_XACTION ): 48 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 3276 bytes
Failed allocation for 8194 blocks, 98328 bytes

#### Exception System.OutOfMemoryException - CLR_E_OUT_OF_MEMORY (4) ####
#### Message: 
#### System.Collections.Queue::Enqueue [IP: 0000] ####
#### Microsoft.SPOT.Dispatcher::BeginInvoke [IP: 001e] ####
#### Gadgeteer.Program::BeginInvoke [IP: 001f] ####
#### Gadgeteer.Program::CheckAndInvoke [IP: 0017] ####
#### Gadgeteer.Interfaces.InterruptInput::OnInterruptEvent [IP: 0030] ####
#### Gadgeteer.Interfaces.InterruptInput::OnInterfaceInterrupt [IP: 0006] ####
#### Gadgeteer.Socket+SocketInterfaces+InterruptInput::RaiseInterrupt [IP: 000f] ####
#### Gadgeteer.Interfaces.NativeInterruptInput::OnPortInterrupt [IP: 0008] ####

GC: performing heap compaction…
A first chance exception of type ‘System.OutOfMemoryException’ occurred in mscorlib.dll
An unhandled exception of type ‘System.OutOfMemoryException’ occurred in mscorlib.dll[/quote]

Workaround by changing the CP7 module driver - no exception if I ignore the I2C interrupt in case of pressing and less than 50ms since the previous interrupt. Here is the change in “Display_CP7_42.cs”:

original code:

        private void _input_Interrupt(GTI.InterruptInput input, bool value)
        {
            this.OnTouchEvent(this, null);
        }

workaround:

        static long lastInterruptTimeTicks = DateTime.Now.Ticks;
        private void _input_Interrupt(GTI.InterruptInput input, bool value)
        {
            // Does not ignore release events (numberOfFingers  == 0).
            int numberOfFingers = (ReadRegister(0x02) & 0xF);
            if ((numberOfFingers == 0) || (DateTime.Now.Ticks - lastInterruptTimeTicks > 50 * 10000))
            {
                this.OnTouchEvent(this, null);
                lastInterruptTimeTicks = DateTime.Now.Ticks;
            }
        }

For now it’s running for 45 min with coin on the lcd.

The workaround can be better - for example OnTouchEvent() also reads number of fingers (ReadRegister(0x02)),
Also don’t know if those 50ms affect the gestures support - I don’t use them.