Мікроконтролер ARDUINO DUE має набагато більші можливості; як мінімум - 12-розрядний АЦП, котрий може працювати у повному диференційному режимі.
Передаюча частина зроблена по схемі Фішер CZ-5; катушка використана від Тесоро Cibola з переробленим кабелем; дане рішення має безліч недоліків (низький струм і, відповідно, поле; значний рівень 3 та 5 гармонік), тому в подальшому планую використати стандартну катушку від Фішер F75 з розкачкою за його схемою (в моделі - ідеально).
Прийомна частина теж зроблена по спрощеній схемі Фішер CZ-5 з додатковим фільтром НЧ на вході (бажано ще встановити "фільтр-пробку" на 3 гармоніку як у F75): Вихід аналогової частини дає змогу підключити її до АЦП в диференційному режимі, що при встановленні підсилення у 1 дасть нам додатковий біт інформації (?). Дане схемотехнічне рішення не є ідеальним, так як вихідний сигнал не є повністю протифазним (є кращі варіанти; найбільш оптимальний, але і найдорожчий - використання спеціалізованих ОУ). Для корекції фази використовується багатооборотний резистор, хоча більш оптимальним є програмний поворот вектора, так як це дає змогу уникнути впливу шуму від переключення ключа Тх на результат вимірювання.
Так як спочатку вимірювання проводились не в диференційному режимі, було прийнято рішення проводити заміри не 2 рази за період, а 4 з відніманням результатів; реалізувавши таким чином псевдодиференційний вхід та нівелювавши дрейф нуля.
Відповідно, частота переривань у два рази вища (40076 Гц для частоти 20038 Гц):
Код: Виділити все
TC0->TC_CHANNEL[0].TC_RC = 524; // Frequency = (Mck/2)/TC_RC/2 = 20038Hz
Код: Виділити все
void ADC_Handler(void)
{
intResultDif = ADC->ADC_CDR[6]; // отримання даних з АЦП
sensorValues[intSs][intCs] = intResultDif; // внесення даних в двомірний масив
//Формування меандру
if ( interruptCtr++ >= 1 ) // вимірювання кожні 90 градусів - 2 такти за період
{
interruptCtr = 0;
REG_PIOB_ODSR ^= 1 << 25; //переключити рівень 2 PWM виходу
}
if (intCs == 2) bolTact = true; // завершення періоду
if (intCs++ >= 3)
{
intCs = 0;
if (intSs++ >= 2)
{
intSs = 0;
}
}
// Дані для фільтру пікового шуму (медіанний фільтр на 3 значення)
....
- назначимо 13 контакт (порт В27) виходом
Код: Виділити все
PIOB->PIO_OER = 1 << 27; // Встановлюємо 2 контакт Arduino DUE як вихід (тільки для тесту синхронізації)
- в обробнику переривань після вимірювання тимчасово додамо команду на зміну рівня на 13 контакті
Код: Виділити все
void ADC_Handler(void)
{
intResultDif = ADC->ADC_CDR[6]; // отримання даних з АЦП
REG_PIOB_ODSR ^= 1 << 27; // переключити рівень 13 виходу (тільки для тесту синхронізації)
sensorValues[intSs][intCs] = intResultDif; // внесення даних в двомірний масив
А ось завади від переключення ключів можуть бути "захоплені" АЦП; тому, більш доцільним, на мою думку, буде зсунути фазу для вимірювання на 45 градусів і "поставити її на місце" помноживши отриманий результат на матрицю повороту. Вимірювання "Х" відбувається у точках "0" та "2", "У" - "1" та "3", котрі відповідають індексам у масиві.
Отримані результати поміщаються у двомірний масив і обробляються медіанним фільтром на 3 значення (краще на 5 або 6, але я не зайшов багатопотокової реалізації такого, і сам написати не можу ) та 4 потоки. Відфільтровані значення поміщаються у одномірний масив і уже в "тілі" програми розраховується значення Х та У:
Код: Виділити все
lngSX = intMiddle[0] - intMiddle[2] + lngSX;
lngSY = intMiddle[3] - intMiddle[1] + lngSY;
if (intS++ >= 511)
Код: Виділити все
Serial.println(90.00000 * lngSY / (lngSY + lngSX));
PS. В архіві скетч проекту та його лістинг в форматі doc.