Устройство контроля напряжения на ардуино. MP220VДатчик контроля сетевого напряжения с опторазвязкой

19.04.2019

В 2010 году компания Intel представила новые торговые марки процессоров — Core i3 , i5 , i7 . Такое событие многих пользователей сбило с толку. А все потому, что цель компании была совсем иной – она хотела предложить более быстрый способ идентификации моделей низких, средних и высоких уровней. Также компания Intel хотела убедить пользователей в том, что Intel Core i7 намного лучше, чем, тот же i5, а этот в свою очередь лучше, чем i3. Но это не дает точного ответа на вопрос, какой все-таки процессор лучше или в чем отличие процессоров Intel Core i3, i5 и i7?

Немного позже, компания выпустила новые поколения процессоров на базе таких архитектур, как Ivy Bridge , Sandy , Haswell , Broadwell и . Такие нововведение еще сильнее сбили с толку множество потребителей. Хоть и появились такие новые технологии, названия не поменялись – Core i3, i5, i7. Различия между этими технологиями заключаются лишь в следующем: Процессоры с i3 предназначены для компьютеров малого (базового) класса, процессоры i5 для компьютерных систем среднего класса, а процессоры i7 для компьютеров высокого класса, для мощных ПК, простыми словами.

Но все же есть и другие различия, о которых мы поговорим.

Ключевые моменты

Некоторые пользователи считают, что названия i3, i5 и i7, связаны с количеством ядер в процессоре, на самом деле это не так. Данные марки выбраны компанией Intel произвольно. Поэтому, чипы всех этих процессоров могут иметь, как два, так и четыре ядра. Существуют и более мощные модели, для настольных компьютеров, которые имеют и ядер больше, и по многим характеристикам превосходят другие процессоры.

Итак, в чем же различия этих трех моделей?

Hyper-Threading

Когда еще только зарождались процессоры, все они имели по одному ядру, выполняющему всего лишь один набор инструкций, а именно thread(поток). Компания смогла повысить количество вычислительных операций путем увеличения количества ядер. Таким образом, процессор мог выполнять больше работы за единицу времени.

Следующая цель компании – увеличение оптимизации такого процесса. Для этого они создали технологию Hyper-Threading , позволяющая одному ядру выполнять несколько потоков одновременно. Например, мы имеем процессор с чипом на 2 ядра, который поддерживает технологию Hyper-Threading, тогда мы можем рассматривать данный процессор, как четырех-ядерный.

Turbo Boost

Раньше процессоры работали на одной тактовой частоте, которую задавал производитель, чтобы изменить эту частоту, на более высокую, люди занимались оверклокингом (разгоном) процессора. Такой вид деятельности требует специальных знаний, без которых, Вы можете за пару мгновений нанести колоссальный ущерб процессору или другим компонентам компьютера.

Сегодня же, все совсем по-другому. Современные процессоры оснащаются технологией Turbo Boost , которая позволяет работать процессору с переменной тактовой частотой. Таким образом, повышается энергоэффективность и время работы, например, ноутбука и других мобильных устройств.

Размер кэш-памяти

Процессоры, как правило, работают с большим количеством данных. Выполняемые операции могут быть разными и по объему, и по сложности, но часто бывает, что процессору необходимо обрабатывать одну и ту же информацию несколько раз. Для ускорения данного процесса, а в особенности самого процессора, такие данные сохраняют в специальном буфере (кэш-памяти). Поэтому, процессор может извлекать такие данные практически мгновенно, без лишней нагрузки.

Объем кэш-памяти в разных процессорах исчисляется по-разному. Например, в процессора низкого класса – 3-4 Мб, а в моделях более высокого класса – 6-12 Мб.

Конечно, чем больше кэш-памяти, тем лучше и быстрее будет работать процессор, но такая инструкция подходит не для всех приложений. Например, приложения для обработки фото и видео воспользуются большим объёмом кэш-памяти. Поэтому, чем больше размер кэша, тем более эффективно будут работать приложения.

Для выполнения простейших задач, таких как, серфинг в интернете или работа в офисных программа, кэш является не таким значительным.

Типы процессоров Intel

Теперь рассмотрим типы процессоров, а именно описание каждого из них.

Intel Core i3

Для чего подходит : Обычная, повседневная работа с офисными приложениями, просмотром интернета и фильмов в высоком качестве. Для таких процессов, Core i3 является оптимальным вариантом.

Характеристика : Данный процессор предлагает до 2 ядер и поддерживает технологию Hyper-Treading. Правда не поддерживает Turbo Boost. Также, процессор имеет достаточно малое потребление энергии, поэтому для ноутбуков такой процессор подходит, несомненно.

Intel Core i5

Для чего подходит : Более интенсивная работа, например, использование программ для обработки видео и фото, можно играть во многие современные игры, на низких, средних и иногда высоких настройках.

Характеристика : Данный процессор используется, как в обычных настольных компьютерах, так и в ноутбуках. Имеет от 2 до 4 ядер, но не поддерживает Hyper-Treading, зато поддерживает Turbo Boost.

Intel Core i7


Для чего подходит : Данный процессор, предрасположен для работы с мощными графическими редакторами. Можно играть в современные игры на максимальных настройках, но тут играют большую роль и другие компоненты, например, видеокарта. Также, можно просматривать видеофайлы в 4К.

Характеристика : На данный момент, этот чип является самым высоким классом. Имеет, как 2, так и 4 ядра и поддержку Hyper-Treading и Turbo Boost.

Мы рассмотрели краткие характеристики 3 типов процессоров, и теперь можете выбрать оптимальный для Вас.

Схема самодельного прибора на основе Arduino Uno, который предназначен для измерения частоты и напряжения в розетке с отображением результатов на дисплее 1602A . Прибор очень прост в изготовлении, благодаря применению готового модуля ARDUINO UNO.

Принципиальная схема

Индикатором служит ЖК-дисплей типа 1602А, он стандартный, на основе контроллера HD44780. Обозначение 1602А фактически значит, что он на две строки по 16 символов в строке.

Основой прибора служит ARDUINO UNO, это относительно недорогой готовый модуль, - небольшая печатная плата, на которой расположен микроконтроллер ATMEGA328, а так же вся его «обвязка», необходимая для его работы, включая USB-программатор и источник питания.

Прибор питается от электросети и измеряет вышеуказанные параметры. Источник питания одновременно служит и датчиком для получения данных о частоте и напряжении в электросети. Источник питания сделан на основе маломощного готового трансформатора Т1, у которого есть две одинаковые обмотки по 9V переменного напряжения каждая.

Рис. 1. Принципиальная схема измерителя частоты и значения напряжения в электросети, использованы Arduino Uno и 1602A.

Одна обмотка служит для получения напряжения питания. Переменное напряжение с неё поступает на выпрямительный мост на диодах VD1-VD4. Конденсатор С3 сглаживает пульсации выпрямленного напояжения.

На С3 полVчается постоянное напряжение около 12V, которое поступает на разъем для подачи питания на плату ARDUINO UNO, на вход имеющегося на этой плате стабилизатора напряжения 5V, которым и питается вся плата и индикатор Н1.

Другая вторичная обмотка трансформатора служит датчиком измерения параметров электросети. Переменное напряжение с неё через R1 поступает на формирователь импульсов с частотой электросети, выполненный на транзисторе VТ1 по схеме ключа. Эти импульсы поступают на цифровой порт D10 платы ARDUINO UNO.

Переменное напряжение сети измеряется при помощи выпрямителя на диоде VD5 и конденсаторе С2. Величина переменного напряжения в сети определяется по величине постоянного напряжения на этом конденсаторе и через настраиваемый делитель на резисторах R4 и R5 поступает на аналоговый вход А1 платы ARDUINO UNO.

Программа

Программа на C++ с подробными комментариями приведена в таблице 1. Для измерения частоты используется функция pulseln , которая измеряет в микросекундах длительность положительного либо отрицательного перепада входного импульса.

Таблица 1.

Рис. 2. Исходный код программы для измерения частоты и значения напряжения в электросети.

Так что, для того чтобы узнать период нужно сложить длительность положительного и отрицательного полупериодов, а чтобы узнать частоту в герцах нужно 1000000 разделить на вычисленный период.

Измерение длительности периода состоит из двух частей, сначала измеряются длительности положительной и отрицательной полуволны в строках:

Htime=pulseln(10,HIGH);

Ltime=pulseln(10,LOW);

Затем, происходит вычисление полного периода в строке:

Ttime=Htime+Ltime ;

И потом, вычисление частоты в строке:

frequency=1000000/Ttime;

Действие программы по измерению напряжения основано на чтении данных с аналогового входа и расчета результата измерения. Выход аналогового порта преобразуется АЦП микроконтроллера в цифровую форму. Для получения результата в единицах вольт, нужно его умножить на 5 (на опорное напряжение, то есть, на напряжение питания микроконтроллера) и разделить на 1024.

Для того чтобы можно было измерять напряжение более 5V, вернее, более напряжения питания микроконтроллера, потому что реальное напряжение на выходе 5-вольтового стабилизатора на плате ARDUINO UNO может отличаться от 5V, и обычно немного ниже, нужно на входе применить обычные резистивные делители. Здесь это делитель напряжения на резисторах R5 и R4.

К тому же играет роль и применение трансформатора, а так же отличие значение постоянного напряжения от переменного. Поэтому добавляется исходный коэффициент деления величиной 0,016. Чтение данных с аналогового порта происходит в строке:

vout=analogRead(analogInput);

Затем, производится вычисление фактического напряжения с учетом коэффициента деления делителя входного напряжения:

volt=vout*5.0/1024.0/0.016;

В этой строке число 5.0 - это напряжение на выходе стабилизатора платы ARDUINO UNO. В идеале должно быть 5V, но для точной работы вольтметра это напряжение нужно предварительно измерить.

Подключите источник питания напряжением 12V и измерьте достаточно точным вольтметром напряжение +5V на разъеме POWER платы. Что будет, то и вводите в эту строку вместо 5.0, например, если будет 4.85V, строка будет выглядеть так:

volt=vout*4.85/1024.0/0.016;

Затем, результаты измерений выводятся на ЖК-дисплей. Напряжение вносится в первую строку дисплея, а частота во вторую. Единицы измерения указаны как «V» и «Hz». Что касается измерения частоты, - налаживание не требуется вообще. А вот для измерения напряжения нужно откалибровать прибор по образцовому подстройкой резистора R5.

Каравкин В. РК-10-17.

Если вы очень переживаете за расход электро энергии и жуть как хочется вычислить виновника - это ваш день. Мы соберем датчик тока напишем простую логику для обработки входных значений для пересчета значений в киловаты/ч.

Для сборки я использовал плату Arduino nano (никто не мешаем вам использовать тот же код для ESP или STM плат), LCD экранный шилд, резистор на 56 Ом, резисторы 100 кОм, конденсатор 10 мКф, датчик тока CT - Talema AC103 (с номинальным измерением 30A и максимальным 75A).

Что такое датчик тока?


Датчик тока - это магнитопровод с зазором и обмоткой компенсации, а так же встроенный датчик Холла и плата управления. Датчик Холла размещается в зазоре магнитопровода и реагирует на создаваемое катушкой магнитное поле. Чем сильнее напряженность магнитного поля, тем сильнее датчик Холла подает сигнал, который усиливается платой управления.
Датчики тока бывают для измерения переменного тока и постоянного тока. Наш - CT-Talema AC103 - для переменного.

Соберем наше устройство согласно схеме:


LCD шилд уже имеет выводы для подключения наших аналоговых портов для измерения сигнала - и это удобно.
Через датчик тока нужно пропустить единственный вводной кабель фазы т.к. на нулевой провод зачастую приходит не все напряжение - часть может уходить через заземление.


Не забываем, что нам нужно выполнить калибровку нагрузочного резистора R3. Формула расчета R = V / I - R = 2,5 / 0,042 = 59,5 Ом где 2,5 - опорное напряжение на плате, а 42mA - потребление платы. По тому принимаем самый близкий резистор по номиналу - 56 Ом.
Для деление основного напряжения питания до опорного 5/2 вам потребуется поставить два одинаковых резистора R1 и R2.

Остается только загрузить пример кода в Arduino:

//Michael Klements //The DIY Life //27 October 2014 #include int currentPin = 1; //Assign CT input to pin 1 double kilos = 0; int peakPower = 0; LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Assign LCD screen pins, as per LCD shield requirements void setup() { lcd.begin(16,2); // columns, rows. use 16,2 for a 16x2 LCD, etc. lcd.clear(); lcd.setCursor(0,0); // set cursor to column 0, row 0 (the first row) lcd.print("Running"); } void loop() { int current = 0; int maxCurrent = 0; int minCurrent = 1000; for (int i=0 ; i<=200 ; i++) //Monitors and logs the current input for 200 cycles to determine max and min current { current = analogRead(currentPin); //Reads current input and records maximum and minimum current if(current >= maxCurrent) maxCurrent = current; else if(current <= minCurrent) minCurrent = current; } if (maxCurrent <= 517) { maxCurrent = 516; } double RMSCurrent = ((maxCurrent - 516)*0.707)/11.8337; //Calculates RMS current based on maximum value int RMSPower = 220*RMSCurrent; //Calculates RMS Power Assuming Voltage 220VAC, change to 110VAC accordingly if (RMSPower > peakPower) { peakPower = RMSPower; } kilos = kilos + (RMSPower * (2.05/60/60/1000)); //Calculate kilowatt hours used delay (2000); lcd.clear(); lcd.setCursor(0,0); // Displays all current data lcd.print(RMSCurrent); lcd.print("A"); lcd.setCursor(10,0); lcd.print(RMSPower); lcd.print("W"); lcd.setCursor(0,1); lcd.print(kilos); lcd.print("kWh"); lcd.setCursor(10,1); lcd.print(peakPower); lcd.print("W"); }

Завершающим шрихом нашей установки станет калибровка. Ее лучше выполнять при включенной эталонной нагрузке известной мощности. Для этого хорошо подходят мощные лампы накаливания. Возьмем лампу на 100 Ват. Включаем плату и высчитываем поправочный коэффициент:
Двойной RMSCurrent = ((maxCurrent - 516) * 0,707) /11,8337 где 11.8337 - подобранный коэффициент для компенсации расхождений в измерениях.

Аналоговые входы платы Ардуино.

Плата Arduino UNO содержит 6 аналоговых входов предназначенных для измерения напряжения сигналов. Правильнее сказать, что 6 выводов платы могут работать в режиме, как дискретных выводов, так и аналоговых входов.

Эти выводы имеют номера от 14 до 19. Изначально они настроены как аналоговые входы, и обращение к ним можно производить через имена A0-A5. В любой момент их можно настроить на режим дискретных выходов.

pinMode(A3, OUTPUT); // установка режима дискретного вывода для A3
digitalWrite(A3, LOW); // установка низкого состояния на выходе A3

Чтобы вернуть в режим аналогового входа:

pinMode(A3, INPUT); // установка режима аналогового входа для A3

Аналоговые входы и подтягивающие резисторы.

К выводам аналоговых входов, так же как и к дискретным выводам, подключены подтягивающие резисторы. Включение этих резисторов производится командой

digitalWrite(A3, HIGH); // включить подтягивающий резистор к входу A3

Команду необходимо применять к выводу настроенному в режиме входа.

Надо помнить, что резистор может оказать влияние на уровень входного аналогового сигнала. Ток от источника питания 5 В, через подтягивающий резистор, вызовет падение напряжения на внутреннем сопротивлении источника сигнала. Так что лучше резистор отключать.

Аналого-цифровой преобразователь платы Ардуино.

Собственно измерение напряжение на входах производится аналого-цифровым преобразователем (АЦП) с коммутатором на 6 каналов. АЦП имеет разрешение 10 бит, что соответствует коду на выходе преобразователя 0…1023. Погрешность измерения не более 2 единиц младшего разряда.

Для сохранения максимальной точности (10 разрядов) необходимо, чтобы внутреннее сопротивление источника сигнала не превышало 10 кОм. Это требование особенно важно при использовании резисторных делителей, подключенных к аналоговым входам платы. Сопротивление резисторов делителей не может быть слишком большим.

Программные функции аналогового ввода.

int analogRead(port)

Считывает значение напряжения на указанном аналоговом входе. Входное напряжение диапазона от 0 до уровня источника опорного напряжения (часто 5 В) преобразовывает в код от 0 до 1023.

При опорном напряжении равном 5 В разрешающая способность составляет 5 В / 1024 = 4,88 мВ.

Занимает на преобразование время примерно 100 мкс.

int inputCod; // код входного напряжения
float inputVoltage; // входное напряжение в В

inputCod= analogRead(A3); // чтение напряжения на входе A3
inputVoltage= ((float)inputCod * 5. / 1024.); // пересчет кода в напряжение (В)

void analogReference(type)

Задает опорное напряжение для АЦП. Оно определяет максимальное значение напряжения на аналоговом входе, которое АЦП может корректно преобразовать. Величина опорного напряжения также определяет коэффициент пересчета кода в напряжение:

Напряжение на входе = код АЦП * опорное напряжение / 1024.

Аргумент type может принимать следующие значения:

  • DEFAULT – опорное напряжение равно напряжению питания контроллера (5 В или 3,3 В). Для Arduino UNO R3 – 5 В.
  • INTERNAL – внутреннее опорное напряжение 1,1 В для плат с контроллерами ATmega168 и ATmega328, для ATmega8 – 2,56 В.
  • INTERNAL1V1 – внутреннее опорное напряжение 1,1 В для контроллеров Arduino Mega.
  • INTERNAL2V56 – внутреннее опорное напряжение 2,56 В для контроллеров Arduino Mega.
  • EXTERNAL – внешний источник опорного напряжения, подключается к входу AREF.

analogReference(INTERNAL); // опорное напряжение равно 1,1 В

Двухканальный вольтметр на Ардуино.

В качестве примера использования функций аналогового ввода создадим проект простого цифрового вольтметра на Ардуино. Устройство должно измерять напряжения на двух аналоговых входах платы, и передавать измеренные значения на компьютер по последовательному порту. На примере этого проекта я покажу принципы создания простых систем измерения и сбора информации.

Решим, что вольтметр должен измерять напряжение в пределах не меньше 0…20 В и разработаем схему подключения входов вольтметра к плате Arduino UNO.

Если мы зададим опорное напряжение равным 5 В, то аналоговые входы платы будут измерять напряжение в пределах 0…5 В. А нам надо как минимум 0…20 В. Значит надо использовать делитель напряжения.

Напряжение на входе и выходе делителя связаны соотношением:

Uвыхода = (Uвхода / (R1 + R2)) * R2

Коэффициент передачи:

K = Uвыхода / Uвхода = R2 / (R1 + R2)

Нам необходим коэффициент передачи 1/4 (20 В * 1/4 = 5 В).

Для сохранения максимальной точности (10 разрядов) необходимо, чтобы внутреннее сопротивление источника сигнала не превышало 10 кОм. Поэтому выбираем резистор R2 равным 4,22 кОм. Рассчитываем сопротивление резистора R1.

0,25 = 4,22 / (R1 + 4,22)
R1 = 4,22 / 0.25 – 4,22 = 12,66 кОм

У меня с ближайшим номиналом нашлись резисторы сопротивлением 15 кОм. С резисторами R1 = 15 кОм и R2 = 4,22:

5 / (4,22 / (15 + 4,22)) = 22,77 В.

Схема вольтметра на базе Ардуино будет выглядит так.

Два делителя напряжения подключены к аналоговым входам A0 и A1. Конденсаторы C1 и C2 вместе с резисторами делителя образуют фильтры нижних частот, которые убирают из сигналов высокочастотные шумы.

Я собрал эту схему на макетной плате.

Первый вход вольтметра я подключил к регулируемому источнику питания, а второй к питанию 3,3 В платы Ардуино. Для контроля напряжения к первому входу я подключил вольтметр. Осталось написать программу.

Программа для измерения напряжения с помощью платы Ардуино.

Алгоритм простой. Надо:

  • с частотой два раза в секунду считывать код АЦП;
  • пересчитывать его в напряжение;
  • посылать измеренные значения по последовательному порту на компьютер;
  • программой монитор порта Arduino IDE отображать полученные значения напряжений на экране компьютера.

Приведу скетч программы сразу полностью.

// программа измерения напряжения
// на аналоговых входах A0 и A1

#include

время периода измерения
#define R1 15. // сопротивление резистора R1
#define R2 4.22 // сопротивление резистора R2


float u1, u2; // измеренные напряжения

void setup() {
Serial.begin(9600); //

MsTimer2::start(); // разрешение прерывания
}

void loop() {

// период 500 мс
if (timeCount >= MEASURE_PERIOD) {
timeCount= 0;

//

// чтение кода канала 2 и пересчет в напряжение
u2= ((float)analogRead(A1)) * 5. / 1024. / R2 * (R1 + R2);

// передача данных через последовательный порт
Serial.print("U1 = "); Serial.print(u1, 2);
Serial.print(" U2 = "); Serial.println(u2, 2);
}
}

// обработка прерывания 1 мс
void timerInterupt() {
timeCount++;
}

Поясню строчку, в которой пересчитывается код АЦП в напряжение:

// чтение кода канала 1 и пересчет в напряжение
u1= ((float)analogRead(A0)) * 5. / 1024. / R2 * (R1 + R2);

  • Считывается код АЦП: analogRead(A0) .
  • Явно преобразуется в формат с плавающей запятой: (float) .
  • Пересчитывается в напряжение на аналоговом входе: * 5. / 1024. Точка в конце чисел показывает, что это число с плавающей запятой.
  • Учитывается коэффициент передачи делителя: / R2 * (R1 + R2) .

Загрузим программу в плату, запустим монитор последовательного порта.

Два бегущих столбика показывают значения измеренных напряжений. Все работает.

Измерение среднего значения сигнала.

Подключим первый канал нашего вольтметра к источнику напряжения с большим уровнем пульсаций. Увидим такую картину на мониторе.

Значения напряжения первого канала на экране монитора все время дергаются, скачут. А показания контрольного вольтметра вполне стабильны. Это объясняется тем, что контрольный вольтметр измеряет среднее значение сигнала, в то время как плата Ардуино считывает отдельные выборки каждые 500 мс. Естественно, момент чтения АЦП попадает в разные точки сигнала. А при высоком уровне пульсаций амплитуда в этих точках разная.

Кроме того, если считывать сигнал отдельными редкими выборками, то любая импульсная помеха может внести значительную ошибку в измерение.

Решение – сделать несколько частых выборок и усреднить измеренное значение. Для этого:

  • в обработчике прерывания считываем код АЦП и суммируем его с предыдущими выборками;
  • отсчитываем время усреднения (число выборок усреднения);
  • при достижении заданного числа выборок – сохраняем суммарное значение кодов АЦП;
  • для получения среднего значения сумму кодов АЦП делим на число выборок усреднения.

Задача из учебника математики 8 класса. Вот скетч программы, двух канального вольтметра среднего значения.

// программа измерения среднего напряжения
// на аналоговых входах A0 и A1

#include

#define MEASURE_PERIOD 500 // время периода измерения
#define R1 15. // сопротивление резистора R1
#define R2 4.22 // сопротивление резистора R2

int timeCount; // счетчик времени
long sumU1, sumU2; // переменные для суммирования кодов АЦП
long avarageU1, avarageU2; // сумма кодов АЦП (среднее значение * 500)
boolean flagReady; // признак готовности данных измерения

void setup() {
Serial.begin(9600); // инициализируем порт, скорость 9600
MsTimer2::set(1, timerInterupt); // прерывания по таймеру, период 1 мс
MsTimer2::start(); // разрешение прерывания
}

void loop() {

if (flagReady == true) {
flagReady= false;
// пересчет в напряжение и передача на компьютер
Serial.print("U1 = ");
Serial.print((float)avarageU1 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
Serial.print(" U2 = ");
Serial.println((float)avarageU2 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
}
}

// обработка прерывания 1 мс
void timerInterupt() {

timeCount++; // +1 счетчик выборок усреднения
sumU1+= analogRead(A0); // суммирование кодов АЦП
sumU2+= analogRead(A1); // суммирование кодов АЦП

// проверка числа выборок усреднения
if (timeCount >= MEASURE_PERIOD) {
timeCount= 0;
avarageU1= sumU1; // перегрузка среднего значения
avarageU2= sumU2; // перегрузка среднего значения
sumU1= 0;
sumU2= 0;
flagReady= true; // признак результат измерений готов
}
}

В формулу пересчета кода АЦП в напряжение добавилось /500 – число выборок. Загружаем, запускаем монитор порта (Cntr+Shift+M).

Теперь, даже при значительном уровне пульсаций, показания меняются на сотые доли. Это только потому, что напряжение не стабилизировано.

Число выборок надо выбирать, учитывая:

  • число выборок определяет время измерения;
  • чем больше число выборок, тем меньше будет влияние помех.

Основным источником помех в аналоговых сигналах является сеть 50 Гц. Поэтому желательно выбирать время усреднения кратное 10 мс – времени полупериода сети частотой 50 Гц.

Оптимизация вычислений.

Вычисления с плавающей запятой просто пожирают ресурсы 8ми разрядного микроконтроллера. Любая операция с плавающей запятой требует денормализацию мантиссы, операцию с фиксированной запятой, нормализацию мантиссы, коррекцию порядка… И все операции с 32 разрядными числами. Поэтому необходимо свести к минимуму употребление вычислений с плавающей запятой. Как это сделать я расскажу в следующих уроках, но давайте хотя бы оптимизируем наши вычисления. Эффект будет значительный.

В нашей программе пересчет кода АЦП в напряжение записан так:

(float)avarageU1 / 500. * 5. / 1024. / R2 * (R1 + R2)

Сколько здесь вычислений, и все с плавающей запятой. А ведь большая часть вычислений – операции с константами. Часть строки:

/ 500. * 5. / 1024. / R2 * (R1 + R2)

(float)avarageU1 * 0.00004447756

Умные компиляторы сами распознают вычисления с константами и рассчитывать их на этапе компиляции. У меня возник вопрос, насколько умный компилятор Андруино. Решил проверить.

Я написал короткую программу. Она выполняет цикл из 10 000 проходов, а затем передает на компьютер время выполнения этих 10 000 циклов. Т.е. она позволяет увидеть время выполнения операций, размещенных в теле цикла.

// проверка оптимизации вычислений

int x= 876;
float y;
unsigned int count;
unsigned long timeCurrent, timePrev;

void setup() {
Serial.begin(9600);
}

void loop() {
count++;
// y= (float)x / 500. * 5. / 1024. / 4.22 * (15. + 4.22);
// y= (float)x * 0.00004447756 ;

if (count >= 10000) {
count= 0;
timeCurrent= millis();
Serial.println(timeCurrent - timePrev);
timePrev= timeCurrent;
}
}

В первом варианте, когда в цикле операции с плавающей запятой закомментированы и не выполняются, программа выдала результат 34 мс.

Т.е. 10 000 пустых циклов выполняются за 34 мс.

Затем я открыл строку:

y= (float)x / 500. * 5. / 1024. / 4.22 * (15. + 4.22);

повторяет наши вычисления. Результат 10 000 проходов за 922 мс или

(922 – 34) / 10 000 = 88,8 мкс.

Т.е. эта строка вычислений с плавающей запятой требует на выполнение 89 мкс. Я думал будет больше.

Теперь я закрыл эту строку комментарием и открыл следующую, с умножением на заранее рассчитанную константу:

y= (float)x * 0.00004447756 ;

Результат 10 000 проходов за 166 мс или

(166 – 34) / 10 000 = 13,2 мкс.

Потрясающий результат. Мы сэкономили 75,6 мкс на одной строке. Выполнили ее почти в 7 раз быстрее. У нас таких строк 2. Но ведь их в программе может быть и гораздо больше.

Вывод – вычисления с константами надо производить самим на калькуляторе и применять в программах как готовые коэффициенты . Компилятор Ардуино их на этапе компиляции не рассчитает. В нашем случае следует сделать так:

#define ADC_U_COEFF 0.00004447756 // коэффициент перевода кода АЦП в напряжение

Serial.print((float)avarageU1 * ADC_U_COEFF, 2);

Оптимальный по быстродействию вариант – это передать на компьютер код АЦП, а вместе с ним и все вычисления с плавающей запятой. При этом на компьютере принимать данные должна специализированная программа. Монитор порта из Arduino IDE не подойдет.

О других способах оптимизации программ Ардуино я буду рассказывать в будущих уроках по мере необходимости. Но без решения этого вопроса невозможно разрабатывать сложные программы на 8ми разрядном микроконтроллере.

На сайте появился еще один урок (

  • Tutorial

Введение

Всем привет! После завершения цикла по датчикам были вопросы различного плана по измерению параметров потребления бытовых и не очень электроприборов. Кто сколько потребляет, как что подключать чтобы измерить, какие бывают тонкости и так далее. Пришло время раскрыть все карты в этой области.
В этом цикле статей мы рассмотрим тему измерения параметров электроэнергии. Этих параметров на самом деле очень даже большое количество, о которых я постараюсь постепенно рассказать небольшими сериями.
Пока в планах три серии:
  • Измерение электроэнергии.
  • Качество электроэнергии.
  • Устройства измерения параметров электроэнергии.
В процессе разбора будем решать те или иные практические задачи на микроконтроллерах до достижения результата. Разумеется, большая часть данного цикла будет посвящена измерению переменного напряжения и может пригодиться всем любителям контролировать электроприборы своего умного дома.
По итогам всего цикла мы изготовим некий умный электросчетчик с выходом в интернет. Совсем отъявленные любители контролировать электроприборы своего умного дома могут оказать посильную помощь в реализации коммуникационной части на базе, например MajorDomo. Сделаем OpenSource умный дом лучше, так сказать.
В этой серии в двух частях мы разберем следующие вопросы:
  • Подключение датчиков тока и напряжения в устройствах постоянного тока, а также однофазных и трехфазных цепей переменного тока;
  • Измерение действующих значений тока и напряжения;
  • Измерение коэффициента мощности;
  • Полная, активная и реактивная мощность;
  • Потребление электроэнергии;
Подкатом вы найдете ответы на первые два вопроса данного списка. Я намеренно не затрагиваю вопросы точности измерения показателей и с данной серии лишь радуюсь полученным результатам с точностью плюс-минус лапоть. Этому вопросу я обязательно посвящу отдельную статью в третьей серии.

1. Подключение датчиков


В прошлом цикле про датчики напряжения и тока я рассказал о видах датчиков, но не рассказал о том как ими пользоваться и куда их ставить. Пришло время это исправить
Подключение датчиков постоянного тока
Понятно что весь цикл будет посвящён системам переменного тока, но быстро пробежимся и по цепям постоянного тока, так как это может нам пригодиться при разработке источников питания постоянного тока. Возьмем к примеру классический понижающий преобразователь с ШИМ :


Рис 1. Понижающий преобразователь с ШИМ
Нашей задачей является обеспечение стабилизированного выходного напряжения. Кроме того, на основании информации с датчика тока возможно контролировать режим работы дросселя L1, не допуская его насыщения, а также реализовывать токовую защиту преобразователя. И честно говоря, вариантов установки датчиков особо и нет.
Датчик напряжения в виде резистивного делителя R1-R2, который единственный способен работать на постоянном токе, устанавливается на выходе преобразователя. Как правило специализированная микросхема преобразователя имеет вход обратной связи, и прилагает все усилия для того, чтобы на этом входе (3) оказался определённый уровень напряжения, прописанный в документации на микросхему. Например 1,25В. Если наше выходное напряжение с этим уровнем совпадает - все хорошо - мы напрямую подаем выходное напряжение на этот вход. Если нет, то устанавливаем делитель. Если нам надо обеспечить выходное напряжение в 5В, то делитель должен обеспечивать коэффициент деления 4, т. е. Например R1 = 30к, R2 = 10к.
Датчик тока обычно устанавливается между источником питания и преобразователем и на микросхему. По разности потенциалов между точками 1 и 2, и при известном сопротивлении резисторы Rs возможно определить текущее значение тока нашего дросселя. Устанавливать датчик тока между источников и нагрузкой не самая хорошая идея, так как конденсатор фильтра будет отрезан резистором от потребителей импульсных токов. Установка резистора в разрыв общего провода тоже нге сулит ничего хорошего - будет два земляных уровня с которыми возиться то еще удовольствие.
Проблемы падения напряжения можно избежать путем использования бесконтактных датчиков тока - например датчиков холла:


Рис 2. Бесконтактный датчик тока
Однако есть более хитрый способ измерения тока. Ведь на транзисторе точно также падает напряжение и через него течет тот же самый ток что и индуктивность. Следовательно, по падению напряжения на нем можно также определить текущее значение тока. Честно говоря, если посмотреть на внутреннюю структуру микросхем преобразователей, например, от Texas Instruments - то такой способ встречается так же часто как и предыдущие. Точность такого способа конечно не самая высокая, но для работы токовой отсечки этого вполне достаточно.


Рис 3. Транзистор в качестве датчика тока
Аналогично поступаем в других схемах подобных преобразователей, будь то повышающий или инвертирующий.
Однако необходимо отдельно упомянуть о трансформаторных прямоходовом и обратноходовом преобразователях.


Рис 4. Подключение датчиков тока в обратноходовых преобразователях
В них точно также может использоваться либо внешнее сопротивление, либо транзистор в его роли.
На этом с подключением датчиков в преобразователи постоянного тока мы закончили. Если у вас есть предложения по другим вариантам - с удовольствием дополню ими статью.
1.2 Подключение датчиков в однофазные цепи переменного тока
В цепях переменного тока у нас гораздо больший выбор возможных датчиков. Рассмотрим несколько вариантов.
Самый простой - использование резистивного делителя напряжения и токового шунта.


Рис 5.Подключение резисторных датчиков
Однако, у нее усть пара существенных недостатков:
Во-первых, либо мы обеспечим значительную амплитуду сигнала с токового шунта, выделив большое количество мощности на нем, либо будем довольствоваться малой амплитудой сигнала и впоследствии усиливать его. А во-вторых, резистор создает разность потенциалов между нейтралью сети и нейтралью прибора. Если прибор изолирован - то это не имеет значения, если же у прибора есть вывод заземления, то мы рискуем остаться без сигнала с датчика тока, так как закоротим его. Пожалуй стоит попробовать датчики, работающие на других принципах.
Например, воспользуемся трансформаторами тока и напряжения, либо датчиком тока на эффекте холла и трансформатором напряжения. Здесь гораздо больше возможностей по работе с оборудованием, так как нулевой провод не имеет потерь, а главное - в обоих случаях присутствует гальваническая развязка измерительного оборудования, что часто может пригодиться. Однако, необходимо учитывать, что трансформаторные датчики тока и напряжения имеют ограниченную частотную характеристику и если мы захотим измерить гармонический состав искажений, то у нас это не факт что выйдет.


Рис 6.Подключение трансформаторных и бесконтактных датчиков тока и напряжения
1.3 Подключение датчиков в многофазные цепи сетей переменного тока
В многофазных сетях наши возможности по подключению датчиков тока немного меньше. Связано это с тем, что токовый шунт использовать совсем не получится, так как разность потенциалов между шунтами фаз будет колебаться в пределах сотен вольт и мне не известен ни один контроллер общего применения, аналоговые входы которого способны выдержать такое издевательство.
Один способ использовать токовые шунты конечно есть - для каждого канала необходимо сделать гальванически развязанный аналоговый вход. Но гораздо проще и надежнее использовать другие датчики.
В своем анализаторе качества я использую резистивные делители напряжения и выносные датчики тока на эффекте холла.

Рис 7.Датчики тока в трехфазной сети
Как видно из рисунка, мы используем четырехпроводное подключение. Разумеется вместо датчиков тока на эффекте холла можно взять трансформаторы тока или петли Роговского.
Вместо резистивных делителей можно использовать трансформаторы напряжения, причем как для четырехпроводной так и для трехпроводной системы.
В последнем случае первичные обмотки трансформаторов напряжения подключаются треугольником, а вторичные звездой, общая точка которых является общей точкой измерительной цепи


Рис 8.Использование трансформаторов напряжения в трехфазной сети

2 Действующее значение тока и напряжения


Пришло время решить задачу измерения наших сигналов. Практическую значимость для нас представляет в первую очередь действующее значение тока и напряжения.
Напомню матчасть из цикла по датчикам. С помощью АЦП нашего микроконтроллера через равные промежутки времени мы будем фиксировать мгновенное значение напряжения. Таким образом, за период измерения у нас будет массив данных уровня мгновенного значения напряжения (для тока все аналогично).


Рис 9. Серия мгновенных значений напряжения
Наша задача - произвести подсчет действующего значения. Для начала воспользуемся формулой интеграла:
(1)
В цифровой системе приходится ограничиваться неким квантом времени, так что мы переходим к сумме:
(2)
Где - период дискретизации нашего сигнала, а - число отсчетов за период измерения. Где-то здесь я в видео начинаю втирать дичь про равенство площадей. Надо было выспаться в тот день. =)
В микроконтроллерах MSP430FE4252, которые применяются в однофазных электросчетчиках Меркурий, за период измерения равный 1, 2 или 4 секунд производится 4096 отсчетов. На T=1с и N=4096 мы и будем опираться в дальшейнем. Более того, 4096 точек в секунду позволят нам использовать алгоритмы быстрого преобразования фурье для определения гармонического спектра вплоть до 40 гармоники, как того требует ГОСТ. Но об этом в следующей серии.
Набросаем алгоритм для нашей программы. Нам требуется обеспечить стабильный запуск АЦП каждую 1/8192 секунды, так как у нас два канал и измерять мы будем эти данные попеременно. Для этого настроим таймер и сигнал прерывания будет автоматически перезапускать АЦП. Все АЦП так умеют.
Писать будущую программу будем на arduino, так как она у многих под рукой. У нас пока чисто академический интерес.
Имея частоту системного кварца 16МГц и 8-разрядный таймер (чтобы жизнь медом не казалась) нам необходимо обеспечить частоту срабатывания хоть какого прерывания таймера с частотой 8192Гц.
Печалимся по поводу того что 16МГц цело не делится как нам надо и итоговая частота работы таймера 8198Гц. Закрываем глаза на погрешность в 0,04% и все равно считываем по 4096 выборок на канал.
Печалимся по поводу того, что прерывание по переполнению в arduino занято расчетом времени (отвечает за millis и delay, так что это работать нормально перестанет), так что пользуемся прерыванием по сравнению.
А еще внезапно понимаем, что сигнал к нам приходит биполярный, и что msp430fe4252 с ним прекрасно справляется. Мы же довольствуемся униполярным АЦП, поэтому на операционном усилителе собираем простой преобразователь биполярного сигнала в униполярный:


Рис 10.Преобразователь биполярного сигнала в униполярный
Причем наша задача обеспечить колебание нашей синусоиды относительно половины опорного напряжения - тогда мы либо отнимем половину диапазона либо активируем опцию в настройках АЦП и получим знаковые значения.
В Arduino 10-разрядный АЦП, поэтому из беззнакового результата в пределах 0-1023 будем вычитать половину и получим -512- 511.
Проверяем модель, собранную в LTSpiceIV и убеждаемся, что все работает как надо. В видеоматериале дополнительно убеждаемся экспериментально.


Рис 11.результат моделирования. Зеленым исходный сигнал, синим - выходной

Скетч для Arduino для одного канала

void setup() { autoadcsetup(); DDRD |=(1<

Программа написана в среде Arduino IDE для микроконтроллера ATmega1280. На моей отладочной плате первые 8 каналов разведены для внутренних нужд платы поэтому используется канал ADC8. Возможно использовать данный скетч и для платы с ATmega168, однако необходимо выбрать правильный канал.
Внутри прерываний передергиваем пару служебных пинов чтобы наглядно видеть рабочую частоту оцифровки.
Пару слов о том, откуда взялся коэффициент 102. При первом запуске с генератора подавался сигнал различной амплитуды, с осциллографа считывалось показание действующего значения напряжения, а из консоли забиралось рассчитанное значение в абсолютных единицах АЦП.

Umax, В Urms, В Counted
3 2,08 212
2,5 1,73 176
2 1,38 141
1,5 1,03 106
1 0,684 71
0,5 0,358 36
0,25 0,179 19

Разделив значения третьего столбца на значения второго получаем в среднем 102. Это и будет наш «калибровочный» коэффициент. Однако можно заметить, что при снижении напряжения точность резко падает. Это происходит из-за низкой чувствительности нашего АЦП. Фактически 10 разрядов для точных расчётов катастрофически мало и если напряжение в розетке измерить таким образом вполне получится, то поставить 10-разрядный АЦП на измерение потребляемого нагрузкой тока будет преступлением против метрологии.

На данном моменте мы прервемся. В следующей части рассмотрим другие три вопроса данной серии и будем плавно переходить к созданию непосредственно самого устройства.

Представленную прошивку, а также другие прошивки для данной серии (так как видеоматериалы я снимаю быстрее чем подготавливаю статьи) вы найдете в репозитории на GitHub.