Ðăng Nhập

View Full Version : Hỏi về ADC của PIC


zoos
16-03-2007, 09:13 PM
Các bạn trả lời giúp với:

1) Mình đang sử dụng ADC 10 bit của 18F4550 lấy tín hiệu vào từ kênh 0, dùng biến trở 100K mắc phân thế để tạo điện thế vào. Ngõ vào mắc thêm 2 diod 1 ngược xuống âm và 1 ngược lên dương, thêm 1 tụ 10uF và 1 tụ 0.01uF mắc xuống âm. Tụ với diod mắc thêm là để ổn định tín hiệu vào (mình mắc vào thấy nó ổn định hơn thật). Có thể giải thích tại sao ko?

2) Tuy nhiên khi đọc giá trị của ADC luôn dao động, khoảng 7-8 đơn vị. Dùng đồng hồ hiện số đo thử thì thấy tín hiệu ít dao động hơn so với số đọc trên ADC (tính thử thì thấy chỉ khoảng = 2 đơn vị ADC của PIC). Cho mình hỏi có cách nào để ADC của PIC lấy tín hiệu ổn định và ít dao động không?

Cảm ơn trước nha.

falleaf
23-03-2007, 06:38 AM
1) Dạng ổn định của bạn là dạng ổn định nguồn. Bạn nên mắc một mạch lọc thông thấp vào ngõ vào analog, để giảm các tần số cao, nhiễu...

2) Việc thiết kế mạch đọc ADC với bất kỳ vi điều khiển hay vi xử lý nào, cũng có nguyên tắc chạy mạch in của nó để đảm bảo tính ổn định của hệ thống. Cho nên bạn cần phải học thêm về cách chạy mạch in với ADC, và một số linh kiện đặc biệt, chứ không phải ADC là cứ nối vào mạch là chạy đâu. Với thiết bị ADC8bit thì mọi thứ có vẻ ổn, nhưng mà với các ADC10bit trở lên, thì bắt đầu có vấn đề với việc chạy mạch in.

Chúc vui.

vokihut
04-04-2007, 12:37 PM
Các bác cho em hỏi chút : em dùng 16F877A, cái Vref+ dùng 10V liệu có được k nhỉ, tại vì em cho cái Vref 10V ( từ TL431) vào chần 5 của 16F877A thì nó sụt xuống còn 5.7V, chả hiểu sao nữa, để lâu thì con TL431 toi luôn. Phần khai báo chắc cũng k ảnh hưởng gì chứ nhỉ :

#include <16F877A.h>
#device *=16 ADC=10
#fuses hs, NOWDT, NOPROTECT, NOLVP
#use delay(clock = 4000000)
......

void main() {
port_b_pullups(TRUE);
setup_adc_ports(AN0_AN1_AN4_VREF_VREF);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
set_timer0(5); setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_psp(PSP_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
.....
}

Tiện thể bác F cho em hỏi chút : bác có tài liệu nào nói về cách dạy đi mạch cho ADC không vậy, hoặc em có thể tìm đọc được ở đâu dc, em rất quan tâm đến cái này, mong bác giúp cho :)

namqn
04-04-2007, 08:14 PM
Các bác cho em hỏi chút : em dùng 16F877A, cái Vref+ dùng 10V liệu có được k nhỉ, tại vì em cho cái Vref 10V ( từ TL431) vào chần 5 của 16F877A thì nó sụt xuống còn 5.7V, chả hiểu sao nữa, để lâu thì con TL431 toi luôn. Phần khai báo chắc cũng k ảnh hưởng gì chứ nhỉ :

#include <16F877A.h>
#device *=16 ADC=10
#fuses hs, NOWDT, NOPROTECT, NOLVP
#use delay(clock = 4000000)
......

void main() {
port_b_pullups(TRUE);
setup_adc_ports(AN0_AN1_AN4_VREF_VREF);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
set_timer0(5); setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_psp(PSP_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
.....
}

Tiện thể bác F cho em hỏi chút : bác có tài liệu nào nói về cách dạy đi mạch cho ADC không vậy, hoặc em có thể tìm đọc được ở đâu dc, em rất quan tâm đến cái này, mong bác giúp cho :)
Các chân của PIC đều có bảo vệ bằng các diode. Điện áp cho phép đặt vào các chân không vượt quá ngưỡng phân cực thuận các diode này, đó là lý do mà điện áp ở chân VREF+ của bạn bị ghim ở 5.7 V.

Bạn xem lại cách dùng TL431, để tạo áp khoảng 5 V cho VREF+.

Thân,

vokihut
04-04-2007, 10:39 PM
Bác namqn nói vậy có nghĩa là Vref ADC của PIC chỉ có thể <=5V ? tệ thật , lại phải sửa mạch rùi :(

zero
20-05-2007, 11:33 PM
Bác F nói về việc chạy mạch in cho ADC để tránh nhiễu.
^^ vay tim tai lieu nay o dau vay? Tên nó là gì?

littlephoc
24-05-2007, 02:19 PM
Mình dùng PIC18F2620 và CCS compiler. Đoạn mã sau mình muốn nhận giá trị từ cổng input cho ADC từ tín hiệu bên ngoài:

#include <18F2620.h>
#DEVICE HIGH_INTS=TRUE
#DEVICE ADC=10
#include <STDLIB.H>
#include "mylib.h"
#fuses HS,NOWDT,NOPROTECT,LVP
#use delay(clock=8000000)
#use SPI(BITS=8)
#use rs232(BAUD=57600,parity=N,XMIT=PIN_C6, RCV=PIN_C7, bits=8)
void setup_node(){
// set_tris_a(0x0F);
set_tris_b(0xFF);
set_tris_c(0x90);
// --- setup SPI -------------------
setup_spi(SPI_MASTER |SPI_H_TO_L |SPI_CLK_DIV_4); //50ns
output_float(PIN_B0);
//-------- setup ADC ----------------
// Setup_port_a(AN0_TO_AN4);
Setup_ADC(ADC_clock_DIV_8);
Setup_ADC_ports(AN0_TO_AN4);
Set_ADC_channel(4);
delay_us(10);
// ---- enable interrupts ----------
enable_interrupts(INT_RDA);
ext_int_edge(H_TO_L);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
}
void main(void)
{
long value;
setup_node();
value=adc_read();

while(true){
}
}

Tín hiệu analog là điện áp có biên độ từ 0V-1.2V .
Không biết mình có setup sai chỗ nào không? giá trị nhận được không được đều cho lắm. Chẳng hạn cùng 1 điều kiện nhưng giá trị nhận được thay đổi từ 0-60 hoặc 160-180

namqn
24-05-2007, 08:04 PM
Mình dùng PIC18F2620 và CCS compiler. ...
Tín hiệu analog là điện áp có biên độ từ 0V-1.2V .
Không biết mình có setup sai chỗ nào không? giá trị nhận được không được đều cho lắm. Chẳng hạn cùng 1 điều kiện nhưng giá trị nhận được thay đổi từ 0-60 hoặc 160-180
Bạn nói đến biên độ của điện áp vào, tức là nó là một đại lượng thay đổi theo thời gian?

Khi bạn nói cùng 1 điều kiện và nhận được giá trị thay đổi trong các phạm vi khác nhau, điều kiện đó là gì?

ADC chỉ lấy mẫu và chuyển đổi điện áp tương tự thành giá trị số tương ứng.

Thân,

littlephoc
24-05-2007, 08:20 PM
Cái sensor node của mình gồm con PIC nhận tín hiệu RSSI từ transceiver (CC1000), tạm hiểu đại lượng này là sóng nhận được mạnh hay yếu giữa 2 cục sensor node khi truyền nhận dữ liệu cho nhau. Khi mình đưa 1 cục sensor ra xa hoặc gần lại với cục còn lại, cường độ tín hiệu sẽ thay đổi. Cùng một điều kiện ở đây là khoảng cách giữa 2 node không đổi, thì cường độ của tín hiệu là giống nhau.

namqn
25-05-2007, 12:21 AM
Cái sensor node của mình gồm con PIC nhận tín hiệu RSSI từ transceiver (CC1000), tạm hiểu đại lượng này là sóng nhận được mạnh hay yếu giữa 2 cục sensor node khi truyền nhận dữ liệu cho nhau. Khi mình đưa 1 cục sensor ra xa hoặc gần lại với cục còn lại, cường độ tín hiệu sẽ thay đổi. Cùng một điều kiện ở đây là khoảng cách giữa 2 node không đổi, thì cường độ của tín hiệu là giống nhau.
Tần số của sóng RF là quá cao so với tốc độ lấy mẫu của ADC, do đó bạn nhận được các kết quả khác nhau trong cùng điều kiện là điều có thể xảy ra.

Cường độ tín hiệu là một đại lượng lý thuyết, trong thực tế phải chuyển nó thành điện áp (tương đối ổn định theo thời gian) thì mới dùng với ADC được.

Bạn đưa tín hiệu vào ADC của PIC bằng cách nào?

Thân,

littlephoc
25-05-2007, 03:00 PM
dạ chân RSSI của CC1000 được nối trực tiếp với chân PIN_A5 của PIC8F2620.
đoạn mã setup em viết như sau:
Setup_ADC(ADC_clock_DIV_8);
Setup_ADC_ports(AN0_TO_AN4);
Set_ADC_channel(4);
delay_us(10);
Đọc manual của PIC18F2620 và file .h của 18F2620 thì với PIN_A5 <->AN4, channel là 4.
Do OSC là dao động thạch anh bên ngoài 8Mhz nên theo manual, em để ADC_clock_DIV_8 là tần số lấy mẫu.

namqn
25-05-2007, 07:46 PM
dạ chân RSSI của CC1000 được nối trực tiếp với chân PIN_A5 của PIC8F2620.
đoạn mã setup em viết như sau:
Setup_ADC(ADC_clock_DIV_8);
Setup_ADC_ports(AN0_TO_AN4);
Set_ADC_channel(4);
delay_us(10);
Đọc manual của PIC18F2620 và file .h của 18F2620 thì với PIN_A5 <->AN4, channel là 4.
Do OSC là dao động thạch anh bên ngoài 8Mhz nên theo manual, em để ADC_clock_DIV_8 là tần số lấy mẫu.
Theo datasheet của CC1000 thì chân RSSI sẽ tạo ra dòng điện DC thay đổi theo cường độ tín hiệu. Trong datasheet cũng đề cập đến tụ lọc và điện trở tải (1 nF và 27k), tôi tin là bạn đã có những linh kiện này trong mạch. Điện trở tải nhất định phải có và đúng giá trị để chuyển dòng điện thành điện áp.

Trước khi xác định ADC của PIC chạy đúng hay không, bạn nên kiểm tra tín hiệu tại chân RSSI của CC1000 bằng một dao động ký, để xem nó có thay đổi theo thời gian hay không, trong điều kiện là bạn không hề thay đổi điều kiện làm việc của CC1000. Nếu nó thay có thay đổi theo thời gian thì tốc độ đó có quá nhanh so với ADC của PIC hay không. ADC của PIC18F có tốc độ chuyển đổi tối đa khoảng 50 kSPS (50000 chuyển đổi/giây). Tín hiệu vào biến thiên với tần số cao hơn 20 kHz là không thích hợp cho ADC của PIC18F.

Chú ý là ADC_clock_DIV_8 của CCS là tốc độ xung clock cho giai đoạn chuyển đổi của module ADC. Việc chuyển đổi A/D bao gồm 2 giai đoạn chính: lấy mẫu tín hiệu và chuyển đổi tín hiệu. Khi lấy mẫu thì chỉ cần chờ 1 thời gian để tụ giữ (holding capacitor) nạp đến giá trị điện áp vào, khi chuyển đổi thì cần 12 xung clock cho dữ liệu 10-bit. Trong giai đoạn chuyển đổi thì tụ giữ sẽ được ngắt khỏi tín hiệu ngõ vào.

Thân,

zero
27-05-2007, 03:57 PM
Hic lạ quá cho em hỏi chút nhé.
Tôi thử đưa 2 tín hiệu
1. từ LM35 (Vout khoảng 0.2V)
2. Từ 1 biến trở (Vout khoảng 2.5V)
Vậy mà ko hiểu sao giá trị của tín hiệu 1 lớn hơn có ai biết xin trả lời dùm với
(Chương trình test nên còn nhiều RÁC)


#include <16F877A.h>
#DEVICE *=16 ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=12000000)

void main() {

int i, value, min, max;

setup_adc_ports(ALL_ANALOG);
// setup_adc_ports(ANALOG_RA3_REF);
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel(0);
set_tris_b(0);
set_tris_d(0);
set_tris_e(0);
// set_tris_d(0b00000010);
output_b(0xf);
output_d(0xff);
delay_ms(500);
output_b(0x0f);
delay_ms(1000);
output_e(7);
i=0;
// setup_vref(FALSE);
// setup_vref (VREF_HIGH | 8);

//while(D1());
while(1){
if(i)
i=0;
else
i=1;
output_e(i);

value = Read_ADC();
delay_ms(800);
output_b(value);
value=value>>8;
output_d(value);
}
}

truongqt
10-11-2012, 11:13 AM
Khối ADC trong PIC sẽ thay thế bằng khối lấy mẫu và giữ mẫu bậc mấy vậy? mình tập tành điều khiển nhiệt độ bằng PIC, đang mô hình hóa trong Matlab. không biết là 'zoh' hay 'foh' vậy nhỉ.

Mong các bác chỉ giáo.