Измеритель мощности ( амперметр и вольтметр)

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Прощу помощи: хочу сделать ваттметр. Получилось своими мучениями сделать вольтмер и вывести это дело на экран, на остальное мозгов не хватает.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int analogInput = A0;  // номер порта ардуино
float vin = 0;      // входное напряжение

void setup(){
lcd.begin();
   pinMode(analogInput, INPUT);
   lcd.print("DC VOLTMETER");
}
void loop(){
   // считывание аналогового значения
    vin = float(analogRead(analogInput))/38;  //значение на входе *1.41 для измерения тока
   
lcd.setCursor(0, 1);
lcd.print("INPUT V= ");
lcd.print(vin);
delay(500);                          // время через которое идет считывание показаний
}

 

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

и нашел для датчика ACS712 5A скетч, но не могу понять как его сделать чтобы показывал на экране и ватты.

void setup() {
 
  Serial.begin(9600);
}
 
void loop() {
 
  float average = 0;
  for(int i = 0; i < 1000; i++) {
    average = average + (.0264 * analogRead(A1) -13.51) / 1000;//this is 
    //for the 5A mode, if 20A or 30A mode, need to modify this formula to 
    //(.19 * analogRead(A0) -25) for 20A mode and 
    //(.044 * analogRead(A0) -3.78) for 30A mode
    delay(1);
  }
  Serial.println(average);  
}

 

Logik
Offline
Зарегистрирован: 05.08.2014

Да как обычно, умножить напряжение на ток.

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

это я помимаю, как это в программе написать?) Я же говорю не буб бум в этом(

Logik
Offline
Зарегистрирован: 05.08.2014

пишите *

gena
Offline
Зарегистрирован: 04.11.2012
angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

выдает ошибку

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int analogInput = A0;  // номер порта ардуино
int ampIn = A1;
float vin = 0;      // входное напряжение
float average = 0;
float Watts = 0;

void setup(){
lcd.begin();
   pinMode(analogInput, INPUT);
   pinMode(ampIn, INPUT);
   pinMode(Watts, INPUT);

}

void loop(){
   // считывание аналогового значения
    vin = float(analogRead(analogInput))/38; 
    average = average + (.0264 * analogRead(A1) -13.51) / 1000;  
     Watts = vin * average
 }

lcd.setCursor(0, 0);
lcd.print("Volt ");
lcd.print(vin);
lcd.setCursor(12,0);
lcd.print(" W");
lcd.setCursor(0, 1);// время через которое идет считывание показаний
lcd.print("Amp");
lcd.print(average);
delay(1);
}



 

Logik
Offline
Зарегистрирован: 05.08.2014

точку с запятой в стр.22

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Logik пишет:

точку с запятой в стр.22

Поставил, выдал ошибку по этой строке lcd.print(average);

exit status 1
'lcd' does not name a type
 

karl2233
karl2233 аватар
Offline
Зарегистрирован: 05.07.2015

глянь туд

Logik
Offline
Зарегистрирован: 05.08.2014

стр.23 удалить

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Logik пишет:

стр.23 удалить

Спасибо получилось, но вот данные амперметра не считываються по нулям.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int analogInput = A0;  // номер порта ардуино
int ampIn = A1;
float vin = 0;      // входное напряжение
float average = 0;
float Watts = 0;

void setup(){
lcd.begin();
   pinMode(analogInput, INPUT);
   pinMode(ampIn, INPUT);
   pinMode(Watts, INPUT);

}

void loop(){
   // считывание аналогового значения
    vin = float(analogRead(analogInput))/38;  
    average = (.0264 * analogRead(A1) -13.51) / 1000;  
     Watts = vin * average;


lcd.setCursor(0, 0);
lcd.print("Volt= ");
lcd.print(vin);
lcd.setCursor(9,1);
lcd.print(" W= ");
lcd.setCursor(0, 1);// время через которое идет считывание показаний
lcd.print("Amp=");
lcd.print(average);
delay(350); 
}

 

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Исходный код датчика, при мониторенге на компе показывает верно:

void setup() {
 
  Serial.begin(9600);
}
 
void loop() {
 
  float average = 0;
  for(int i = 0; i < 1000; i++) {
    average = average + (.0264 * analogRead(A1) -13.51) / 1000;//this is 
    //for the 5A mode, if 20A or 30A mode, need to modify this formula to 
    //(.19 * analogRead(A0) -25) for 20A mode and 
    //(.044 * analogRead(A0) -3.78) for 30A mode
    delay(1);
  }
  Serial.println(average);  
}

 

Araris
Онлайн
Зарегистрирован: 09.11.2012

Вы цикл потеряли, в скетч из #11 вместо строки 21 вставьте строки 9-15 из скетча #12.

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Araris пишет:

Вы цикл потеряли, в скетч из #11 вместо строки 21 вставьте строки 9-15 из скетча #12.

Не помогло ошибка по этой строке (int i = 0; i < 1000; i++)

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int analogInput = A0;  // номер порта ардуино
int ampIn = A1;
float vin = 0;      // входное напряжение
float average = 0;
float Watts = 0;

void setup(){
lcd.begin();
   pinMode(analogInput, INPUT);
   pinMode(ampIn, INPUT);
   pinMode(Watts, INPUT);

}

void loop(){
   // считывание аналогового значени
    vin = float(analogRead(analogInput))/37.5;  
    (int i = 0; i < 1000; i++)
    average = average + (.0264 * analogRead(A1) -13.51) / 1000; 
    Watts = vin * average;


lcd.setCursor(0, 0);
lcd.print("Volt= ");
lcd.print(vin);
lcd.setCursor(9,1);
lcd.print(" W= ");
lcd.setCursor(0, 1);// время через которое идет считывание показаний
lcd.print("Amp=");
lcd.print(average);
delay(350); 
}

И ватт нет

Araris
Онлайн
Зарегистрирован: 09.11.2012
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int analogInput = A0;  // номер порта ардуино
int ampIn = A1;
float vin = 0;      // входное напряжение
float average = 0;
float Watts = 0;

void setup(){
lcd.begin();
   pinMode(analogInput, INPUT);
   pinMode(ampIn, INPUT);
   pinMode(Watts, INPUT);

}

void loop(){
   // считывание аналогового значения
    vin = float(analogRead(analogInput))/38;  
    average = 0;
    for (int i = 0; i < 1000; i++) 
    {
    average = average + (.0264 * analogRead(A1) -13.51) / 1000;//this is 
    //for the 5A mode, if 20A or 30A mode, need to modify this formula to 
    //(.19 * analogRead(A0) -25) for 20A mode and 
    //(.044 * analogRead(A0) -3.78) for 30A mode
    delay(1);
    }
    Watts = vin * average;

lcd.setCursor(0, 0);
lcd.print("Volt= ");
lcd.print(vin);
lcd.setCursor(9,1);
lcd.print(" W= ");
lcd.setCursor(0, 1);// время через которое идет считывание показаний
lcd.print("Amp=");
lcd.print(average);
delay(350); 
}

 

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Araris вы гений, спасибо!!

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Дорогие друзья а почему у меня вычесления не производиться: амп. не умножается на вольт= ватт?

Araris
Онлайн
Зарегистрирован: 09.11.2012

Спасибо, я-то может и гений, а вот Вы, по-моему, даже и не пытаетесь. Так неинтересно.

Между 36-й и 37-й строкой скетча вставьте lcd.print(Watts);

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Araris пишет:

Спасибо, я-то может и гений, а вот Вы, по-моему, даже и не пытаетесь. Так неинтересно.

Между 36-й и 37-й строкой скетча вставьте lcd.print(Watts);

В общем что получилось) Конечно с ващей помощью.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
int analogInput = A0;  
int ampIn = A1;
float vol = 0;     
float average = 0;
float Watts = 0;

void setup(){
lcd.begin();
   pinMode(analogInput, INPUT);
   pinMode(ampIn, INPUT);
   pinMode(Watts, INPUT);

}

void loop(){
  vol = float(analogRead(analogInput))/42;    
    if (vol<0.01) {
   vol=0.0;
}
    average = 0;
    for (int i = 0; i < 1000; i++) 
{
    average = average + (.0264 * analogRead(A1) -13.51) / 1000;
 if (average<-0.00)
    average=0.0;
    Watts = vol * average;

}

lcd.setCursor(0, 0);
lcd.print("Volt= ");
lcd.print(vol);
lcd.setCursor(9,1);
lcd.print(" W= ");
lcd.print(Watts);
lcd.setCursor(0, 1);
lcd.print("Amp=");
lcd.print(average);
delay(500); 
}

 

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

В общем пришел датчик тока на 20А изменил стороку, показания стали не верные

average = average + (.0264 * analogRead(A1) -13.51) / 1000;
average = average + (.19 * analogRead(A1) -25) / 1000;

 

MagicianT
Offline
Зарегистрирован: 03.10.2015

А ток какой, и напряжение, где меряете?

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

просто измерительный прибор, ток от 0 до 20 меняеться, напрежение до 30в

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

angersos пишет:

просто измерительный прибор, ток от 0 до 20 меняеться, напрежение до 30в

Ардуино непосредственно не может измерять ни то, ни другое.

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Есть формула

average = average + (.049 * analogRead(A1) -25) / 1000;

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

angersos, а Вы понимаете, что в этой формуле откуде берется?

При замене датчика нужно соответствующим образом изменить знаменатель. Нужное значение содержится в дэйташите.

(это то, как я понял Вашу проблему. А так - MagicianT прав: нужно приводить схему включения.)

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

ну примерно,0185 по даташит.,2,5 напрежение

MagicianT
Offline
Зарегистрирован: 03.10.2015

В даташите другие данные, датчик на 20А - 100мВ/А. Те 2.5В смещения, они не всегда 2.5, и ошибка будет накапливаться. Надо мерять при отключеной нагрузке, скажем в сетапе прокрутите 1000 циклов, наберите сумму и сохраните как лонг переменную, а потом в основной программе её и отнимайте. 

 Я не вижу смысла 1000 раз умножать и делить, при измерении сделайте проще - в цикле сначала наберите сумму а потом сразу по выходу один раз поделите отнимите.
 average = 0;
    for (int i = 0; i < 1000; i++)
{
    average = average +  analogRead(A1); 
}
 
  average = (0.049 * average  -/*primerno*/2500.51) / 1000;
 if (average<-0.00)
    average=0.0;
    Watts = vol * average;
 

 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Вот-вот, мне тоже что-то припоминается, что 185 mV/A - это для 5-Амперного датчика.

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

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

Все нормально, измерил ток тестером, немного исправил значения)

tmr
Offline
Зарегистрирован: 19.05.2014

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

Для 32u4:

long readVcc() {
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
    
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both

  long result = (high<<8) | low;

  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

Сам столкнулсь с такой проблемой, когда с питания usb (4.9В) вычислялись одни значения тока, с внешнего питания (5.2В) другие на одной и той же нагрузке.

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

tmr и куда это вставить?)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

tmr пишет:

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

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

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

tmr
Offline
Зарегистрирован: 19.05.2014
andriano, так точно Капитан.
 
Погрешность кристалла стабильна для конкретной платы, устраняется единожды поправочным коэффициентом.
 
В любом случае это лучше чем ничего.
 
angersos,
long vref = readVcc();

float a = vref / 2 / 100; //ток для датчика 20А, если я правильно помню

float v = vref * (R2 / (R1 + R2)) //напряжение, если собрано на делителях

далее по смыслу

angersos
angersos аватар
Offline
Зарегистрирован: 09.06.2016

ну меня пока устраивает моя система)