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

12079212 564322747053248 1472748919650209953 n
Trung Hoang

I am a graduate student at the Mechanical Engineering Department-University of Louisville

Replications

Did you replicate this project? Share it!

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

Give feedback

Comments

Similar projects you might like

Solar Smart Greenhouse using Vertical Aquaponic Towers
Intermediate
  • 1,207
  • 22

Work in progress

Feed your family with 22 sqm greenhousing by combining permaculture, aquaponic vertical towers and IOT.

IOT Aquarium controller
Intermediate
  • 330
  • 3

Full instructions

An opensource 3D printed aquarium controller with IOT capabilities.

4 Wheel Drive, DC Motor Control for Raspberry Pi
Intermediate
  • 1,282
  • 10

Full instructions

Base project for implementing DC motor control using the Raspberry Pi's I2C interface and an Adafruit 16-Channel Servo Shield.

Overkill GENIE garage door opener
Intermediate
  • 1,070
  • 11

Work in progress

Web app garage door opener with up/down direction detection, https password protection, lots of error detection and activity/error logging.

Arduino - Motor PID Speed Control
Intermediate
  • 806
  • 4

Full instructions

Make a program for the Arduino Pro Mini in Visual Studio to control motor speed with PID which can archive it exactly.

Stairway To Lights
Intermediate
  • 1,871
  • 12

Full instructions

Using LED strips, Raspberry PI and PIR sensors, see your path into the stairway to lights.

Add projectSign up / Login
Respect project