![]() |
|
Tài trợ cho PIC Vietnam |
Giao tiếp USB, CAN, I2C, SPI, USART... Những giao tiếp được tích hợp trên PIC |
![]() |
|
Ðiều Chỉnh | Xếp Bài |
![]() |
#1 |
Đệ tử 1 túi
Tham gia ngày: Feb 2010
Bài gửi: 15
: |
Hỏi về cách lấy dữ liệu từ VDK trong c# đễ vẽ đồ thị.
Mình đang gặp khó khăn về vấn đề này. Mình không biết cách nào để nhận dữ liệu động, truyền từ VDK qua USB, sau đó vẽ lên c#. Mình dùng một timer(trong c#) để tạo thời gian lấy mẩu trên trục x, còn trục y là dữ liệu mình đọc từ VDK lên. Các bạn nào đã làm qua cái này rồi hướng dẫn cho mình với. Mình có tham khảo cái này, http://zedgraph.org/wiki/index.php?t...Real-Time_Data
Ý của mình là như thế này: Trong hàm vẽ mình sẽ khai báo: for (i = 0; i < 50; i++) { list1.Add(data_x[i], data_y0[i] ); list2.Add(data_x[i], data_y1[i] ); list3.Add(data_x[i], data_y2[i] ); } trong đó data_x[i] là biến thời gian lấy mẩu nằm trong hàm này: private void timer1_Tick( object sender, EventArgs e ) { } cái này thì chắc không khó, cái khó của mình là data_y phải là biến động lấy từ VDK, mà mình chưa biết phải làm như thế nào với nó. Hiện giờ thì mình đã truyền được nhiều byte lên máy tính qua USB rồi, nhưng mình cũng chưa suy nghĩ được phải khai báo như thế nào với cái data_y. Mong được giúp đỡ. |
![]() |
![]() |
![]() |
#2 |
Đệ tử 4 túi
Tham gia ngày: Aug 2008
Bài gửi: 89
: |
Bạn than khảo ứng dụng mẫu dùng ADC làm Oscilloscope trên PIC18F2550, ở đây dữ liệu nhận được từ VDK ko sử dụng timer mà dùng cơ chế event đọc bất đồng bộ từ USB. Cứ sau 1 thời gian nhất định thì sẽ có dữ liệu từ VDK gởi về PC, sau đó 1 event xảy ra và phần mềm sẽ vẽ lại, như vậy thời gian định thời là từ VDK:
http://www.picvietnam.com/forum/showthread.php?t=5071 Regards
__________________
Quang báo RG/RGB 6/8/12/16 bits màu Phone No: 0905.034.086 Email: lmquyen@gmail.com |
![]() |
![]() |
![]() |
#3 | |
Đệ tử 1 túi
Tham gia ngày: Feb 2010
Bài gửi: 15
: |
Trích:
|
|
![]() |
![]() |
![]() |
#4 |
Nhập môn đệ tử
Tham gia ngày: Mar 2010
Bài gửi: 4
: |
![]() chao tat ca cac ban :
mình muốn hỏi tất cả mọi người về cái mach thu âm thanh với tiêu chí như sau : thiết kế mạch thu âm thanh sử dụng micro ,rồi dùng pic điều khiển để thu tín hiệu âm thanh đó ghi vào ic nhớ (ROM)rồi phát trở lại ra loa.(trong mạch bắt buột phải dùng vi điều khiển ),ai biết hoặc đã từng làm thì vẽ cho mình với .Mình cảm ơn rất nhiều ai cho ta kiến thức là còn quý hơn cho vàng anhstanh |
![]() |
![]() |
![]() |
#5 |
Đệ tử 1 túi
Tham gia ngày: Mar 2010
Bài gửi: 14
: |
Mình cũng đang làm về vấn đề này. Mình không biết khi con pic18 truyền lên được c#, thì làm thế nào lấy được dữ liệu đó để đưa vào hàm vẽ đồ thị, chỉ biết được là giá trị đó hiển thị lên trên texbox.
Ví dụ như đoạn chương trình sau là hiển thị giá trị ADC từ VDK lên texbox khi ấn buttom: //Khi nhan nut "doc" thi`>>>>> truyen hai byte tu VDK len MT private void btdoc_Click(object sender, EventArgs e) { TraceMsg("Receiver:\r\n"); SingleReceiver(); } private void SingleReceiver() { usb_pipe_rev.SetContiguous(true); DWORD dwBuffSize = 2; byte[] buffer = new byte[2]; usb_pipe_rev.UsbPipeTransferAsync(true, 2, buffer, 0, 100000, new D_USER_TRANSFER_COMPLETION(Transfer_rev_Completion )); } private void Transfer_rev_Completion(pic18f4550_usb_Pipe pipe) { if (pipe.GetTransferStatus() == (DWORD)wdu_err.WD_STATUS_SUCCESS) { TraceMsg(DisplayHexBuffer(pipe.GetBuffer(), 2)); } else { TraceMsg("receiver failure!\r\n"); } } Như vậy thì dữ liệu đó nằm đâu, làm thế nào để lấy ra và vẽ đồ thì. Mong các bạn chỉ dùm cho mình, mình cũng chưa hiểu rỏ lắm. |
![]() |
![]() |
![]() |
#6 | |
Đệ tử 4 túi
Tham gia ngày: Aug 2008
Bài gửi: 89
: |
Trích:
Do đó, sau khi nhấp button, sẽ có 1 request 'chờ' dữ liệu và khi dữ liệu này 'đến' nó được USB PIPE đọc tự động, đưa vào buffer và gọi hàm callback Transfer_rev_Completion xử lý buffer đó. Chính xác nó là 1 thread thực thi ngầm do Hệ điều hành quản lý để giám sát dữ liệu in trên PIPE. Thực ra library mà bạn dùng này nó đã 'che' phần thao tác in/out trên USB PIPE nên bạn không thấy được luồng dữ liệu được đưa vào buffer như thế nào. Thông qua phương thức GetBuffer() bạn sẽ lấy được dữ liệu đã trên PIPE cho phần xử lý của mình mà thôi. PS: Vì hàm callback Transfer_rev_Completion được gọi từ thread giám sát PIPE nên nếu bạn muốn thực hiện câu lệnh vẽ, hiện thị, thay đổi giá trị lên forms, components,... bên trong hàm này thì nhớ phải sử dụng cơ chế Invoke. Regards
__________________
Quang báo RG/RGB 6/8/12/16 bits màu Phone No: 0905.034.086 Email: lmquyen@gmail.com |
|
![]() |
![]() |
![]() |
#7 |
Đệ tử 1 túi
Tham gia ngày: Mar 2010
Bài gửi: 14
: |
mình đã vẽ được ba đồ thị cùng mọt lúc trong c#, cập nhập liên tục khi giá trị ADC ở VDK thay đôi.
Code như thế này: //khai báo biến toàn cục public ushort[] data_y0;// du lieu truc y public ushort[] data_y1; public ushort[] data_y2; ..................... Khi ấn nút btlisten, thì sẽ thực hiện việc đọc liên tục sau mỗi 'polling time', máy tính sẽ quét và đọc dữ liệu từ usb driver. void btlisten_Click(object sender, EventArgs e) { data_y0 = null; data_y0 = null; data_y1 = null; SingleTransfer(); Listen_pipe(); } private void Listen_pipe() { //-------------------- DWORD dwOptions = 0;// usb_pipe_rev.SetContiguous(true); // khi ham nay kich hoat thi cu sau moi polling time thi computer se quet va doc du lieu tu usb device TraceMsg(string.Format("began listening to {0} pipe number " + "0x{1:X}", usb_device.DeviceDescription(), usb_pipe_rev.GetPipeNum())); usb_pipe_rev.UsbPipeTransferAsync(true, 0, TIME_OUT, new D_USER_TRANSFER_COMPLETION(Transfer_rev_Completion )); } //---------------- sau đó hàm Transfer_rev_Completion mình sẽ lấy dữ liệu ra để vẻ: private void Transfer_rev_Completion(DOAN_MINH_THUONG_Pipe pipe) { DWORD dwStatus = pipe.GetTransferStatus(); byte[] buff; bool IsListenStopped = (dwStatus == (DWORD)wdu_err.WD_IRP_CANCELED) && !pipe.IsContiguous(); if (dwStatus != (DWORD)wdu_err.WD_STATUS_SUCCESS && !IsListenStopped) { ErrMsg(string.Format("Transfer Failed! Error {0}: {1} ", dwStatus.ToString("X"), utils.Stat2Str(dwStatus))); } else { TraceMsg(DisplayHexBuffer(pipe.GetBuffer(), 3)); buff = pipe.GetBuffer();//hàm này sẽ lấy dữ liệu từ ống pipe // TraceMsg(string.Format("{0}", // DisplayHexBuffer(buff,pipe.GetBytesTransferred())) ); // ham pipe.getbuffer tra ve 1 mang chua cac gia tri nhan dc tu usb // ham getbytes transferred tra ve so byte nhan duoc time++; //data_x[time] = time; data_y0[time] = (ushort)(buff[0] ); data_y1[time] = (ushort)(buff[1]); data_y2[time] = (ushort)(buff[2]); } //Hàm vẽ khi ấn nút btplot private void btplot_Click(object sender, EventArgs e) { CreateGraph(zedGraphControl1 ); SetSize(); } private void CreateGraph(ZedGraphControl zgc) { timer1.Interval = 50; timer1.Enabled = true; timer1.Start(); /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// // get a reference to the GraphPane GraphPane myPane = zgc.GraphPane; double v_desire = 120; // Set the Titles myPane.Title.Text = "Đọc gia trị ADC"; myPane.XAxis.Title.Text = "Time ( đơn vị : 10 ms )"; myPane.YAxis.Title.Text = "ADC "; myPane.XAxis.MajorGrid.IsVisible = true; myPane.YAxis.MajorGrid.IsVisible = true; myPane.YAxis.Scale.MagAuto = false; myPane.XAxis.Scale.MagAuto = false; myPane.XAxis.Scale.Mag = 1; // Make up some data arrays based on the Sine function // Make up some data arrays based on the Sine function PointPairList list1 = new PointPairList(); PointPairList list2 = new PointPairList(); PointPairList list3 = new PointPairList(); LineItem myCurve1 = myPane.AddCurve("ADC 1", list1, Color.Blue, SymbolType.None); LineItem myCurve2 = myPane.AddCurve("ADC 2", list2, Color.Green, SymbolType.None); LineItem myCurve3 = myPane.AddCurve("ADC 3", list3, Color.Tomato, SymbolType.None); //LineItem myCurve2 = myPane.AddCurve("ADC 2", list3, Color.Green, SymbolType.None); //LineItem myCurve3 = myPane.AddCurve("ADC 3", list8, Color.Red, SymbolType.None); myCurve1.Line.IsSmooth = true; myCurve1.Line.SmoothTension = 0.5F; //--------- myCurve2.Line.IsSmooth = true; myCurve2.Line.SmoothTension = 0.5F; //-------- myCurve3.Line.IsSmooth = true; myCurve3.Line.SmoothTension = 0.5F; //myCurve3.Line.IsSmooth = true; // myCurve3.Line.SmoothTension = 0.5F; myCurve1.Line.Width = 2; myCurve2.Line.Width = 2; myCurve3.Line.Width = 2; //myCurve3.Line.Width = 2; //myCurve_desire.Line.Width = 2; zgc.AxisChange(); //RollingPointPairList list2 = new RollingPointPairList(120); // instead of discrete step-sized jumps myPane.XAxis.Scale.Min = 0; myPane.XAxis.Scale.Max = 30; myPane.XAxis.Scale.MinorStep = 1; myPane.XAxis.Scale.MajorStep = 5; // Save the beginning time for reference tickStart = Environment.TickCount; } private void timer1_Tick(object sender, EventArgs e)//để tạo thời gian và lấy mẩu { if (zedGraphControl1.GraphPane.CurveList.Count <= 0) return; LineItem curve1 = zedGraphControl1.GraphPane.CurveList[0] as LineItem; if (curve1 == null) return; LineItem curve2 = zedGraphControl1.GraphPane.CurveList[1] as LineItem; if (curve2 == null) return; LineItem curve3 = zedGraphControl1.GraphPane.CurveList[2] as LineItem; if (curve3 == null) return; IPointListEdit list1 = curve1.Points as IPointListEdit; IPointListEdit list2 = curve2.Points as IPointListEdit; IPointListEdit list3 = curve3.Points as IPointListEdit; if (list1 == null) return; if (list2 == null) return; if (list3 == null) return; double time1 = (Environment.TickCount - tickStart) / 1000.0; // 3 seconds per cycle list1.Add(time1, data_y0[time]); list2.Add(time1, data_y1[time]); list3.Add(time1, data_y2[time]); Scale xScale = zedGraphControl1.GraphPane.XAxis.Scale; if (time1 > xScale.Max - xScale.MajorStep) { xScale.Max = time1 + xScale.MajorStep; xScale.Min = xScale.Max - 30.0; } zedGraphControl1.AxisChange(); zedGraphControl1.Invalidate(); } Nhưng ở đây mình chỉ vẽ được 3 ADC 8bit(max=255), giờ mình muốn vẽ ADC 10bit thì làm thế nào. VDK chi gửi lên được 8bit một lần(gửi nhiều byte). Như vậy thì đối với chương trình CCS thì phải cắt ra để gửi, một byte chứa 8bit, con một byte chứa 2bit, thuật toán cắt sẻ như thế nào, các bạn nào biết chỉ mình với. Giả sử như mình gửi được rồi thì trên C# mình cũng phải có thuật toán ghép chuổi lại, chứ không thể nào cộng hai byte đó lại được. Như thế thì thuật toán trong c# cũng là vấn đề. mong các bạn biết và chỉ dùm. |
![]() |
![]() |
![]() |
#8 |
Đệ tử 4 túi
Tham gia ngày: Aug 2008
Bài gửi: 89
: |
Rất đơn giản thôi bạn ah, trên C bạn dùng struct lưu 3 số integer 16 bit để chứa dữ liệu
Code:
typedef struct{ unsigned int16 ADC0; unsigned int16 ADC1; unsigned int16 ADC2; } USBAdc; Còn trên C# bạn làm việc ngược lại, khai báo 1 struct hoặc class tương ứng nhưng nhớ dùng thêm chỉ thị alignment từng byte 1(để đảm bảo đúng thứ tự dữ liệu): Code:
using System.Runtime.InteropServices; ... [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public class USBAdc { public UInt16 ADC0; public UInt16 ADC1; public UInt16 ADC2; .... static public USBAdc FromByteArray(byte[] byte_Array) { USBAdc ret; GCHandle handle = GCHandle.Alloc(byte_Array, GCHandleType.Pinned); ret = (USBAdc)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(USBAdc)); handle.Free(); return ret; } } Code:
USBAdc adc= USBAdc.FromByteArray(usb_array_data); ... adc.ADC0 adc.ADC1 adc.ADC2
__________________
Quang báo RG/RGB 6/8/12/16 bits màu Phone No: 0905.034.086 Email: lmquyen@gmail.com |
![]() |
![]() |
![]() |
#9 |
Đệ tử 1 túi
Tham gia ngày: Mar 2010
Bài gửi: 14
: |
Cảm ơn anh, em sẻ nghiên cứu thuật toán của anh nói, có gì mới em sẻ hồi âm lại.
Chào anh! |
![]() |
![]() |
![]() |
#10 |
Nhập môn đệ tử
Tham gia ngày: Mar 2010
Bài gửi: 1
: |
Anh cskiiler !Anh có thể nói rõ hơn về cách truyền ADC 10 bit lên máy tính thông qua USB được không?Em cảm ơn Anh.
__________________
Chúc một ngày vui vẻ! |
![]() |
![]() |
![]() |
#11 |
Đệ tử 1 túi
Tham gia ngày: Feb 2010
Bài gửi: 15
: |
Theo mình nghỉ thì như thế này, mổi ADC 10bit chia thành 2 byte:
unsigned int16 value, value1,value2; //----------------- value=read_adc(); value1=value&255;//max cua vlue1 la 255 value2=value&768;//max cua value2 la 768, nhu vay thi > 255=1byte delay_ms(20); //value1+value2=1023 Sau đó truyền hai byte đó lên, nhưng không biết value2 có thể truyền được không bởi vì nó lớn hơn 255. Như vậy phải giải quyết như thế nào, mong anh cskiller có thể giúp đỡ được không a.? |
![]() |
![]() |
![]() |
#12 | |
Đệ tử 1 túi
Tham gia ngày: Mar 2010
Bài gửi: 14
: |
Trích:
unsigned int16 value, value1,value2; //----------------- value=read_adc(); value1=value&255;//max cua vlue1 la 255 value2=value&768;//max cua value2 la 768, nhu vay thi > 255=1byte delay_ms(20); //value1+value2=1023 Đoạn chương trình trên bạn sẻ gửi lên 2 byte là value1 và value2/256 Trên c# bạn sẻ nhận lai 2 byte đó như sau: ADC10bit=value1+value*256; OK! |
|
![]() |
![]() |
![]() |
#13 | |
Đệ tử 1 túi
Tham gia ngày: Mar 2010
Bài gửi: 14
: |
Trích:
unsigned int16 value, value1,value2; //----------------- value=read_adc(); value1=value&255;//max cua vlue1 la 255 value2=value&768;//max cua value2 la 768, nhu vay thi > 255=1byte delay_ms(20); //value1+value2=1023 Đoạn chương trình trên bạn sẻ gửi lên 2 byte là value1 và value2/256 Trên c# bạn sẻ nhận lai 2 byte đó như sau: ADC10bit=value1+value2*256; OK! |
|
![]() |
![]() |
![]() |
#14 |
Đệ tử 4 túi
Tham gia ngày: Aug 2008
Bài gửi: 89
: |
Như bạn tbk_05 đã giải quyết là cách cơ bản và dễ dàng nhất, cắt số integer 16bits chứa giá trị ADC 10bits sau đó ghép lại phía nhận.
Tuy nhiên cách này làm thủ công bằng tay nên khá mệt và dễ lộn xộn. Cách mình trình bày trên sẽ dễ dàng truyền nhận ko chỉ số integer 16 bits mà còn có thể áp dụng cho số 32 bits, các kiểu dữ liệu khác hoặc là 1 struct phức tạp. Giả sử như với khai báo trên, phía VDK bạn đọc 3 kênh ADC sau đó gởi vào USB: Code:
set_adc_channel(0); adc.ADC0=read_adc(); // 100 set_adc_channel(1); adc.ADC1=read_adc(); // 200 set_adc_channel(2); adc.ADC2=read_adc(); // 300 ... usb_put_data((char*)&adc,sizeof(USBAdc)) // Giả sử gởi array là 6 bytes Code:
USBAdc adc= USBAdc.FromByteArray(usb_byte_array); ... TextBox0.Text = adc.ADC0; // Giá trị sẽ là 100 TextBox1.Text = adc.ADC1; // Giá trị sẽ là 200 TextBox2.Text = adc.ADC2; // Giá trị sẽ là 300 ... Bạn có thể mở rộng hơn 6 bytes hoặc thêm bớt các thành phần, biến, cấu trúc dữ liệu khác cho khai báo USBAdc, miễn sao đảm bảo đúng thứ tự và cấu trúc tương ứng 1 gói giữa C/VDK và C#/PC là ok. Regards
__________________
Quang báo RG/RGB 6/8/12/16 bits màu Phone No: 0905.034.086 Email: lmquyen@gmail.com |
![]() |
![]() |
![]() |
#15 |
Nhập môn đệ tử
|
Anh cskiier!Sau khi vẻ được đồ thị trên C# rồi.Làm sao để lưu những gì trị vẻ đó vào file .txt.Gồm 2 thành phần là thời gian và giá trị vi điều khiển đọc được.Nhờ Anh chỉ dùm.Em cảm ơn Anh!!!!
__________________
letanminhqn@gmail.com |
![]() |
![]() |
![]() |
Ðiều Chỉnh | |
Xếp Bài | |
|
|