Stuck on NHVN Cap Touch Display - Touch

Hello again, I am struggling to move forward with a 4.3 inch new haven cap touch display that I have hooked up to a Spider II using the gadgateer system. I am trying to learn c#, Visual Studio 2013, Glide, and NetMF 4.3 all at once so I could use a bit of help…

I have the display up and running fine using glide, this once uses an I2C connection for the touch controls, but touch is not functional, the program throws an error as soon as the screen is ‘touched’… (hooked up using the “I” connector, not “T”). I have it ‘connected’ through the VS gadgateer interface, so the program can access methods etc under the GHI Electronics.NHVN “Driver”, along with Glide, and presumably the microsoft.touch. I have been told to research driver files on Codeplex, which I have done. So I can include a .cs file that implements the touch controls so it seems. So a couple questions…

  1. The standard Gadgateer interface implemented by GHI for the NVHN display only implements the display functions, it dosen’t implement touch. Hence the need for a separate ‘driver’. Right?

2 Glide seems to have touch built into it, but it must be for resistive displays, not capacitive displays using I2C, right?

  1. The driver files (.cs programs) written for the I2C capacitive touch interface seem to be written for a non-gadgateeer environment. That being the case, do I just include the file in my project, and how do I make it work with gadgateer, or do I just remove the display object from VS, and ‘talk’; to the display entirely using non-gadgateer calls and functions?

My lack of experience in this environment is a bit frustrating, I am going to do some reading in VS and .NETMF which should help, but I would appreciate a hand if possible from you wizards, thanks!!

John

@ jscmanson - have you added an event handler for touch events?

as I’d mentioned in the other thread, you need to look at @ Dave McLaughlin’s posts. Here’s the ones that are most useful, probably in order:
https://www.ghielectronics.com/community/forum/topic?id=23254
https://www.ghielectronics.com/community/forum/topic?id=23456
https://www.ghielectronics.com/community/forum/topic?id=22957

Let us know how you go

OK, I have added a display ‘touch’ driver class called CapacitiveTouchController into my project under the project namespace, as follows:

using GHI.Glide;
using GHI.Glide.Geom;
using Microsoft.SPOT.Hardware;


namespace LCD_Test1
{
    public class CapacitiveTouchController
    {
        private InterruptPort touchInterrupt;
        private I2CDevice i2cBus;
        private I2CDevice.I2CTransaction[] transactions;
        private byte[] addressBuffer;
        private byte[] resultBuffer;

        private static CapacitiveTouchController _this;

        public static void Initialize(Cpu.Pin PortId)
        {
            if (_this == null)
                _this = new CapacitiveTouchController(PortId);
        }

        private CapacitiveTouchController()
        {
        }

        private CapacitiveTouchController(Cpu.Pin portId)
        {
            transactions = new I2CDevice.I2CTransaction[2];
            resultBuffer = new byte[1];
            addressBuffer = new byte[1];
            i2cBus = new I2CDevice(new I2CDevice.Configuration(0x38, 400));
            touchInterrupt = new InterruptPort(portId, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
            touchInterrupt.OnInterrupt += (a, b, c) => this.OnTouchEvent();
        }

        private void OnTouchEvent()
        {
            for (var i = 0; i < 5; i++)
            {
                var first = this.ReadRegister((byte)(3 + i * 6));
                var x = ((first & 0x0F) << 8) + this.ReadRegister((byte)(4 + i * 6));
                var y = ((this.ReadRegister((byte)(5 + i * 6)) & 0x0F) << 8) + this.ReadRegister((byte)(6 + i * 6));

                if (x == 4095 && y == 4095)
                    break;

                if (((first & 0xC0) >> 6) == 1)
                    GlideTouch.RaiseTouchUpEvent(null, new GHI.Glide.TouchEventArgs(new Point(x, y)));
                else
                    GlideTouch.RaiseTouchDownEvent(null, new GHI.Glide.TouchEventArgs(new Point(x, y)));
            }
        }

        private byte ReadRegister(byte address)
        {
            this.addressBuffer[0] = address;

            this.transactions[0] = I2CDevice.CreateWriteTransaction(this.addressBuffer);
            this.transactions[1] = I2CDevice.CreateReadTransaction(this.resultBuffer);

            this.i2cBus.Execute(this.transactions, 1000);

            return this.resultBuffer[0];
        }
    }
}

So it has an “ontouchevent” in there. I also soldered a couple of I2C pullup resisters on the “I” connector, not sure the Spider II needs them but they are now there.

Now when I touch the screen, Visual studio goes looking for the file “NativeI2Cbus.cs”, address 56. So it sounds like I have to add a handler for the I2C, even though the included file seems to be handling the I2C communications… The error description says “I2C: Exception writing to device at adrdress 56 - prerhaps device is not respoding or not plugged in”.

Interesting, if I remove the two resisters, the I2C error goes away, and I get a nullreferenceexception - CLR_E_NULL_REFERENCE (5), and goes looking for a file interruptInput.cs, if all of this helps…

P.S. the resisters are just 2 - 2.6K resisters connecting P8 and P9 to +3.3 volts on an extender board that I can swap in or out. xxx Crap never mind I soldered the wrong value resisters in there so that explains why the I2c comms weren’t working, will fix and try again. lol…

John

… and here is the main program…

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 Microsoft.SPOT.Hardware;
using System.IO;
using GHI.Glide;

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



namespace LCD_Test1
{
  
    
    public partial class Program
    {
        
        private bool isLEDON = true;
        private static GHI.Glide.Display.Window _mainWindow;
        private GHI.Glide.UI.Button _btnToggle;
        private GHI.Glide.UI.TextBox _tbCounter;
        private GHI.Glide.UI.TextBlock _WellFull;
        private GHI.Glide.UI.ProgressBar _WellPercentFull;
        private GHI.Glide.UI.TextBlock _DomFull;
        private GHI.Glide.UI.ProgressBar _DomPercentFull;
        private GHI.Glide.UI.TextBlock _IrrFull;
        private GHI.Glide.UI.ProgressBar _IrrPercentFull;
        private GHI.Glide.UI.TextBlock _IrrLow;
        private GHI.Glide.UI.TextBlock _WellLow;
        private GHI.Glide.UI.TextBlock _DomLow;
        
        private int clickcounter = 22;
        private int dom_tank_percent_full = 0;
        private int dom_tank_full = 1250;
        private int dom_tank_capacity = 0;
        private int well_percent_full = 0;
        private int well_full = 67;
        private int well_capacity = 0;
        private int irr_tank_percent_full = 0;
        private int irr_tank_full = 2250;
        private int irr_tank_capacity = 0;
   
 
        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        
          {
          /*
            Debug.Print("Program Started");
            Debug.Print("SD should be auto-mounted");
            //sdCard.MountSDCard();
            if (sdCard.IsCardMounted)
            {
                ethernetENC28.UseDHCP();
                VolumeInfo vi = sdCard.StorageDevice.Volume;
                Debug.Print(vi.Name);
                Debug.Print(vi.IsFormatted.ToString());
                Debug.Print(vi.FileSystem);
                Debug.Print(vi.TotalFreeSpace.ToString());
 
                string root = sdCard.GetStorageDevice().RootDirectory;
                Debug.Print("Root: " + root);
                Debug.Print("Program Finished");
            }
            else
            {
                Debug.Print("SD Card Failed to mount!");
            }
        
        */
        
        
        
        
        
        
        
        
        
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
            
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
            
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/


            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");
            sdCard.DebugPrintEnabled = true;
            led7C.SetColor(GTM.GHIElectronics.LED7C.Color.Blue);
            isLEDON = true;

            Glide.FitToScreen = true;
            _mainWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.Main_Window_File));


            _btnToggle = (GHI.Glide.UI.Button)_mainWindow.GetChildByName("btnToggle");
            _tbCounter = (GHI.Glide.UI.TextBox)_mainWindow.GetChildByName("tbCounter");
            _WellFull = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("WellFull");
            _WellPercentFull = (GHI.Glide.UI.ProgressBar)_mainWindow.GetChildByName("WellFullPercent");
            _IrrFull = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("IrrFull");
            _IrrPercentFull = (GHI.Glide.UI.ProgressBar)_mainWindow.GetChildByName("IrrFullPercent");
            _DomFull = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("DomFull");
            _DomPercentFull = (GHI.Glide.UI.ProgressBar)_mainWindow.GetChildByName("DomFullPercent");

            //_DomFull = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("DomFull");
            // _DomFull = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("DomFull");
            // _DomFull = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("DomFull");

            _WellLow = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("WellLow");
            _IrrLow = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("IrrLow");
            _DomLow = (GHI.Glide.UI.TextBlock)_mainWindow.GetChildByName("DomLow");

            // _btnToggle.TapEvent += _btnToggle_TapEvent;
            xbutton.ButtonPressed += xbutton_ButtonPressed;
            // fbutton.ButtonPressed += fbutton_ButtonPressed;


            Glide.MainWindow = _mainWindow;

        }  

void xbutton_ButtonPressed(GTM.GHIElectronics.Button sender, GTM.GHIElectronics.Button.ButtonState state)
{
    Debug.Print("Button Pressed");
    clickcounter -= 1;
    if (clickcounter < 0)
    {
        clickcounter = 22;
    }
    dom_tank_capacity = 50 * clickcounter;
    dom_tank_percent_full = 100 * dom_tank_capacity / dom_tank_full;
    _DomFull.Text = dom_tank_capacity.ToString();
    _DomPercentFull.Value = dom_tank_percent_full;
    
    well_capacity = 3 * clickcounter;
    well_percent_full = 100 * dom_tank_capacity / dom_tank_full;
    _WellFull.Text = well_capacity.ToString();
    _WellPercentFull.Value = well_percent_full;

    irr_tank_capacity = 100 * clickcounter;
    irr_tank_percent_full = 100 * irr_tank_capacity / irr_tank_full;
    _IrrFull.Text = irr_tank_capacity.ToString();
    _IrrPercentFull.Value = irr_tank_percent_full;

    if (well_percent_full <= 10)
    {
        _WellLow.Text = "WELL IS LOW!";
    }
    else
    {
        _WellLow.Text = "";
    }

    if (dom_tank_percent_full <= 30)
    {
        _DomLow.Text = "DOMESTIC IS LOW!";
    }
    else
    {
        _DomLow.Text = "";
    }
    if (irr_tank_percent_full <= 20)
    {
        _IrrLow.Text = "IRRIGATION IS LOW!";
    }
    else
    {
        _IrrLow.Text = "";
    }

    if (isLEDON)
    {
        isLEDON = false;
        led7C.SetColor(GTM.GHIElectronics.LED7C.Color.Off);
    }
    else
    {
        isLEDON = true;
        led7C.SetColor(GTM.GHIElectronics.LED7C.Color.Blue);
    }
    _tbCounter.Text = clickcounter.ToString();
    _mainWindow.Invalidate();

}

}

      
}

And with the fixed pull-ups, I am back to the original interrupt error, so it looks like the Spider doesn’t need the pullups.

Here is the error text:

The thread ‘’ (0x3) has exited with code 0 (0x0).
#### Exception System.NullReferenceException - CLR_E_NULL_REFERENCE (5) ####
#### Message:
#### Gadgeteer.Modules.GHIElectronics.DisplayNHVN::OnTouchEvent [IP: 0076] ####
#### Gadgeteer.Modules.GHIElectronics.DisplayNHVN::<.ctor>b__1 [IP: 0004] ####
#### Gadgeteer.SocketInterfaces.NativeInterruptInput::OnPortInterrupt [IP: 0008] ####
A first chance exception of type ‘System.NullReferenceException’ occurred in GTM.GHIElectronics.DisplayNHVN.dll

John

@ jscmanson - The driver for the display does not have an event handler assigned. Normally, a driver should not get a null exception if an event handler has not been assigned, but often with Gadgeteer it happens. You can get the source for the DisplayNHVN driver, and see what is happening. https://bitbucket.org/ghi_elect/gadgeteer

Sorry, the learning curve is fairly steep and it is taking me a while…

In the code above, I have included the following to initialize the capacitive touch driver.cs ‘file’:

CapacitiveTouchController.Initialize(Cpu.Pin.GPIO_Pin10); (I am guessing that Pin 10 is the Gadgeteer “I” socket, which I am using)

When the program runs it executes this commend, enters the the following routine:

private CapacitiveTouchController(Cpu.Pin portId)
{
transactions = new I2CDevice.I2CTransaction[2];
resultBuffer = new byte[1];
addressBuffer = new byte[1];
i2cBus = Gadgeteer.SocketInterfaces.I2CBus();
i2cBus = new I2CDevice(new I2CDevice.Configuration(0x38, 400));
touchInterrupt = new InterruptPort(portId, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
touchInterrupt.OnInterrupt += (a, b, c) => this.OnTouchEvent();
}

and fails at the folllowing line:

i2cBus = new I2CDevice(new I2CDevice.Configuration(0x38, 400));

with the following error:

A first chance exception of type ‘System.NullReferenceException’ occurred in GTM.GHIElectronics.DisplayNHVN.dll

sooo, I am guessing that GHI did not write any I2C code into the NHVN driver , I have read the NVHN .cs ‘driver’ file, but I can’t figure out why the I2C isn’t working.

so Pin10 is possibly wrong.

CapacitiveTouchController.Initialize(Cpu.Pin.GPIO_Pin10);

What device do you have again? Raptor?

If this is a Gadgeteer app, is there any reason you haven’t just used the SDK’s included driver? (I actually can’t recall for sure if the touch interface is working with that - I’d expect it does, but perhaps someone from GHI can confirm?).

I’ve got the spider ii… The I2C interface for the NVHN display board uses socket “I”, on my mainboard I have it plugged in to socket 10, I think this mainboard only has one I2C interface.

ok, reading your original post, Spider2 not Raptor. What I socket are you using?

I’d still suggest ditching your own code and just using NHVN display code since you are using a Gadgeteer app. That way the correct handling of the I2C is done.

The driver handles touch, but it exposes to you public touch events that you then need to connect your own handlers to. You then need to connect those into Glide. If you start with small steps, create handlers that report touch down and up events, that will prove the driver functions. Then you can research how others have then wired handlers into Glide.

Edit: our replies passed in the night :slight_smile: .

Thanks Brett, OK the touch works fine with glide removed entirely, I can capture screen presses and releases without errors. The basic driver provides two events, capacitivetouch pressed and released.

1 Like

It looks like the Glide Driver does not handle Hardware I2C properly, folks have written drivers etc to get around that. I will code around it and just use the basic non-glide interface to implement touch, thanks for your help!!

John

The Glide driver doesn’t do any I2C. The touch driver hooks into the RaiseTouchEvent’s in Glide. eg, in my Down handler I call this.


touches[0].X = e.X;
touches[0].Y = e.Y;
GlideTouch.RaiseTouchDownEvent(null, new GHI.Glide.TouchEventArgs(touches));

Try this instead when you init the driver. I think Brett is correct, it is the GPIO pin that is the issue. You can find out the GPIO pin from the FEz Spider II schematic.


CapacitiveTouchController.Initialize(GHI.Pins.G120.P0_23);

Hi Dave, OK the NHVN spec (and the GHI NVHN board) for this display sends the I2C interrupt on pin 3 of socket 10, which on the Spider is P0-12 (ADC6).
So the call to CapacitiveTouchController.Initialize(GHI.Pins.G120.P0_12); gets down to the I2c initializtion statement:

i2cBus = new I2CDevice(new I2CDevice.Configuration(0x38, 400));

and vs reports:

‘Microsoft.SPOT.Debugger.CorDebug.12.dll’ (Managed): Loaded ‘C:\Users\jscma\OneDrive\Documents\Visual Studio 2013\Projects\LCD_Test1\LCD_Test1\bin\Debug\le\LCD_Test1.exe’, Symbols loaded.
‘Microsoft.SPOT.Debugger.CorDebug.12.dll’ (Managed): Loaded ‘C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.3\Assemblies\le\System.Net.Security.dll’, Symbols loaded.
‘Microsoft.SPOT.Debugger.CorDebug.12.dll’ (Managed): Loaded ‘C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.3\Assemblies\le\System.Http.dll’, Symbols loaded.
‘Microsoft.SPOT.Debugger.CorDebug.12.dll’ (Managed): Loaded ‘C:\Program Files (x86)\Microsoft .NET Gadgeteer\Core\Assemblies.NET Micro Framework 4.3\le\Gadgeteer.WebClient.dll’, Symbols loaded.
‘Microsoft.SPOT.Debugger.CorDebug.12.dll’ (Managed): Loaded ‘C:\Program Files (x86)\GHI Electronics\NETMF v4.3 SDK\Libraries\le\GHI.Pins.dll’
The thread ‘’ (0x2) has exited with code 0 (0x0).
Using mainboard GHI Electronics FEZ Spider II version 1.0
Program Started
#### Exception System.InvalidOperationException - CLR_E_INVALID_OPERATION (1) ####
#### Message:
#### Microsoft.SPOT.Hardware.Port::ReservePin [IP: 0000] ####
#### Microsoft.SPOT.Hardware.I2CDevice::.ctor [IP: 0021] ####
#### LCD_Test1.CapacitiveTouchController::.ctor [IP: 002e] ####
#### LCD_Test1.CapacitiveTouchController::Initialize [IP: 0012] ####
#### LCD_Test1.Program::ProgramStarted [IP: 0100] ####
A first chance exception of type ‘System.InvalidOperationException’ occurred in Microsoft.SPOT.Hardware.dll
An unhandled exception of type ‘System.InvalidOperationException’ occurred in Microsoft.SPOT.Hardware.dll

So I am back to the I2C issue, using the included class - public class CapacitiveTouchController

Any ideas? Otherwise I will proceed without the glide touch interface, which is fine…

@ jscmanson - Package up your code and send it to me at my email address and I will have a look at what you are trying to.

Hm, the Spider II uses a G120E, not the G120, you are trying to set the G120-Pin on the G120E…
If I read your debug-code correctly, thats the reason, why it fails.

Thanks, changed the reference to 120E instead of 120, but the I2C error remains. Dave is sending me his driver file separately so we work with that.

Can you send me your code? The I2C driver is failing because it looks like you might be using I2C for your own use?