Things used in this project

Hardware components:
Db410c blue 2a
Qualcomm DragonBoard 410c
×1
Pi 3 02
Raspberry Pi 3 Model B
×1
Software apps and online services:
10
Microsoft Windows 10 IoT Core

Code

CONTROLLER.csC#
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Devices.Gpio;
using Windows.Devices.I2c;
using Windows.Devices.SerialCommunication;
using Windows.Devices.Spi;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

namespace IoTController
{
    class CONTROLLER
    {
        private List<I2cDevice> i2cDeviceList;

        public CONTROLLER(string remoteHostname, string localPortName, string remotePortName)
        {
            var now = DateTime.Now;
            Debug.WriteLine(now + " : " + " Controller Unit CONSTRUCTOR");
            i2cDeviceList = new List<I2cDevice>();
            
            RemoteHostname = remoteHostname;
            LocalPortName = localPortName;
            RemotePortName = remotePortName;
            InitGPIOController();
            InitNetworkUPD();
        }

        public string RemoteHostname
        {
            get; set;
        }

        public string LocalPortName
        {
            get; set;
        }

        public string RemotePortName
        {
            get; set;
        }

        private HostName remoteHostname;
        private DatagramSocket socket = new DatagramSocket();
        private DatagramSocket listenerSocket = new DatagramSocket();

        private DataWriter writer;
        private IOutputStream outputStream;

        public async void InitNetworkUPD()
        {
            remoteHostname = new HostName(RemoteHostname);
            listenerSocket.MessageReceived += UDPMessageReceived;
            //listenerSocket.Control.MulticastOnly = true;
            // Start listen operation.

            try
            {
                await listenerSocket.BindServiceNameAsync(LocalPortName); //ServiceName.Text
                //listenerSocket.JoinMulticastGroup(remoteHostname);  //RemoteAddress.Text
            }
            catch (Exception exception)
            {
                listenerSocket.Dispose();
                listenerSocket = null;

                // If this is an unknown status it means that the error is fatal and retry will likely fail.
                if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
                {
                    throw;
                }

                Debug.WriteLine("Start listening failed with error: " + exception.Message);
            }

            try
            {
                // UPD SENDING SETUP ======================================================
                outputStream = await socket.GetOutputStreamAsync(remoteHostname, RemotePortName);
                // Send out some multicast or broadcast data. Datagrams generated by the IOutputStream will use
                // <source host, source port> information obtained from the parent socket (i.e., 'listenSocket' in
                // this case).
                writer = new DataWriter(outputStream);
            }
            catch (Exception exception)
            {
                Debug.WriteLine("outputStream error: " + exception.Message);
            }
        }

        private void UDPMessageReceived(DatagramSocket socket, DatagramSocketMessageReceivedEventArgs eventArguments)
        {
            try
            {
                // Interpret the incoming datagram's entire contents as a string.
                uint stringLength = eventArguments.GetDataReader().UnconsumedBufferLength;
                string receivedMessage = eventArguments.GetDataReader().ReadString(stringLength);


                Debug.WriteLine(
                    "Received data from remote peer (Remote Address: " +
                    eventArguments.RemoteAddress.CanonicalName +
                    ", Remote Port: " +
                    eventArguments.RemotePort + "): \"" +
                     receivedMessage + "\"");
            }
            catch (Exception exception)
            {
                SocketErrorStatus socketError = SocketError.GetStatus(exception.HResult);

                if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
                {
                    Debug.WriteLine($"Unknown UDPMessageReceived Error: {exception}");
                }

                Debug.WriteLine("Error happened when receiving a datagram:" + exception.Message);
            }
        }

        public async void Send_UDP(byte[] ReadBuf) //MPUDATA mpudata
        {
            try
            {
                // GetOutputStreamAsync can be called multiple times on a single DatagramSocket instance to obtain
                // IOutputStreams pointing to various different remote endpoints. The remote hostname given to
                // GetOutputStreamAsync can be a unicast, multicast or broadcast address.


                //Array.Copy(ReadBuf, 0, updData, 1, ReadBuf.Length-1);
                writer.WriteBytes(ReadBuf);

                //writer.WriteString(sOut);
                await writer.StoreAsync();
            }
            catch (Exception exception)
            {
                // If this is an unknown status it means that the error is fatal and retry will likely fail.
                if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
                {
                    Debug.WriteLine($"Unknown Sending UPD Error: {exception}");
                }
            }
        }


        public async Task<I2cDevice> InitI2cCommunication(DEVICE device)
        {
            string aqs = I2cDevice.GetDeviceSelector();                     /* Get a selector string that will return all I2C controllers on the system */
            var dis = await DeviceInformation.FindAllAsync(aqs);            /* Find the I2C bus controller device with our selector string           */

            /* Checking number of I2C ports available
            for (int i=0;i<dis.Count;i++)
            {
                Debug.WriteLine(dis[i].Id.ToString());
            }
            */

            if (dis.Count == 0)
            {
                Debug.WriteLine("No I2C controllers were found on the system");
                return null;
            }

            int I2CPort = (int)device.I2CPort;

            var settings = new I2cConnectionSettings(device.I2C_ADDRESS);
            settings.BusSpeed = I2cBusSpeed.FastMode;
            device.I2cCommunication = await I2cDevice.FromIdAsync(dis[I2CPort].Id, settings);    /* Create an I2cDevice with our selected bus controller and I2C settings */

            if (device.I2cCommunication != null)
            {
                i2cDeviceList.Add(device.I2cCommunication); //Debug.WriteLine("i2C List Count: " + i2cDeviceList.Count.ToString());
            }

            else
            {
                Debug.WriteLine($"Slave address {settings.SlaveAddress} on I2C Controller {dis[I2CPort].Id} is currently in use by another application.");
                return null;
            }

            return device.I2cCommunication;
        }

        public async Task<SpiDevice> InitSPICommunication(DEVICE device)
        {
            const string SPI_CONTROLLER_NAME = "SPI0";  /* For DragonBoard, use SPI0                                */
            const Int32 SPI_CHIP_SELECT_LINE = 0;       /* Line 0 maps to physical pin number 12 on the DragonBoard */
            try
            {
                var settings = new SpiConnectionSettings(SPI_CHIP_SELECT_LINE);
                settings.ClockFrequency = 4800000;                              /* 5MHz is the rated speed of the ADXL345 accelerometer                     */
                settings.Mode = SpiMode.Mode3;                                  /* The accelerometer expects an idle-high clock polarity, we use Mode3    
                                                                                 * to set the clock polarity and phase to: CPOL = 1, CPHA = 1         
                                                                                 */

                string aqs = SpiDevice.GetDeviceSelector(SPI_CONTROLLER_NAME);                     /* Get a selector string that will return all SPI controllers on the system */
                var dis = await DeviceInformation.FindAllAsync(aqs);            /* Find the SPI bus controller devices with our selector string             */
                device.SPICommunication = await SpiDevice.FromIdAsync(dis[0].Id, settings);    /* Create an SpiDevice with our bus controller and SPI settings             */
                if (device.SPICommunication == null)
                {
                    Debug.WriteLine($"SPI Controller {dis[0].Id} is currently in use by another application.");
                    return null;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("SPI Initialization failed. Exception: " + ex.Message);
                return null;
            }

            return device.SPICommunication;
        }

        public async Task<SerialDevice> InitUARTCommunication(DEVICE device)
        {
            string aqs = SerialDevice.GetDeviceSelector();
            var dis = await DeviceInformation.FindAllAsync(aqs);

            int UARTPort = -1;
            for (int i = 0; i < dis.Count; i++)
            {
                //string stest = dis[i].Id.ToString();
                if (dis[i].Id.ToString().Contains(device.UARTPort))
                {
                    UARTPort = i;
                    break;
                }
            }
            //Debug.WriteLine(dis[UARTPort].Id.ToString());

            if (UARTPort != -1)
            {
                try
                {
                    device.UARTCommunication = await SerialDevice.FromIdAsync(dis[UARTPort].Id);
                    device.UARTCommunication.WriteTimeout = TimeSpan.FromMilliseconds(device.UARTWriteTimeout);
                    device.UARTCommunication.ReadTimeout = TimeSpan.FromMilliseconds(device.UARTReadTimeout);
                    device.UARTCommunication.BaudRate = device.UARTBaudRate;
                    device.UARTCommunication.Parity = SerialParity.None;
                    device.UARTCommunication.StopBits = SerialStopBitCount.One;
                    device.UARTCommunication.DataBits = 8;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }

            return device.UARTCommunication;
        }

        public GpioController IoController
        {
            get; set;
        }

        public void InitGPIOController()
        {
            IoController = GpioController.GetDefault(); /* Get the default GPIO controller on the system */

            if (IoController == null)
            {
                throw new Exception("GPIO does not exist on the current system.");
            }
        }

        public void InitGPIOInterruptPin(DEVICE device)
        {
            try
            {
                device.IoInterruptPin = IoController.OpenPin(device.IoInterruptPinID);
                //Check if input pull-up resistors are supported
                if (device.IoInterruptPin.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
                    device.IoInterruptPin.SetDriveMode(GpioPinDriveMode.InputPullUp);
                else
                    device.IoInterruptPin.SetDriveMode(GpioPinDriveMode.Input);

                // Set a debounce timeout to filter out switch bounce noise from a button press
                device.IoInterruptPin.DebounceTimeout = TimeSpan.FromMilliseconds(0);
                //Debug.WriteLine("GPIO pins " + sensor.IoInterruptPinID.ToString() + " initialized correctly.");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Fail to Open INTERRUPT Pin: {ex}");
            }            
        }

        public void InitGPIOControlPin(DEVICE device)
        {
            try
            {
                device.IoControlPin = IoController.OpenPin(device.IoControlPinID);
                if (device.IoControlPin == null)
                {
                    return;
                }
                device.IoControlPin.SetDriveMode(GpioPinDriveMode.Output);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Fail to Open CONTROL Pin: {ex}");
            }
        }
    }
}
Device.csC#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Gpio;
using Windows.Devices.I2c;
using Windows.Devices.SerialCommunication;
using Windows.Devices.Spi;
using Windows.Storage.Streams;

namespace IoTController
{
    public enum I2CPortID { I2C0, I2C1 };

    abstract class DEVICE
    {
        public DEVICE()
        {
            this.DeviceName = "Device Name";
            this.DeviceID = 0;
            this.DeviceDescription = " Device Description";
            this.DeviceAvailable = false;
        }

        #region Device Info

        public int DeviceID
        {
            get; set;
        }

        public string DeviceDescription
        {
            get; set;
        }

        public string DeviceName
        {
            get; set;
        }

        public bool DeviceAvailable
        {
            get; set;
        }
        #endregion

        #region SPI-Communication
        public SpiDevice SPICommunication
        {
            get; set;
        }

        public void SPIWriteByte(byte regAddr, byte data)
        {
            byte[] buffer = new byte[2];
            buffer[0] = regAddr;
            buffer[1] = data;
            SPICommunication.Write(buffer);
        }
        #endregion

        #region I2C Communication

        public I2CPortID I2CPort
        {
            get; set;
        }

        public byte I2C_ADDRESS
        {
            get; set;
        }

        public I2cDevice I2cCommunication
        {
            get; set;
        }

        byte[] i2CWriteByte_writeBuffer = new byte[2];
        public void I2CWriteByte(byte regAddr, byte data)
        {
            i2CWriteByte_writeBuffer[0] = regAddr;
            i2CWriteByte_writeBuffer[1] = data;
            I2cCommunication.Write(i2CWriteByte_writeBuffer);
        }

        byte[] i2cReadByte_writeBuffer = new byte[1];
        byte[] i2cReadByte_readBuffer = new byte[1];
        public byte I2CReadByte(byte regAddr)
        {
            i2cReadByte_writeBuffer[0] = regAddr;
            I2cCommunication.WriteRead(i2cReadByte_writeBuffer, i2cReadByte_readBuffer);
            return i2cReadByte_readBuffer[0];
        }

        #endregion

        #region Serial Communication- UART

        public SerialDevice UARTCommunication
        {
            get; set;
        }

        public string UARTPort
        {
            get; set;
        }

        public uint UARTBaudRate
        {
            get; set;
        }

        public int UARTWriteTimeout
        {
            get; set;
        }

        public int UARTReadTimeout
        {
            get; set;
        }

        public DataWriter UARTDataWriteObject
        {
            get; set;
        }
        public DataReader UARTDataReaderObject
        {
            get; set;
        }
        #endregion

        #region GPIO

        public int IoInterruptPinID
        {
            get; set;
        }

        public int IoControlPinID
        {
            get; set;
        }

        public GpioPin IoInterruptPin
        {
            get; set;
        }

        public GpioPin IoControlPin
        {
            get; set;
        }
        #endregion
    }
}
StartupTask.csC#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Http;
using Windows.ApplicationModel.Background;
using Windows.System.Threading;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Devices.Gpio;
using Windows.Storage.Streams;
using System.Threading.Tasks.Dataflow;
using System.Runtime.InteropServices.WindowsRuntime;

// The Background Application template is documented at http://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409

namespace IoTController
{
    public sealed class StartupTask : IBackgroundTask
    {
        BackgroundTaskDeferral deferral;

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            
            deferral = taskInstance.GetDeferral();

            InitSystem();

        }

        CONTROLLER dragonBoard;

        SHT21 temperatureSensor;

        LIDAR_LITEv2 lidarShortRange; LIDAR_SF11C lidarLongRange;

        MPU_925x_SPI mpuSPI; MPU_925x_I2C mpuI2C;

        GPS_ARDUINO gpsArduino; GPS_UbloxNEOM8N gpsUART;

        OBD2_ELM327 obd2;

        LED_INDICATOR processStatusLED, errorStatusLED;

        SERVO_CONTROLLER pantiltSERVO;

        public void InitSystem()
        {
            dragonBoard = new CONTROLLER(remoteHostname: "192.168.137.255", localPortName : "61556", remotePortName : "61557");            

            //temperatureSensor = new SHT21() { I2CPort = I2CPortID.I2C1 };   InitSHT21();
           
            processStatusLED = new LED_INDICATOR() { IoControlPinID = 21 }; errorStatusLED = new LED_INDICATOR() { IoControlPinID = 120 }; InitLEDIndicator();
            //pantiltSERVO = new SERVO_CONTROLLER() { UARTPort = "UART1", UARTBaudRate = 115200 }; InitPanTiltSERVO();

            ProcessDATA();
        }

        #region Processing Sensor Data
        BufferBlock<char> deviceDataQueue = new BufferBlock<char>();

        char deviceDataToken;
        const char lidarDataToken = 'L', lidarShortRangeDataToken = 'L', lidarLongRangeDataToken = 'L';
        const char gpsDataToken = '$';
        const char mpuSPIDataToken = 'S', mpuI2CDataToken = 'I';
        const char obd2DataToken = 'V';

        double Ax, Ay, Az;
        double Gx, Gy, Gz;
        double mpuTemperature;

        ushort LidarShortRangeDistanceCentimeter, LidarLongRangeDistanceCentimeter;

        double VehicleSpeed, VehicleRPM;

        private async void ProcessDATA()
        {
            while (await deviceDataQueue.OutputAvailableAsync())
            {
                processStatusLED.IoControlPin.Write(GpioPinValue.High);
                deviceDataToken = await deviceDataQueue.ReceiveAsync();
                //dragonBoard.Send_UDP(adasDataBytes);

                switch (deviceDataToken)
                {
                    case lidarDataToken: // LIDAR

                        //Debug.WriteLine($"Lidar Longrange-Distance = {LidarLongRangeDistanceCentimeter} (cm)");
                        /*
                         * 
                        if (LidarLongRangeDistanceCentimeter>300)
                        {
                            servo_angles[0] = 90; // Roll
                            servo_angles[1] = 90; // Pitch
                            panTiltController.ControlServo(servo_angles);
                        }
                        else
                        {
                            servo_angles[0] = 70; // Roll
                            servo_angles[1] = 90; // Pitch
                            panTiltController.ControlServo(servo_angles);
                        }
                        */
                        break;

                    case mpuSPIDataToken: // MPU-SPI

                        //Debug.WriteLine($"AX = {ax_SPI},AY = {ay_SPI},AZ = {az_SPI} ");
                        //Debug.WriteLine($"AZ = {Az}, MPU Temp ={mpuTemperature}");
                        Debug.WriteLine($"AZ_SPI = {Az_SPI}");
                        //Debug.WriteLine($"GX = {Gx},GY = {Gy}, GZ = {Gz} ");
                        break;

                    case mpuI2CDataToken: // MPU-SPI
                        Debug.WriteLine($"AZ_I2C = {Az_I2C}");
                        break;

                    case obd2DataToken: // OBD2-Speed, RPM

                        break;
                }

                processStatusLED.IoControlPin.Write(GpioPinValue.Low);
            }
        }
        #endregion
        
       ring length: {gpsStringRAW.Length}");
                                    /*

                                    //Debug.WriteLine($"Time UTC: {gpsParameters[1]}, Date: {gpsParameters[9]}");
                                    if (gpsParameters[1] != "")
                                    {
                                        gpsUTCParameters = gpsParameters[1].Split(dateTimeDelimiterChars);
                                        UTChour = gpsUTCParameters[0].Substring(0, 2);
                                        UTCminute = gpsUTCParameters[0].Substring(2, 2);
                                        UTCsecond = gpsUTCParameters[0].Substring(4, 2);

                                        GPSdate = gpsParameters[9].Substring(0, 2);
                                        GPSmonth = gpsParameters[9].Substring(2, 2);
                                        GPSyear = gpsParameters[9].Substring(4, 2);


                                        DateTime date1 = new DateTime(2000 + Int32.Parse(GPSyear), Int32.Parse(GPSmonth), Int32.Parse(GPSdate), Int32.Parse(UTChour) - 4,
                                                                            Int32.Parse(UTCminute), Int32.Parse(UTCsecond));
                                        Debug.WriteLine($"GPSDateTime : {date1}");                                   

                                    }

                                    if (gpsParameters[3] != "")
                                    {
                                        Debug.WriteLine($"GPSLocation: Latitude {gpsParameters[3]}, Longtidue : {gpsParameters[5]}");
                                        //Debug.WriteLine($"GPSLocation: Latitude {gpsParameters[3]}");

                                    }
                                    */

                                    break;

                                    //case "$GNGLL":
                                    //Debug.WriteLine($"Lattitude: {gpsParameters[1]}");
                                    //break;
                            }

                            gpsStringRAW = "";

                        }
                    }
                }

            });
        }
        #endregion

       

        
    }
}

Credits

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

End-Effector and Control Logic for Robot
Intermediate
  • 3,339
  • 25

For my thesis, I have developed the control system and end-effector for a robot, easily implementable and economic.

Theremino Adapter for CNC.
Intermediate
  • 302
  • 8

Full instructions

Attention: This adapter is used to replace the parallel port with the USB, and not to operate Mach3 CNC or Linux.

Theremino Logger
Intermediate
  • 173
  • 5

Datalogger is simple to use but with great performance. The base, concise and intuitive.

Theremino - Access to Slots “WriteSlot”  “ReadSlot”.
Intermediate
  • 52
  • 4

Full instructions

A description of how to communicate with the slots of Theremino System by simply calling the functions: “WriteSlot” and “ReadSlot”.

Theremino - Use the serial port to write data to Slots.
Intermediate
  • 81
  • 4

Theremino_SeriHAL lets you send data to slots from a serial port.

Pulse Train HAT Pick & Place Example
Intermediate
  • 438
  • 3

Protip

With this example, we show how to use the PTHAT and Raspberry Pi being used to learn commands for pick and place applications.

Add projectSign up / Login
Respect project