Вольтметр с использованием Arduino mega 2560 дает неожиданный результат через некоторое время

Я пытался создать интеллектуальный счетчик электроэнергии, который мог бы отслеживать показания бытового напряжения 220 В. На данный момент я работаю над вольтметром. Я следил за цепью, которую я прикрепил. Трансформатор понижающий с 220В до 6В. Стабилитрон на 5В. Выход схемы (максимум 5 В) подается на контакт arduino Mega 2560 A0. * Я питаю Arduino с помощью USB-кабеля * Arduino принимает это напряжение в качестве входного сигнала от контакта A0 в виде аналоговых значений от 0 до 1023. 0 — это 0 вольт, а 1023 — это 5 вольт. Аналоговое значение jpg">dom соответствует X=(5/1023)*Y, где Y - полученное аналоговое значение. Затем X умножается на значение, полученное методом проб и ошибок (165 в моем случае), чтобы получить точное значение напряжения в линии, наблюдаемое с помощью мультиметра. Теперь проблема в том, что все работает нормально, когда я его калибрую, но через некоторое время, когда я включаю схему, значение становится неточным с запасом, и мне приходится калибровать его снова и снова каждый раз, когда я включаю схему через некоторое время. Если я включаю схему вскоре после выключения, она дает почти точное значение. Я предполагаю, что эта проблема связана с конденсатором, но я ничего не знаю об этом или как это решить Я собирал одну и ту же схему более 5 раз, припаивая ее 3 раза и 2 раза на макетная плата, и я уверен, что с моей реализацией проблем нет, проверено много раз. это мой код:

float V; // Образцы напряжения
float V0;

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

void loop() {
  for(int i=0; i<=20000; i++){
    V = V + analogRead(A0); 
  } 
  V = V / 20000;
  V = round(V);

  float V0 = V * (5.0 / 1023.0);
  I0 = I0 * 165; // приходится калибровать снова и снова каждый раз, когда схема включается через некоторое время

  Serial.print("Voltage = ");
  Serial.print(V0);
  Serial.println(" -------------- ");
  delay(1500);
}

это ссылка, по которой я перехожу http://engineerexperiences.com/3-phase-smart-energy-meter-using- arduino.html

Мы будем признательны за любую помощь, спасибо!

, 👍0

Обсуждение

вы следите за домочадцами или только за каким-то прибором или прибором?, @Juraj

спасибо, что спросили г-на Эдгара Боне, моя цель - контролировать потребление электроэнергии в домашнем хозяйстве., @Ali Kashan


2 ответа


1

С этой схемой вы можете ожидать отклонение выходного напряжения примерно на 10% в зависимости от точного момента, когда вы измеряете напряжение.

Основная схема, которая у вас есть, и сгенерированные сигналы выглядят так:

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

Поскольку вы пытаетесь получить среднее значение за неопределенный период (20 000 отсчетов, сколько именно за один отсчет?), вы не получите четко определенных результатов.

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

В идеале вы хотите повторно сэмплировать как минимум один полный цикл сигнала. При 50 Гц это период 20 мс (17 мс для 60 Гц).

Например:

uint16_t maxval = 0;
uint32_t ts = millis();
while (millis() - ts < 20) {
    uint16_t val = analogRead(0);
    if (val > maxval) {
       maxval = val;
    }
}

// Используйте "maxval" в своих вычислениях.

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

,

он использует в среднем 20000 показаний A0, @Juraj

Да, теперь пост отформатирован, я вижу это. Однако это не совсем идеально, поскольку вы зависите от а) скорости чтения АЦП и б) скорости разряда конденсатора. Найдя максимум по крайней мере за 1 волновой период, вы не заботитесь ни о том, ни о другом., @Majenko

Переформулировал его, чтобы немного больше соответствовать существующему методу., @Majenko

Уважаемый Маженко, прежде всего благодарю вас за то, что уделили мне время и поделились со мной удивительными знаниями. Раньше я использовал этот подход для (целое я = 0; я <= 39; я ++) { adc_int[i] = AnalogRead(A0); } интервал макс = adc_int[0]; для (целое я = 0; я <= 39; я ++) { если (макс. < adc_int[i]) макс = adc_int[i]; } и я использовал это пиковое значение в своих расчетах, результаты были непредсказуемы по прошествии времени, как я объяснил в своем вопросе, в любом случае я буду следовать тому, что вы проинструктировали, и вернусь к вам вскоре после реализации ваших учений., @Ali Kashan


0

Я просто хотел добавить несколько моментов к тому, что уже сказал Маженко.

Вы делаете измерительное устройство, поэтому вам нужен точный эталон. Итак, почему вы используете эталон 5 В?

Предполагается, что напряжение 5 В в вашей цепи стабильно. Но так ли это? Возможно, какое-то время вы используете ПК для его питания, затем подключаете много нагрузок к USB-портам, затем используете настенный блок питания USB. Каждый раз, когда 5V может меняться (см., например, здесь). Отклонение в подаче на +/-5% будет преобразовано в +/- 12 В для входа 240 В (я не знаю, выше или ниже ожидаемой точности).

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

В вашем случае (Arduino MEGA 2560) у вас есть внутренние ссылки 1,1 В или 2,56 В. Ваш трансформатор представляет собой трансформатор 240-> 6 В, что означает, что значение, которое вы должны прочитать после него, составляет около 8,5 В (6 В среднеквадратичного значения имеет пик 6 * 1,415 = 8,5 В). После делителя напряжения это становится 1,53 В. Следовательно, в этом случае вы можете использовать опорное значение 2,56 В. Для этого напишите в своей функции установки analogReference(INTERNAL2V56);. Тогда ваши показания будут относиться к 2,56 В, а не к 5,0 В (поэтому float V0 = V * 2,56 / 1023,0;).

(Примечание: способ реализации взят из справочного руководства arduino; я никогда не реализовывал это, поэтому может потребоваться настройка)

,