利用arduino採集溫溼度,客戶端程式顯示實時曲線圖
阿新 • • 發佈:2019-01-03
// Example testing sketch for various DHT humidity/temperature sensors // Written by ladyada, public domain #include "DHT.h" #define DHTPIN 2 // what digital pin we're connected to // Uncomment whatever type you're using! #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //#define DHTTYPE DHT21 // DHT 21 (AM2301) // Connect pin 1 (on the left) of the sensor to +5V // NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1 // to 3.3V instead of 5V! // Connect pin 2 of the sensor to whatever your DHTPIN is // Connect pin 4 (on the right) of the sensor to GROUND // Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor // Initialize DHT sensor. // Note that older versions of this library took an optional third parameter to // tweak the timings for faster processors. This parameter is no longer needed // as the current DHT reading algorithm adjusts itself to work on faster procs. DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(9600); Serial.println("DHTxx test!"); dht.begin(); } void loop() { // Wait a few seconds between measurements. delay(2000); // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) float h = dht.readHumidity(); // Read temperature as Celsius (the default) float t = dht.readTemperature(); // Read temperature as Fahrenheit (isFahrenheit = true) float f = dht.readTemperature(true); // Check if any reads failed and exit early (to try again). if (isnan(h) || isnan(t) || isnan(f)) { Serial.println("Failed to read from DHT sensor!"); return; } // Compute heat index in Fahrenheit (the default) float hif = dht.computeHeatIndex(f, h); // Compute heat index in Celsius (isFahreheit = false) float hic = dht.computeHeatIndex(t, h, false); // Serial.print("Humidity: "); Serial.print("ST"); Serial.print(h); // Serial.print(" %\t"); // Serial.print("Temperature: "); Serial.print(t); // Serial.print(" *C "); Serial.print(f); // Serial.print(" *F\t"); // Serial.print("Heat index: "); // Serial.print(hic); // Serial.print(" *C "); // Serial.print(hif); // Serial.println(" *F"); }
以上是arduino微控制器程式 網上找別人的
以下是客戶端介面和程式碼
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO.Ports; using System.Windows.Forms.DataVisualization.Charting; using System.Data.SqlClient; using System.Runtime.InteropServices; namespace 溫溼度採集 { public partial class Form1 : Form { private SerialPort comm = new SerialPort(); private StringBuilder builder = new StringBuilder();//避免在事件處理方法中反覆的建立,定義到外面。 private long received_count = 0;//接收計數 private long send_count = 0;//傳送計數 private bool Listening = false;//是否沒有執行完invoke相關操作 private bool Closing = false;//是否正在關閉串列埠,執行Application.DoEvents,並阻止再次invoke private List<byte> buffer = new List<byte>(8192);//預設分配1頁記憶體,並始終限制不允許超過 private byte[] binary_data_1 = new byte[31];//53 54 32 30 2E 30 30 32 31 2E 30 30 36 39 2E 38 30 double wend; double shid; public Form1() { InitializeComponent(); InitChart(); InitChart2(); ConsoleEx.AllocConsole(); } System.Windows.Forms.Timer chartTimer = new System.Windows.Forms.Timer(); private void InitChart() { DateTime time = DateTime.Now; chartTimer.Interval = 1000; wendu.DoubleClick += wendu_DoubleClick; Series series = wendu.Series[0]; series.ChartType = SeriesChartType.Spline; wendu.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss"; wendu.ChartAreas[0].AxisX.ScaleView.Size = 5; wendu.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true; wendu.ChartAreas[0].AxisX.ScrollBar.Enabled = true; chartTimer.Start(); } private void InitChart2() { DateTime time1 = DateTime.Now; chartTimer.Interval = 1000; // wendu.DoubleClick += wendu_DoubleClick; Series series = shidu.Series[0]; series.ChartType = SeriesChartType.Spline; shidu.ChartAreas[0].AxisX.LabelStyle.Format = "HH:mm:ss"; shidu.ChartAreas[0].AxisX.ScaleView.Size = 5; shidu.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true; shidu.ChartAreas[0].AxisX.ScrollBar.Enabled = true; chartTimer.Start(); } void wendu_DoubleClick(object sender, EventArgs e) { wendu.ChartAreas[0].AxisX.ScaleView.Size = 5; wendu.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = true; wendu.ChartAreas[0].AxisX.ScrollBar.Enabled = true; //throw new NotImplementedException(); } private void Form1_Load(object sender, EventArgs e) { comm.PortName = "COM3"; comm.BaudRate = 9600; comm.DataBits = 7; comm.Open(); comm.NewLine = "\r\n"; comm.RtsEnable = true;//根據實際情況吧。 //新增事件註冊 comm.DataReceived += comm_DataReceived; } private void comm_DataReceived(object sender, SerialDataReceivedEventArgs e) { if (Closing) return;//如果正在關閉,忽略操作,直接返回,儘快的完成串列埠監聽執行緒的一次迴圈 try { Listening = true;//設定標記,說明我已經開始處理資料,一會兒要使用系統UI的。 int n = comm.BytesToRead;//先記錄下來,避免某種原因,人為的原因,操作幾次之間時間長,快取不一致 byte[] buf = new byte[n];//宣告一個臨時陣列儲存當前來的串列埠資料 received_count += n;//增加接收計數 comm.Read(buf, 0, n);//讀取緩衝資料 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// //<協議解析> int data_1_catched = 0;//快取記錄資料是否捕獲到 //1.快取資料 buffer.AddRange(buf); //2.完整性判斷 while (buffer.Count >= 17)//至少要包含頭(2位元組)+長度(1位元組)+校驗(1位元組) { //請不要擔心使用>=,因為>=已經和>,<,=一樣,是獨立操作符,並不是解析成>和=2個符號 //2.1 查詢資料頭 if (buffer[0] == 0x53) { //2.2 探測快取資料是否有一條資料的位元組,如果不夠,就不用費勁的做其他驗證了 //前面已經限定了剩餘長度>=4,那我們這裡一定能訪問到buffer[2]這個長度 int len = 17;//資料長度 //資料完整判斷第一步,長度是否足夠 //len是資料段長度,4個位元組是while行註釋的3部分長度 if (buffer.Count < len) break;//資料不夠的時候什麼都不做 //這裡確保資料長度足夠,資料頭標誌找到,我們開始計算校驗 //2.3 校驗資料,確認資料正確 //異或校驗,逐個位元組異或得到校驗碼 #region 校驗和 //byte checksum = 0; //for (int i = 0; i < len + 3; i++)//len+3表示校驗之前的位置 //{ // checksum ^= buffer[i]; //} //if (checksum != buffer[len + 3]) //如果資料校驗失敗,丟棄這一包資料 //{ // buffer.RemoveRange(0, len + 4);//從快取中刪除錯誤資料 // continue;//繼續下一次迴圈 //} //至此,已經被找到了一條完整資料。我們將資料直接分析,或是快取起來一起分析 //我們這裡採用的辦法是快取一次,好處就是如果你某種原因,資料堆積在快取buffer中 //已經很多了,那你需要迴圈的找到最後一組,只分析最新資料,過往資料你已經處理不及時 //了,就不要浪費更多時間了,這也是考慮到系統負載能夠降低。 #endregion buffer.CopyTo(0, binary_data_1, 0, 17);//複製一條完整資料到具體的資料快取 data_1_catched = 1; buffer.RemoveRange(0, 17);//正確分析一條資料,從快取中移除資料。 } else { //這裡是很重要的,如果資料開始不是頭,則刪除資料 buffer.RemoveAt(0); } } //分析資料 if (data_1_catched == 1) { foreach (byte str in binary_data_1) Console.Write("{0} ", Convert.ToChar(str)); int h1 = binary_data_1[2]-48; Console.WriteLine( h1); int h2 = binary_data_1[3] - 48; int h3 = binary_data_1[5] - 48; int h4 = binary_data_1[6] - 48; double h = h1 * 10 + h2 + h3 * 0.1 + h4 * 0.01; int w1 = binary_data_1[7] - 48; int w2 = binary_data_1[8] - 48; int w3 = binary_data_1[10] - 48; int w4 = binary_data_1[11] - 48; double w = w1 * 10 + w2 + w3 * 0.1 + w4 * 0.01; //Console.WriteLine("{0} {1} {2} {3} {4}" ,h1,h2,h3,h4,h); shid = h; wend = w; this.Invoke((EventHandler)(delegate { Series series = shidu.Series[0]; series.Points.AddXY(DateTime.Now, shid); shidu.ChartAreas[0].AxisX.ScaleView.Position = series.Points.Count - 5; Series series1 = wendu.Series[0]; series1.Points.AddXY(DateTime.Now, wend); wendu.ChartAreas[0].AxisX.ScaleView.Position = series.Points.Count - 5; })); //int to1 = (Convert.ToInt32(binary_data_1[22]) - 48); //int to2 = (Convert.ToInt32(binary_data_1[23]) - 48); //int t = t1 * 10 + t2; //int h = h1 * 10 + h2; //int to = to1 * 10 + to2; //DateTime d = DateTime.Now; //Console.Write(d); #region 連線資料庫 //string constr = "Data source=(local);Initial Catalog=ww;Integrated Security=true"; //using (SqlConnection con = new SqlConnection(constr)) //{ // //con.Open(); // string sql = string.Format("insert into hj values('{0}','{1}','{2}',getdate())", t, h, to); // using (SqlCommand cmd = new SqlCommand(sql, con)) // { // con.Open(); // int r = cmd.ExecuteNonQuery(); // if (r > 0) // { // Console.Write("charuchengg"); // } // else // { // Console.Write("shibai"); // } // } //} #endregion //int val = Convert.ToInt16((b1 << 8) + b2);//兩個位元組合併 //int b3 = Convert.ToInt16(binary_data_1[6]); //int b4 = Convert.ToInt16(binary_data_1[7]); //int b5 = Convert.ToInt16(binary_data_1[8]); //int b6 = Convert.ToInt16(binary_data_1[9]); //int b7 = Convert.ToInt16(binary_data_1[10]); //int czbh1 = Convert.ToInt16(binary_data_1[11]); //int czbh2 = Convert.ToInt16(binary_data_1[12]); //int sd = Convert.ToInt32((czbh1 << 8) + czbh2); //int jsd = Convert.ToInt32(binary_data_1[13]); //Console.WriteLine("{0}年{1}月{2}日{3}時{4}分{5}秒,編號時{6},是否超限{7}", Convert.ToString(val), // Convert.ToString(b3), Convert.ToString(b4), Convert.ToString(b5), Convert.ToString(b6), // Convert.ToString(b7), Convert.ToString(sd), Convert.ToString(jsd )); //Console.WriteLine("H的值{0} }", h); //Console.WriteLine(b2); //foreach (byte str in binary_data_1) // Console.Write("{0} ", Convert.ToChar(str)); } //如果需要別的協議,只要擴充套件這個data_n_catched就可以了。往往我們協議多的情況下,還會包含資料編號,給來的資料進行 //編號,協議優化後就是: 頭+編號+長度+資料+校驗 //</協議解析> ///////////////////////////////////////////////////////////////////////////////////////////////////////////// builder.Clear();//清除字串構造器的內容 #region MyRegion //因為要訪問ui資源,所以需要使用invoke方式同步ui。 //this.Invoke((EventHandler)(delegate //{ // //判斷是否是顯示為16禁止 // if (checkBoxHexView.Checked) // { // //依次的拼接出16進位制字串 // foreach (byte b in buf) // { // builder.Append(b.ToString("X2") + " "); // } // } // else // { // //直接按ASCII規則轉換成字串 // builder.Append(Encoding.ASCII.GetString(buf)); // } // //追加的形式新增到文字框末端,並滾動到最後。 // this.txGet.AppendText(builder.ToString()); // //修改接收計數 // labelGetCount.Text = "Get:" + received_count.ToString(); //})); #endregion } finally { Listening = false;//我用完了,ui可以關閉串列埠了。 } //throw new NotImplementedException(); } } public class ConsoleEx { /// <summary> /// 啟動控制檯 /// </summary> [DllImport("kernel32.dll")] public static extern bool AllocConsole(); /// <summary> /// 釋放控制檯 /// </summary> [DllImport("kernel32.dll")] public static extern bool FreeConsole(); } }