Gadgeteer communication with PC software + IO60P16

First of all, thank you to developers for such a great product.

A brief explanation, I am doing my master thesis developing a “sort of” a medical simulator for a local hospital.
All the simulator needs is to have multiple analogue inputs just to read voltages.

Problem 1:
I have managed to get the voltages from A type sockets pins 3, 4, 5, but I cannot seem to use IO60P16 to read any voltages for me, therefore if you are able to explain me how do I use the IO60P16 to read analogue voltages, please let me know
(or, as an alternative, generating multiple different PWM signals and reading them with different PWM inputs would do the job too as I need to give each metal object in space a different voltage or PWM to be able to identify what the user is currently touching)

Problem 2:
The Gadgeteer device is supposed to be a part of a bigger application.
The “bigger application” is supposed to support various types of I/O devices and use them collect data, show webcam, upload to Azure and so on. One of the devices we are already using is Arduino which is being accessed through System.IO.Ports.SerialPort.
But this seem to have a conflict with libraries required for Gadgeteer.

Error	4	The type 'System.IO.Ports.Handshake' exists in both 'C:\Program Files (x86)\Microsoft .NET Micro Framework\v4.1\Assemblies\le\Microsoft.SPOT.Hardware.dll' and 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll'	C:\Users\Audrius\Documents\Visual Studio 2010\Projects\PasteurWPFTest\Hardware\ArduinoDevice\ArduinoDevice.cs	38	50	PasteurClient

Problem 3:
I thought, OK, let’s make the Gadgeteer classes a class library and try to include it in our project.
So I started a new class library with the following code:

Class library:


using System;
using System.Collections.Generic;
using Gadgeteer;

namespace GadgeteerAdaper
{
    public class GadgeteerAdapterBase : Gadgeteer.Program
    {
        private static List<Socket> sockets = new List<Socket>();
        private List<IGadgeteerListener> listeners = new List<IGadgeteerListener>();
        public static void Main()
        {
            Mainboard = new GHIElectronics.Gadgeteer.FEZSpider();
            Socket socket = Socket.GetSocket(10, true, null, null);
            sockets.Add(socket);
            GadgeteerAdapterBase baser = new GadgeteerAdapterBase();
            baser.SetUpGadgeteer();
            baser.Run();
        }
        public GadgeteerAdapterBase()
        {
            
        }
        public GadgeteerAdapterBase(Mainboard board, List<int> socketNumbers)
        {
            Mainboard = board;
            Socket socket = null;
            foreach (int socketNumber in socketNumbers)
            {
                socket = Socket.GetSocket(socketNumber, true, null, null);
                if (!socket.SupportsType('A'))
                {
                    throw new Exception("Socket " + socket.SocketNumber + " does not support type A.");
                }
                if (socket != null)
                {
                    sockets.Add(socket);
                }
            }
            SetUpGadgeteer();
            Run();
        }
        private void SetUpGadgeteer()
        {
            Timer timer = new Timer(1);
            timer.Tick += new Timer.TickEventHandler(timer_Tick);
            timer.Start();
        }
        private void timer_Tick(Timer timer)
        {
            int port = 0;
            foreach (Socket socket in sockets)
            {
                int currentValue;
                currentValue = (int)System.Math.Round(socket.AnalogInput3.ReadVoltage() * 1024 / 3.3);
                ReportToListeners(port++,currentValue);
                currentValue = (int)System.Math.Round(socket.AnalogInput4.ReadVoltage() * 1024 / 3.3);
                ReportToListeners(port++,currentValue);
                currentValue = (int)System.Math.Round(socket.AnalogInput5.ReadVoltage() * 1024 / 3.3);
                ReportToListeners(port++,currentValue);
                
            }
        }
        private void ReportToListeners(int port, int value)
        {
 #if DEBUG
            Microsoft.SPOT.Debug.Print("Port:" + port + " Value:" + value);
 #endif
            foreach (IGadgeteerListener listener in listeners)
            {
                if (listener != null)
                {
                    listener.ReceiveGadgeteerUpdate(port, value);
                }
            }
        }
        public void RegisterListener(IGadgeteerListener listener)
        {
            listeners.Add(listener);
        }
        public void UnregisterListener(IGadgeteerListener listener)
        {
            if (listeners.Contains(listener))
            {
                listeners.Remove(listener);
            }
        }
        public Mainboard GetMainboard()
        {
            return Mainboard;
        }
    }
}

Interface:


namespace GadgeteerAdaper
{
    public interface IGadgeteerListener
    {
        void ReceiveGadgeteerUpdate(int port,int value);
    }
}

I can avoid the arguments in the constructor so that the “bigger application” should not have to care about any objects involved within Gadgeteer, but Main() still doesn’t work well.
I made a separate console app which tries to use the class library but due to reflections, you start getting exceptions of missing libraries and have to add Microsoft.SPOT.Hardware, Microsoft.SPOT.TinyCore to make it work, which is fine, but then eventually I hit the following exception which I have no clue how to go about:


ECall methods must be packaged into a system module.

Microsoft.SPOT.Hardware
at Microsoft.SPOT.Hardware.OutputPort..ctor(Pin portId, Boolean initialState)
   at GHIElectronics.Gadgeteer.FEZSpider..ctor() in C:\Gadgeteer SVN\Main\Mainboards\GHIElectronics\FEZSpider\Software\FEZSpider\FEZSpider.cs:line 313
   at GadgeteerAdaper.GadgeteerAdapterBase.Main() in c:\users\audrius\documents\visual studio 2010\Projects\GadgeteerBase\GadgeteerBase.cs:line 15
   at GadgeteerTester.UnitTest.Init() in c:\users\audrius\documents\visual studio 2010\Projects\GadgeteerTester\UnitTest.cs:line 19

This happens at:


            Mainboard = new GHIElectronics.Gadgeteer.FEZSpider();

The main question is if what I am trying to do is doable, or am I misunderstanding something?
As far as I understand the C# code gets compiled to byte code and sent to the device, but is there any way to send information from the device back to code running on the PC via the Usb cable used for compiling? Or do I need to resort to some sort of “use an additional module” solutions (such as using WiFi, Ethernet modules) to send data back to PC?

This device should be manageable from my “bigger application”, therefore if I use WiFi as an option, and the device gets moved to different premises, someone within the different premises will have to recompile the Gadgeteer code with different Wifi settings? Or can my bigger application somehow take care of this?

I want to enable users to use any Gadgeteer mainboard with my “bigger application”, hence the constructor where I pass a Mainboard. Is this even possible?
How do I go about it?

Sorry for the long post, and thank you for help!
Regards,
Audrius.

Welcome Jammer, big first post ! :slight_smile:

Communicating with the PC - you need to look at CDC. You will however need to look at serial debugging to allow that to work.

I didn’t look in too much detail at your issues, but in general I don’t think you’re asking too much of anything. It will just require you to unravel what you’re doing to take the project in the correct direction (and that’s where I’m unlikely to be able to help you go further, you’re wanting to do more complex stuff than I can help with)

One thing you need to clarify, did you create a Gadgeteer project or did did you create some other project (and if so, what type?). Either way, it seems to me that you would be better off creating a Gadgeteer app and copying your code into that app rather than trying to mess with what you have. Create a new project, put the Spider mainboard on the design surface, and then deploy your app and see if your “ecall” issue goes away. I don’t exactly understand why you say you need a second console app, it seems to me you need a single app that does everything, serial comms to the arduino, IO60P handling, network handling etc. Perhaps you should explain how your “solution” is going to be shared with others who would supply their own mainboard, would you be giving them the source code?

The next one (Problem 2) I think is easy to get rid of - the serial port warning. That to me says you have references in your app to an old framework version. Did you manually add ref’s to file system locations? You should only ever need to add references via the dialog as it makes sure it lists the versions you need.

hope that helps - sorry to ask you to explain more when you posted such a comprehensive report first up ! :slight_smile:

Can you draw out, or explain a little better on the ‘what’ for the end desired result. Ie, is this a test set for another existing piece of equipment? is this stateless, or does it need to log interactions.

Generally the more info you can share, pics etc - the more interested people will be to assist.
.

The IO60P16 doesn’t have any analog pins - only GPIO & PWM. Therefore you would need some sort of A/D convert between your analog signal & the IO60P16. Hopefully this week the final release of the 4.2 drivers will be released. It contains a much more feature rich driver than the previous version for you to test with.

Again, you might test this and your other issues with the latest 4.2 firmware to make sure it’s still an issue.

Thank you for your answers.
I am impressed with the amount of em, and again, sorry for the long post.

Ok, a bit more information in general.
I have a multi threaded WPF application which uses lots of fancy stuff such as web services, Entity Framework, Azure Blobs, background workers.
What this fancy WPF application is supposed to do, is read voltage from Gadgeteer and then push them to WCF/Entity Framework/Azure.
I have already managed to implement the required behaviour with Arduino via serial port (so I have a abstract class MyDevice which has got methods read voltage, and I have a class ArduinoDevice which has a serial socket in it, which actually reads the values over serial port and returns em when the method is called from the WPF app).

Now my goal is to make a new class GadgeteerDevice, or AnyOtherDeviceWhichComesOutInTheFutureAndHasAnalogInputs

Using reflections the user would choose which sort of device he is using with the software, what I then would do, is connect to the device start returning voltages of pins 3,4,5, when called by my big WPF application. These voltages actually mean things such as "user is touching object A (analog input) to object B (2.1V) " and so on, which later is used to build up exercises for surgeons.

As for the device, the device should be stateless, it should just periodically return voltages of pins 3,4,5 of all sockets supporting type A, no matter what the device is, that’s it.

The CDC is exactly what I was looking for, but its like a young moon, sometimes it starts and works, sometimes it doesn’t and you cannot debug it.

Is there a way to write a more generalised code, so that for example if the code gets uploaded to any mainboard, I could check which sockets support type A, also if there is any internet connection modules connected or available without even knowing if they are connected or not? Even better, maybe there is some binary I could give to the users to upload via some sort of uploader so that the users would not need to have VS and all the SDK’s in order to use their devices with my solution?