Всем искателям и электронщикам доброго дня
Исходный Трекер код от Вячеслава Ветрова.
Код:
//Металлоискатель Трекер ПИ2 ака 8042 - на основе прошивки V 1.0b
//--no_cross_call - ОБЯЗАТЕЛЬНО!!!
#include <ioavr.h>
#include <intrinsics.h>
#include <stdio.h>
#include <stdlib.h>
#include "ina90.h"
#include "lcd.h"
#include "timeout.h"
#include "hardware.h"
#include "global_var.h"
#define START_DELAY 240 // 240 милисекунд R14 х С3 для установления режимов усилителя по постоянному току
#define UTC_DELAY_1 6 // 6 мкС
#define UTC_DELAY_2 6 // 6 мкС
#define baudrate 38400 //156248 //38400
#define ENABLE_LCD // если включено (define) светодиоды не используются только ЖКИ
#define ENABLE_SOUND
#define ENABLE_USART
#define AVERAGE_FILTER // усредняющий и помехоподавляющий фильтр
//#define USE_BATTERY_METER // не использовать пин для измерения степени разряженности аккума
#define USE_MANUAL_TIME_TX // задать время накачки вручную - для особо крутых датчиков
#define ManualTimeTX 0x75 //Tx= 117 мкС
#define BoardV3 // если на плате 3 версии находятся ускоряющие конденсаторы 470н и открывающий вспомогательный транзистор в драйвере полевика
#ifdef BoardV3 // если есть ускоряющие конденсаторы от 470н то нужен новы ускоренный тайминг за 5мкС
#define CAP_BOOST_TIME 5//5мкС
#define TIME_GUARD 0x0c // защитный интервал 12 мкС
#define START_TIME_TX 59 //65 //Тх тайм = 59мкС
#else
#define CAP_BOOST_TIME 0 // нет конденсаторов
#define TIME_GUARD 0x0a // защитный интервал 10 мкС
#define START_TIME_TX 0x41 //Тх тайм = 65 мкС
#endif
void LowBatIndicationLoop (void);
void __watchdog_init (void)
{
//запускаю сторожевой таймер на 2 секунды
__watchdog_reset ();
WDTCR |= ((1<<WDCE)|(1<<WDE));
WDTCR = (1<<WDE)|(7<<WDP0);
__watchdog_reset ();
}
void InitTimers (void)
{
TCCR1A = 0x00;
TCCR1B |= ((1<<CS10) | (1<<WGM12));
OCR1A = 58500; //50000+6; //0xc350; //0xc350;
TCCR0B |= (4<<CS00);
TIMSK |= ((1<<TOIE0) | (1<<OCIE1A));
ACSR |= (1<<ACIC);
}
void InitPorts (void)
{
PortPot |= (1<<Pot);
PortPotDir |= (1<<Pot);
PortKeys |= ((1<<Q2) | (1<<Q0) | (1<<Q1));
PortKeysDir |= ((1<<Q2) | (1<<Q0) | (1<<Q1));
PortSpeakerDir |= (1<<Speaker);
#ifndef ENABLE_LCD
PortLeds |= ((1<<Led1) | (1<<Led2) | (1<<Led3) | (1<<Led4) | (1<<Led5) | (1<<Led6));
PortLedsDir |= ((1<<Led1) | (1<<Led2) | (1<<Led3) | (1<<Led4) | (1<<Led5) | (1<<Led6));
#endif //ENABLE_LCD
/*
#ifdef USE_BATTERY_METER //не используется. по идее это просто вход, поэтому можно просто включить подтяжку, на случай неиспользования измерителя
PortBatMeter |= (1<<BatMeter); //
#endif USE_BATTERY_METER
*/
PortSys |= ((1<<Pot) | (1<<Q2) | (1<<Q0) | (1<<Q1) | (1<<BatMeter));
PortSysDir |= ((1<<Pot) | (1<<Q2) | (1<<Q0) | (1<<Q1) | (1<<Speaker));
}
void InitUsart (unsigned int baud)
{
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
UCSRB |= (1<<TXEN);
}
void USARTSendChar (unsigned char data)
{
#ifdef ENABLE_USART
while (!( UCSRA & (1<<UDRE))); // ждем, пока отправится предыдущий байт
UDR = data;
#endif //ENABLE_USART
}
void InitMode (void)
{
IntegratorCycleEnd = 0x00; // переменная глобальная, поэтому равна 0 после RESET
//устанавливаем начальные временные интервалы
TimeTX = START_TIME_TX-CAP_BOOST_TIME; //т.е 59мкС - 5мкС = 54мкС Тх тайм
TimeGuardAfterTXOFF = 0; // переменная глобальная, поэтому равна 0 после RESET
TimeGuardAfterRXON = 0 + CAP_BOOST_TIME + UTC_DELAY_1; // переменная глобальная, поэтому равна 0 после RESET
TimeIntegration = 0x10;
__enable_interrupt();
}
void GetPotPosition (void)
{
unsigned int counter = 0;
__disable_interrupt();
PortPotDir &= ~(1<<Pot); //переключаем выход на вход
PortPot &= ~(1<<Pot);
while (PinPot & (1<<Pot)) { counter += PositionAddStep; } //ждем, пока напряжение упадет до порогового
UDR = (unsigned char)counter;
PortPot |= (1<<Pot); //переключаем вход на выход
PortPotDir |= (1<<Pot);
counter -= PositionSub;
if ((counter > PositionMax) || (counter == 0)) counter = 1; // проверяем, не вылезло ли за пределы
Sensitivity = counter;
UDR = (unsigned char)Sensitivity;
}
__flash signed int segmentsDec[5]={10000,1000,100,10,1};
unsigned char String[5];
void CharToStringDec(signed int inp)
{
unsigned char i;
String[0]=String[1]=String[2]=String[3]=String[4]=0;
for(i=0;i<5;)
{
if((inp-segmentsDec[i])>=0)
{
inp-=segmentsDec[i];
String[i]++;
}
else i++;
}
}
void LedBarUpdate (unsigned char level)
{
if (level >= threshold5) { PortLeds = ((1<<Led1) | (1<<Led2) | (1<<Led3) | (1<<Led4) | (1<<Led5)); ToneNumber = 5; }
else if (level >= threshold4) { PortLeds = ((1<<Led1) | (1<<Led2) | (1<<Led3) | (1<<Led4) | (1<<Led6)); ToneNumber = 4; }
else if (level >= threshold3) { PortLeds = ((1<<Led1) | (1<<Led2) | (1<<Led3) | (1<<Led5) | (1<<Led6)); ToneNumber = 3; }
else if (level >= threshold2) { PortLeds = ((1<<Led1) | (1<<Led2) | (1<<Led4) | (1<<Led5) | (1<<Led6)); ToneNumber = 2; }
else if (level >= threshold1) { PortLeds = ((1<<Led1) | (1<<Led3) | (1<<Led4) | (1<<Led5) | (1<<Led6)); ToneNumber = 1; }
else { PortLeds = ((1<<Led2) | (1<<Led3) | (1<<Led4) | (1<<Led5) | (1<<Led6)); ToneNumber = 0; }
}
#ifdef ENABLE_LCD
static __flash char str01 [] = " -<>+ "; //+000
static __flash char str02 [] = "Low Bat"; //+000
static __flash char str03 [] = "Wait"; //+000
void LCDBarUpdate (signed int level)
{
unsigned char col, pos;
signed int t;
//if (level < 0) t = 0;
if (level < 256) t = (signed int)level;
else t = 255;
if (level >= threshold5) { ToneNumber = 5; }
else if (level >= threshold4) { ToneNumber = 4; }
else if (level >= threshold3) { ToneNumber = 3; }
else if (level >= threshold2) { ToneNumber = 2; }
else if (level >= threshold1) { ToneNumber = 1; }
else { ToneNumber = 0; }
if (++LCDPrescaler > 2)
{
LCDPrescaler = 0;
lcd_gotoxy(0,0);//здесь показать уровень
lcd_puts_p(str01);
/*
if (level < 0) { lcd_putc('-'); }
else { lcd_putc(' '); }
*/
CharToStringDec(level); // конвертация
for (unsigned char v=1; v<5; v++) lcd_putc(String[v]+0x30);
lcd_gotoxy(0,1);
col = (t+48) / 16;//рассчитываем номер знакоместа для рисования палки
if (col>0) for (unsigned char z=0; z<col; z++) lcd_putc(0x05);//рисуем несколько полностью закрашенных знакомест
//рассчитываем номер символа для отображения в знакоместе //5 вариантов
pos = (t+48) - (col*16); // остаток
pos = (pos)/3;
lcd_putc(pos); //0x00+
for (unsigned char t=0; t<16; t++) lcd_putc(' '); //не чистим экран, а заполняем пробелами
}
}
#endif //ENABLE_LCD
void DelayUnits (unsigned long time)
{
while (time--) {}
}
#pragma vector = TIMER1_COMPA_vect //вызывается раз в 5мс
__interrupt void KeyDrive (void)
{
//unsigned char temp = 10;
unsigned int ICRData = ICR1; //получаем данные о времени срабатывания компаратора
PortKeys &= ~(1<<Q1); //выключаем первый усилитель
DelayUnits (10);
PortKeys &= ~(1<<Q0); //включаем накачку катушки
DelayUnits (TimeTX);
PortKeys |= (1<<Q0); //выключаем накачку катушки
DelayUnits (TimeGuardAfterTXOFF);
PortKeys |= (1<<Q1); //включаем первый усилитель
DelayUnits (TimeGuardAfterRXON);
PortKeys &= ~(1<<Q2); //включаем интегратор
DelayUnits (TimeIntegration);
PortKeys |= (1<<Q2); //выключаем интегратор
IntegratorCycleCount++;
Integrator += ICRData;
__enable_interrupt(); //вероятно таки придется разрешить здесь прерывания
if (IntegratorCycleCount > 7)
{
IntegratorCycleCount = 0;
Integrator = (Integrator >> 3); // деление на 8
ReceivedSignal = (unsigned int)Integrator;
//UDR = ReceivedSignal>>8;
IntegratorCycleEnd = 0xFF;
Integrator = 0;
}
GetPotPosition ();
__watchdog_reset ();
}
unsigned char SoundCycleCount;
#pragma vector = TIMER0_OVF0_vect
__interrupt void Sound (void)
{
TCNT0 = 0xFE; // перезагрузить таймер
if ((ToneNumber != 0) && (SoundCycleCount == 0))
{
SoundCycleCount = 16 - ToneNumber;
#ifdef ENABLE_SOUND
if (PortSpeaker & (1<<Speaker)) PortSpeaker &= ~(1<<Speaker); // speaker toggle
else PortSpeaker |= (1<<Speaker);
#endif //ENABLE_SOUND
}
if (SoundCycleCount) SoundCycleCount--;
#ifdef ENABLE_SOUND
if (ToneNumber == 0) PortSpeaker &= ~(1<<Speaker); // не потребляем динамиком лишний ток
#endif //ENABLE_SOUND
}
void LowBatIndicationLoop (void) // отсюда никогда не выходим
{
#ifndef ENABLE_LCD //светодиодный столбец
PortLeds = ((1<<Led1) | (1<<Led2) | (1<<Led3) | (1<<Led4) | (1<<Led5) | (1<<Led6)); //тушим все диоды
#endif //ENABLE_LCD
//TimeTX = 0; //Полная накачка уже ни к чему
PortSysDir &= ~(1<<Q0); //Выключаем ключ совсем - Полная накачка уже ни к чему
#ifdef ENABLE_LCD //экран
lcd_clrscr();
lcd_gotoxy(4,0);
lcd_puts_p(str02);
#endif //ENABLE_LCD
while (1)// батарея разряжена
{
__delay_cycles((CtrlClockRate/1000)*500);
if (ToneNumber == 1) ToneNumber =0;
else ToneNumber = 1;
#ifndef ENABLE_LCD //светодиодный столбец
if (PortLeds & (1<<Led1)) PortLeds &= ~(1<<Led1); // мигаем зеленым диодом с интервалом 0,5с
else PortLeds |= (1<<Led1);
#endif //ENABLE_LCD
}
}
int main (void)
{
signed int Ka=0, Kb=0, Kc=0, Kd=0, temp, tempdebug;
InitPorts ();
#ifdef ENABLE_LCD
lcd_init(LCD_DISP_ON);
//lcd_clrscr();
lcd_gotoxy(6,0);
lcd_puts_p(str03);
#endif //ENABLE_LCD
#ifdef ENABLE_USART
InitUsart (((CtrlClockRate/16)/baudrate)-1);
#endif //ENABLE_USART
InitTimers ();
InitMode ();
__delay_cycles((CtrlClockRate/1000)*START_DELAY); // стартовая задержка
__watchdog_init ();
unsigned int tem;
for (unsigned char i=0; i<8; i++)
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
EchoSumm = EchoSumm + ReceivedSignal;
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)ReceivedSignal);
IntegratorCycleEnd = 0;
}
USARTSendChar ((unsigned char)EchoSumm);
EchoSumm = EchoSumm >> 8; // деление на 256
Echo = (unsigned char)(EchoSumm);
USARTSendChar (Echo);
Echo -= 0x32;
USARTSendChar (Echo); // эхо, полученное при калибровке
if (Echo >= 0x19) // катушка в порядке, эхо достаточной величины
{
if (Echo <= 0x37) {Ka = 0x19; Kb = 0x37; Kc = 0xA0; Kd = 0x8C; }
else if (Echo <= 0x4B) {Ka = 0x37; Kb = 0x4B; Kc = 0x8C; Kd = 0x67; }
else if (Echo <= 0x52) {Ka = 0x4B; Kb = 0x52; Kc = 0x67; Kd = 0x52; }
else if (Echo <= 0x5F) {Ka = 0x52; Kb = 0x5F; Kc = 0x52; Kd = 0x41; }
temp = Echo - Ka;
temp = temp * (Kd - Kc);
temp = Kc + (temp / (Kb - Ka));
#ifndef USE_MANUAL_TIME_TX
TimeTX = temp - CAP_BOOST_TIME; //устанавливаем рабочие тайминги
if (Echo >= 0x60) TimeTX = 0x41 - CAP_BOOST_TIME; // Если эхо при калибровке >= 96 мкС, Тх тайм = 60 мкС 65-5
#endif
#ifdef USE_MANUAL_TIME_TX
TimeTX = ManualTimeTX;
#endif //USE_MANUAL_TIME_TX
TimeGuardAfterTXOFF = TIME_GUARD;
TimeGuardAfterRXON = 0x00 + CAP_BOOST_TIME + UTC_DELAY_1 + UTC_DELAY_2;
TimeIntegration = 0x32; // время интеграции 50 мкС очигледно за самородок т.е. нужео равенство с R21 x C6
USARTSendChar (TimeTX); // вычисленное время накачки
/*
for (unsigned char i=0; i<10; i++) // пропускаем 10 циклов для устаканивания интегратора, этого достаточно ?
{
while (IntegratorCycleEnd == 0) {} // пропускаем 1 цикл
IntegratorCycleEnd = 0;
}
*/
while (IntegratorCycleEnd == 0) {} // здесь пропускаем 1 цикл, этого достаточно ?
IntegratorCycleEnd = 0;
unsigned int tem;
EchoSumm = 0;
for (unsigned char i=0; i<32; i++)
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)ReceivedSignal);
EchoSumm += ReceivedSignal;
IntegratorCycleEnd = 0;
}
EchoSumm = EchoSumm >> 5; // деление на 32
BaseValue = (unsigned int)EchoSumm; // получили базовое значение при отсутствии металла
tem = BaseValue >> 8; // деление на 256
USARTSendChar ((unsigned char)tem);
USARTSendChar ((unsigned char)BaseValue);
USARTSendChar (BaseValue>>8); //базовое значение
while (1) // основной цикл обнаружения металла
{
while (IntegratorCycleEnd == 0) {} // ждем пока пройдет интегрирование
IntegratorCycleEnd = 0;
#ifdef AVERAGE_FILTER //усреднитель сигнала
EchoSumm = 0;
for (unsigned char z=0; z<(ArrayLength-1); z++) { ArrayReceivedSignal [z] = ArrayReceivedSignal [z+1]; } // сдвинули массив к 0 ячейке
ArrayReceivedSignal [ArrayLength-1] = ReceivedSignal; // в последнюю ячейку вносим свежее значение
for (unsigned char z=0; z<ArrayLength; z++) EchoSumm += ArrayReceivedSignal [z]; // суммируем последние показания
ReceivedSignal = (unsigned int)(EchoSumm / ArrayLength);
#endif //AVERAGE_FILTER
#ifdef USE_BATTERY_METER //измерение напряжения аккума
PortBatMeterDir |= (1<<BatMeter); // назначаем как выход, для преодоления гистерезиса
__delay_cycles((CtrlClockRate/1000000)*2); // чтобы устаканилось
PortBatMeterDir &= ~(1<<BatMeter); // назначаем как вход
__delay_cycles((CtrlClockRate/1000000)*2); // чтобы устаканилось
if (!(PinBatMeter & (1<<BatMeter))) LowBatIndicationLoop (); // и меряем на порту 2,10 В
#endif //USE_BATTERY_METER
UDR = ReceivedSignal;
tem = ReceivedSignal >> 8;
USARTSendChar ((unsigned char)ReceivedSignal);
USARTSendChar ((unsigned char)tem);
temp = ReceivedSignal - BaseValue; // сравнение с опорным значением
tempdebug = temp + 127;
if (tempdebug > 255) tempdebug = 255;
if (tempdebug < 0) tempdebug = 0;
UDR = tempdebug;
temp += temp; // разницу удваиваем со знаком
temp += temp; // разницу удваиваем со знаком
temp = 250;
temp = temp / ((signed int)Sensitivity);
USARTSendChar ((unsigned char)Sensitivity);
#ifndef ENABLE_LCD //Если нет ЖКИ то светодиодный столбец
if (temp < 0) temp = 0; // следим за рамками
if (temp > 254) temp = 255;
USARTSendChar ((unsigned char)temp); // результат
LedBarUpdate ((unsigned char)temp);
#endif //ENABLE_LCD
#ifdef ENABLE_LCD // тут своя процедура вывода полосы
if (temp < -48) temp = -48; // следим за рамками
if (temp > 9998) temp = 9999;
if (++LCDPrescaler > 2)
LCDPrescaler = 0;
LCDBarUpdate (temp);
}
#endif //ENABLE_LCD
}
}
//else LowBatIndicationLoop ();
// Основой устройства является микроконтроллер.
// С его помощью осуществляется формирование временных интервалов для управления всеми узлами устройства, а также
// индикация и общее управление прибором. // С помощью мощного ключа производится импульсное накопление энергии в катушке датчика,
// а затем прерывание тока, после которого возникает импульс самоиндукции, возбуждающий электромагнитное поле в мишени.
// Изюминкой предлагаемой схемы является применение дифференциального усилителя во входном каскаде. Он служит для усиления сигнала, напряжение которого выше напряжения питания и привязке его к определенному потенциалу - + 5 (В). Для дальнейшего усиления служит приемный усилитель с большим коэффициентом усиления. Для измерения полезного сигнала служит первый интегратор. Во время прямого интегрирования производится накопление полезного сигнала в виде напряжения, а во время обратного интегрирования производится преобразование результата в длительность импульса. Второй интегратор имеет большую постоянную интегрирования и служит для балансировки усилительного тракта по постоянному току.
// пытаться заменить на отечественные, об этом будет сказано ниже.
// Мощный ключ собран на полевом транзисторе VT1.
// Так как примененный полевой транзистор типа IRF740 имеет емкость затвора более 1000п,
// для его быстрого закрытия используется предварительный каскад на транзисторе VT2.
// Скорость открытия мощного ключа уже не столь критична из-за того, что ток в индуктивной нагрузке нарастает постепенно.
// Резисторы R1, R3 предназначены для “гашения” энергии самоиндукции.
// Их номинал выбран из соображений безопасной работы транзистора VT1, а также обеспечения апериодического характера
// переходного процесса в контуре, который образован индуктивностью датчика и паразитной межвитковой емкостью.
// Защитные диоды VD1,VD2 ограничивают перепады напряжения на входе дифференциального усилителя.
// Дифференциальный усилитель собран на ОУ D1.1. Микросхема D1 представляет собой счетверенный операционный усилитель типа
// TL074CN. Его отличительными свойствами являются высокое быстродействие, малое потребление, низкий уровень шумов,
// высокое входное сопротивление, а также возможность работы при напряжениях на входах, близких к напряжению питания.
// Эти свойства и обусловили его применение в дифференциальном усилителе в частности и в схеме в целом.
// Коэффициент усиления дифференциального усилителя составляет около 7 и определяется номиналами резисторов R3, R6…R9, R11.
// Приемный усилитель D1.2 представляет собой неинвертирующий усилитель с коэффициентом усиления 57.
// Во время действия высоковольтной части импульса самоиндукции этот коэффициент снижается до 1 с помощью аналогового ключа
// D2.1 CD4066. Это предотвращает перегрузку входного усилительного тракта и обезпечивает быстрое вхождение в режим
// для усиления слабого сигнала. Транзисторы VT3 и VT4 предназначены для согласования уровней управляющих сигналов,
// подаваемых с микроконтроллера на аналоговые ключи.
// С помощью второго интегратора D1.3 TL074CN производится автоматическая балансировка входного усилительного тракта
// по постоянному току. Постоянная интегрирования 240мс, R14xC3 (2М4 х 100н) выбрана достаточно большой,
// чтобы эта обратная связь не влияла на усиление быстро изменяющегося полезного сигнала.
// С помощью второго интегратора на выходе усилителя D1.2 (ножка 8 TL074CN) при отсутствии сигнала поддерживается
// уровень +5В.
// Первый интегратор (Измерительный) выполнен на D1.4. TL074CN. На время интегрирования полезного сигнала открывается ключ
// D2.2. CD4066 и, соответственно, закрывается ключ D2.4. CD4066. На ключе D2.3. CD4066 реализован логический инвертор.
// После завершения интегрирования сигнала ключ D2.2 закрывается и открывается ключ D2.4.
// Накопительный конденсатор C6 (470п) начинает разряжаться через резистор R21 (300К). Время разряда будет пропорционально
// напряжению, которое установилось на конденсаторе C6 (470п) к концу интегрирования полезного сигнала.
// Это время измеряется с помощью микроконтроллера, который осуществляет аналого-цифровое преобразование.
// Для измерения времени разряда конденсатора C6 используются аналоговый компаратор и таймеры, которые встроены
// в микроконтроллер D3 АТТiny2313. Кнопка S1 (ножка 1 АТТiny2313) предназначена для начального сброса микроконтроллера.
// С помощью переключателя S3 задается режим индикации устройства (ЖКИ или светодиоды).
// С помощью переменного резистора R29 (4К7) регулируется чувствительность металлоискателя.
// С помощью светодиодов VD3…VD8 производится световая индикация.
// Алгоритм функционирования
// Для разъяснения принципа работы описываемого импульсного металлоискателя приведены осциллограммы сигналов
// в наиболее важных точках прибора.
// На время интервала A (60…200мкс) открывается ключ VT1. Через катушку датчика начинает протекать пилообразный ток.
// При достижении величины тока 2А ключ закрывается. На стоке транзистора VT1 возникает выброс напряжения самоиндукции.
// Величина этого выброса - более 300В ограничивается резисторами R1 (390ом), R3(390ом).
// Для предотвращения перегрузки усилительного тракта служат ограничительные диоды VD1, VD2.
// Также для этой цели на время интервала A (накопление энергии в катушке) и интервала B (выброс самоиндукции) открывается
// ключ D2.1. CD4066 Это снижает сквозной коэффициент усиления тракта с 400 до 7.
// На осциллограмме 3 показан сигнал на выходе усилительного тракта (вывод 8 D1.2).
// Начиная с интервала C (8мкс), ключ D2.1 закрывается и коэффициент усиления тракта становится большим.
// После завершения защитного интервала C, за время (8мкс), усилительный тракт входит в режим усиления, открывается
// ключ D2.2 (CD4066) и закрывается ключ D2.4 (CD4066) – начинается интегрирование полезного сигнала – интервал D (50мкс).
// По истечении этого интервала интегрирования ключ D2.2 закрывается, а ключ D2.4 открывается и начинается
// “обратное” интегрирование. За это время (интервалы E и F) конденсатор C6 (470п) полностью разряжается.
// С помощью встроенного аналогового компаратора микроконтроллер отмеряет величину интервала E,
// которая оказывается пропорциональной уровню входного полезного сигнала.
// Для текущих версий микропрограммного обеспечения установлены следующие значения интервалов:
// A – 60…200 мкс, B – 12 мкс, С – 8 мкс, D – 50 мкс. A + B + C + D + E + F – 5 (мс) - период повторения.
// Микроконтроллер обрабатывает полученные цифровые данные и индицирует с помощью светодиодов VD3…VD8 и
// излучателя звука Y1 степень воздействия мишени на датчик.
// Светодиодная индикация представляет собой аналог стрелочного индикатора – при отсутствии мишени горит светодиод VD8,
// далее в зависимости от уровня воздействия последовательно загораются VD7, VD6 и т.д. до VD3.
//
C++ для микроконтроллеров Atmel AVR берем здесь
https://www.iar.com/products/architectu ... h-for-avr/