【问题标题】:How to get a flag from an Arduino button through serial communication?如何通过串行通信从 Arduino 按钮获取标志?
【发布时间】:2019-09-11 00:19:10
【问题描述】:

我的目标是获得一个通过按钮从 Arduino 发送的标志。此标志将通过串行通信发送到 C# windows 窗体程序,我将能够在该程序中获取该标志。

Arduino 向串口发送的数据是“ON”和“OFF”,点击按钮时为“ON”,未点击按钮时为“OFF”。此标志将用于打开和关闭将在 windows 窗体中显示的红色图表。

我的问题是我如何从串行通信中获得这个“ON”和“OFF”,记住来自传感器的数据也被发送到 Windows 窗体应用程序。

//C# Code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using rtChart;

namespace Distance_Sensor_using_Flight_of_time
{
    public partial class Form1 : Form
    {
        string recvData = "temporary";
        bool breakloop = false;
        kayChart chartData;
        bool buttonPress = false;
        string bufferString = "";
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            //chart1.Series.Add("Series1");
            //Connection COM & Baud Rate
            string[] ports = SerialPort.GetPortNames();
            string[] rates = new string[10] { "300", "600", "1200", "2400", "9600", "14400", "19200", "38400", "57600", "115200" };
            cboBaudRate.SelectedText = "9600";
            cboCOM.Items.AddRange(ports);
            cboBaudRate.Items.AddRange(rates);
            if (ports.Length >= 1)
                cboCOM.SelectedIndex = 0;

            //kayChart real time
            chartData = new kayChart(chart1, 60);

            btnStart.Enabled = false;
            btnSave.Enabled = false;
            chart1.Series["Series1"].Enabled = false;
        }

        private void BtnConnect_Click(object sender, EventArgs e)
        {
            try
            {
                if (btnConnect.Text == "Disconnect")
                {
                    if (btnStart.Text == "Stop")
                        MessageBox.Show("Please click \"Stop\" button first!");
                    else
                    {
                        serialPort1.Close();
                        btnStart.Enabled = false;
                        btnConnect.Text = "Connect";
                    }
                }
                else
                {
                    serialPort1.PortName = cboCOM.Text;
                    serialPort1.BaudRate = Convert.ToInt32(cboBaudRate.Text);
                    serialPort1.Parity = Parity.None;
                    serialPort1.StopBits = StopBits.One;
                    serialPort1.DataBits = 8;
                    serialPort1.Open();

                    btnStart.Enabled = true;
                    btnConnect.Text = "Disconnect";
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void serialDataReceive(object sender, SerialDataReceivedEventArgs e)
        {
            if (!breakloop)
            {
                SerialPort sData = sender as SerialPort;
                recvData = sData.ReadLine();

                bufferString = recvData;
                //rtbData.Invoke((MethodInvoker)delegate {rtbData.AppendText(recvData); });

                //update chart
                if (recvData == "ON\r" || recvData == "OFF\r")
                {
                    if (recvData == "ON")
                        buttonPress = true;
                    else
                        buttonPress = false;
                }
                else
                {
                    double data;
                    bool result = Double.TryParse(recvData, out data);
                    if (result)
                    {
                        chartData.TriggeredUpdate(data);
                        if (buttonPress == false)
                        {
                            chart1.Invoke((MethodInvoker)delegate { chart1.Series["Series1"].Enabled = false; });
                            chartData.serieName = "Length";
                        }
                        else
                        {
                            chart1.Invoke((MethodInvoker)delegate { chart1.Series["Series1"].Enabled = true; });
                            chartData.serieName = "Series1";
                        }
                    }
                }
                rtbData.Invoke((MethodInvoker)delegate { rtbData.AppendText(recvData); });
            }
        }

        private void BtnStart_Click(object sender, EventArgs e)
        {
            try
            {
                if (btnStart.Text == "Start")
                {
                    serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialDataReceive);
                    btnStart.Text = "Stop";
                    breakloop = false;
                }
                else
                {
                    btnStart.Text = "Start";
                    breakloop = true;
                    //serialPort1.DataReceived += null;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
                btnStart.Text = "Start";
            }
        }

        private void RtbData_TextChanged(object sender, EventArgs e)
        {
            rtbData.SelectionStart = rtbData.Text.Length;
            rtbData.ScrollToCaret();
        }        
    }
}
//Arduino Code

/* This example shows how to get single-shot range
 measurements from the VL53L0X. The sensor can optionally be
 configured with different ranging profiles, as described in
 the VL53L0X API user manual, to get better performance for
 a certain application. This code is based on the four
 "SingleRanging" examples in the VL53L0X API.

 The range readings are in units of mm. */

#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor;


// Uncomment this line to use long range mode. This
// increases the sensitivity of the sensor and extends its
// potential range, but increases the likelihood of getting
// an inaccurate reading because of reflections from objects
// other than the intended target. It works best in dark
// conditions.

//#define LONG_RANGE


// Uncomment ONE of these two lines to get
// - higher speed at the cost of lower accuracy OR
// - higher accuracy at the cost of lower speed

//#define HIGH_SPEED
#define HIGH_ACCURACY

const int buttonPin = 2;
const int ledPin = 8;
int buttonState = 0;
bool inLoop = false;

void setup()
{
  Serial.begin(9600);
  Wire.begin();

  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);

  sensor.init();
  sensor.setTimeout(500);

#if defined LONG_RANGE
  // lower the return signal rate limit (default is 0.25 MCPS)
  sensor.setSignalRateLimit(0.1);
  // increase laser pulse periods (defaults are 14 and 10 PCLKs)
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
#endif

#if defined HIGH_SPEED
  // reduce timing budget to 20 ms (default is about 33 ms)
  sensor.setMeasurementTimingBudget(20000);
#elif defined HIGH_ACCURACY
  // increase timing budget to 200 ms
  sensor.setMeasurementTimingBudget(200000);
  //sensor.setMeasurementTimingBudget(900000);
#endif
}

void loop()
{
  buttonState = digitalRead(buttonPin);

  Serial.print(sensor.readRangeSingleMillimeters());
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }

  Serial.println();

  if (buttonState == HIGH && inLoop == false)
  {
    Serial.write("ON");
    Serial.println();
    digitalWrite(ledPin, HIGH);
    inLoop = true;
  }
  else if (buttonState == LOW && inLoop == true)
  {
    Serial.write("OFF");
    Serial.println();
    digitalWrite(ledPin, LOW);
    inLoop = false;
  }
}

我希望单击按钮后图表将变为红色,未单击按钮时图表将变为蓝色。提前谢谢你。

【问题讨论】:

  • 阅读时获得一本好的沟通书籍!!!。客户端是主机,服务器(设备)是从机。所以通常客户端会发送一个命令,服务器会回复。在某些情况下,从站可能处于连续模式并发送状态。您有两层网络(网络有 7 层)1)传输层是串行端口 2)应用层是消息。您需要在消息中添加以指示消息类型以及数据。传感器数据应指示它是传感器和传感器编号。按钮应包含按钮编号。
  • 看来你很接近了,你能否提供更多关于它做错了什么或什么不工作的描述?

标签: c# arduino serial-port


【解决方案1】:

虽然您正在做的事情可能会奏效(即只是想弄清楚接收端的消息是什么),但如果您使用某种形式的消息头和分隔符,它的可扩展性要大得多。所以你的消息看起来像这样:

"btnState,true"

"btnState,false"

“数据,124”

在接收端,您需要执行 recvData.Split(',') 然后检查数组的第一个成员以找出它们的消息类型,然后相应地解析第二部分。

另外,关于你的代码,我不确定你为什么选择使用 Serial.write 为你“开”和“关”,而不是坚持使用 Serial.println。没有测试我不是肯定的,但很确定你正在尝试使用 println 作为消息分隔符,我认为它可能会将 write 和空 println 作为两个单独的消息发送(这可以解释为什么你的 on off 相等可能会失败)。

【讨论】:

  • 这可能是个好主意,很快就会尝试。我目前的问题是,即使检测到“ON”或“OFF”,程序也不会进入if语句。如果可能的话,我还想知道一种更好的方法来调试我当前的项目......因为发送到我的应用程序的数据是每 200 毫秒,所以当 arduino 发送“ON”或“OFF”时我很难得到按钮,因此我无法调试,因为“ON”或“OFF”信号需要时间。提前谢谢你。
  • 您可以查看wireshark 或任何串行嗅探器。这将为您提供所有串行通信的历史记录。如果它没有进入 if 语句,听起来好像没有检测到 ON 和 OFF...您是否尝试过在这些条件中进行一些调试打印以确保它们被触发?
  • 我已经成功地通过 Sneaky Polar Bear 的解决方案将旗帜加入了我的程序。提前感谢大家,特别感谢 Sneaky Polar Bear 给了我一个不错的选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多