реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> AVR и дифф сигналы, как правильно измерить?
ivainc1789
сообщение Oct 24 2007, 13:50
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Собрал простую схемку и измерил мультиметром VC9808+ разность ADC4-ADC3=-7mV. Далее попробовал измерить разность напряжений делителей двумя способами: измерить сигналы как single ended и differential с внутренним усилителем с Ку=1. Первый способ стабильно дает правильный результат в 7 милливольт (по модулю). А со вторым проблемы, АЦП возвращает чаще всего 0x3FF, что "в переводе с биполярного режима" равно -1. Получить -7 никак не удается даже произведя 10 измерений и взяв среднее. Где может быть ошибка?

Прикрепленное изображение


Код
unsigned int AdcResult;

__C_task void main (void) {
  unsigned char i;
  unsigned long AdcSumma=0;
  unsigned int tmp1;  
  ADCSRA = BIN(10010110); // 125kHz,Fosc=8MHz
  ADCSRB = BIN(10000000); // bipolar mode
  DIDR0 = BIN(11111111);  // digital inputs disable
  DIDR1 = BIN(11110000);  
  ADMUX = BIN(10010011);  // (ADC4-ADC3)*1
  Delay(500*ms);// wait for ADC stable
  for(i=0;i<10;i++){// get 10 conversions
    SETBIT(ADCSRA,ADSC);while(CHKBIT(ADCSRA,ADSC));
    AdcSumma += ADC;
  }
  AdcResult = AdcSumma/10;
  
  while(1);
}
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 24 2007, 14:11
Сообщение #2


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Надо оцифровать разность при подключении к одному и тому же каналу - ADC3-ADC3 - и запомнить напряжение смещения нуля внутреннего диффусилителя, потом его вычитать из кода.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Oct 24 2007, 14:36
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Цитата(ReAl @ Oct 24 2007, 18:11) *
Надо оцифровать разность при подключении к одному и тому же каналу - ADC3-ADC3 - и запомнить напряжение смещения нуля внутреннего диффусилителя, потом его вычитать из кода.


Да, я измерил в биполярном режиме (ADC3-ADC3)*20 (измерить при таком подключении делителей можно только так). ADC вернул +3. Т.е. ИМХО ошибка очень мала, если ее еще на 20 разделить. Ведь при исходном измерении Ку=1.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 25 2007, 10:41
Сообщение #4


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(ivainc1789 @ Oct 24 2007, 12:50) *
Собрал простую схемку и измерил мультиметром VC9808+ разность ADC4-ADC3=-7mV. Далее попробовал измерить разность напряжений делителей двумя способами: измерить сигналы как single ended и differential с внутренним усилителем с Ку=1. Первый способ стабильно дает правильный результат в 7 милливольт (по модулю). А со вторым проблемы, АЦП возвращает чаще всего 0x3FF, что "в переводе с биполярного режима" равно -1. Получить -7 никак не удается даже произведя 10 измерений и взяв среднее. Где может быть ошибка?

Разрешение в Bipolar Differential Conversion уменьшается в два раза, так что вы должны получить -3, а не -7.

Ошибка у вас в том, что тип AdcSumma беззнаковая переменная, а результат из регистра ADC вы читаете, как знаковый. Сделайте AdcSumma знаковой и будет вам щастье.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Oct 25 2007, 16:17
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Цитата(=GM= @ Oct 25 2007, 14:41) *
Разрешение в Bipolar Differential Conversion уменьшается в два раза, так что вы должны получить -3, а не -7.


Затупил smile.gif ... А я все думаю, почему в макете все дифф измерения ровно в два раза меньше чем ожидается. Большое спасибо, что нашли время ответить.
Вот только с ошибкой усилителя есть вопрос (ADC возвращает ADCe == +3 для (ADC3-ADC3)*20). Правильно ли будет ее вычесть из результата так: Result = 2*((ADC4-ADC3)*20 - ADCe)?
Да, в коде ошибка, спасибо... Осознал!
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 25 2007, 22:46
Сообщение #6


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(ivainc1789 @ Oct 25 2007, 16:17) *
Затупил smile.gif ... А я все думаю, почему в макете все дифф измерения ровно в два раза меньше чем ожидается. Большое спасибо, что нашли время ответить.
Вот только с ошибкой усилителя есть вопрос (ADC возвращает ADCe == +3 для (ADC3-ADC3)*20). Правильно ли будет ее вычесть из результата так: Result = 2*((ADC4-ADC3)*20 - ADCe)?
Да, в коде ошибка, спасибо... Осознал!

Ну, если считать, что смещение линейно, то Result = 2*(ADC4-ADC3) - ADCe/10.0


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Oct 26 2007, 05:57
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Цитата(=GM= @ Oct 26 2007, 02:46) *
Ну, если считать, что смещение линейно, то Result = 2*(ADC4-ADC3) - ADCe/10.0


Разве не так: 2*((ADC4-ADC3) - ADCe)/10.0
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 26 2007, 09:29
Сообщение #8


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(ivainc1789 @ Oct 26 2007, 04:57) *
Разве не так: 2*((ADC4-ADC3) - ADCe)/10.0

Ну вы ж вроде меряли ADC4-ADC3 при Ку=1, а ADCe с Ку=20.

(Замечу в скобках, если вы подставите ваши данные в вашу формулу, 2*((ADC4-ADC3) - ADCe)/10.0, то получите (2*(-3)-3)/10=-0.9, что явно неверно, должно быть в районе 6..7)


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Oct 26 2007, 21:25
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Код модифицировал так:
Код
signed int AdcResult;
__C_task void main (void) {
  unsigned char i;
  signed long AdcSumma=0;
  signed int tmp1;  
  ADCSRA = BIN(10010110); // 125kHz,Fosc=8MHz
  ADCSRB = BIN(10000000); // bipolar mode
  DIDR0 = BIN(11111111);  // digital inputs disable
  DIDR1 = BIN(11110000);  
  ADMUX = BIN(10010011);  // (ADC4-ADC3)*1
  Delay(500*ms);// wait for ADC stable
  for(i=0;i<10;i++){// get 10 conversions
    SETBIT(ADCSRA,ADSC);while(CHKBIT(ADCSRA,ADSC));
    tmp1 = ADC;
    if (CHKBIT(tmp1,9))tmp1|= 0xFC00;
    AdcSumma += tmp1;
  }
  AdcResult = AdcSumma/10;  
  while(1);
}

Результаты измерений в целом:
(ADC3-ADC3)*20=ADCe=+3;
(ADC4-ADC3)*1=-1;
Смотрел через EEPROM все 10 значений как unsigned int - там большинство результатов 0x3FF, реже 0x000. Округление конечного результата при делении на 10 дает существенную ошибку. Если смотреть на формулу Result = 2*(ADC4-ADC3) - ADCe/10.0 то искомого результата (-3) чуть-чуть не получается... Если следовать общей формуле биполярного режима ADC = (ADC4-ADC3)*512*GAIN/Vref, то уверенно должно возвращаться (-3.2). Вижу необходимость переходить к float. Верно ли?
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 27 2007, 08:03
Сообщение #10


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(ivainc1789 @ Oct 26 2007, 23:25) *
AdcResult = AdcSumma/10;
...
Округление конечного результата при делении на 10 дает существенную ошибку.
Вижу необходимость переходить к float. Верно ли?

Смотря какая ошибка устроит.
"простое" деление в С происходит с отбрасыванием остатка, а не с округлением к ближайшему.
Надо так (тут предполагаем, что N положительно, что справедливо при усреднении)
Код
averaged_A =  (A < 0 ?  A - N/2 : A + N/2 ) / N;
// или более по-паскальному
if( A < 0 )
    averaged_A =  (A - N/2) / N;
else
    averaged_A =  (A + N/2) / N;

Это уменьшает ошибку и может оказаться достаточно.
Можно также воспользоваться числами с фиксированной точкой, например, 13.3 (13 бит до точки, три после, дискретность представления числа 1/8).
Тогда при простом суммировании восьми отсчётов с АЦП в 16-битной целочисленной переменной мы получаем их среднее значение в формате 13.3 без никаких делений smile.gif, и ещё остаётся запас разрядности "сверху", от переполнения, так как отсчёты АЦП 10-битные.
Далее взяв очередной отсчёт и умножив его на 8 (сдвинув влево на 3) мы отнимаем от него то "среднее" и получаем отклонение от среднего в том же формате 13.3
Суммировение чисел с фиксированной точкой между собой производится так же, как и целых (толи 13.3, толи 16.0 - какая разница, главное помнить положение точки). Множатся и делятся на целые тоже "обычно", просто запас точности есть.
Вопросы возникают при умножении и делении чисел с фиксированной точкой между собой, так как при умножении (13.3) * (13.3) выходит (25.6) и нужно сдвинуть на 3 бита вправо, чтобы опять вышло .3
Но можно и к плавающей перейти, особенно если в 16 бит точно не лезет и в алгоритме много умножений или делений не на константу - эти операции у AVR что с long, что с float работает с приблизительно одинаковой скоростью (точнее, медленностью), так как 32-битной целочисленной арифметики у него всё равно нет, работа с отличается отсутствием необходимости в выравниваниях/нормировках для long и меньшей длиной мантиссы для float.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 27 2007, 14:04
Сообщение #11


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(ivainc1789 @ Oct 26 2007, 21:25) *
Код
signed int AdcResult;
. . . . .
  for(i=0;i<10;i++)
  {
   SETBIT(ADCSRA,ADSC);while(CHKBIT(ADCSRA,ADSC));
   tmp1 = ADC;
   if (CHKBIT(tmp1,9)) tmp1|=0xFC00;
   AdcSumma += tmp1;
  }
  AdcResult = AdcSumma/10;  
  while(1);
}

Оператор if(CHKBIT(tmp1,9)) tmp1|=0xFC00; здесь использовать нельзя, уберите.
Понятно и ёжику, что для усреднения надо сложить 10 результатов измерений, неважно положительные они или отрицательные, и поделить на 10, а вы вдруг хотите сделать все слагаемые положительными. С какого припрыгу?
Цитата(ivainc1789 @ Oct 26 2007, 21:25) *
Смотрел через EEPROM все 10 значений как unsigned int - там большинство результатов 0x3FF, реже 0x000
Ничего не понимаю. Если у вас -7 мВ на входе, то код должен быть равен -3 или 0хFFFD.

Цитата(ivainc1789 @ Oct 26 2007, 21:25) *
Вижу необходимость переходить к float. Верно ли?
А что это вам даст? Сначала получите reasonable значения в целых числах.

Вообще, для получения хорошей точности надо бы слабые диффсигналы мерять с Ку=20 или даже Ку=32, потом поделить на 20 или 32, заодно учесть смещение. А смещение, кстати, лучше мерять непосредственно перед измерением диффсигнала.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Oct 27 2007, 17:16
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Цитата(=GM= @ Oct 27 2007, 18:04) *
Оператор if(CHKBIT(tmp1,9)) tmp1|=0xFC00; здесь использовать нельзя, уберите.
а вы вдруг хотите сделать все слагаемые положительными. С какого припрыгу?


Данная операция является попыткой перейти от знакового 10 р. значения ADC к обычному знаковому int путем размножения знака влево... Не ВСЕ слагаемые делаются положительными, как вы говорите, а только 10р. отрицательные становятся 16р. отрицательными...

Цитата
Ничего не понимаю. Если у вас -7 мВ на входе, то код должен быть равен -3 или 0хFFFD.


В том то и дело, что результат получен (-1=0xFFFF) и то, если принять меры к обеспечению округления не отбрасыванием остатка а до ближайшего целого, т. к. в выборке из 10-ти значений ВСЕГДА присутствует один 0x0000, остальные 0xFFFF. Отчего такая ошибка сказать затруднительно, особенно на фоне вполне корректного измерения single ended.

Цитата
А что это вам даст? Сначала получите reasonable значения в целых числах.


Согласен. Только вот вариантов источника ошибки больше не видится. АЦП работает на корректной частоте, настройки вроде все верные, меняем только значение ADMUX. Single ended результат подтверждает показания мультиметра, что доказывает исправность входных цепей....

Цитата
А смещение, кстати, лучше мерять непосредственно перед измерением диффсигнала.


Согласен, но помимо смещения есть еще погрешность резисторов в делителях. Например, у меня в зарядном устройстве измеряется сигнал на токоизмерительном резисторе, делители подключены к нему. Для учета этой ошибки нужно подать одинаковое напряжение на сами делители, и это требует "откл" тока токоизмерительного резистора, а это может быть недопустимо. Поэтому такая ошибка измеряется только на старте программы один раз...
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 27 2007, 18:46
Сообщение #13


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(ivainc1789 @ Oct 27 2007, 17:16) *
Согласен, но помимо смещения есть еще погрешность резисторов в делителях. Например, у меня в зарядном устройстве измеряется сигнал на токоизмерительном резисторе, делители подключены к нему. Для учета этой ошибки нужно подать одинаковое напряжение на сами делители, и это требует "откл" тока токоизмерительного резистора, а это может быть недопустимо. Поэтому такая ошибка измеряется только на старте программы один раз...

Погрешность резисторов это отдельная песня, не надо бежать впереди паровоза. Начинать надо с ошибки смещения. Для её учёта при измерении диффсигналов надо измерить смещение, выбрав один и тот же канал, и непосредственно после этого измерить диффсигнал, затем вычесть смещение из полученного значения. Вообще, снимите график зависимости кода АЦП от диффсигнала, и всё увидите.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Oct 27 2007, 23:56
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Так сказать, ура! Действительно, нужно было мерять (ADC4-ADC3)*20 и такое измерение возвращает у меня -64 !!! Модифицировал код для получения округленных результатов к ближайшему целому. Теперь я добился абсолютно одинаковых показаний двух методов измерений!!! Как я понял, из-за падения разрешения сигнал оказался слишком слабым для использования дифф метода.

Анализируя формулу Result = 2*(ADC4-ADC3) - ADCe/10.0 и требуемую точность видим, что ошибка смещения (ADC3-ADC3)*20=ADCe=+3 слишком мала и вроде как ею можно пренебречь, не так ли? Правда наверно стоит учитывать разброс этого значения между разными ИС?
Go to the top of the page
 
+Quote Post
=GM=
сообщение Oct 28 2007, 20:10
Сообщение #15


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(ivainc1789 @ Oct 27 2007, 23:56) *
Анализируя формулу Result = 2*(ADC4-ADC3) - ADCe/10.0 и требуемую точность видим, что ошибка смещения (ADC3-ADC3)*20=ADCe=+3 слишком мала и вроде как ею можно пренебречь, не так ли? Правда наверно стоит учитывать разброс этого значения между разными ИС?

3/64=5%. Сами решайте, можно пренебречь или нет. А в общем, поздравляю с победой!


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 00:02
Рейтинг@Mail.ru


Страница сгенерированна за 0.01586 секунд с 7
ELECTRONIX ©2004-2016