我正在尝试创建一个从Arduino读取模拟值的GUI,并通过GUI在zedGraph中显示它们。我已完成发送模拟值并使用GUI显示它。但现在我一直在控制何时通过命令启动读取伺服。我可以通过串行监视器控制伺服,但是当我尝试通过Visual Studio控制伺服时没有任何反应。我想制作一个程序,当我点击开始按钮时,伺服将旋转180度,当我点击停止时,伺服将旋转到10度。
很抱歉乱码,但我想你可以专注于Arduino代码中的void serialEvent()
,以及Visual Studio代码中的arduino.WriteLine("180")
或arduino.WriteLine("0")
。
这是我的Arduino代码:
#include <OneWire.h>
#include <Servo.h>
#define StartConvert 0
#define ReadTemperature 1
Servo myservo;
const byte numReadings = 20; //the number of sample times
byte ECsensorPin = A1; //EC Meter analog output,pin on analog 1
byte DS18B20_Pin = 2; //DS18B20 signal, pin on digital 2
unsigned int AnalogSampleInterval=25,printInterval=1000,tempSampleInterval=1000; //analog sample interval;serial print interval;temperature sample interval
unsigned int readings[numReadings]; // the readings from the analog input
byte index = 0; // the index of the current reading
unsigned long AnalogValueTotal = 0; // the running total
unsigned int AnalogAverage = 0,averageVoltage=0; // the average
unsigned long AnalogSampleTime,printTime,tempSampleTime;
float temperature,ECcurrent;
int val;
//Temperature chip i/o
OneWire ds(DS18B20_Pin); // on digital pin 2
void setup() {
//initialize serial communication with computer:
Serial.begin(115200);
//initialize all the readings to 0:
for (byte thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0;
TempProcess(StartConvert); //let the DS18B20 start the convert
AnalogSampleTime=millis();
printTime=millis();
tempSampleTime=millis();
myservo.attach(9);
}
/**----------------------THIS IS ANALOG READING CODE--------------------
void loop() {
//Every once in a while,sample the analog value and calculate the average.
if(millis()-AnalogSampleTime>=AnalogSampleInterval)
{
AnalogSampleTime=millis();
// subtract the last reading:
AnalogValueTotal = AnalogValueTotal - readings[index];
// read from the sensor:
readings[index] = analogRead(ECsensorPin);
// add the reading to the total:
AnalogValueTotal = AnalogValueTotal + readings[index];
// advance to the next position in the array:
index = index + 1;
// if we're at the end of the array...
if (index >= numReadings)
// ...wrap around to the beginning:
index = 0;
// calculate the average:
AnalogAverage = AnalogValueTotal / numReadings;
}
// Every once in a while,MCU read the temperature from the DS18B20 and then let the DS18B20 start the convert.
// Attention:The interval between start the convert and read the temperature should be greater than 750 millisecond,or the temperature is not accurate!
if(millis()-tempSampleTime>=tempSampleInterval)
{
tempSampleTime=millis();
temperature = TempProcess(ReadTemperature); // read the current temperature from the DS18B20
TempProcess(StartConvert); //after the reading,start the convert for next reading
}
//Every once in a while,print the information on the serial monitor.
if(millis()-printTime>=printInterval)
{
printTime=millis();
averageVoltage=AnalogAverage*(float)5000/1024;
//Serial.print("Analog value:");
//Serial.print(AnalogAverage); //analog average,from 0 to 1023
//Serial.print(" Voltage:");
//Serial.print(averageVoltage); //millivolt average,from 0mv to 4995mV
//Serial.print("mV ");
//Serial.print("temp:");
//Serial.print(temperature); //current temperature
//Serial.print("^C EC:");
float TempCoefficient=1.0+0.0185*(temperature-25.0); //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.0185*(fTP-25.0));
float CoefficientVolatge=(float)averageVoltage/TempCoefficient;
if(CoefficientVolatge<150)Serial.println("No solution!"); //25^C 1413us/cm<-->about 216mv if the voltage(compensate)<150,that is <1ms/cm,out of the range
else if(CoefficientVolatge>3300)Serial.println("Out of the range!"); //>20ms/cm,out of the range
else
{
if(CoefficientVolatge<=448)ECcurrent=6.84*CoefficientVolatge-64.32; //1ms/cm<EC<=3ms/cm
else if(CoefficientVolatge<=1457)ECcurrent=6.98*CoefficientVolatge-127; //3ms/cm<EC<=10ms/cm
else ECcurrent=5.3*CoefficientVolatge+2278; //10ms/cm<EC<20ms/cm
ECcurrent/=1000; //convert us/cm to ms/cm
float concentration = 0.0145*ECcurrent-0.0184;
Serial.println(concentration,3); //two decimal
//Serial.println("ms/cm");
}
}
//----------------------THIS IS ANALOG READING CODE--------------------
}
**/
void serialEvent(){
val = Serial.parseInt(); //-----TRY READ INPUT FROM SERIAL MONITOR
if(val != 0){
myservo.write(val);
}
}
/*
ch=0,let the DS18B20 start the convert;ch=1,MCU read the current temperature from the DS18B20.
*/
float TempProcess(bool ch)
{
//returns the temperature from one DS18B20 in DEG Celsius
static byte data[12];
static byte addr[8];
static float TemperatureSum;
if(!ch){
if ( !ds.search(addr)) {
Serial.println("no more sensors on chain, reset search!");
ds.reset_search();
return 0;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return 0;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized!");
return 0;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
}
else{
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
TemperatureSum = tempRead / 16;
}
return TemperatureSum;
}
这是我的Visual C#代码:
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;
//namespace untuk zedGrpah
using ZedGraph;
//namespace untuk class serial
using System.IO.Ports;
//namespace untuk melihat setting global komputer
using System.Globalization;
namespace Monitor_Suhu
{
public partial class Form_utama : Form
{
/**Inisialisaisi arduino
* Setup port serial dengan nama port COM3,
* dan baud rate sebesar 115200.
* **/
SerialPort arduino = new SerialPort("COM3", 115200);
//waktu mulai dalam milidetik
double waktuStart = 1000;
//konstruktor
public Form_utama()
{
InitializeComponent();
}
//event ketuka tombol start diklik
private void btn_kontrol_start_Click(object sender, EventArgs e)
{
if(arduino.IsOpen){
arduino.WriteLine("180"); //This command probably will send 180 to Arduino serial monitor
}
//start detak untuk mulai mengaktifkan grapher
try
{
//arduino.WriteLine("on");
//matikan tombol start
btn_kontrol_start.Enabled = false;
//nyalakan tombol stop
btn_kontrol_stop.Enabled = true;
//set batas waktu pembacaan serial sebelum dinyatakan gagal
arduino.ReadTimeout = 1000;
//set batas waktu penulisan serial
arduino.WriteTimeout = 1000;
//nyalakan detak
Detak.Enabled = true;
//mulai detak
Detak.Start();
}
catch (Exception gagal)
{
//Error handling
//MessageBox.Show(gagal.ToString());
}
}
//event ketika detak dimulai
private void Detak_Tick(object sender, EventArgs e)
{
try
{
//Mulai komunikasi dengan arduino
arduino.Open();
//get item kurva pertama pada grafik
LineItem kurvaKonsentrasi = zedGraphKonsentrasi.GraphPane.CurveList[0] as LineItem;
//get PointPairList
IPointListEdit listKonsentrasi = kurvaKonsentrasi.Points as IPointListEdit;
//waktu yang terlewati
double waktu = (Environment.TickCount - waktuStart) / 1000;
//baca data konsentrasi yang dikirim arduino,
//konversi data tersebut (string) ke double,
//dan tambahkan ke listKonsentrasi
float dataKonsentrasi = float.Parse(arduino.ReadLine(), CultureInfo.InvariantCulture.NumberFormat);
listKonsentrasi.Add(waktu, Convert.ToDouble(dataKonsentrasi));
String konsentrasi = dataKonsentrasi.ToString();
data_tb.AppendText( Environment.NewLine +konsentrasi);
//Tutup komunikasi dengan arduino
arduino.Close();
//Buat scale X tetap rolling dalam interval 30 detik, dengan satu
//langkah besar antara nilai X maksimal dan akhir dari axis
Scale xScale = zedGraphKonsentrasi.GraphPane.XAxis.Scale;
if (waktu > xScale.Max - xScale.MajorStep)
{
xScale.Max = waktu + xScale.MajorStep;
xScale.Min = xScale.Max - 30.0;
}
// Pastikan Y axis di scale ulang untuk mengakomodir data aktual
zedGraphKonsentrasi.AxisChange();
// Redraw paksa
zedGraphKonsentrasi.Invalidate();
String tampil = arduino.ReadLine();
data_tb.Text = tampil;
}
catch (Exception gagal)
{
//error handling
//tutup komunikasi dengan arduino jika masih terhubung
if (arduino.IsOpen)
{
arduino.Close();
}
//MessageBox.Show(gagal.ToString());
}
}
//event ketika tombol stop diklik
private void btn_kontrol_stop_Click(object sender, EventArgs e)
{
if(arduino.IsOpen){
arduino.WriteLine("0"); //This command probably will send 0 to Arduino serial monitor
}
try
{
// arduino.WriteLine("off");
//nyalakan kembali tombol start
btn_kontrol_start.Enabled = true;
//matikan tombol stop
btn_kontrol_stop.Enabled = false;
//stop detak
Detak.Stop();
//matikan detak
Detak.Enabled = false;
//jika komunikasi masih terbuka, tutup komunikasi
if (arduino.IsOpen)
{
arduino.Close();
}
}
catch (Exception gagal)
{
//error handling
MessageBox.Show(gagal.ToString());
}
}
//event ketika form utama dibuka
private void Form_utama_Load(object sender, EventArgs e)
{
try
{
//catat waktu pertama sebagai referensi
waktuStart = Environment.TickCount;
//Inisialisasi ZedGraph
GraphPane grafikKonsentrasi = zedGraphKonsentrasi.GraphPane;
grafikKonsentrasi.Title.Text = "Concentration Graph";
grafikKonsentrasi.XAxis.Title.Text = "Time (Second)";
grafikKonsentrasi.YAxis.Title.Text = "Concentration (mol/l)";
//Simpan 120 point. Pada 500 ms sampel rate.
//RollingPointPairList adalah class penyimpanan yang efisien
//dengan tetap merolling kumpulan point data tanpa perlu
//men-shift nilai data apapun
RollingPointPairList listKonsentrasi = new RollingPointPairList(120);
//Inisialisasi kurva
LineItem kurvaKonsentrasi = grafikKonsentrasi.AddCurve("Concentration", listKonsentrasi, Color.Red, SymbolType.None);
}
catch (Exception gagal)
{
//error handling
//MessageBox.Show(gagal.ToString());
}
}
private void btnSave_Click(object sender, EventArgs e)
{
try
{
string pathfile = @"C:\Users\ajis.aprl\Documents\TA bgt\data_GUI\";
string filename = "concentration.txt";
System.IO.File.WriteAllText(pathfile + filename, data_tb.Text);
MessageBox.Show("Data has been saved to " + pathfile, "Save File");
}
catch (Exception ex3)
{
MessageBox.Show(ex3.Message, "Error");
}
}
}
}