Задача такая: замер сигнала на 4х ногах ацп, пропуск каждого сигнала через "экспоненциальное скользящее среднее" с маленьким коэффициентом, и последовательная передача этих четырех значений в манчестер-коде с разделителем. Реализовано все на if(){}, так что код заифан чуть более, чем почти полностью.
Для передачи бита используются два манбита. В свою очередь... Короче, передача работает отлично. Вопрос в АЦП.
Когда я снимаю сигнал с переменного резистора, и подаю его на PA0, а другие каналы АЦП висят в воздухе - на них каким-то чудесным образом передается сигнал, приложенный к PA0. Я прекрасно понимаю, что многое насасывается из воздуха, да и 50Гц вполне может быть там... Стоит мне коснуться осциллографом к одному из висячих в воздухе каналов, так там сразу наводка уходит, и остается значение около 7-12 в относительных величинах (от 0 до 255). Если посчитать, то... напряжение опоры у меня примерно 5 вольт. Допустим, что 4.5 вольта. Не важно. 5000/256 = 19.5мВ на инкремент. То есть постоянно присутствует примерно 200 мВ. Если я замыкаю на землю висячий канал, то там все равно эти ~200мВ. Переменным резистором, в принципе, я тоже замыкаю на землю канал, когда выкручиваю его до упора.
Но это еще не все! Теперь подключаю другой переменный резистор к PA1. PA2 и PA3 вообще убираю из программы. То есть переключение идет между двумя каналами PA0 и PA1. Выставляю на PA1 максимум, кручу PA0, и смотрю при этом что на выходе фильтра (m1 эксп.скользящее среднее) порта PA1. По идее значения должны не меняться, т.к. каналы влиять друг на друга не должны. Да и по осциллографу питание не просаживается. Однако, если я уменьшаю сигнал на PA0 до 0, то у меня уменьшаются выходные значения PA1 на 10 значений (от 0 до 255).
Чего я только не пробовал: делал паузы, пропуск первых двух преобразований после переключения, изменял внутреннюю частоту АЦП, частоту семплов, отключал от схемы все что можно отключить. Однако влияние это оставалось, а на осциллографе никаких изменений, кроме небольшого изменения шума. Если брать Aref , которое у меня равно VCC=~5вольт, и разведенно по правилам, то шум этот имеет амплитуду ~10-20мВ относительно этих 5 вольт, а может и меньше. 10-20 мВ - это не 200мВ. И не видно, что шум этот меняется по амплитуде. В него просто добавляется какая-то фигня, которая по амплитуде не меняет шум.
Я использую отладочную плату, купленную по ebay. На AREF и AVCC конденсатор с обозначением 104 (100нФ или 10нФ?), на AVCC питание через дроссель с неизвестным номиналом. Порты все отключены от схемы, и сопротивление между ними более 200кОм. Питание от 7805. Вроде бы все по уму сделано.
Прошу помощи.
CODE
#include <avr/io.h>
#include <avr/interrupt.h>
#define bits 8
#define buffsize 4
#define freq_timer 1000
#define syncsize 8
#define syncperiod 4
#define shift 23
unsigned char c=256-(125000/freq_timer);
unsigned char sync[syncsize]={1,0,0,0,0,0,0,1};
unsigned char buff[buffsize]={0,0,0,0};
unsigned char a[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char m=0,st,st=0,count=0,prevbit=0,prevnbit=0,prevnbyte=0,nbyte=0,nbit=0;
long m0=0,m1=0,m2=0,m3=0,adcdata=0,g=0;
long k=625;
ISR(TIMER0_OVF_vect)
{
TCNT0=c;
ADCSRA|=0x40;
if ((ADCSRA & 0x10)==0){};
ADCSRA|=0x10;
adcdata=ADCH;
adcdata<<=shift;
//здесь считаем среднее и переключаем каналы
if (count<=17)
{
m0+=(adcdata-m0)/k;
if (count==17)
{
ADMUX=0x61;
ADCH=0;
buff[0]=m0>>shift;
}
}
if ((count>17)&&(count<=35))
{
m1=m1 + (adcdata-m1)/k;
if (count==35)
{
ADMUX=0x60;
ADCH=0;
buff[1]=m1>>shift;
}
}
/*if ((count>35)&&(count<=53))
{
m2=m2 + (adcdata-m2)/k;
if (count==53)
{
ADMUX=0x63;
ADCH=0;
buff[2]=m2>>shift;
}
}
if (count>=54)
{
m3=m3 + (adcdata-m3)/k;
if (count==71)
{
ADMUX=0x60;
ADCH=0;
buff[3]=m3>>shift;
}
}
//здесь реализована передача.
if (count<(syncperiod*16))
{
if (count&0x01)
{
if(buff[prevnbyte]&a[prevnbit])
{
PORTC=0;
}
else
{
PORTC=1;
}
}
else
{
if(buff[nbyte]&a[nbit])
{
PORTC=1;
}
else
{
PORTC=0;
}
prevnbit=nbit;
prevnbyte=nbyte;
nbit++;
if(nbit==8)
{
nbit=0;
nbyte++;
if (nbyte==buffsize){nbyte=0;}
}
}
}
if (count>=(syncperiod*16))
{
PORTC=sync[st];
st++;
if (st==(syncsize)){st=0;}
}
count++;
if (count==((syncperiod*16)+syncsize)){count=0;};
}
int main(void)
{
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0xFF;
PORTD=0x00;
DDRD=0xFF;
PORTB=0x00;
DDRB=0xFF;
ASSR=0x00;
TCCR0=0x03;
TCNT0=c;
OCR0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
TIMSK=0x01;
ACSR=0x80;
SFIOR=0x00;
ADCSRA=0x86;
ADMUX=0x60;
SPCR=0x00;
TWCR=0x00;
sei();
while (1)
{
}}