串行输入的Visual Basic图形无法正确读取Arduino输出 [英] Visual Basic Graph of Serial Input is Not Correctly Reading Arduino Output

查看:116
本文介绍了串行输入的Visual Basic图形无法正确读取Arduino输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个相当简单的程序,该程序从Arduino Uno获取温度数据并将其发送到VB 2010以制作实时图形.到目前为止,我已经在新的一行上显示了Arduino输出温度,我知道这可以在Arduino IDE串行监视器上使用.

基本上我可以得到输入,但不是我应该阅读的内容. Arduino在9600波特下以25摄氏度的速度输出,但我的VB程序配置错误或无法跟上.例如,如果Arduino发送的流为25.16s,则我的程序可能会选择5.16或"或0.16.

一个快速的解决方法是,如果我有一种方法可以忽略任何不会转换为双精度值的值,然后重复执行直到获得有效字符串而不破坏程序.然后摆脱太小的值.我不知道如何做第一部分,但这是我认为我需要做的.

我是编程新手,所以如果我的程序完全错误,请原谅我.
另外,即使与我的问题无关,我也希望对我的两个程序有任何反馈.

这是我的Arduino代码,以防万一是错误的.我正在使用数字温度计.

I''m trying to make a fairly simple program that takes temperature data from an Arduino Uno and sends it to VB 2010 to make a real time graph. So far I have the Arduino output temperatures on a new line, I know this works from the Arduino IDE serial monitor.

Basically I can get input but is not what I should be reading. Arduino is putting out 25 degC at 9600 baud but my VB program is either configured incorrectly or it can''t keep up. For example if Arduino is sending a stream of 25.16s my program might pick out 5.16 or "" or 0.16.

A quick fix would be if I had a way to ignore any value that doesn''t convert to a double and repeat until it gets a valid string without breaking the program. Then get rid of values that are too small as well. I don''t know how to do the first part but it''s what I think I need to do.

I''m new to programming so if my programs are totally wrong, please forgive me.
Also I would love any feedback on my two programs, even if it isn''t relevant to my problem.

Here is my Arduino code just in case it is wrong. I''m using a digital thermometer.

#include <LiquidCrystal.h>
#include <OneWire.h>
int DS18S20_Pin = 9; //DS18S20 Signal pin on digital 2
int buttonPin = 8;     // the number of the pushbutton pin
int ledPin = 7;        // LED pin
OneWire ds(DS18S20_Pin); // on digital pin 2
// Connections:
// rs (LCD pin 4) to Arduino pin 12
// rw (LCD pin 5) to Arduino pin 11
// enable (LCD pin 6) to Arduino pin 10
// LCD pin 15 to Arduino pin 13
// LCD pins d4, d5, d6, d7 to Arduino pins 5, 4, 3, 2
// Digital Temperature sensor to Arduino pin 9
// Button to Arduino pin 8
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
int backLight = 13;    // pin 13 will control the backlight
int val = 0;
int oldVal = 0;
int state = 0;
void setup()
{
  Serial.begin(9600);
  pinMode(backLight, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(backLight, HIGH); // turn backlight on. Replace 'HIGH' with 'LOW' to turn it off.
  lcd.begin(16,2);              // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  lcd.clear();                  // start with a blank screen
  lcd.setCursor(0,0);           // set cursor to column 0, row 0 (the first row)
  lcd.print("Temperature");    // change this text to whatever you like. keep it clean.
}

void loop(void) 
{
val = digitalRead(buttonPin);  // Check for the button's state
if (val == HIGH && oldVal == LOW)
{
  state = 1 - state;
  delay(10);                  //Debounce
}
oldVal = val;   // Store val for comparison 
if (state == 1)
{
  float temperature = getTemp();
  temperature = temperature*(9/5)+32;
  lcd.setCursor(0,1);
  lcd.print(temperature);
  Serial.println(temperature);
  lcd.setCursor(6,1);
  lcd.print(char(223));
  lcd.setCursor(7,1);
  lcd.print("F");
  digitalWrite(ledPin, LOW); //Turn off LED when Tempearutre is in Celsius
  
  delay(10); //just here to slow down the output so it is easier to read
}
else
{
  float temperature = getTemp();
  lcd.setCursor(0,1);
  lcd.print(temperature);
  Serial.println(temperature);
  lcd.setCursor(6,1);
  lcd.print(char(223));
  lcd.setCursor(7,1);
  lcd.print("C");
  digitalWrite(ledPin, HIGH); //Turn on LED when Tempearutre is in Celsius
  delay(10);
}
}
float getTemp()
{
//returns the temperature from one DS18S20 in DEG Celsius
byte data[9];
byte addr[8];
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
   ds.reset_search();
return -1000;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.print("CRC is not valid!\n");
return -1000;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return -1000;
}
 ds.reset();
 ds.select(addr);
 ds.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds.reset();
 ds.select(addr);  
 ds.write(0xBE); // Read Scratchpad

for (int i = 0; i < 9; i++) { // we need 9 bytes
  data[i] = ds.read();
}
 ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}



这是我的VB代码,可能是我的错误所在:



Here is my VB code which is probably where my mistake is:

Imports System.Windows.Forms.DataVisualization.Charting
Imports System
Imports System.ComponentModel
Imports System.Threading
Imports System.IO.Ports

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim Time As Long = 0
        Dim line As String = ""
        Dim Chart1 As New Chart

        If (SerialPort1.IsOpen = True) Then
            SerialPort1.Close()
            SerialPort1.DiscardInBuffer()
        End If

    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim i As Long = 0
        Dim temp As Double = 0
        Dim tempArray(0) As Double
        Dim length As Long = 0
        Dim message1 As String = ""
        Chart1.ChartAreas(0).AxisX.Maximum = 20
        Chart1.ChartAreas(0).AxisX.Minimum = 0
        Chart1.ChartAreas(0).AxisY.Maximum = 20
        Chart1.ChartAreas(0).AxisY.Minimum = 0
        Chart1.Series(0).ChartType = DataVisualization.Charting.SeriesChartType.Line

        SerialPort1.PortName = "COM3"
        SerialPort1.BaudRate = 9600
        SerialPort1.Parity = IO.Ports.Parity.None
        SerialPort1.DataBits = 8
        SerialPort1.StopBits = IO.Ports.StopBits.One
        'Dim message2 As String = ""
        SerialPort1.Open()
        'SerialPort1.DiscardInBuffer()

        While (SerialPort1.IsOpen())
            If SerialPort1.BytesToRead() = 0 Then
                SerialPort1.DiscardInBuffer()
            Else
                message1 = SerialPort1.ReadLine()
                SerialPort1.DiscardInBuffer()

                If message1 = "" Then
                    While message1 = ""
                        message1 = SerialPort1.ReadLine()
                        SerialPort1.DiscardInBuffer()
                    End While
                End If

                If message1 = " " Then
                    While message1 = " "
                        message1 = SerialPort1.ReadLine()
                        SerialPort1.DiscardInBuffer()
                    End While
                End If
                Try
                    temp = Convert.ToDouble(message1)
                Catch ex As FormatException

                End Try

                tempArray(i) = temp
                length = UBound(tempArray)
                If length >= 0 Then
                    ReDim Preserve tempArray(length + 1)
                End If

                Label1.text = message1
                Chart1.Series(0).Points.Add(tempArray(i))
                If (tempArray(i) > Chart1.ChartAreas(0).AxisY.Maximum) Then
                    Chart1.ChartAreas(0).AxisY.Maximum = tempArray(i)
                End If
                Chart1.Series(0).Points.AddY(tempArray(i))

                If Chart1.Series(0).Points.Count = 30 Then
                    Chart1.Series(0).Points.RemoveAt(0)
                    Chart1.ChartAreas(0).AxisX.Maximum = UBound(tempArray)
                    Chart1.ChartAreas(0).AxisX.Minimum = UBound(tempArray) - 30
                End If
                i += 1
            End If
        End While
        MessageBox.Show("Session has ended.")
    End Sub
End Class




谢谢Kyle




Thanks Kyle

推荐答案

可能,您的问题是您经常调用DiscardInBuffer.如果您的VB代码与Arduino代码不同步(顺便说一句,那是因为Arduino持续不断地实时短暂地抽取数据,而Windows在感觉到它时VB仍在工作)从数据缓冲区读取一行时,数据缓冲区包含一个以上样本的可能性:
Probably, your problem is that you are calling DiscardInBuffer so often. If your VB code is out of sync with your Arduino code (and lets face it, it will be since the Arduino is continuously pumping data in realtime with a brief delay, and the VB is working when windows feels like it) There is a good chance that you data buffer contains more than one sample when you read a line from it:
25.16\n25.16\n25.16\n

您将读取第一个(最旧的)样本,并丢弃其余的样本.除了缓冲区中的数据不完整时,这似乎可以正常工作:

You would read the first (oldest) sample, and discard the remainder. This appears to work fine, except when the data in the buffer is not complete:

25.16\n25.16\n2

同样,您阅读最早的内容,而丢弃其余的内容.您的下一个示例有所不同:

Again, you read the oldest, and discard the rest. Your next sample is different:

5.16\n25.16\n25.

所以这一次,您的样本为5.16,然后再次丢弃其余部分,为下一个错误做好准备.

更改来自Arduino的数据:将其封装为(例如)"\ tnn.nn \ n",并扫描您的数据以仅使用完整的示例.我也将解析所有数据,而不是丢弃以后的样本,或者从上一个样本而不是第一个样本开始工作-这样,您将最新的样本作为当前温度,而不是最旧的

So this time, your sample is 5.16 and you again discard the rest, ready for the next error.

Change the data from the Arduino: Encapsulate it as (say) "\tnn.nn\n" and scan through your data to use complete samples only. I would also either parse all of the data rather than discarding later samples, or work from the last sample, rather than the first - that way you get the most recent sample as the current temp, rather than the oldest


这篇关于串行输入的Visual Basic图形无法正确读取Arduino输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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