27 МОСКОВСКАЯ ВСТРЕЧА
Форум самогонщиков Сайт Барахолка Магазин 27 МОСКОВСКАЯ ВСТРЕЧА

Регулятор напряжения и тока на Arduino Pro Mini

Форум самогонщиков Автоматика
1 ... 26 27 28 29 30 31 32 ... 58 29
nod32 Бакалавр Новокузнецк 90 20
Отв.560  04 Янв. 18, 15:54
Какой надо использовать arduino ide? На 1.0.5 и 1.8.5 при компиляции показывает ошибки.Например
U_regulator1.ino: In function 'void setup()':
U_regulator1:63: error: 'class LiquidCrystal' has no member named 'backlight'
Практически все связаны с дисплеем.
U-M Магистр MSK 210 39
Отв.561  04 Янв. 18, 17:32
Похоже у Вас библиотека отсутствует LiquidCrystal_I2C.h. В комментарии ссылка для скачивания есть: https://github.com/marcoschwartz/LiquidCrystal_I2C лучше все файлы архивом скачать и распаковать в папку с библиотеками IDE.



Добавлено через 15мин.:

Скрестил тут ужа с ежом. Точнее библиотека, выложенная коллегой Tomat7 [сообщение #13199115] вместе со скетчем, где используется LCD+EEPROM+энкодер+внешний старт-стоп. Однако LCD подключен 4-битным способом, а энкодер заменил на кнопки (ну и библиотека для их обслуживания) без подтягивающих резисторов. Дополнительно отбросил экран с суммарной мощностью и временем работы.
Для себя из плюсов с этой клавиатурой - нет задумчивости и эффекта цикличности, когда кнопка нажата долго и какой-то режим щелкает туда-обратно.
Трансформатор тока на 30А Talema AC1030. Под него добавочный резистор в 56 Ом (в идеале 59 Ом). 30А многовато - менее 100Вт нагрузку не видит и соответственно некоректро работает. С нормальной нагрузкой нормально. Ну и сейчас нечем входное напряжение пошатать, посмотреть как стабилизируется мощность нагрузки.

Скрытый текст/*
  Вход с детектора нуля - 3 (D3)
  Выход на триак - 5 (D5)
  Аналоговый вход с датчика тока - 15 (A1)
 
  LCD 8,       9,  10,  11,  12,  13
      (D8,     D9, D10, D11, D12, D13)
      A0 (RS), E,  DB4, DB5, DB6, DB7
      R/W - GND
         
  Разгон - 7 (D7)
  Стоп - 6 (D6)
 
  Общий для всех кнопок - 2 (D2)
  Кнопка записи в память - 14 (A0)
  Кнопка меню настроек - 16 (A2)
  Кнопка вкл/выкл - 17 (A3)
  Кнопка режима ректификации (- мощности) - 18 (A4)
  Кнопка режима дистилляции (+ мощности) - 19 (A5)
 
  Serial:
  Rx - 0 (D0)
  Tx - 1 (D1)
*/


#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <Keypad.h>
#include "RegPower.h"

#define MAXPOWER 1400                                   // мощность ТЭНа при 230В
#define SERIALSPEED 9600                                // скорость serial
#define ACCELERATOR 7                                   // Вывод разгона
#define STOP 6                                          // Вывод стоп

uint16_t inst_P = 0;                                    // мощность с serial
double step_W = 5;                                      // шаг установки мощности с кнопок
byte set = 0;                                           // флаг включения разгона-стопа
byte set_menu_I = false;                                // флаг главного меню или меню настроек мощности
byte set_W = false;                                     // флаг включения регулятора с кнопок
String T1, Var;                                         // переменные для обработки строки из serial
char buttonCode;                                        // код нажатой кнопки
unsigned long displayMillis = 0;                        // для циклического опроса lcd, serial, кнопки 0
unsigned long serialMillis = 0;
unsigned long wrMillis = 0;
int preset_max = 1;                                     // число предустановок + 1 = 2
char* name_preset[] = {"RECT ", "DIST "};               // имена предустановок
int preset = 0;                                         // начальная предустановка
int buffer_ust_W[3];                                    // буфер для предустановок
int ACCELERATOR_press_time = 0;                         // для циклического опроса и состояния выводов стопа и разгона
unsigned long ACCELERATOR_time_press = 0;
int STOP_press_time = 0;
unsigned long STOP_time_press = 0;
const byte ROWS = 1;                                    // одна строка клавиатуры
const byte COLS = 5;                                    // пять столбцов клавиатуры
char hexaKeys[ROWS][COLS] = {                           // массив имен кнопок клавиатуры
 {'0','1','2','3','4'}
};
byte rowPins[ROWS] = {2};                               // клавиатура
byte colPins[COLS] = {14, 16, 17, 18, 19};              

 Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);              

 LiquidCrystal lcd(8, 9, 10, 11, 12, 13);              


void setup() {  
 Serial.begin(SERIALSPEED);                            // инициализация serial
 
 TEH.init(MAXPOWER);                                   // инициалbзация регулятора
 
 lcd.begin(16, 2);                                     // инициализация LCD
 lcd.clear();  

 pinMode(ACCELERATOR, INPUT);                          // разгон
 pinMode(STOP, INPUT);                                 // стоп
 
 digitalWrite(ACCELERATOR, HIGH);                      // pull-upp
 digitalWrite(STOP, HIGH);  

 for (preset = preset_max ; preset >= 0 ; preset--) {  // чтение значений предустановок из eeprom
   buffer_ust_W[preset] = EEPROM_read(preset * 2);
 }
 
 preset = 1;                                           // начальная предустанока dist=1 или rect=0
}


void loop() {  
 TEH.control();                                        // регулирование мощности Непонимающий
 
 buttonCode = customKeypad.getKey();                   // код нажатой кнопки

 readPins();                                           // опрос выводов разгона/стопа

 if (set_W){
  TEH.setpower(buffer_ust_W[preset]);                  // корректируем мощность? если режим вкл с кнопок или просто все отключено, если выкл с кнопок
 }
   else {
    TEH.setpower(0);
   }

 readKeys();                                           // опрос кнопок
 readSerial();                                         // чтение из serial
 sendLCD();                                            // вывод на lcd
 sendSerial();                                         // вывод в serial
}


void sendLCD() {
 if (millis() - displayMillis >= 1000) {               // каждую секунду обновляем экран
   displayMillis = millis();
   
   switch (!set_menu_I) {                              // основной экран
    case true:
     lcd.setCursor(0, 0);
     lcd.print("REAL ");
     lcd.print(TEH.Pnow);                              // текущая мощность
     lcd.print(" W    ");
    break;
   }

 lcd.setCursor(0, 1);
 lcd.print(name_preset[preset]);                       // активная предустановка

   switch (set) {                                      // отображение режима разгон-стоп
    case 3:
      lcd.print("STOPPED   ");
    break;      
    case 1:
      lcd.print("FORSAGE   ");
    break;      
    default:
      lcd.print(TEH.Pset);                             // предустановленная мощность
      lcd.print(" W        ");
   }

   switch (set_menu_I) {                               // экран настройки мощости для предустановок и регулирования текущей мощности        
    case true:
     lcd.setCursor(0, 0);
     lcd.print("SET POWER:  ");
     lcd.setCursor(0, 1);
     lcd.print(name_preset[preset]);
     lcd.print("< ");
     lcd.print(TEH.Pset);
     lcd.print(" W      ");
    break;
   }
   
   switch (set_W) {                                    // вывод состояния регулятора вкл/выкл, независимо от состояния входов стоп-разгон  
    case true:
      lcd.setCursor(13, 0);
      lcd.print(" ON");
    break;      
    case false:
      lcd.setCursor(12, 0);
      lcd.print(" OFF");
    break;
   }
 }
}


void readPins() {
 if (digitalRead(STOP) == LOW ) {                                   // считаем сколько времени активен стоп
   if (millis() - STOP_time_press > 1) {
     STOP_press_time++;
     STOP_time_press = millis();
   }
 }

 if ( STOP_press_time > 1000) {                                     // если стоп более 1000 мс, ставим мощность в ноль и взводим флаг останова
   STOP_press_time = 0;
   buffer_ust_W[preset] = 0;
   set = 3;
   }
   
 if (digitalRead(STOP) == HIGH && set == 3) {                       // очищаем счетчик, если стоп отпущен и перед этим был включен, на заданную мощность
   buffer_ust_W[preset] = EEPROM_read(preset * 2);
   set = 0;
 }

 if (digitalRead(STOP) == HIGH && ACCELERATOR_press_time > 1000) {  // если разгон активен более 1000 мс и нет стопа, ставим MAXPOWER Ватт и взводим флаг разгона
   ACCELERATOR_press_time = 0;
   buffer_ust_W[preset] = MAXPOWER;
   set = 1;
 }
 
 if (digitalRead(ACCELERATOR) == LOW ) {                            // считаем сколько времени активен разгон
   if (millis() - ACCELERATOR_time_press > 1) {
     ACCELERATOR_press_time++;
     ACCELERATOR_time_press = millis();
   }
 }

 if (digitalRead(ACCELERATOR) == HIGH && set == 1) {                // очищаем счетчик, если разгон отпущен и перед этим был включен, на заданную мощность
   buffer_ust_W[preset] = EEPROM_read(preset * 2);
   set = 0;
 }
}


void sendSerial() {
 if (millis() - serialMillis >= 1000) {                             // каждые 1000 сек в serial отправляем реальную, предустановленную мощность, предустановку
   serialMillis = millis();
   Serial.print("Pnow=");
   Serial.println(TEH.Pnow);
   Serial.print("Pset=");
   Serial.println(TEH.Pset);
   Serial.print("Preset:");
   Serial.println(name_preset[preset]);
   Serial.println("-----------");
 }
}


void readSerial() {
 while (Serial.available()) {                                       // Serial port, пока не конец сообщения, читаем данные и формируем строку
   char ch = Serial.read();
   Var += ch;
   if (ch == '\n') {
     if (Var.substring(0, 2) == "sp") {
       T1 = Var.substring(Var.indexOf("sp", 2) + 3);                // признак команды sp
       inst_P = T1.toFloat();                                       // выставленная мощность с Serial
        if (inst_P >= MAXPOWER) {                                   // если мощность больше чем MAXPOWER, то мощность ограничивается значением MAXPOWER
          inst_P = MAXPOWER;
        }        
       TEH.setpower(inst_P);        
       buffer_ust_W[preset] = inst_P;                               // мощность с serial для активной предустановки сразу пишется в eeprom
       EEPROM_write(preset * 2, buffer_ust_W[preset]);
       Var = "";
     }
   }
 }
}


int EEPROM_read(int addr) {
 byte raw[2];
 for (byte i = 0; i < 2; i++) raw = EEPROM.read(addr + i);
 int &num = (int&)raw;
 return num;
}


void EEPROM_write(int addr, int num) {
 byte raw[2];
 (int&)raw = num;
 for (byte i = 0; i < 2; i++) EEPROM.update(addr + i, raw);
}


void readKeys() {
 switch (buttonCode) {                              
  case '0':                                                      
           if (set_menu_I) {
           EEPROM_write(preset * 2, buffer_ust_W[preset]);
           lcd.setCursor(14, 1);
           lcd.print("WR");
            if (millis() - wrMillis > 1000) {
              wrMillis  = millis();
            }
           }
  break;      
  case '1':                                                      
         switch (!set_menu_I) {          
          case true:
           set_menu_I = true;
          break;      
          case false:
           set_menu_I = false;
          break;
         }
  break;  
  case '2':                                                      
         switch (!set_W) {          
          case true:
           set_W = true;
          break;      
          case false:
           set_W = false;
          break;
         }
  break;
  case '3':                                                      
   if (!set_menu_I) {
     if (!set_menu_I) {
      preset = preset - 1;                                      
       if (preset < 0) preset = 0;
     }
   }
   else {
    if (buffer_ust_W[preset] >= 0 + step_W) {
     buffer_ust_W[preset] = buffer_ust_W[preset] - step_W;
    }    
   }
  break;
  case '4':                                                      
   if (!set_menu_I) {
     preset = preset + 1;                                      
      if (preset > preset_max) preset = preset_max;
   }
   else {
    if (buffer_ust_W[preset] <= MAXPOWER - step_W) {
     buffer_ust_W[preset] = buffer_ust_W[preset] + step_W;
    }
   }
  break;    
 }    
}
nod32 Бакалавр Новокузнецк 90 20
Отв.562  04 Янв. 18, 19:21
U-M, Программировал последний раз 30 лет назад. Поэтому и прошу помощи. Хочу просто стабилизатор напряжения с LCD 1602.
sebra Куратор Республика Коми 147 85
Отв.563  04 Янв. 18, 21:02
U-M, Программировал последний раз 30 лет назад. Поэтому и прошу помощи. Хочу просто стабилизатор напряжения с LCD 1602.nod32, 04 Янв. 18, 19:21

Какая версия планируется к использованию, Регулятор напряжения с LCD индикатором ?
nod32 Бакалавр Новокузнецк 90 20
Отв.564  05 Янв. 18, 06:07
Регулятор напряжения с LCD индикаторомsebra, 04 Янв. 18, 21:02
Да. Регулятор имеет функцию стабилизации? Диммер на ардуино с дисплеем не нужен. Не понял плюса стабилизации тока. ASC712 есть, есть где то в закромах и токовый трансформатор. Если стабилизатор тока лучше(проще) можно его.
U-M Магистр MSK 210 39
Отв.565  05 Янв. 18, 07:10
Стабилизация есть.
Ток или напряжение - кому что интереснее или у кого что есть?
Плюсом напряжения - можно с мелких мощностей начать.
ACS-более подвержен помехам (отверку над ним поместите поближе и увидите, что регулятор без подключенной нагрузки начал врать ватт на 20). ТТ более устойчивый к помехам и более точный, но под свой надо резистор посчитать (кстати, без резистора желательно нагрузку не давать - можно перемагнитить сердечник).
sebra Куратор Республика Коми 147 85
Отв.566  05 Янв. 18, 07:35, через 25 мин
nod32, скачайте с шапки архив, закомментируйте в скетче все строки
// Для подключения ЛСД экрана через I2C

и раскомментируйте все строки
// Для подключения ЛСД экрана напрямую

Строк всего семь, так же нужно установить библиотеку LiquidCrystal.h
nod32 Бакалавр Новокузнецк 90 20
Отв.567  05 Янв. 18, 11:55
Не думал что надо  ( //lcd.init();// Для подключения ЛСД экрана через I2C
  //lcd.backlight();// Для подключения ЛСД экрана через I2C) ремировать (комментируйть) эти строки. Залилось с первого раза. Пошел паять дисплей.
RGB33 Студент Владимир 11
Отв.568  08 Янв. 18, 13:03
Так вот здесь же [сообщение #13199115] RegPower.zip приложен!Tomat7, 28 Дек. 17, 11:58
Сделайте одолжение, соберите Ваш алгоритм с остальными потрахами от версии  Chatterbox, ну не все здесь кодят и понимают в этом. Я пользуюсь вариантом  Chatterbox, немного индикацию под себя подогнал, но прошу если есть возможность, как вывести на дисплей текущий ток?
U-M Магистр MSK 210 39
Отв.569  09 Янв. 18, 13:56
Короткий отчет - погонял скетч на основе библиотеки коллеги Tomat7. В качестве нестабильной сети использовал ТЭНы последовательно с рабочим ТЭНом (всего вышло 3 ступени нестабильности сети). По контрольной лампе, в установившемся режиме, смигиваний или погасаний на выходе регулятора не было. Напряжение перерегулируется плавно, время регулировки от 3 до 6 секунд (зависит как сильно просаживал сеть).
Единственно, иногда, при нажатии кнопок и прыгании по меню, бывает пригасание контрольной лампы. По ощущению, меньше пол-секунды, наверное на 1-2 периода сетевого напряжения. Но это не каждый раз при нажатии кнопок.
sechevoy Специалист Запорожье 148 26
Отв.570  21 Янв. 18, 23:23
Подскажите пожалуйста, как рассчитать обвязку под трансформатор тока на 30А https://ru.aliexpress.com/...2041629455.html
Ссылка в шапке темы на сайт с расчетом не работает. И какой должен быть коэффициент для данного трансформатора тока?
Заранее благодарен.

sebra Куратор Республика Коми 147 85
Отв.571  21 Янв. 18, 23:58, через 35 мин
sechevoy, Ну елы палы

https://learn.openenergymonitor.org/...c-power-adapter

https://www.google.ru/...920&bih=968
U-M Магистр MSK 210 39
Отв.572  22 Янв. 18, 19:00
как рассчитать обвязку под трансформатор токаsechevoy, 21 Янв. 18, 23:23
Дано: трансформатор тока на 30А, коэффициент трансформации 1 к 1000.
Найти: резистор и коэффициент.

Ток на выходе трансформатора тока: 30 А/1000=0.03 А
Пиковый ток за полный период: 0,03 А*2*1.41=0.0846 А
Прикидываем резистор, с учетом того, что на вход АЦП atmega328 можно подавать не более 5 В: 0.0846 А*59 ом=4.99 В
Нужен резистор на 59 ом, но такого нет в стандартном ряде. Есть 62 - много, есть 56 ом - его и применим.
Отсчеты под резистор 56 ом: (0.03 А*56 ом*1024)/5 В=344 отсчета.
Коэффициент для прошивки: 30 А/344 отсчета=0.087209.

Коэффициент наверное придется немного подправить - это зависит от точности резистора и от напряжения питания 5 В. Поэтому или поточнее надо глянуть напряжение (ну будет 4.88 В - уже оказывает влияние) или проще немного подобрать экспериментально коэффициент под известную эталонную нагрузку.

m16 Модератор Тамбов 1.9K 1K
Отв.573  22 Янв. 18, 21:31
    резисторы 130 и 110ом  в параллель дадут 59,58(3)ома. кстати нам препод на лекции доказывал что резистор(конденсатор) набранный последовательно-параллельным соединением по точности будет лучше чем его доноры.
mak Модератор Екатеринбург 6.3K 1.8K
Отв.574  22 Янв. 18, 22:14, через 44 мин
m16, в смысле что абсолютная погрешность блока меньше относительной будет?
sevpro Доктор наук Worldwide 769 281
Отв.575  22 Янв. 18, 22:15, через 2 мин
кстати нам препод на лекции доказывал что резистор(конденсатор) набранный последовательно-параллельным соединением по точности будет лучше чем его доноры.m16, 22 Янв. 18, 21:31
Будет справедливо только для случая, когда отклонения соединяемых деталей будут иметь противоположный знак, например один резистор +4%, а другой -5%.
Ну или лучше худшего из двух, но хуже лучшего. Но никак не обоих
sebra Куратор Республика Коми 147 85
Отв.576  22 Янв. 18, 22:27, через 13 мин
Нужен резистор на 59 ом, но такого нет в стандартном ряде. Есть 62 - много, есть 56 ом - его и применим.U-M, 22 Янв. 18, 19:00

А не на 550 Ом в ту схему с опенэнерджи?
mak Модератор Екатеринбург 6.3K 1.8K
Отв.577  22 Янв. 18, 22:35, через 8 мин
sevpro, угу среднеквадратичная погрешность ))
U-M Магистр MSK 210 39
Отв.578  23 Янв. 18, 21:35
А не на 550 Ом в ту схему с опенэнерджи?sebra, 22 Янв. 18, 22:27

Для трансформатора тока 59.1 ом выходит (https://learn.openenergymonitor.org/...ce-with-arduino). Коэффициент не считал...
sechevoy Специалист Запорожье 148 26
Отв.579  25 Янв. 18, 10:48
Дано: трансформатор тока на 30А, коэффициент трансформации 1 к 1000.
Найти: резистор и коэффициент.

Ток на выходе трансформатора тока: 30 А/1000=0.03 А
Пиковый ток за полный период: 0,03 А*2*1.41=0.0846 А
Прикидываем резистор, с учетом того, что на вход АЦП atmega328 можно подавать не более 5 В: 0.0846 А*59 ом=4.99 В
Нужен резистор на 59 ом, но такого нет в стандартном ряде. Есть 62 - много, есть 56 ом - его и применим.
Отсчеты под резистор 56 ом: (0.03 А*56 ом*1024)/5 В=344 отсчета.
Коэффициент для прошивки: 30 А/344 отсчета=0.087209.

Коэффициент наверное придется немного подправить - это зависит от точности резистора и от напряжения питания 5 В. Поэтому или поточнее надо глянуть напряжение (ну будет 4.88 В - уже оказывает влияние) или проще немного подобрать экспериментально коэффициент под известную эталонную нагрузку.U-M, 22 Янв. 18, 19:00

Для моего трансформатора выходной ток 30мА при 30А в нагрузке. Количество витков соответственно 1000. Для 3кВт ток идеально должен быть 13,63А. Округлим для 15А. Для этого тока на выходе ТТ будет 15мА. 15*1,41=21,15мА (пиковое полупериод). Следовательно искомое сопротивление должно быть R=2,5/0,02115=118,2 Ом Нужно выбирать в меньшую сторону, поэтому 110 Ом. Пиковое напряжение на Ардуино будет 0,0423*110=4,65В
0,015*110=1,65В
1,65/(5В/1024)=338 отсчётов
Точность 15А/338=0,04437А на отсчёт
Вроде так?
Сомнения только по поводу коэффициента, он рассчитывается от максимально допустимого тока через трансформатор или от номинального?