窗10 IOT串行 - 工作RP2但读串行数据不完整 [英] Windows 10 IOT serial - Working on RP2 but read serial data incomplete

查看:496
本文介绍了窗10 IOT串行 - 工作RP2但读串行数据不完整的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我一直在尝试与IOT串行样品和RP2自10月发布开辟了串行引脚。即时通讯使用Windows IOT串行样本。有几个问题我无法弄清楚。

So I have been experimenting with the IOT serial sample and RP2 since the october release opened up the serial pins. Im using the windows iot serial sample. Have a few issues i cant figure out.


  1. 读出的数据似乎不完整的。我有一个Arduino输出模拟量输入通过串行9600波特读书。窗户上universial应用,不适读取一个完整产品线再一个不完整的线。例如:如果arduiono正在输出的2.25的值,应用程序会读取一行2.25那么接下来的.25(没有前面的任何时期)。香港专业教育学院试图拖延在应用程序方面和Arduino的,但没有成功。

  1. The read data seems incomplete. I have an arduino outputting an analog input reading through the serial at 9600 baud. On the windows universial app, ill read one complete line then one incomplete line. For example: if the arduiono is outputting a value of "2.25", the app will read one line 2.25 then the next ".25"(without anything in front the period). Ive tried delays on the app side and arduino with no success.

在次尝试连接时,它会抛出一个异常的格式。有时可以打断开并重新连接,它会正常工作。其他我必须重新启动Arduino的。

At times when trying to connect, it will throw a formatting exception. Sometimes can hit disconnect and reconnect and it will work fine. Others i have to reboot the arduino.

即时通讯思想的东西code样品中,因为我有同样的问题,如果我从笔记本电脑或覆盆子PI运行。

Im thinking its something in the code sample because i have the same issues if i run from laptop or raspberry pi.

下面是C#的程序。我修改一点点。

Here is the c# for the program. i modified a little bit.

// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Collections.ObjectModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;
using System.Threading;
using System.Threading.Tasks;

namespace SerialSample
{    
public sealed partial class MainPage : Page
{
    /// <summary>
    /// Private variables
    /// </summary>
    private SerialDevice serialPort = null;
    DataWriter dataWriteObject = null;
    DataReader dataReaderObject = null;

    private ObservableCollection<DeviceInformation> listOfDevices;
    private CancellationTokenSource ReadCancellationTokenSource;

    public MainPage()
    {
        this.InitializeComponent();            
        comPortInput.IsEnabled = false;
        sendTextButton.IsEnabled = false;
        listOfDevices = new ObservableCollection<DeviceInformation>();
        ListAvailablePorts();
    }

    /// <summary>
    /// ListAvailablePorts
    /// - Use SerialDevice.GetDeviceSelector to enumerate all serial devices
    /// - Attaches the DeviceInformation to the ListBox source so that       DeviceIds are displayed
    /// </summary>
    private async void ListAvailablePorts()
    {
        try
        {
            string aqs = SerialDevice.GetDeviceSelector();
            var dis = await DeviceInformation.FindAllAsync(aqs);

            status.Text = "Select a device and connect";

            for (int i = 0; i < dis.Count; i++)
            {
                listOfDevices.Add(dis[i]);
            }

            DeviceListSource.Source = listOfDevices;
            comPortInput.IsEnabled = true;
            ConnectDevices.SelectedIndex = -1;
        }
        catch (Exception ex)
        {
            status.Text = ex.Message;
        }
    }

    /// <summary>
    /// comPortInput_Click: Action to take when 'Connect' button is clicked
    /// - Get the selected device index and use Id to create the SerialDevice object
    /// - Configure default settings for the serial port
    /// - Create the ReadCancellationTokenSource token
    /// - Add text to rcvdText textbox to invoke rcvdText_TextChanged event
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void comPortInput_Click(object sender, RoutedEventArgs e)
    {
        var selection = ConnectDevices.SelectedItems;

        if (selection.Count <= 0)
        {
            status.Text = "Select a device and connect";
            return;
        }

        DeviceInformation entry = (DeviceInformation)selection[0];         

        try
        {                
            serialPort = await SerialDevice.FromIdAsync(entry.Id);

            // Disable the 'Connect' button 
            comPortInput.IsEnabled = false;

            // Configure serial settings
            serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
            serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);                
            serialPort.BaudRate = 9600;
            serialPort.Parity = SerialParity.None;
            serialPort.StopBits = SerialStopBitCount.One;
            serialPort.DataBits = 8;

            // Display configured settings
            status.Text = "Serial port configured successfully!\n ----- Properties ----- \n";
            status.Text += "BaudRate: " + serialPort.BaudRate.ToString() + "\n";
            status.Text += "DataBits: " + serialPort.DataBits.ToString() + "\n";
            status.Text += "Handshake: " + serialPort.Handshake.ToString() + "\n";
            status.Text += "Parity: " + serialPort.Parity.ToString() + "\n";
            status.Text += "StopBits: " + serialPort.StopBits.ToString() + "\n";                            

            // Set the RcvdText field to invoke the TextChanged callback
            // The callback launches an async Read task to wait for data
            rcvdText.Text = "Waiting for data...";

            // Create cancellation token object to close I/O operations when closing the device
            ReadCancellationTokenSource = new CancellationTokenSource();

            // Enable 'WRITE' button to allow sending data
            sendTextButton.IsEnabled = true;
        }
        catch (Exception ex)
        {
            status.Text = ex.Message;
            comPortInput.IsEnabled = true;
            sendTextButton.IsEnabled = false;
        }
    }

    /// <summary>
    /// sendTextButton_Click: Action to take when 'WRITE' button is clicked
    /// - Create a DataWriter object with the OutputStream of the SerialDevice
    /// - Create an async task that performs the write operation
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void sendTextButton_Click(object sender, RoutedEventArgs e)
    {
        try
        {                
            if (serialPort != null)
            {
                // Create the DataWriter object and attach to OutputStream
                dataWriteObject = new DataWriter(serialPort.OutputStream);

                //Launch the WriteAsync task to perform the write
                await WriteAsync();
            }
            else
            {
                status.Text = "Select a device and connect";                
            }
        }
        catch (Exception ex)
        {
            status.Text = "sendTextButton_Click: " + ex.Message;
        }
        finally
        {
            // Cleanup once complete
            if (dataWriteObject != null)
            {
                dataWriteObject.DetachStream();
                dataWriteObject = null;
            }
        }
    }

    /// <summary>
    /// WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream 
    /// </summary>
    /// <returns></returns>
    private async Task WriteAsync()
    {
        Task<UInt32> storeAsyncTask;

        if (sendText.Text.Length != 0)
        {
            // Load the text from the sendText input text box to the dataWriter object
            dataWriteObject.WriteString(sendText.Text);                

            // Launch an async task to complete the write operation
            storeAsyncTask = dataWriteObject.StoreAsync().AsTask();

            UInt32 bytesWritten = await storeAsyncTask;
            if (bytesWritten > 0)
            {                    
                status.Text = sendText.Text + '\n';
                status.Text += "Bytes written successfully!";
            }
            sendText.Text = "";
        }
        else
        {
            status.Text = "Enter the text you want to write and then click on 'WRITE'";
        }
    }

    /// <summary>
    /// rcvdText_TextChanged: Action to take when text is entered in the 'Read Data' textbox
    /// - Create a DataReader object
    /// - Create an async task to read from the SerialDevice InputStream
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void rcvdText_TextChanged(object sender, TextChangedEventArgs e)
    {
        try
        {
            if (serialPort != null)
            {
                dataReaderObject = new DataReader(serialPort.InputStream);
                await ReadAsync(ReadCancellationTokenSource.Token);
            }
        }
        catch (Exception ex)
        {
            if (ex.GetType().Name == "TaskCanceledException")
            {
                status.Text = "Reading task was cancelled, closing device and cleaning up";
                CloseDevice();
            }
            else
            {
                status.Text = ex.Message;
            }
        }
        finally
        {
            // Cleanup once complete
            if (dataReaderObject != null)
            {
                dataReaderObject.DetachStream();
                dataReaderObject = null;
            }
        }
    }

    /// <summary>
    /// ReadAsync: Task that waits on data and reads asynchronously from the serial device InputStream
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async Task ReadAsync(CancellationToken cancellationToken)
    {
        Task<UInt32> loadAsyncTask;

        uint ReadBufferLength = 128;

        // If task cancellation was requested, comply
        cancellationToken.ThrowIfCancellationRequested();

        // Set InputStreamOptions to complete the asynchronous read operation when one or more bytes is available
        dataReaderObject.InputStreamOptions = InputStreamOptions.Partial;

        // Create a task object to wait for data on the serialPort.InputStream
        loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(cancellationToken);

        // Launch the task and wait
        UInt32 bytesRead = await loadAsyncTask;

        if (bytesRead > 0)
        {

            rcvdText.Text = dataReaderObject.ReadString(bytesRead);
            status.Text = bytesRead.ToString();
            //status.Text = "\nBytes read successfully!";
        }            
    }

    /// <summary>
    /// CancelReadTask:
    /// - Uses the ReadCancellationTokenSource to cancel read operations
    /// </summary>
    private void CancelReadTask()
    {         
        if (ReadCancellationTokenSource != null)
        {
            if (!ReadCancellationTokenSource.IsCancellationRequested)
            {
                ReadCancellationTokenSource.Cancel();
            }
        }         
    }

    /// <summary>
    /// CloseDevice:
    /// - Disposes SerialDevice object
    /// - Clears the enumerated device Id list
    /// </summary>
    private void CloseDevice()
    {            
        if (serialPort != null)
        {
            serialPort.Dispose();
        }
        serialPort = null;

        comPortInput.IsEnabled = true;
        sendTextButton.IsEnabled = false;            
        rcvdText.Text = "";
        listOfDevices.Clear();               
    }

    /// <summary>
    /// closeDevice_Click: Action to take when 'Disconnect and Refresh List' is clicked on
    /// - Cancel all read operations
    /// - Close and dispose the SerialDevice object
    /// - Enumerate connected devices
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void closeDevice_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            status.Text = "";
            CancelReadTask();
            CloseDevice();
            ListAvailablePorts();
        }
        catch (Exception ex)
        {
            status.Text = ex.Message;
        }          
    }        
}
}

下面是Arduino的素描:

Here is the Arduino Sketch:

void setup() 
{
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

}

// the loop routine runs over and over again forever:
void loop() 
{
// read the input on analog pin 0:  
float sensorValue = analogRead(A3);
sensorValue = (sensorValue / 1023) * 4.30;

// print out the value you read:
Serial.print(sensorValue);
Serial.println("");  
delay(1);        // delay in between reads for stability

}

这里是一个快速的视频显示问题的链接。而你也知道,它连接在第一时间视频哈哈哈。

And Here is a link to a quick video showing the issue. And you would know that it connected the first time for the video hahaha.

在此先感谢所有帮助和建议。

Thanks in advance for all help and suggestions.

推荐答案

我精简了code好位。我相信,在原来的code中的取消标记可能是问题的一部分。现在,它连接并读取每次:)这里是如果有人想尝试一下的code。

I streamlined the code a good bit. I believe the cancellation tokens in the original code may have been part of the issue. Now it connects and reads every time:) Here is the code if anyone wants to try it out.

using System;
using System.Collections.Generic;
using System.IO;
using Windows.UI.Popups;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Collections.ObjectModel;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;
using System.Threading;
using System.Threading.Tasks;



namespace Serial_Data_Read
{

public sealed partial class MainPage : Page
{

    private SerialDevice serialPort = null;

    DataReader dataReaderObject = null;

    public uint BytesReceived { get; }

    public MainPage()
    {
        this.InitializeComponent();
        ListAvailablePorts();

    }

    private async void ListAvailablePorts()
    {
        try
        {
            string aqs = SerialDevice.GetDeviceSelector();
            var dis = await DeviceInformation.FindAllAsync(aqs);

            var selectedPort = dis.First();
            serialPort = await SerialDevice.FromIdAsync(selectedPort.Id);


            serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
            serialPort.BaudRate = 9600;
            serialPort.Parity = SerialParity.None;
            serialPort.StopBits = SerialStopBitCount.One;
            serialPort.DataBits = 8;

            infoBox.Text = "Serial port configured successfully!\n ----- Properties ----- \n";
            infoBox.Text += "BaudRate: " + serialPort.BaudRate.ToString() + "\n";
            infoBox.Text += "DataBits: " + serialPort.DataBits.ToString() + "\n";
            infoBox.Text += "Handshake: " + serialPort.Handshake.ToString() + "\n";
            infoBox.Text += "Parity: " + serialPort.Parity.ToString() + "\n";
            infoBox.Text += "StopBits: " + serialPort.StopBits.ToString() + "\n";

            data.Text = "configuring port";

        }

        catch (Exception ex)
        {
            infoBox.Text = "OOps, Something went wrong! \n" + ex.Message ;
        }
    }

    private async void data_TextChanged(object sender, TextChangedEventArgs e)
    {
        dataReaderObject = new DataReader(serialPort.InputStream);
        try
        {
            var bytesRecieved = await dataReaderObject.LoadAsync(128);

            if (bytesRecieved > 0)
            {

                data.Text = dataReaderObject.ReadString(bytesRecieved).Trim();
            }

        }
        catch (Exception ex)
        {
            data.Text = ex.Message;
            ListAvailablePorts();
        }
        finally
        {
            if (dataReaderObject != null)
            {
                dataReaderObject.DetachStream();
                dataReaderObject = null;
            }
        }
    }    
}
}

和XAML中...

<Page
x:Class="Serial_Data_Read.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Serial_Data_Read"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
   Width="800" Height="480">

<Grid Background="{ThemeResource AppBarItemDisabledForegroundThemeBrush}">
    <TextBox x:Name="infoBox" HorizontalAlignment="Left" Margin="10,288,0,0" TextWrapping="Wrap" Text="Waiting to establish a connection" VerticalAlignment="Top" Height="182" Width="382"/>
    <TextBox x:Name="data" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Waiting for data" VerticalAlignment="Top" Height="154" Width="780"  TextChanged="data_TextChanged" />
</Grid>

这篇关于窗10 IOT串行 - 工作RP2但读串行数据不完整的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆