Доброго времени суток, уважаемые читатели. Зарегистрировался на хабре я давно, но никак не решался оформить свой первый пост.
Хотелось написать что-то, что действительно может показаться интересным. Время шло, а идеи все никак не приходили.
И вот, буквально на днях, я закончил работу над одним из своих первых проектов, после чего, мне в голову пришла мысль сделать некий видео обзор и написать небольшую статью о приборе, над которым я работал достаточно продолжительный период времени. Работал не один, но речь пойдет о части, которая «висела» целиком и полностью на мне.

Во-первых, необходимо было разработать программу, управляющую зарядным устройством. Состоит оно по большому счету из микроконтроллера ADUC814 со встроенным аналого-цифровым преобразователем, пяти светодиодов, отвечающих за уровень заряда аккумулятора и кнопки включения заряда. Все достаточно просто, детально описывать смысла не вижу. По прерыванию АЦП получаем данные, которые потом переводятся в вольты, далее оперируя этим значением программа принимает те или иные решения, например какие диоды зажечь, что делать при критических уровнях заряда и т.п., а так же следит за кнопкой включения заряда.
Во-вторых, и это собственно самая сложная часть для меня, необходимо было разработать программу, управляющую блоком обработки информации и индикации. В БОИ входят такие узлы, как дисплей, клавиатура, пара вспомогательных светодиодов и управляющий всем этим микроконтроллер AT89C51RC2 (МК_БОИ). Обзор всех основных функций ваттметра представлен на видео.
К ваттметру подключается один из четырех преобразователей, в зависимости от измеряемой мощности. Данные с преобразователя поступают на аналого-цифровой преобразователь фирмы Analog Devices и далее с помощью RS232 передаются на еще одни ADUC814 (МК_АЦП), в котором проходят предварительную обработку. Программа пред. обработки и связи непосредственно с АЦП разрабатывалась не мной.
МК_АЦП по RS232 получает от МК_БОИ одну из нескольких команд, каждая из которых состоит из трех байт, далее он анализирует команду и в зависимости от нее, посылает обратно три байта номера команды и запрашиваемый результат. Это может быть номер преобразователя или, например, результаты измерений, которые подвергаются дальнейшей математической обработке. Некоторые команды отвечают за коррекцию нуля или калибровку АЦП. Всего около 8-9 команд, подробно останавливаться на них я также не вижу смысла.
В конце хотелось бы немного написать о функционале, подробней с которым можно ознакомиться на видео.
Основная часть кнопок клавиатуры выполняет двойную функцию, вспомогательные светодиоды позволяют легче сориентироваться в режимах работы, которых всего два, это режим меню, горит верхний диод и режим работы, горит нижний диод.
Вся необходимая информация выводится на дисплее. Значение измеряемой величины, которое так же переводится в dBm и dB, во время дрейфа нуля попадаются и отрицательные значения, в этих случаях на экран выводится сообщение Err. Результат сравнения мощности с величиной Рс. Номер подключенного преобразователя. Информация о том, что нажата кнопка СТОП, а так же при выходе из возможного диапазона измерений конкретного преобразователя также выводится соответствующее сообщение.
Еще хотелось бы добавить, что помимо частотных поправочных коэффициентов так же имеется и динамический поправочный коэффициент, рассчитывается индивидуально для каждого конкретного измерения.
На этом все, надеюсь, что найдутся люди, которым данный пост понравится, а так же хотелось бы увидеть комментарии, критического характера, возможно у кого-то будут интересные идеи, которые я смогу реализовать в дальнейшем в рамках этого проекта, учитывая, что намечается замена МК_БОИ на аналогичный, с большим объемом памяти, так как эти 32 кБ забиты под завязку.
Спасибо за внимание.
Прошу прощения за долгий перерыв. В комментариях были вопросы касательно процесса самого программирования, в связи с этим хочу обновить данную статью и добавить сюда код.
Вывод информации на дисплей был организован следующим образом. Был составлен список повторяющихся фраз и написана под них библиотека «alphabetLCD.h»:
Так как иногда приходилось выводить на дисплей результаты вычислений, реализованных в «main.c», я использовал ключевое слово
Ниже описаны все основные функции «main.h»:
Для удобства программирования дисплея, вызова его команд, перемещения курсора по строкам и т.п. активно использовались макросы:
ПРОДОЛЖЕНИЕ СЛЕДУЕТ...
Хотелось написать что-то, что действительно может показаться интересным. Время шло, а идеи все никак не приходили.
И вот, буквально на днях, я закончил работу над одним из своих первых проектов, после чего, мне в голову пришла мысль сделать некий видео обзор и написать небольшую статью о приборе, над которым я работал достаточно продолжительный период времени. Работал не один, но речь пойдет о части, которая «висела» целиком и полностью на мне.
Для начала приведу немного сухой технической информации

Ваттметр поглощаемой СВЧ мощности М3-114 предназначен для измерения в коаксиальном тракте среднего значения мощности непрерывных и импульсно- модулированных СВЧ сигналов при электропитании от промышленной электросети 220 В, 50 Гц, так и в автономном режиме, от внутренней или внешней аккумуляторной батареи 12 В. В приборе применён четырёх строчный текстовый вакуумно-люминесцентного дисплей высокой яркости. Подготовка прибора к работе осуществляется в диалоговом режиме, что упрощает эксплуатацию. Прибор оснащён портом RS-232, что позволяет выводить данные на ЭВМ.
Диапазон рабочих частот от 0,00 до 17,85 ГГц.
Диапазон измерения средних значений мощности от 1,0 мкВт до 100 Вт.
В диапазоне измеряемой мощности более 10 мВт на частотах от 0 до 12,05 ГГц предел основной погрешности ваттметра не превышает ±4 %, а в диапазоне частот свыше 12,05 ГГц до 17,85 ГГц — ±6 %.
КСВН ваттметра не более:
1,3 в диапазоне частот от 0,02 до 12,05 ГГц;
1,4 в диапазоне частот свыше 12,05 до 17,85 ГГц.
Нестабильность показаний ваттметра с учетом дрейфа “электрического нуля” не более 40 мкВт/мин.
Мощность, потребляемая ваттметром от сети напряжением 220 ±22 В, частотой 50±0,5 Гц при работе с ППК1 – ППК3, не более 12 ВА, при работе с ППК 4 — не более 15 ВА, при работе от автономного источника питания 6,5 ВА
Теперь перейдем непосредственно к тем задачам, которые были поставлены передо мной
Во-первых, необходимо было разработать программу, управляющую зарядным устройством. Состоит оно по большому счету из микроконтроллера ADUC814 со встроенным аналого-цифровым преобразователем, пяти светодиодов, отвечающих за уровень заряда аккумулятора и кнопки включения заряда. Все достаточно просто, детально описывать смысла не вижу. По прерыванию АЦП получаем данные, которые потом переводятся в вольты, далее оперируя этим значением программа принимает те или иные решения, например какие диоды зажечь, что делать при критических уровнях заряда и т.п., а так же следит за кнопкой включения заряда.
Во-вторых, и это собственно самая сложная часть для меня, необходимо было разработать программу, управляющую блоком обработки информации и индикации. В БОИ входят такие узлы, как дисплей, клавиатура, пара вспомогательных светодиодов и управляющий всем этим микроконтроллер AT89C51RC2 (МК_БОИ). Обзор всех основных функций ваттметра представлен на видео.
К ваттметру подключается один из четырех преобразователей, в зависимости от измеряемой мощности. Данные с преобразователя поступают на аналого-цифровой преобразователь фирмы Analog Devices и далее с помощью RS232 передаются на еще одни ADUC814 (МК_АЦП), в котором проходят предварительную обработку. Программа пред. обработки и связи непосредственно с АЦП разрабатывалась не мной.
МК_АЦП по RS232 получает от МК_БОИ одну из нескольких команд, каждая из которых состоит из трех байт, далее он анализирует команду и в зависимости от нее, посылает обратно три байта номера команды и запрашиваемый результат. Это может быть номер преобразователя или, например, результаты измерений, которые подвергаются дальнейшей математической обработке. Некоторые команды отвечают за коррекцию нуля или калибровку АЦП. Всего около 8-9 команд, подробно останавливаться на них я также не вижу смысла.
В конце хотелось бы немного написать о функционале, подробней с которым можно ознакомиться на видео.
Основная часть кнопок клавиатуры выполняет двойную функцию, вспомогательные светодиоды позволяют легче сориентироваться в режимах работы, которых всего два, это режим меню, горит верхний диод и режим работы, горит нижний диод.
С помощью меню можно выполнять ряд функций
- Управлять яркостью дисплея
- Выбирать частотный диапазон, на котором проводятся измерения. В зависимости от выбранного диапазона применяются те или иные поправочные коэффициенты, влияющие на конечный результат. Коэффициенты рассчитаны путем сравнения с эталонным прибором.
- Устанавливать некую величину P, с которой сравнивается измеряемая величина. Результат выводится на дисплей в процентах
- Устанавливать диапазон измеряемой величины, при выходе из которого, на дисплей выводиться соответствующая надпись < Pmin, > Pmax
В режиме работы пользователь может:
- Проводить коррекцию нуля и калибровку АЦП.
- Включить усреднение измеряемой величины или выключить его.
- «Заморозить» дисплей, путем нажатия кнопки СТОП
Вся необходимая информация выводится на дисплее. Значение измеряемой величины, которое так же переводится в dBm и dB, во время дрейфа нуля попадаются и отрицательные значения, в этих случаях на экран выводится сообщение Err. Результат сравнения мощности с величиной Рс. Номер подключенного преобразователя. Информация о том, что нажата кнопка СТОП, а так же при выходе из возможного диапазона измерений конкретного преобразователя также выводится соответствующее сообщение.
Еще хотелось бы добавить, что помимо частотных поправочных коэффициентов так же имеется и динамический поправочный коэффициент, рассчитывается индивидуально для каждого конкретного измерения.
На этом все, надеюсь, что найдутся люди, которым данный пост понравится, а так же хотелось бы увидеть комментарии, критического характера, возможно у кого-то будут интересные идеи, которые я смогу реализовать в дальнейшем в рамках этого проекта, учитывая, что намечается замена МК_БОИ на аналогичный, с большим объемом памяти, так как эти 32 кБ забиты под завязку.
Спасибо за внимание.
КОДИНГ
Прошу прощения за долгий перерыв. В комментариях были вопросы касательно процесса самого программирования, в связи с этим хочу обновить данную статью и добавить сюда код.
Алфавит дисплея
Вывод информации на дисплей был организован следующим образом. Был составлен список повторяющихся фраз и написана под них библиотека «alphabetLCD.h»:
void m3114(); // "��ЕТЕОР МЗ-114" void noSignalADC(); // "НЕТ СВЯЗИ С АЦП" void wait(); // "ОЖИДАНИЕ" void norma(); // норма void PPK1(); void PPK2(); void PPK3(); void PPK4(); void prepareToWorkOnPPKEnter(); // подготовка к работе подключите ппк к источнику сигнала и нажмите "ввод" void heating(); // прогерв 6с прервать? 34 void ifTNorm(); // ЕСЛИ Т=15-25 НАЖМИТЕ "ВВОД" ЕСЛИ НЕТ НАЖМИТЕ "ОТМЕНА" void Kcoeff(); // К преобразования 1,000 void preparationOfMeasurement(); // ПОДГОТОВКА ИЗМЕРЕНИЙ САМОКАЛИБРОВКА 12с void resetMenuParams(); // переустновка параметров в меню void readyToMeasurement(); // ваттметр готов к измерениям void menuSet1(); // установка К частот *** установка частоты *** установка Р сравнения *** допусковый контроль void switchOffSVCHAndPressEnter(); // "ВЫКЛЮЧИТЕ свч сигнал и нажмите ввод void preparationOfMeasurementCorrection0(); // подготовка измерений коррекция "0" норма void preparationOfMeasurementCooling(); // подготовка измерений остывание 30 с void preparationOfMeasurementStop32(); // подготовка измерений 32с прервать? 24 void preparationToWork(); // подготовка к работе выключите свч сигнал и нажмите ввод void hertzType0(); // 0-1 1-4 4-8 8-12 void hertzType1(); // 12-15 15-17.85 void setPCompare(); //установка Р сравн. сохранить значение? 1,000 mW void setPCompareChange(); //установка Р сравн. зпт - кнопкой зпт измените цифру: х,ххх void allowenceControlMin(); // допусковый контроль Рmin: сохранить значение? Х,ХХХ W void allowenceControlMax(); // допусковый контроль Рmax: сохранить значение? Х,ХХХ W void setAllowenceControlMin(); //установка Р min зпт - кнопкой зпт измените цифру: х,ххх void setAllowenceControlMax(); //установка Р max зпт - кнопкой зпт измените цифру: х,ххх void menuSet2(); // без усреднения усреднение по 4м 8ми 16ти void brightnessSet(); // 25% 50% 75% 100% void fault(); // НЕИСПРАВНОСТЬ!!! void incorrectValue(); // ОШИБКА ВВОДА! ОВТОРИТЕ ПОПЫТКУ void overload(); // ПЕРЕГРУЗКА!!! при Р > крайнего значения диаппазона
Приведу пример реализации одной из функций из «alphabetLCD.с»:
void noSignalADC() // "НЕТ СВЯЗИ С АЦП" { writeData('H'); writeData('E'); writeData('T'); writeData(' '); writeData('C'); writeData('B'); writeData(0x99); writeData(0x8D); writeData(0x8E); writeData(' '); writeData('C'); writeData(' '); writeData('A'); writeData(0x90); writeData(0x85); }
Так как иногда приходилось выводить на дисплей результаты вычислений, реализованных в «main.c», я использовал ключевое слово
extern:extern bit hertzType; extern float xdata calibrFl; extern unsigned char xdata ppkNumberCh; // номер ППК char extern float xdata pCompareFl; extern float xdata pMinFl; // записывает массив в float extern float xdata pMaxFl; // записывает массив в float
Плавно перейдем к основной программе
Ниже описаны все основные функции «main.h»:
void initialization(); void delay(unsigned int); void delay2s(); void zeroCorrection(); void calibration(); void measurement(); //****UART**** void sendData (unsigned char); // send to UART //unsigned char recvData(); // recive from UART void iToA (int , char * ); void getPPKnumber(); //****Keyboard**** void keyboardInit(); void keyboardPolling(); void downZero(); void upCalibr(); void lessAveraging(); void morePC(); void commaStop(); void cancel(); void enter(); void menu(); //****Display**** void dispInit(); void writeCmd(int); void writeData(char); void readBF(); void returnHome(); void clearDisp(); void reloadDisp(); void moreLessCheck();
Макросы
Для удобства программирования дисплея, вызова его команд, перемещения курсора по строкам и т.п. активно использовались макросы:
/* __________MAKROS BLOCK__________ */ #define FIRST_LINE 0x80 #define SECOND_LINE 0xC0 #define THIRD_LINE 0x94 #define FOURTH_LINE 0xD4 #define CURSOR_HOME 0x02 #define CLEAR_DISP 0x01 #define DISP_OFF 0x08 #define DISP_ON_CB_OFF 0x0C // Disp ON cursore & blink OFF #define DISP_ON_CB_ON 0x0F #define FIRST_SIMBOL 0xD4 #define SECOND_SIMBOL 0xD5 #define THIRD_SIMBOL 0xD6 #define FOURTH_SIMBOL 0xD7 #define FIFTH_SIMBOL 0xD8 #define SIXTH_SIMBOL 0xD9 /* __________MAKROS BLOCK END__________ */
Конфигурирование ножек процессора
* __________PINS BLOCK__________ */ sbit E = P3^4; sbit RS = P3^6; sbit RW = P3^5; sbit workLed = P3^2; sbit menuLed = P3^3; sbit enterBut = P1^6; sbit cancelBut = P1^5; sbit uartPC = P3^7; /* __________PINS BLOCK END__________ */
Описание переменных
/* __________VARIABLES BLOCK__________ */ unsigned char keyPressed = 0; // key pressed value bit keyFlag = 0; // software flag unsigned char xdata uartDataRecv = 0; // запоминает данные с уарт unsigned char xdata uartDataSend = 0; // отправляет данные с уарт char xdata uartRecvCount = 0; // счетчик принятых данных с уарт bit menuFlag = 0; // контролирует зажигание диодов клавиатуры, если 1 - горит верхний, если 0 - нижний char xdata move = 1; // перемещение по пунктам меню bit signalFlag = 0; // если флаг установлен значит есть инфа о номере ППК char xdata enterFlag = 0; // инкрементируется при нажатии ввод char xdata cancelFlag = 0; // инкрементируется при нажатии отмена bit modeFlag = 0; // игнорирует нажатие кнопок вне бесконечного цикла bit brightnessFlag = 0; // устанавливается, если мы внутри меню яркости дисплея char xdata brightnessMove = 1; // флаг для перемещения по меню яркости char xdata brightnessSetFlag = 0; // установка яркости дисплея, контролирует нажатие ввод bit hertzFlag = 0; // устанавливается, если мы внутри меню установки частоты char xdata hertzSetFlag = 0; char xdata menuStep = 0; // глубина меню char xdata hertzMove = 1; // флаг для перемещения по меню частоты bit hertzType; // флаг типа меню частоты bit compareFlag; // флаг меню Р сравнения char xdata compareFlagEnter = 0; // нажат ВВОД для Р сравнения char xdata compareFlagCancel = 0; // нажата ОТМЕНА для Р сравнения char xdata moreLess = 0x30; // значение Р сравнения и допускового контроля char xdata moreLessFlag = 0; // флаг для подсчета количества введенных знаков bit moreFlag = 0; // если 1 то при вычитании moreLess -= 2 bit lessFlag = 0; // если 1 то при прибавлении moreLess +=2 char xdata wattFlag = 0; // флаг переключения размерности Р сравн bit commaFlag = 0; // проверка нажатия кнопки ЗПТ для ввода Р сравн и допускового контроля unsigned char xdata pCompare[10] = 0; // запоминает Р сравн float xdata pCompareFl = 1.0; //float xdata pCompareFlTemp = 1.0; // для сохранения предыдущего состояния переменной в случае отмены. // ДОРАБОТАТЬ, ЗНАЧЕНИЕ НЕ СОХРАНЯЕТСЯ!!! bit controlFlag = 0; // флаг меню допускового контроля char xdata controlFlagEnter = 0; // нажат ВВОД для допускового контроля char xdata controlFlagCancel = 0; // нажата ОТМЕНА для допускового контроля unsigned char xdata pMin[10]; // запоминает Р min unsigned char xdata pMax[10]; // запоминает Р max float xdata pMinFl = 0; // записывает массив в float float xdata pMaxFl = 0; // записывает массив в float bit pMinFlag = 0; // устанавливаем флаг когда изменяем Р min bit pMaxFlag = 0; // устанавливаем флаг когда изменяем Р max unsigned char xdata zeroCoef1 = 50; // коэффициент коррекции нуля 50 - 200 unsigned char xdata zeroCoef2 = 30; // коэффициент коррекции нуля 50 - 200 unsigned char xdata zeroCoef3 = 30; // коэффициент коррекции нуля 50 - 200 unsigned char xdata zeroCoef4 = 100; // коэффициент коррекции нуля 50 - 200 unsigned long xdata zero; // значение после коррекции нуля unsigned char xdata calibrCoef1 = 50; // коэффициент калибровки 50 - 200 unsigned char xdata calibrCoef2 = 30; // коэффициент калибровки 50 - 200 unsigned char xdata calibrCoef3 = 30; // коэффициент калибровки 50 - 200 unsigned char xdata calibrCoef4 = 100; // коэффициент калибровки 50 - 200 unsigned long xdata calibr; // значение после калибровки К преобразования float xdata calibrFl; // значение после калибровки К преобразования unsigned int xdata PPK1CalibrPower; // эталон калибровочного коэффициента для ППК1 мощьность Р unsigned long xdata PPK23CalibrPower; // эталон калибровочного коэффициента для ППК1 - 2 мощьность Р unsigned long xdata PPK4CalibrPower; // эталон калибровочного коэффициента для ППК4 мощьность Р float xdata PPK1CalibrStandart; // эталон для проверки вхождения в диапазон (0,5 - 1,5) float xdata PPK2CalibrStandart; // эталон для проверки вхождения в диапазон (0,5 - 1,5) float xdata PPK3CalibrStandart; // эталон для проверки вхождения в диапазон (0,5 - 1,5) float xdata PPK4CalibrStandart; // эталон для проверки вхождения в диапазон (0,5 - 1,5) unsigned char xdata uartData[10]; // данные о номере ППК приходящие на УАРТ по запросу unsigned char xdata ppkNumberCh; // номер ППК char float xdata measurementResult = 0; // результат основных измерений bit averagingFlag = 0; // флаг устреднения bit averaging4 = 0; // усреднение по 4-ем bit averaging8 = 0; // усреднение по 8-ми char xdata averagingMove = 1; // для перемещения по меню усреднения float idata hertzRate = 1; // поправочный коэффициент для коррекции принимает 6(диаппазонов) * 4(ППК) = 24 значения float idata dynamicRate = 1; // динамический поправочный коэффициент //для коррекции принимает 4(диаппазонов) * 4(ППК) = 16 значения char idata stop = 0; // устанавливается в 1 и экран замирает при нажатии кнопки СТОП, в 0 при повторном нажатии char idata pc = 0; // бит для вывода данных на ПК //bit key = 0; xdata union { unsigned long bytes; unsigned char byteArr[4]; } byteUnion; /* __________VARIABLES BLOCK END__________ */
Прерывания
/* __________INTERUPTS BLOCK__________ */ void keyboard_interrupt() interrupt 7 using 1 { IEN1 &= ~(1<<0); //запрещаем прерывания клавиатуры keyFlag = 0; keyPressed = KBF; /* save pressed key */ keyFlag = 1; /* set the software flag */ KBF = 0x00; /* clear keyboard flags */ delay(50000); // 50 mc IEN1 |= 0x01; //разрешаем прерывания клавиатуры } void serial_IT(void) interrupt 4 { if (RI == 1) { uartDataRecv = SBUF; uartData[uartRecvCount] = uartDataRecv; ++uartRecvCount; } RI = 0; } /* __________INTERUPTS BLOCK END__________ */
ПРОДОЛЖЕНИЕ СЛЕДУЕТ...
