Sưu tầm tại: Điện tử Việt Nam
mình đang dùng atmega8 để đọc adc về, nhưng mình muốn đọc về 10 lần và lấy trung bình để chống nhiễu, vậy xin hỏi có ai đã từng làm về cái này rồi thì cho mình xin đoạn code nhe.thank
=>
Zinix: Cách tính giá trị trung bình như sau:
main
{
unsigned int count=0;
double sum=0;
….
….
if(count++<10)
{
sum += adc_data[..];
}
else
{
count=0;
adc_val=sum/10;// gia trị trung bình
sum=0;
}
…..
….
}
Nếu trường hợp giá trị trung bình vẫn chưa tốt trong điều kiện khắc khe ( chống nhiễu từ nguồn phát RF cao tần chẳng hạn…) thì bạn dùng thêm bộ digital filter như sau:
main
{
unsigned int count=0;
double sum=0;
float buff[2];
….
….
if(count++<10)
{
sum += adc_data[..];
}
else
{
count=0;
adc_val=sum/10;// gia trị trung bình
sum=0;
buff[1]=buff[0];
buff[0]=adc_val;
adc_val= adc_val -(adc_val-buff[0])*a0 -(adc_val-buff[1]) *a1;// digital filter.
}
delay_ms(…);//giá trị delay ảnh hưởng đến sự trễ pha..
}
Giải thích đơn giản cho digital filter là: giá trị lấy mẫu hiện tại thứ n không chỉ phụ thuộc vào thời điểm hiện tại mà còn phụ thuộc vào thời điểm n-1, n-2,…..Ví dụ ở thời điểm thứ n có nhiễu đột biến thi thành phần thứ n-1 và thứ n-2 trong biểu thức sẽ cân bằng lại ko cho nó tăng quá lớn, giảm nhiễu
Giá trị a0 va a1 bạn phải làm thực nghiệm ( 0<a0,a1<1)> Lưu ý là các phương pháp chống nhiễu như giá trị trung bình hay digital filter đều gây ra trễ pha (đáp ứng chậm hơn so với giá trị thưc tế).
Blackmoon: ADC cũng như các loại ngoại vi khác, cần có clock để có thể hoạt động.
Câu trích trên của bạn dịch ra rất rõ nghĩa mà. Mỗi lần chuyển đổi sẽ mất 13 chu kỳ clock. Tuy nhiên lần chuyển đổi đầu tiên sẽ mất 25 chu kỳ clock, lâu hơn vì cần thời gian để khởi tạo và ổn định các mạch điện bên trong ngay sau khi ADC được cho phép hoạt động (turn on, hay có thể coi là cấp nguồn) bằng cách đặt bit ADEN trong thanh ghi ADCSRA lên 1.
Việc delay giữa các lần lấy mẫu là do thuật toán của bạn, tức là bạn muốn lấy mẫu nhanh hay chậm, còn bản thân một chu kỳ chuyển đổi của ADC được tự động tính toán xử lý (người ta gọi là “timing”) bên trong nó, khi xong việc sẽ báo ra cờ bên ngoài. Trong suốt quá trình chuyển đổi, CPU (hay chính bạn) làm gì tùy thích.
Chestnut: Có một cách chống nhiễu nữa là dùng Runge-Kutta filter để lọc tín hiệu :
Đây là đoạn code mẫu mình viết dùng C :
for (i=0; i < 6; i++)
{
adc_filter_buffer[current_buf][i] = ADC16Ptr[i];
}
for (i=0; i < 6; i++)
{
adc_buf[i] = (adc_filter_buffer[current_buf][i]/6 +
adc_filter_buffer[(current_buf+1)%4][i]/6 +
adc_filter_buffer[(current_buf+2)%4][i]/3 +
adc_filter_buffer[(current_buf+3)%4][i]/3);
}
current_buf = (current_buf+1) % 4;