Вольтамперметр для блока питания (Arduino)

Цифровой вольтамперметр предназначенный для установки в блок питания для отображения выходного напряжения и тока. Дополнительно используется отключение нагрузки когда ток нагрузки превышает допустимый порог. Допустимый порог устанавливается кнопками «+» и «-» с шагом 0,01 А. При превышении допустимого тока срабатывает реле и отключает нагрузку на 10 секунд, на индикаторе (1602 на базе контроллера HD44780) появляется надпись «10sOFF». Если ток нагрузки не превышает допустимый предел, на индикаторе высвечивается надпись «ON». При изменении уставки максимальной нагрузки на индикаторе высвечивается надпись «REG». Значение максимально допустимого тока сохраняются в энергонезависимой памяти при каждом его изменении.

Для обеспечения высокой точности измерения тока до 10 А и напряжения до 30 В используется АЦП-модуль ADS1115 который представляет собой 16-битный аналого-цифровой преобразователь, он имеет 4 входа для преобразования аналогового сигнал в цифровой.

При измерении напряжения от 0 до 30 множитель АЦП равен 1, при этом максимальное измеряемое напряжение равно  4.096 В с разрешением 1 bit = 0.125 мВ, но с учетом делителя напряжения на резисторах R2 R3 (8 раз) разрешение падает до 2 мВ при измерении напряжения до 30 В.

При измерении тока от 0 до 10 А множитель АЦП равен 16, а максимальное измеряемое напряжение равно 0.256 В с разрешением 1 bit = 0.0078125 мВ. Но на шунте при токе 10 А (практически можно измерять ток до 25,6 А, но в данном варианте, на индикатор выводится ток до 10 А) возникает падение напряжения 100 мВ, поэтому измерение тока производится с минимальным разрешением 0,001 А (0,78125 мА).

Как видно на схеме R4 R6 замыкают входы на землю, это сделано для измерения дрейфа нуля АЦП, эти измерения вносят поправку на результаты измерения тока и напряжения. Дополнительно используется программная коррекция измерений при падении напряжения на шунте.

При каждом цикле программы измерения напряжения и тока производятся по 10 раз, далее выводится среднее значение тока и напряжения.

При подключении шунта, следует обратить внимание на порядок подключения: минус питания ИП подключается к шунту, а затем из точки соединения шунта с ИП идет подключение к земле платы Arduino. Далее коротким проводом второй конец шунта подключается к нагрузке.

Шунт (до 10 А) и делитель напряжения R1 R2 (0,25 Вт и выше) могут иметь достаточно большую погрешность, во время калибровки в скетче необходимо указать калибровочные значения для тока и напряжения.

#include <Wire.h>
#include <Adafruit_ADS1015.h> // Adafruit_ADS1X15-master.zip
#include <EEPROM.h>//#include <EEPROMex.h>
Adafruit_ADS1115 ads;
#include <LiquidCrystal.h>
  LiquidCrystal lcd(7, 6, 2, 3, 4, 5);// RS,E,D4,D5,D6,D7
 
  int u0,u1,a2,a3,i;
  byte w,stop;
  float u_0,u_1,u_ob0,u_ob1,a_2,a_3,a_ob2,a_ob3,i_reg;
  unsigned long time=millis();
  const float kalib0=7.970;// калибровка вольтметра А0 по максимальному напряжению 30V I=0
  const float kalib2=1.000;// калибровка амперметра А2 по максимальному току 10 А
 
void setup(void){
  Serial.begin(9600);
  lcd.begin(16, 2);
  pinMode(12,INPUT);pinMode(11,INPUT);pinMode(10,OUTPUT);
  i_reg = EEPROM.read(0)+(float)EEPROM.read(1)/100;// reg eeprom
  ads.begin();delay(100);
}
 
void loop(){
  if(digitalRead(12)==HIGH){i_reg=i_reg+0.01;if(i_reg>=9.99){i_reg=9.99;}time=millis();delay(200);w=1;}
  if(digitalRead(11)==HIGH){i_reg=i_reg-0.01;if(i_reg<0){i_reg=0.01;}time=millis();delay(200);w=1;}
  if(millis()-time>3000){
////////////////////////////////// вольтметр //////////////////////////////////////////// 
 while(i<10){i++;ads.setGain(GAIN_ONE);
   u0 = ads.readADC_SingleEnded(0);u_0 = u0*0.125*kalib0/1000;delay(20);
   u1 = ads.readADC_SingleEnded(1);u_1 = u1*0.125*kalib0/1000;delay(5);
   u_ob0=u_ob0+u_0;u_ob1=u_ob1+u_1;}
   u_0=u_ob0/10;u_ob0=0;u_1=u_ob1/10;u_ob1=0;i=0;  u_0=u_0-u_1;
  ///////////////////////////////// амперметр /////////////////////////////////////////////
 while(i<10){i++;ads.setGain(GAIN_SIXTEEN);
   a2 = ads.readADC_SingleEnded(2);a_2 = a2*0.0078125*kalib2/10;
   if(a_2>=i_reg){digitalWrite(10,LOW);stop=1;break;}else{digitalWrite(10,HIGH);}delay(20);
   a3 = ads.readADC_SingleEnded(3);a_3 = a3*0.0078125*kalib2/10;delay(5);
   a_ob2=a_ob2+a_2;a_ob3=a_ob3+a_3;}
   a_3=a_ob3/10;a_ob3=0;a_2=a_ob2/10;a_ob2=0;i=0;a_2=a_2-a_3; 
    ///////////////////////////////// вывод на экран ///////////////////////////////////////
   if(a_2<0.005){a_2=0;}if(u_0<0.005){u_0=0;}// измерения начинаются с 0,005 В и с 0,005 А
   u_0=u_0-(a_2/100);// компенсация напряжения шунта
  }
   lcd.setCursor(0,0);if(u_0<=9.999){lcd.print(" ");}lcd.print(abs(u_0),3);lcd.print(" B");
   if(millis()-time<3000){lcd.print("  REG    ");}
   lcd.setCursor(0,1);lcd.print(" ");lcd.print(abs(a_2),3);lcd.print(" A  ");lcd.print(i_reg,2);lcd.print(" A ");
   if(stop==1){lcd.setCursor(9,0);lcd.print(" 10sOFF ");stop=0;delay(10000);}
   if(stop==0&&millis()-time>3000){lcd.setCursor(9,0);lcd.print(" ON    ");}
 
   if(w==1){EEPROM.update(0,(int)i_reg);EEPROM.update(1,i_reg*100-(int)i_reg*100);w=0;}
}

Библиотека — https://github.com/addicore/ADS1115/archive/master.zip

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=5243#p5243

Comments

  1. Здравствуйте. Заинтересовал Ваш ампервольтметр,поэтому вопрос:почему коэфициент делителя R2,R3 равен 8,и надо ли изменять множитель АЦП при сопротивлении шунта 0,1 Ом

    1. В статье опечатка, делитель напряжения R1 R2 47к 6,8К — это делитель для напряжения.
      Да множитель GAIN_SIXTEEN надо менять на GAIN_FOUR и 0.0078125 заменить 0.03125

  2. кнопками с шагом 0.01А очень долго регулировать от 0 до 9.99.
    добавил еще две кнопки с шагом 1А
    ////
    pinMode(9,INPUT);
    pinMode(8,INPUT);
    ////
    if(digitalRead(9)==HIGH){i_reg=i_reg+1.00;if(i_reg>=9.99)
    {i_reg=9.99;}time=millis();delay(200);w=1;}
    if(digitalRead(8)==HIGH){i_reg=i_reg-1.00;if(i_reg<0)
    {i_reg=0.01;}time=millis();delay(200);w=1;}

  3. Здравствуйте.Подскажите как перевести АЦП в режим 860FPS,хочу сделать преобразование и усреднение в прерываниях,а вычисления и индикацию в основном цикле.

    1. ADS1115.cpp

      void ADS1115::initialize() {
      setMultiplexer(ADS1115_MUX_P0_N1);
      setGain(ADS1115_PGA_2P048);
      setMode(ADS1115_MODE_SINGLESHOT);
      setRate(ADS1115_RATE_128);
      setComparatorMode(ADS1115_COMP_MODE_HYSTERESIS);
      setComparatorPolarity(ADS1115_COMP_POL_ACTIVE_LOW);
      setComparatorLatchEnabled(ADS1115_COMP_LAT_NON_LATCHING);
      setComparatorQueueMode(ADS1115_COMP_QUE_DISABLE);
      }

      >>>

      void ADS1115::initialize() {
      setMultiplexer(ADS1115_MUX_P0_N1);
      setGain(ADS1115_PGA_2P048);
      setMode(ADS1115_MODE_SINGLESHOT);
      setRate(ADS1115_RATE_860);
      setComparatorMode(ADS1115_COMP_MODE_HYSTERESIS);
      setComparatorPolarity(ADS1115_COMP_POL_ACTIVE_LOW);
      setComparatorLatchEnabled(ADS1115_COMP_LAT_NON_LATCHING);
      setComparatorQueueMode(ADS1115_COMP_QUE_DISABLE);
      }

Добавить комментарий

Войти с помощью: