Things used in this project

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

Wireless Sensor Node
Intermediate
  • 220
  • 4

Work in progress

This project is a compact wireless sensor node that connects directly to a smart phone or tablet to display data from connected sensors.

Trigger Google Assistant on Pi Using Ultrasonic HC-SR04
Intermediate
  • 326
  • 4

Trigger Google Assistant SDK on RPi using ultrasonic sensor HC-SR04 on Raspberry Pi.

Sense and Display with Android Things and Kotlin
Intermediate
  • 29
  • 1

Full instructions

This project shows how to get started to read I2C temperature sensor and display the reading to OLED display using Android Things and Kotlin

Smart Conductive 'On Air' Sign!
Intermediate
  • 710
  • 10

Full instructions

Raspberry Pi + Bare Conductive Paint + Pi Cap + RGB LEDs = AWESOME CONDUCTIVE SIGN!

CNC Controller in Python
Intermediate
  • 790
  • 8

Full instructions

First ever CNC machine controller implementation in pure Python.

AWS IoT Environment for Home Assistant
Intermediate
  • 1,263
  • 10

Work in progress

Home Assistant is an automation platform that can track and control all kinds of devices and automate actions, which fits well with AWS IoT.

ProjectsCommunitiesTopicsContestsLiveAppsBetaFree StoreBlogAdd projectSign up / Login