Download presentation
Presentation is loading. Please wait.
1
아두이노 조도센서 모니터링 PhotoCell
2
ReadingSerialPort MenuStrip ComboBox ProgressBar Button ListBox Button
chart
3
1. Arduino 프로그램 아두이노는 PhotoCell과 저항을 직렬로 연결하여 전압 분배회로를 만든다.
PhotoCell과 저항 사이의 전압을 ANALOG IN A0에 연결한다. PhotoCell의 저항이 작아지면 전압도 낮아지고 저항이 커지면 전압이 높아진다, 즉 A0의 값이 커진다. A0의 값은 0~1023까지의 숫자로 표현된다 setup() 에서는 Serial.begin(9600); 으로 시리얼 통신을 시작, Loop()에서 analogRead(A0) 함수로 A0의 값을 읽어서 Serial.println()으로 보낸다. 이 값을 C# 코드에서 읽을 것이다. 한번 출력한 후에는 1초간 delay(1000) 를 갖는다 이를 반복한다. 즉 1초에 한번씩 A0의 값을 시리얼로 보낸다
4
Arduino 회로
5
2. Serial 값을 읽어오기 장치관리자를 열어보면 포트에 COM3가 Arduino에 연결되어 있다는 것을 알 수 있다
6
C#에서 Serial통신 Serial Port에서 값을 받아와서 출력 using System.IO.Ports;
namespace SerialComm { public partial class Form1 : Form SerialPort sPort; // 시리얼 포트 선언 public Form1() InitializeComponent(); sPort = new SerialPort("COM3", 9600); sPort.Open(); sPort.DataReceived += SPort_DataReceived; } // 시리얼 포트의 Data_Received 이벤트 private void SPort_DataReceived(object sender, SerialDataReceivedEventArgs e) string s = sPort.ReadLine(); this.BeginInvoke((new Action(delegate { showValue(s); }))); private void showValue(string s) label1.Text = "Serial Value : " + s; Serial Port에서 값을 받아와서 출력
7
3. COM Port 선택 항상 COM3가 아니므로 ComboBox를 사용하여 시리얼 포트를 선택하게 함
public Form1() { InitializeComponent(); // ComboBox foreach (var ports in SerialPort.GetPortNames()) comboBox1.Items.Add(ports); } comboBox1.Text = "Select Port"; private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) ComboBox cb = sender as ComboBox; sPort = new SerialPort( cb.SelectedItem.ToString() ); sPort.Open(); sPort.DataReceived += SPort_DataReceived; 항상 COM3가 아니므로 ComboBox를 사용하여 시리얼 포트를 선택하게 함
8
4. ProgressBar 추가 private void showValue(string s) {
label1.Text = "Serial Value : " + s; // 아두이노의 A0에서 받는 값의 범위(0~1023) progressBar1.Minimum = 0; progressBar1.Maximum = 1023; progressBar1.Value = Int32.Parse(s); } GroupBox 로 ProgressBar와 두 개의 Label 을 감싸고 photoCell의 값을 표시함
9
5. ListBox의 추가 private void showValue(string s) {
label1.Text = "Serial Value : " + s; // 아두이노의 A0에서 받는 값의 범위(0~1023) progressBar1.Minimum = 0; progressBar1.Maximum = 1023; progressBar1.Value = Int32.Parse(s); // ListBox에 시간과 값을 표시 string item = DateTime.Now.ToString() + "\t" + s; listBox1.Items.Add(item); // 계속 스크롤이 되도록 처리 listBox1.SelectedIndex = listBox1.Items.Count - 1; }
10
6. Chart 추가 public Form1() { InitializeComponent(); foreach (string s in SerialPort.GetPortNames()) comboBox1.Items.Add(s); comboBox1.Text = "Select Port"; // Chart Setting chartSetting(); } private void showValue(string s) { …. // Chart 표시 chart1.Series["PhotoCell"].Points.Add(v); }
11
chartSetting() private void chartSetting() { chart1.ChartAreas.Clear(); chart1.ChartAreas.Add("draw"); chart1.ChartAreas["draw"].AxisX.Minimum = 0; chart1.ChartAreas["draw"].AxisX.Maximum = xCount; chart1.ChartAreas["draw"].AxisX.Interval = xCount / 5; chart1.ChartAreas["draw"].AxisX.MajorGrid.LineColor = Color.White; chart1.ChartAreas["draw"].AxisX.MajorGrid.LineDashStyle = ChartDashStyle.Dash; chart1.ChartAreas["draw"].AxisY.Minimum = 0; chart1.ChartAreas["draw"].AxisY.Maximum = 1024; chart1.ChartAreas["draw"].AxisY.Interval = 200; chart1.ChartAreas["draw"].AxisY.MajorGrid.LineColor = Color.White; chart1.ChartAreas["draw"].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dash; chart1.ChartAreas["draw"].BackColor = Color.Blue; chart1.Series.Clear(); chart1.Series.Add("PhotoCell"); chart1.Series["PhotoCell"].ChartType = SeriesChartType.Line; chart1.Series["PhotoCell"].Color = Color.LightGreen; chart1.Series["PhotoCell"].BorderWidth = 3; if(chart1.Legends.Count > 0) // 범례를 안보이게 한다 chart1.Legends.RemoveAt(0); }
12
7. 숫자 버튼 추가 public Form1() { InitializeComponent(); …. // 숫자 버튼
button1.BackColor = Color.Blue; button1.ForeColor = Color.White; button1.Text = ""; button1.Font = new Font("맑은 고딕", 16, FontStyle.Bold); } private void showValue(string s) // 숫자버튼 표시 button1.Text = sPort.PortName + "\n" + s;
13
8. Port 연결/비연결 Disconnect 했다가 다시 Connect 하면 숫자를 다시 읽어 들일 수 있다
// Connect Serial Port private void button2_Click(object sender, EventArgs e) { if (sPort.PortName == "") MessageBox.Show("Select Serial Port Available First", "Warning"); return; } sPort.Open(); sPort.DataReceived += SPort_DataReceived; // Connect 버튼 비활성화, Disconnect 버튼 활성화 button2.Enabled = false; button3.Enabled = true; // disconnect Serial Port private void button3_Click(object sender, EventArgs e) { sPort.Close(); button3.Enabled = false; button2.Enabled = true; } Disconnect 했다가 다시 Connect 하면 숫자를 다시 읽어 들일 수 있다
14
9. label1 -> 연결 시간 표시 public Form1() { ….
label1.Text = "Connection Time : "; } private void showValue(string s) //label1.Text = "Serial Value : " + s; private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) ComboBox cb = sender as ComboBox; sPort = new SerialPort( cb.SelectedItem.ToString() ); sPort.Open(); sPort.DataReceived += SPort_DataReceived; label1.Text = "Connection Time : " + DateTime.Now.ToString();
15
10. 데이터 값에 시간 포함 class sensorData { public DateTime dt; public int value; // 생성자 public sensorData(DateTime dt, int value) this.dt = dt; this.value = value; } // 저장하기 위한 자료구조 List<sensorData> myData = new List<sensorData>(); private void showValue(string s) { int v = Int32.Parse(s); if (v < 0 || v > 1023) return; myData.Add(new sensorData(DateTime.Now, v)); … }
16
11. 메뉴 추가 파일 – 저장/읽어 오기
17
12. 저장하기 private void 저장ToolStripMenuItem_Click(object sender, EventArgs e) { SaveFileDialog saveFileDialog1 = new SaveFileDialog(); saveFileDialog1.Filter = "txt files(*.txt)|*.txt|All files(*.*)|*.*"; if(saveFileDialog1.ShowDialog() == DialogResult.OK) string fileName = saveFileDialog1.FileName; FileStream fs = new FileStream(fileName, FileMode.Create); StreamWriter sw = new StreamWriter(fs); foreach (var item in myData) string s = string.Format("{0}\t{1}", item.dt.ToString(), item.value.ToString()); sw.WriteLine(s); } sw.Close();
18
13. 읽어오기 - 1 Timer myTimer; private void 읽어오기ToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "txt files(*.txt)|*.txt|All files(*.*)|*.*"; if(ofd.ShowDialog() == DialogResult.OK) string fileName = ofd.FileName; string[] lines = File.ReadAllLines(fileName); foreach (var line in lines) string[] items; items = line.Split('\t'); myData.Add(new sensorData(Convert.ToDateTime(items[0]), Int32.Parse(items[1]) )); } label1.Text = "Connection Time : " + myData[0].dt.ToString(); myTimer = new Timer(); myTimer.Interval = 1; myTimer.Start(); myTimer.Tick += MyTimer_Tick;
19
13. 읽어오기 - 2 int Count = 0; // 현재 프로세싱 중인 데이터 인덱스 private void MyTimer_Tick(object sender, EventArgs e) { string line = ""; line += myData[Count].dt.ToString() + "\t" + myData[Count].value.ToString(); listBox1.Items.Add(line); listBox1.SelectedIndex = listBox1.Items.Count - 1; progressBar1.Value = myData[Count].value; button1.Text = myData[Count].value.ToString(); chart1.Series["PhotoCell"].Points.Add(myData[Count].value); // zoom을 위해 200개까지는 기본, 데이터 갯수가 많아지면 200개만 보이지만, 스크롤 나타남 chart1.ChartAreas["draw"].AxisX.Minimum = 0; chart1.ChartAreas["draw"].AxisX.Maximum = (Count >= xCount) ? Count : xCount; if (Count > xCount) chart1.ChartAreas["draw"].AxisX.ScaleView.Zoom(Count - xCount, Count); else chart1.ChartAreas["draw"].AxisX.ScaleView.Zoom(0, xCount); if (++Count >= myData.Count) myTimer.Stop(); }
20
14. Chart에 스크롤바 달기 chart1.ChartAreas["draw"].CursorX.AutoScroll = true; chart1.ChartAreas["draw"].AxisX.ScaleView.Zoomable = true; chart1.ChartAreas["draw"].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll; chart1.ChartAreas["draw"].AxisX.ScrollBar.ButtonColor = Color.LightSteelBlue; // zoom을 위해 200개까지는 기본, 데이터 갯수가 많아지면 200개만 보이지만, 스크롤 나타남 chart1.ChartAreas["draw"].AxisX.Minimum = 0; chart1.ChartAreas["draw"].AxisX.Maximum = (myData.Count >= xCount) ? myData.Count : xCount; // change chart range : Zoom 사용 if (myData.Count > xCount) { chart1.ChartAreas["draw"].AxisX.ScaleView.Zoom (myData.Count - xCount, myData.Count); } else chart1.ChartAreas["draw"].AxisX.ScaleView.Zoom(0, xCount);
21
15. View All 과 Zoom 처리 // View All Button
private void button4_Click(object sender, EventArgs e) { chart1.ChartAreas["draw"].AxisX.Minimum = 0; chart1.ChartAreas["draw"].AxisX.Maximum = myData.Count; chart1.ChartAreas["draw"].AxisX.ScaleView.Zoom(0, myData.Count); chart1.ChartAreas["draw"].AxisX.Interval = myData.Count / 4; } // Zoom Button private void button5_Click(object sender, EventArgs e) chart1.ChartAreas["draw"].AxisX.ScaleView.Zoom(myData.Count - xCount, myData.Count); chart1.ChartAreas["draw"].AxisX.Interval = xCount / 4;
22
16. 시뮬레이션 시리얼 포트의 Data_Received() 이벤트 대신 1초에 한번씩 시간과 데이터를 myData에 저장한다
이를 위해 Timer를 하나 추가한다 아두이노가 없다면, 시리얼 통신 대신 랜덤 숫자를 만들어서 처리하자 private void 시작ToolStripMenuItem_Click(object sender, EventArgs e) { // 1초에 한번씩 현재 시간과 랜덤 값을 myData에 저장 timer2 = new Timer(); timer2.Interval = 1000; timer2.Start(); timer2.Tick += Timer2_Tick; } private void 끝ToolStripMenuItem_Click(object sender, EventArgs e) timer2.Stop(); private void Timer2_Tick(object sender, EventArgs e) { Random r = new Random(); int v = r.Next(1023); myData.Add(new sensorData(DateTime.Now, v)); …
Similar presentations