// *** SendandReceiveBinaryArguments *** // This example expands the previous SendandReceiveArguments example. The PC will // send and receive multiple Binary values, demonstrating that this is more compact and faster. Since the output is not human readable any more, // the logging is disabled and the NewLines are removed // // It adds a demonstration of how to: // - Receive multiple binary parameters, // - Send multiple binary parameters // - Callback events being handled while the main program waits // - How to calculate milliseconds, similar to Arduino function Millis() using System; using System.Threading; using CommandMessenger; using CommandMessenger.Transport.Serial; namespace SendAndReceiveBinaryArguments { // This is the list of recognized commands. These can be commands that can either be sent or received. // In order to receive, attach a callback function to these events enum Command { RequestPlainTextFloatSeries , // Command Request to send series in plain text ReceivePlainTextFloatSeries , // Command to send an item in plain text RequestBinaryFloatSeries , // Command Request to send series in binary form ReceiveBinaryFloatSeries , // Command to send an item in binary form }; public class SendAndReceiveBinaryArguments { public bool RunLoop { get; set; } private SerialTransport _serialTransport; private CmdMessenger _cmdMessenger; private int _receivedItemsCount; // Counter of number of plain text items received private int _receivedBytesCount; // Counter of number of plain text bytes received long _beginTime; // Start time, 1st item of sequence received long _endTime; // End time, last item of sequence received private bool _receivePlainTextFloatSeriesFinished; // Indicates if plain text float series has been fully received private bool _receiveBinaryFloatSeriesFinished; // Indicates if binary float series has been fully received const int SeriesLength = 2000; // Number of items we like to receive from the Arduino private const float SeriesBase = 1111111.111111F; // Base of values to return: SeriesBase * (0..SeriesLength-1) // ------------------ M A I N ---------------------- // Setup function public void Setup() { // Create Serial Port object _serialTransport = new SerialTransport { CurrentSerialSettings = { PortName = "COM15", BaudRate = 115200 } // object initializer }; // Initialize the command messenger with the Serial Port transport layer // Set if it is communicating with a 16- or 32-bit Arduino board _cmdMessenger = new CmdMessenger(_serialTransport, BoardType.Bit16); // Attach the callbacks to the Command Messenger AttachCommandCallBacks(); // Start listening _cmdMessenger.Connect(); _receivedItemsCount = 0; _receivedBytesCount = 0; // Clear queues _cmdMessenger.ClearReceiveQueue(); _cmdMessenger.ClearSendQueue(); Thread.Sleep(100); // Send command requesting a series of 100 float values send in plain text form var commandPlainText = new SendCommand((int)Command.RequestPlainTextFloatSeries); commandPlainText.AddArgument((UInt16)SeriesLength); commandPlainText.AddArgument((float)SeriesBase); // Send command _cmdMessenger.SendCommand(commandPlainText); // Now wait until all values have arrived while (!_receivePlainTextFloatSeriesFinished) { Thread.Sleep(100); } // Clear queues _cmdMessenger.ClearReceiveQueue(); _cmdMessenger.ClearSendQueue(); _receivedItemsCount = 0; _receivedBytesCount = 0; // Send command requesting a series of 100 float values send in binary form var commandBinary = new SendCommand((int)Command.RequestBinaryFloatSeries); commandBinary.AddBinArgument((UInt16)SeriesLength); commandBinary.AddBinArgument((float)SeriesBase); // Send command _cmdMessenger.SendCommand(commandBinary); // Now wait until all values have arrived while (!_receiveBinaryFloatSeriesFinished) { Thread.Sleep(100); } } // Loop function public void Loop() { RunLoop = false; } // Exit function public void Exit() { // Stop listening _cmdMessenger.Disconnect(); // Dispose Command Messenger _cmdMessenger.Dispose(); // Dispose Serial Port object _serialTransport.Dispose(); // Pause before stop Console.WriteLine("Press any key to stop..."); Console.ReadKey(); } /// Attach command call backs. private void AttachCommandCallBacks() { _cmdMessenger.Attach(OnUnknownCommand); _cmdMessenger.Attach((int)Command.ReceivePlainTextFloatSeries, OnReceivePlainTextFloatSeries); _cmdMessenger.Attach((int)Command.ReceiveBinaryFloatSeries, OnReceiveBinaryFloatSeries); } // ------------------ C A L L B A C K S --------------------- // Called when a received command has no attached function. void OnUnknownCommand(ReceivedCommand arguments) { Console.WriteLine("Command without attached callback received"); } // Callback function To receive the plain text float series from the Arduino void OnReceivePlainTextFloatSeries(ReceivedCommand arguments) { _receivedBytesCount += CountBytesInCommand(arguments, true); var count = arguments.ReadInt16Arg(); var receivedValue = arguments.ReadFloatArg(); if (count != _receivedItemsCount) { Console.WriteLine("Values not matching: received {0} expected {1}", count, _receivedItemsCount); } if (_receivedItemsCount % (SeriesLength/10) == 0) Console.WriteLine("Received value: {0}", receivedValue); if (_receivedItemsCount == 0) { // Received first value, start stopwatch _beginTime = Millis; } else if (count == SeriesLength - 1) { // Received all values, stop stopwatch _endTime = Millis; var deltaTime = (_endTime - _beginTime); Console.WriteLine("{0} milliseconds per {1} items = is {2} ms/item, {3} Hz", deltaTime, SeriesLength, (float)deltaTime / (float)SeriesLength, (float)1000 * SeriesLength / (float)deltaTime ); Console.WriteLine("{0} milliseconds per {1} bytes = is {2} ms/byte, {3} bytes/sec, {4} bps", deltaTime, _receivedBytesCount, (float)deltaTime / (float)_receivedBytesCount, (float)1000 * _receivedBytesCount / (float)deltaTime, (float)8 * 1000 * _receivedBytesCount / (float)deltaTime ); _receivePlainTextFloatSeriesFinished = true; } _receivedItemsCount++; } private int CountBytesInCommand(CommandMessenger.Command command, bool printLfCr) { var bytes = command.CommandString().Length; // Command + command separator //var bytes = _cmdMessenger.CommandToString(command).Length + 1; // Command + command separator if (printLfCr) bytes += 2; // Add bytes for carriage return ('\r') and /or a newline ('\n') return bytes; } // Callback function To receive the binary float series from the Arduino void OnReceiveBinaryFloatSeries(ReceivedCommand arguments) { var count = arguments.ReadBinUInt16Arg(); var receivedValue = arguments.ReadBinFloatArg(); _receivedBytesCount += CountBytesInCommand(arguments, false); if (count != _receivedItemsCount) { Console.WriteLine("Values not matching: received {0} expected {1}", count, _receivedItemsCount); } if (_receivedItemsCount % (SeriesLength / 10) == 0) Console.WriteLine("Received value: {0}", receivedValue); if (_receivedItemsCount == 0) { // Received first value, start stopwatch _beginTime = Millis; } else if (count == SeriesLength - 1) { // Received all values, stop stopwatch _endTime = Millis; var deltaTime = (_endTime - _beginTime); Console.WriteLine("{0} milliseconds per {1} items = is {2} ms/item, {3} Hz", deltaTime, SeriesLength, (float)deltaTime / (float)SeriesLength, (float)1000 * SeriesLength / (float)deltaTime ); Console.WriteLine("{0} milliseconds per {1} bytes = is {2} ms/byte, {3} bytes/sec, {4} bps", deltaTime, _receivedBytesCount, (float)deltaTime / (float)_receivedBytesCount, (float)1000 * _receivedBytesCount / (float)deltaTime, (float)8 * 1000 * _receivedBytesCount / (float)deltaTime ); _receiveBinaryFloatSeriesFinished = true; } _receivedItemsCount++; } // Return Milliseconds since 1970 public static long Millis { get { return (long)((DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds); } } } }