Re: LM723 + ARDUINO = ИСТОЧНИК ПИТАНИЯ 0-28В 0-2.5А С ЗАЩИТОЙ ПО ТОКУ
Выходной ток транзистора единственное ограничение.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
forum.rcl-radio.ru → Тестирование скетчей → LM723 + ARDUINO = ИСТОЧНИК ПИТАНИЯ 0-28В 0-2.5А С ЗАЩИТОЙ ПО ТОКУ
Выходной ток транзистора единственное ограничение.
Добавлена кнопка I/U на D3
Тестируйте:
#include <Wire.h>
#include <EEPROM.h>
#include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
Encoder myEnc(8, 9);//CLK, DT
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
unsigned long times,oldPosition = -999,newPosition,times_lcd,times_u=millis()+50000,times_i=millis()+50000;
int u_out,u_dig,menu,i_out;
const float u_k = 7.10; // калибровка регулятора напряжения
const float i_k = 0.975;// калибровка измерителя тока
const float r = 0.01; // сопротивление шунта
byte power = 1; // при подачи питания выходное напряжение 0 В - OFF
float i;
byte w,set_u,set_i;
void setup(){
Serial.begin(9600);
Wire.begin();lcd.init();lcd.backlight();
MsTimer2::set(1, to_Timer);MsTimer2::start();
pinMode(10,INPUT);// SW энкодер MENU
pinMode(2,INPUT_PULLUP); // кнопка ON/OFF
pinMode(3,INPUT_PULLUP); // кнопка U/I
pinMode(A0,INPUT); // input I
u_out=EEPROM.read(0)*256+EEPROM.read(1);
i_out=EEPROM.read(2)*256+EEPROM.read(3);
}
void loop(){i_kz();
if(digitalRead(3)==LOW){menu++;if(menu>1){menu=0;}delay(200);}
if(digitalRead(2)==LOW&&power==0){power = 1;delay(200);}
if(digitalRead(2)==LOW&&power==1){power = 0;delay(200);}
if(digitalRead(10)==LOW && menu==0){set_u++;if(set_u>1){set_u=0;}set_i=100;times_u=millis();times_i=millis()+50000;delay(200);}
if(digitalRead(10)==LOW && menu==1){set_i++;if(set_i>1){set_i=0;}set_u=100;times_i=millis();times_u=millis()+50000;delay(200);}
//////// set out 0-28 V
if(menu==0 && set_u==0 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition*10;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==0 && set_u==1 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(u_out<0){u_out=0;}if(u_out>280){u_out=280;}u_dig = float(u_out)/10/u_k*4096/5.00;
Serial.println(u_dig);
//////// set i 0-2.5 A
if(menu==1 && set_i==0 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition*100;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==1 && set_i==1 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(i_out<0){i_out=0;}if(i_out>999){i_out=999;}
//////// lcd
i_kz();
if(millis()-times_lcd>400){times_lcd=millis();}
lcd.setCursor(0, 0);if(menu==0){lcd.print("U*= ");}else{lcd.print("U = ");}
if(millis()-times_u<5000&&menu==0){
if(set_u==0){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(" ");lcd.print(".");lcd.print(u_out%10);}}
if(set_u==1){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);set_u=1;}
lcd.print(" V ");
lcd.setCursor(11, 0);lcd.print(abs(i),2);lcd.print("A");
lcd.setCursor(0, 1);if(menu==1){lcd.print("I*= ");}else{lcd.print("I = ");}
if(millis()-times_i<5000&&menu==1){
if(set_i==0){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(" ");lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}}
if(set_i==1){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);set_i=1;}
lcd.print(" A ");
i_kz();
//////////////// EEPROM
if(millis()-times>5000&&w==1){EEPROM.update(0,highByte(u_out));EEPROM.update(1,lowByte(u_out));
EEPROM.update(2,highByte(i_out));EEPROM.update(3,lowByte(i_out));
times=millis();w=0;}
}//loop
void MCP4725(int data){
byte buffer[3];
buffer[0] = 0b01000000;
// data=0;
// buffer[0] = 0b01100000; // запись в память ЦАП 0 В
buffer[1] = data >> 4;
buffer[2] = data << 4;
Wire.beginTransmission(0x60);
Wire.write(buffer[0]);
Wire.write(buffer[1]);
Wire.write(buffer[2]);
Wire.endTransmission();
}
void i_kz(){
i = analogRead(A0)/250.00*i_k;
if(i > float(i_out/100.0)){MCP4725(0);lcd.setCursor(12, 1);lcd.print("ERR");delay(3000);power=1;}
else{lcd.setCursor(12, 1);
if(power==0){MCP4725(u_dig+i*4.00);lcd.print("ON ");}
if(power==1){MCP4725(0);lcd.print("OFF");}
}
}
void to_Timer(){newPosition = myEnc.read()/4;}
Уточните какую схему Вы используете в измерители тока с ОУ или АЦП?
Скетч который я переделал для ОУ.
Если с ОУ, то Вам надо будет подобрать номиналы R6 R7, то есть уменьшить коэффициент усиления, так как я расширил регулировку тока до 9,99 А.
Уточните какую схему Вы используете в измерители тока с ОУ или АЦП?
Скетч который я переделал для ОУ.
Если с ОУ, то Вам надо будет подобрать номиналы R6 R7, то есть уменьшить коэффициент усиления, так как я расширил регулировку тока до 9,99 А.
Премного благодарен! Собрал вариант с ОУ, про резисторы R6, R7 уже понял (использую заводской шунт на 5А). За максимальный ток отвечает строка: if(i_out<0){i_out=0;}if(i_out>999){i_out=999;} ?
За максимальный ток отвечает строка: if(i_out<0){i_out=0;}if(i_out>999){i_out=999;} ?
да
Так же понадобится подобрать коэффициент:
const float i_k = 0.975;// калибровка измерителя тока
Добавлена кнопка I/U на D3
Тестируйте:
Работает как часы! Помощь ресурсу по реквизитам: 4276 4500 1139 3002 ?
Помощь ресурсу по реквизитам: 4276 4500 1139 3002
Да, все верно. Заранее спасибо!
Есть еще предложение:
Сделать выбор режима работы токовой защиты: "отсечка/стабилизация" дополнительной кнопкой, это возможно?
Стабилизация по току возможна, но измерение тока производится на 10 битном входе ардуино, что не очень точно, стабилизация по току будет иметь большую нестабильность и инертность, так как она будет программной. В этом режиме при КЗ выхода потребуется несколько десятков мсек чтобы контроллер дал команду снизить выходное напряжение до нуля.
Суть метода программной стабилизации тока такая - при повышении тока нагрузки от заданного, контроллер даст команду снизить на какое то значение выходное напряжение, далее измерение тока, если ток все равно большой, процесс повторяется по новой, пока ток нагрузки не станет равным установленному значению. На это может уйти несколько десятков или даже сотен циклов измерения тока и отправки команды в ЦАП. Из-за этого и проявляется большая инертность программной стабилизации тока.
Стабилизация по току возможна, но измерение тока производится на 10 битном входе ардуино, что не очень точно, стабилизация по току будет иметь большую нестабильность и инертность, так как она будет программной. В этом режиме при КЗ выхода потребуется несколько десятков мсек чтобы контроллер дал команду снизить выходное напряжение до нуля.
Суть метода программной стабилизации тока такая - при повышении тока нагрузки от заданного, контроллер даст команду снизить на какое то значение выходное напряжение, далее измерение тока, если ток все равно большой, процесс повторяется по новой, пока ток нагрузки не станет равным установленному значению. На это может уйти несколько десятков или даже сотен циклов измерения тока и отправки команды в ЦАП. Из-за этого и проявляется большая инертность программной стабилизации тока.
В общим чертах понятно о чем речь. Но все же, прошу критически оценить следующий алгоритм:
- в режиме "отсечки" выставляем требуемое значение тока и напряжения;
- нажимаем кнопку "отсечка/стабилизация", при этом фиксируется значение тока и соответствующая данному напряжению мощность (схема переходит в режим стабилизации);
- при каждой итерации замера тока, меняем значение напряжения через зафиксированное значение мощности (с точностью до 0,1В);
- выход из режима стабилизации: нажатие кнопки "отсечка/стабилизация";
Индикация:
- режим "отсечка": маленькая буква "О" после символа тока (I) вверху (наподобие отображения градусов);
- режим "стабилизация": маленькая буква "С" после символа тока (I) вверху, если в режиме "стабилизация" происходит увеличение тока от заданного, надпись "ON" меняется на "SТВ";
Переключение режимов осуществляется кнопкой "отсечка/стабилизация".
Установка тока или напряжения в режиме "стабилизация" не доступна.
Я подумаю как это реализовать. У меня возможности собрать полностью схему, поэтому понадобится с Вашей стороны провести несколько тестов скетча.
Я подумаю как это реализовать. У меня возможности собрать полностью схему, поэтому понадобится с Вашей стороны провести несколько тестов скетча.
Конечно, не вопрос.
Скетч изменил, на D4 кнопка STAB
- режим "отсечка": маленькая буква "О" после символа тока (I) вверху (наподобие отображения градусов);
- режим "стабилизация": маленькая буква "С" после символа тока (I) вверху,
Индикацию пока не реализовал, есть сложности с размещением символов. Пока просто сделал букву S после буквы A если активен режим стабилизации.
Не уверен что сразу заработает.
#include <Wire.h>
#include <EEPROM.h>
#include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
Encoder myEnc(8, 9);//CLK, DT
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
unsigned long times,oldPosition = -999,newPosition,times_lcd,times_u=millis()+50000,times_i=millis()+50000;
int u_out,u_dig,menu,i_out;
const float u_k = 7.10; // калибровка регулятора напряжения
const float i_k = 0.975;// калибровка измерителя тока
const float r = 0.01; // сопротивление шунта
byte power = 1; // при подачи питания выходное напряжение 0 В - OFF
float i;
byte w,set_u,set_i;
bool stab;
int u_stab;
void setup(){
Wire.begin();lcd.init();lcd.backlight();
MsTimer2::set(1, to_Timer);MsTimer2::start();
pinMode(10,INPUT);// SW энкодер MENU
pinMode(2,INPUT_PULLUP); // кнопка ON/OFF
pinMode(3,INPUT_PULLUP); // кнопка U/I
pinMode(4,INPUT_PULLUP); // кнопка STAB_I
pinMode(A0,INPUT); // input I
u_out=EEPROM.read(0)*256+EEPROM.read(1);
i_out=EEPROM.read(2)*256+EEPROM.read(3);
}
void loop(){
if(stab==0){i_kz();}
if(digitalRead(3)==LOW){menu++;if(menu>1){menu=0;}delay(200);}
if(digitalRead(2)==LOW&&power==0){power = 1;delay(200);}
if(digitalRead(2)==LOW&&power==1){power = 0;delay(200);}
if(digitalRead(4)==LOW&&stab==0){stab = 1;lcd.setCursor(10, 1);lcd.print("S");delay(300);}
if(digitalRead(4)==LOW&&stab==1){stab = 0;lcd.setCursor(10, 1);lcd.print(" ");delay(300);}
if(digitalRead(10)==LOW && menu==0){set_u++;if(set_u>1){set_u=0;}set_i=100;times_u=millis();times_i=millis()+50000;delay(200);}
if(digitalRead(10)==LOW && menu==1){set_i++;if(set_i>1){set_i=0;}set_u=100;times_i=millis();times_u=millis()+50000;delay(200);}
//////// set out 0-28 V
if(menu==0 && set_u==0 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition*10;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==0 && set_u==1 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(u_out<0){u_out=0;}if(u_out>280){u_out=280;}u_dig = float(u_out/10)/u_k*4096/5.00;
if(stab==1){
i = analogRead(A0)/250.00*i_k;
if(i > float(i_out/100.0)){u_dig--;if(u_dig<0){u_dig=0;}lcd.setCursor(12, 1);lcd.print("STB");}
else{
u_dig = float(u_out/10)/u_k*4096/5.00;lcd.setCursor(12, 1);lcd.print("ON ");
}
if(power==1){MCP4725(0);lcd.setCursor(12, 1);lcd.print("OFF");}else{MCP4725(u_dig+i*4.00);}
}
//////// set i 0-2.5 A
if(menu==1 && set_i==0 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition*100;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==1 && set_i==1 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(i_out<0){i_out=0;}if(i_out>999){i_out=999;}
//////// lcd
if(stab==0){i_kz();}
if(millis()-times_lcd>400){times_lcd=millis();}
lcd.setCursor(0, 0);if(menu==0){lcd.print("U*= ");}else{lcd.print("U = ");}
if(millis()-times_u<5000&&menu==0){
if(set_u==0){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(" ");lcd.print(".");lcd.print(u_out%10);}}
if(set_u==1){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);set_u=1;}
lcd.print(" V ");
lcd.setCursor(11, 0);lcd.print(abs(i),2);lcd.print("A");
lcd.setCursor(0, 1);if(menu==1){lcd.print("I*= ");}else{lcd.print("I = ");}
if(millis()-times_i<5000&&menu==1){
if(set_i==0){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(" ");lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}}
if(set_i==1){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);set_i=1;}
lcd.setCursor(9, 1);lcd.print("A");
if(stab==0){i_kz();}
//////////////// EEPROM
if(millis()-times>5000&&w==1){EEPROM.update(0,highByte(u_out));EEPROM.update(1,lowByte(u_out));
EEPROM.update(2,highByte(i_out));EEPROM.update(3,lowByte(i_out));
times=millis();w=0;}
}//loop
void MCP4725(int data){
byte buffer[3];
buffer[0] = 0b01000000;
// data=0;
// buffer[0] = 0b01100000; // запись в память ЦАП 0 В
buffer[1] = data >> 4;
buffer[2] = data << 4;
Wire.beginTransmission(0x60);
Wire.write(buffer[0]);
Wire.write(buffer[1]);
Wire.write(buffer[2]);
Wire.endTransmission();
}
void i_kz(){
i = analogRead(A0)/250.00*i_k;
if(i > float(i_out/100.0)){MCP4725(0);lcd.setCursor(12, 1);lcd.print("ERR");delay(3000);power=1;}
else{lcd.setCursor(12, 1);
if(power==0){MCP4725(u_dig+i*4.00);lcd.print("ON ");}
if(power==1){MCP4725(0);lcd.print("OFF");}
}
}
void to_Timer(){newPosition = myEnc.read()/4;}
Я плохо протестировал предыдущий скетч с кнопкой I/U:
- При выборе регулировки значения напряжения после запятой, на экране цифры меняются, а по факту напряжение на выходе нет. До запятой напряжение регулируется.
- Защита по току не работает (на экране ток меняется).
По второму скетчу:
- При выборе регулировки значения напряжения после запятой, на экране цифры меняются, а по факту напряжение на выходе нет. До запятой напряжение регулируется.
- токовая отсечка работает, но показания тока на экране стали отличатся от фактических процентов на 30;
- Режим стабилизации: индикация стабилизации работает, ток показывает, но напряжение остается неизменным.
Давайте сначала решим вопрос по первому скетчу. Изменения я в него внес (http://forum.rcl-radio.ru/viewtopic.php?pid=7203#p7203), сейчас все должно работать.
Вообще ничего не изменилось. Дополнение про ток: величина тока энкодером выставляется, но показаний фактического тока нет, одни нули. Защита не работает.
Должно работать
Я ошибки увидел, вывел значение регулировки ЦАПа в монитор порта, 10 доли не регулировались, теперь регулируются. На вход А0 измеритель тока подаю 3,3 В показания тока 2,66 А, токовый вход работает, показания меняются.
#include <Wire.h>
#include <EEPROM.h>
#include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
Encoder myEnc(8, 9);//CLK, DT
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
unsigned long times,oldPosition = -999,newPosition,times_lcd,times_u=millis()+50000,times_i=millis()+50000;
int u_out,u_dig,menu,i_out;
const float u_k = 7.10; // калибровка регулятора напряжения
const float i_k = 0.975;// калибровка измерителя тока
const float r = 0.01; // сопротивление шунта
byte power = 1; // при подачи питания выходное напряжение 0 В - OFF
float i;
byte w,set_u,set_i;
void setup(){
Serial.begin(9600);
Wire.begin();lcd.init();lcd.backlight();
MsTimer2::set(1, to_Timer);MsTimer2::start();
pinMode(10,INPUT);// SW энкодер MENU
pinMode(2,INPUT_PULLUP); // кнопка ON/OFF
pinMode(3,INPUT_PULLUP); // кнопка U/I
pinMode(A0,INPUT); // input I
u_out=EEPROM.read(0)*256+EEPROM.read(1);
i_out=EEPROM.read(2)*256+EEPROM.read(3);
}
void loop(){i_kz();
if(digitalRead(3)==LOW){menu++;if(menu>1){menu=0;}delay(200);}
if(digitalRead(2)==LOW&&power==0){power = 1;delay(200);}
if(digitalRead(2)==LOW&&power==1){power = 0;delay(200);}
if(digitalRead(10)==LOW && menu==0){set_u++;if(set_u>1){set_u=0;}set_i=100;times_u=millis();times_i=millis()+50000;delay(200);}
if(digitalRead(10)==LOW && menu==1){set_i++;if(set_i>1){set_i=0;}set_u=100;times_i=millis();times_u=millis()+50000;delay(200);}
//////// set out 0-28 V
if(menu==0 && set_u==0 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition*10;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==0 && set_u==1 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(u_out<0){u_out=0;}if(u_out>280){u_out=280;}u_dig = float(u_out)/10/u_k*4096/5.00;
Serial.println(u_dig);
//////// set i 0-2.5 A
if(menu==1 && set_i==0 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition*100;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==1 && set_i==1 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(i_out<0){i_out=0;}if(i_out>999){i_out=999;}
//////// lcd
i_kz();
if(millis()-times_lcd>400){times_lcd=millis();}
lcd.setCursor(0, 0);if(menu==0){lcd.print("U*= ");}else{lcd.print("U = ");}
if(millis()-times_u<5000&&menu==0){
if(set_u==0){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(" ");lcd.print(".");lcd.print(u_out%10);}}
if(set_u==1){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);set_u=1;}
lcd.print(" V ");
lcd.setCursor(11, 0);lcd.print(abs(i),2);lcd.print("A");
lcd.setCursor(0, 1);if(menu==1){lcd.print("I*= ");}else{lcd.print("I = ");}
if(millis()-times_i<5000&&menu==1){
if(set_i==0){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(" ");lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}}
if(set_i==1){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);set_i=1;}
lcd.print(" A ");
i_kz();
//////////////// EEPROM
if(millis()-times>5000&&w==1){EEPROM.update(0,highByte(u_out));EEPROM.update(1,lowByte(u_out));
EEPROM.update(2,highByte(i_out));EEPROM.update(3,lowByte(i_out));
times=millis();w=0;}
}//loop
void MCP4725(int data){
byte buffer[3];
buffer[0] = 0b01000000;
// data=0;
// buffer[0] = 0b01100000; // запись в память ЦАП 0 В
buffer[1] = data >> 4;
buffer[2] = data << 4;
Wire.beginTransmission(0x60);
Wire.write(buffer[0]);
Wire.write(buffer[1]);
Wire.write(buffer[2]);
Wire.endTransmission();
}
void i_kz(){
i = analogRead(A0)/250.00*i_k;
if(i > float(i_out/100.0)){MCP4725(0);lcd.setCursor(12, 1);lcd.print("ERR");delay(3000);power=1;}
else{lcd.setCursor(12, 1);
if(power==0){MCP4725(u_dig+i*4.00);lcd.print("ON ");}
if(power==1){MCP4725(0);lcd.print("OFF");}
}
}
void to_Timer(){newPosition = myEnc.read()/4;}
Так же учтите что схема рассчитана на ток нагрузки 2,5 А, если вы будете использовать ток до 5 А, то Ван нужно коэффициент усиления ОУ понизить в два раза.
Так же подобрать значение
const float i_k = 0.975;// калибровка измерителя тока
оно должно быть примерно равно:
const float i_k = 0.975*2;// калибровка измерителя тока
Все работает!
Так же учтите что схема рассчитана на ток нагрузки 2,5 А, если вы будете использовать ток до 5 А, то Ван нужно коэффициент усиления ОУ понизить в два раза.
Так же подобрать значение
const float i_k = 0.975;// калибровка измерителя тока
оно должно быть примерно равно:
const float i_k = 0.975*2;// калибровка измерителя тока
Для начального скетча с первой страницы я подобрал кэф ОУ и значение калибровки.
Мне другое непонятно:
i = analogRead(A0)/250.00*i_k; этой строкой мы определяем величину напряжения подаваемого на А0? Я не могу найти в коде где участвует сопротивление шунта.
По второму скетчу, есть ряд моментов
токовая отсечка работает, но показания тока на экране стали отличатся от фактических процентов на 30;
Тут надо отстаивать коэффициент усиления ОУ если ток выше 2,5 А, и менять параметр:
const float i_k = 0.975;// калибровка измерителя тока
что бы ток точно показывал.
Режим стабилизации: индикация стабилизации работает, ток показывает, но напряжение остается неизменным.
Напряжение на индикаторе не должно меняться, так это напряжение не измеренное а выставленное энкодером, можно сделать чтобы оно менялось на фактическое, но тогда Вы не сможете регулировать напряжение которое устанавливается энкодером.
Места на экране мало, вывести установленное напряжение и фактическое напряжение при токовой стабилизации проблематично.
По факту, реальное значение напряжения должно меняться (быть меньше установленного) при токовой стабилизации, так как токовая стабилизация осуществляется только за счет уменьшения напряжения на выходе.
Я внесу сейчас исправления во второй скетч, устраню проблему с регулятором напряжения.
По вопросу отображения фактического напряжения в режиме стабилизации тока, подумайте как поступить. Есть вариант отображать его и заблокировать энкодер или оставить как есть.
Второй скетч:
#include <Wire.h>
#include <EEPROM.h>
#include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
Encoder myEnc(8, 9);//CLK, DT
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
unsigned long times,oldPosition = -999,newPosition,times_lcd,times_u=millis()+50000,times_i=millis()+50000;
int u_out,u_dig,menu,i_out;
const float u_k = 7.10; // калибровка регулятора напряжения
const float i_k = 0.975;// калибровка измерителя тока
const float r = 0.01; // сопротивление шунта
byte power = 1; // при подачи питания выходное напряжение 0 В - OFF
float i;
byte w,set_u,set_i;
bool stab;
int u_stab;
void setup(){
Wire.begin();lcd.init();lcd.backlight();
MsTimer2::set(1, to_Timer);MsTimer2::start();
pinMode(10,INPUT);// SW энкодер MENU
pinMode(2,INPUT_PULLUP); // кнопка ON/OFF
pinMode(3,INPUT_PULLUP); // кнопка U/I
pinMode(4,INPUT_PULLUP); // кнопка STAB_I
pinMode(A0,INPUT); // input I
u_out=EEPROM.read(0)*256+EEPROM.read(1);
i_out=EEPROM.read(2)*256+EEPROM.read(3);
}
void loop(){
if(stab==0){i_kz();}
if(digitalRead(3)==LOW){menu++;if(menu>1){menu=0;}delay(200);}
if(digitalRead(2)==LOW&&power==0){power = 1;delay(200);}
if(digitalRead(2)==LOW&&power==1){power = 0;delay(200);}
if(digitalRead(4)==LOW&&stab==0){stab = 1;lcd.setCursor(10, 1);lcd.print("S");delay(300);}
if(digitalRead(4)==LOW&&stab==1){stab = 0;lcd.setCursor(10, 1);lcd.print(" ");delay(300);}
if(digitalRead(10)==LOW && menu==0){set_u++;if(set_u>1){set_u=0;}set_i=100;times_u=millis();times_i=millis()+50000;delay(200);}
if(digitalRead(10)==LOW && menu==1){set_i++;if(set_i>1){set_i=0;}set_u=100;times_i=millis();times_u=millis()+50000;delay(200);}
//////// set out 0-28 V
if(menu==0 && set_u==0 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition*10;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==0 && set_u==1 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(u_out<0){u_out=0;}if(u_out>280){u_out=280;}u_dig = float(u_out)/10/u_k*4096/5.00;
if(stab==1){
i = analogRead(A0)/250.00*i_k;
if(i > float(i_out/100.0)){u_dig--;if(u_dig<0){u_dig=0;}lcd.setCursor(12, 1);lcd.print("STB");}
else{
u_dig = float(u_out)/10/u_k*4096/5.00;lcd.setCursor(12, 1);lcd.print("ON ");
}
if(power==1){MCP4725(0);lcd.setCursor(12, 1);lcd.print("OFF");}else{MCP4725(u_dig+i*4.00);}
}
//////// set i 0-2.5 A
if(menu==1 && set_i==0 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition*100;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==1 && set_i==1 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(i_out<0){i_out=0;}if(i_out>999){i_out=999;}
//////// lcd
if(stab==0){i_kz();}
if(millis()-times_lcd>400){times_lcd=millis();}
lcd.setCursor(0, 0);if(menu==0){lcd.print("U*= ");}else{lcd.print("U = ");}
if(millis()-times_u<5000&&menu==0){
if(set_u==0){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(" ");lcd.print(".");lcd.print(u_out%10);}}
if(set_u==1){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);set_u=1;}
lcd.print(" V ");
lcd.setCursor(11, 0);lcd.print(abs(i),2);lcd.print("A");
lcd.setCursor(0, 1);if(menu==1){lcd.print("I*= ");}else{lcd.print("I = ");}
if(millis()-times_i<5000&&menu==1){
if(set_i==0){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(" ");lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}}
if(set_i==1){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);set_i=1;}
lcd.setCursor(9, 1);lcd.print("A");
if(stab==0){i_kz();}
//////////////// EEPROM
if(millis()-times>5000&&w==1){EEPROM.update(0,highByte(u_out));EEPROM.update(1,lowByte(u_out));
EEPROM.update(2,highByte(i_out));EEPROM.update(3,lowByte(i_out));
times=millis();w=0;}
}//loop
void MCP4725(int data){
byte buffer[3];
buffer[0] = 0b01000000;
// data=0;
// buffer[0] = 0b01100000; // запись в память ЦАП 0 В
buffer[1] = data >> 4;
buffer[2] = data << 4;
Wire.beginTransmission(0x60);
Wire.write(buffer[0]);
Wire.write(buffer[1]);
Wire.write(buffer[2]);
Wire.endTransmission();
}
void i_kz(){
i = analogRead(A0)/250.00*i_k;
if(i > float(i_out/100.0)){MCP4725(0);lcd.setCursor(12, 1);lcd.print("ERR");delay(3000);power=1;}
else{lcd.setCursor(12, 1);
if(power==0){MCP4725(u_dig+i*4.00);lcd.print("ON ");}
if(power==1){MCP4725(0);lcd.print("OFF");}
}
}
void to_Timer(){newPosition = myEnc.read()/4;}
Считаю более правильным на экран выводить фактическое напряжение. А в режиме "Стабилизация" изменение тока или напряжения сделать недоступным.
По работе ОУ.
При питании 5 В, напряжение на выходе ОУ не может быть больше 3,5 В(примерно), при изменении коэффициента усиления ОУ проследите чтобы при токе от 0 до 5 А напряжение на выходе ОУ меняться, а не упираться в потолок отсечки выхода ОУ в 3,5 В.
Второй скетч поправил, сделал немного по другому. Когда активна стабилизация по току, на дисплей выводится текущее значение напряжения, но регулировка напряжения тоже доступна, если нажать кнопку энкодера то начинаю мигать выставленные значения напряжение. Через 5 секунд мигание прекращается и на дисплей снова выводится текущее напряжение.
#include <Wire.h>
#include <EEPROM.h>
#include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <LiquidCrystal_I2C.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
Encoder myEnc(8, 9);//CLK, DT
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
unsigned long times,oldPosition = -999,newPosition,times_lcd,times_u=millis()+50000,times_i=millis()+50000;
int u_out,u_dig,menu,i_out;
const float u_k = 7.10; // калибровка регулятора напряжения
const float i_k = 0.975;// калибровка измерителя тока
const float r = 0.01; // сопротивление шунта
byte power = 1; // при подачи питания выходное напряжение 0 В - OFF
float i;
byte w,set_u,set_i;
bool stab;
int u_stab;
void setup(){
Serial.begin(9600);
Wire.begin();lcd.init();lcd.backlight();
MsTimer2::set(1, to_Timer);MsTimer2::start();
pinMode(10,INPUT);// SW энкодер MENU
pinMode(2,INPUT_PULLUP); // кнопка ON/OFF
pinMode(3,INPUT_PULLUP); // кнопка U/I
pinMode(4,INPUT_PULLUP); // кнопка STAB_I
pinMode(A0,INPUT); // input I
u_out=EEPROM.read(0)*256+EEPROM.read(1);
i_out=EEPROM.read(2)*256+EEPROM.read(3);
}
void loop(){
if(stab==0){i_kz();}
if(digitalRead(3)==LOW){menu++;if(menu>1){menu=0;}delay(200);}
if(digitalRead(2)==LOW&&power==0){power = 1;delay(200);}
if(digitalRead(2)==LOW&&power==1){power = 0;delay(200);}
if(digitalRead(4)==LOW&&stab==0){stab = 1;lcd.setCursor(10, 1);lcd.print("S");delay(300);}
if(digitalRead(4)==LOW&&stab==1){stab = 0;lcd.setCursor(10, 1);lcd.print(" ");delay(300);}
if(digitalRead(10)==LOW && menu==0){set_u++;if(set_u>1){set_u=0;}set_i=100;times_u=millis();times_i=millis()+50000;delay(200);}
if(digitalRead(10)==LOW && menu==1){set_i++;if(set_i>1){set_i=0;}set_u=100;times_i=millis();times_u=millis()+50000;delay(200);}
//////// set out 0-28 V
if(menu==0 && set_u==0 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition*10;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==0 && set_u==1 && millis()-times_u<5000){
if (newPosition != oldPosition){times_u=millis();oldPosition = newPosition;u_out=u_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(stab==0){
if(u_out<0){u_out=0;}if(u_out>280){u_out=280;}u_dig = float(u_out)/10/u_k*4096/5.00;
}
Serial.println(u_dig);
if(stab==1){
i = analogRead(A0)/250.00*i_k;
if(i > float(i_out/100.0)){u_dig--;if(u_dig<0){u_dig=0;}lcd.setCursor(12, 1);lcd.print("STB");}
else{
u_dig = float(u_out)/10/u_k*4096/5.00;lcd.setCursor(12, 1);lcd.print("ON ");
}
if(power==1){MCP4725(0);lcd.setCursor(12, 1);lcd.print("OFF");}else{MCP4725(u_dig+i*4.00);}
}
//////// set i 0-2.5 A
if(menu==1 && set_i==0 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition*100;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(menu==1 && set_i==1 && millis()-times_i<5000){
if (newPosition != oldPosition){times_i=millis();oldPosition = newPosition;i_out=i_out+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;}}
if(i_out<0){i_out=0;}if(i_out>999){i_out=999;}
//////// lcd
if(stab==0){i_kz();}
if(millis()-times_lcd>400){times_lcd=millis();}
lcd.setCursor(0, 0);if(menu==0){lcd.print("U*= ");}else{lcd.print("U = ");}
if(millis()-times_u<5000&&menu==0){
if(set_u==0){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(" ");lcd.print(".");lcd.print(u_out%10);}}
if(set_u==1){ if(millis()-times_lcd>200){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);}else{lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(" ");}}
}
else{
if(stab==0){lcd.print(u_out/100);lcd.print(u_out/10%10);lcd.print(".");lcd.print(u_out%10);set_u=1;}
if(stab==1){lcd.print((u_dig *10 *u_k *5.00/4096.00)/10,1);set_u=1;}
}
lcd.print(" V ");
lcd.setCursor(11, 0);lcd.print(abs(i),2);lcd.print("A");
lcd.setCursor(0, 1);if(menu==1){lcd.print("I*= ");}else{lcd.print("I = ");}
if(millis()-times_i<5000&&menu==1){
if(set_i==0){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(" ");lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}}
if(set_i==1){ if(millis()-times_lcd>200){lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(" ");}}
}
else{lcd.print(i_out/100);lcd.print(".");lcd.print(i_out/10%10);lcd.print(i_out%10);set_i=1;}
lcd.setCursor(9, 1);lcd.print("A");
if(stab==0){i_kz();}
//////////////// EEPROM
if(millis()-times>5000&&w==1){EEPROM.update(0,highByte(u_out));EEPROM.update(1,lowByte(u_out));
EEPROM.update(2,highByte(i_out));EEPROM.update(3,lowByte(i_out));
times=millis();w=0;}
}//loop
void MCP4725(int data){
byte buffer[3];
buffer[0] = 0b01000000;
// data=0;
// buffer[0] = 0b01100000; // запись в память ЦАП 0 В
buffer[1] = data >> 4;
buffer[2] = data << 4;
Wire.beginTransmission(0x60);
Wire.write(buffer[0]);
Wire.write(buffer[1]);
Wire.write(buffer[2]);
Wire.endTransmission();
}
void i_kz(){
i = analogRead(A0)/250.00*i_k;
if(i > float(i_out/100.0)){MCP4725(0);lcd.setCursor(12, 1);lcd.print("ERR");delay(3000);power=1;}
else{lcd.setCursor(12, 1);
if(power==0){MCP4725(u_dig+i*4.00);lcd.print("ON ");}
if(power==1){MCP4725(0);lcd.print("OFF");}
}
}
void to_Timer(){newPosition = myEnc.read()/4;}
forum.rcl-radio.ru → Тестирование скетчей → LM723 + ARDUINO = ИСТОЧНИК ПИТАНИЯ 0-28В 0-2.5А С ЗАЩИТОЙ ПО ТОКУ
Форум работает на PunBB, при поддержке Informer Technologies, Inc
|