Лабораторный блок питания

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Здраствуйте. Планирую собрать лабораторный блок питания с управлением через ардуино.

Напряжение на выходе 0...15в.
Максимальный ток нагрузки - около 3-5 А
Сам БП не импульсный, а обычный трансформаторный.

Именно с управлением а не просто с помощью МК отображать напряжение и т. д. Задумка такая: Управление ключевым транзастором проводится с помощью одного из ШИМ выходов Ардуино. Один из аналоговых входов использовать для контроля напряжения. И еще один для контроля тока (снять напряжение с шунта и через ОУ подать на алалоговый вход). Если все это реально - то уже програмно можно будет реализовать стабилизацию не только напряжения, но и тока и многое другое.

Схема будет приблизительно такая:

Реально?

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

>>Управление ключевым транзастором проводится с помощью одного из ШИМ выходов Ардуино.<<
Имейте в виду что на выходе  транзистора вы получите тот же ШИМ , только другого порядка.

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

nestandart пишет:

>>Управление ключевым транзастором проводится с помощью одного из ШИМ выходов Ардуино.<<
Имейте в виду что на выходе  транзистора вы получите тот же ШИМ , только другого порядка.

ШИМ сигнал, по идеи будет сглажен на выоде и/или на входе транзистора конденсатором.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Сглаженый ШИМ тоже ШИМ.

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

nestandart пишет:

Сглаженый ШИМ тоже ШИМ.

Ну после обычного трансформатора с выпрямителем тоже импульсный ток выходит, но он сглаживается конденсатором. Не думаю, что это может быть проблемой...

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

TheGupic, вы понимаете чем отличается ШИМирование напряжение от постоянно-стабильного ?

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

nestandart пишет:

TheGupic, вы понимаете чем отличается ШИМирование напряжение от постоянно-стабильного ?

Понимаю. Но ведь если с ШИМ выхода подать сигнал на RC фильтр, то от ширины выдаваемых импульсов будет завивит величина постоянного напряжения после RC фильтра. Этим то напряжением и будет управлятся ключевой транзистор. 

Схему я начиркал упрощенную, чтобы для начала поделится самой идеей. Там еще много всего будет.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Нарисуйте данный RC фильтр.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

А почему бы не реализовать уже готовую и отработанную схему, во всяком случае в интернете есть их и не одна. У меня тоже мысли на эту тему крутятся, но пока что я для себя не решил, самому делать или купить готовый.
И еще, есть ли смысл под это ставить Ардуино, или это на время отладки? Напрашиваетсязапаять МП сразу на плату, всё равно её делать, меньше проводов - как минимум - надежней.

Есть варианты переделать из БП от компа, но это для меня достаточно сложная задача, если в цифре я разберусь, то там всё намного сложнее для меня. В инете тоже море ссылок, но работы там немало, выбросить лишнее и добавить нужное.

Удачи!

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Ну по правде говоря мне не так нужен блок питания как процес его сборки. На время отладки будер сам ардуино, а там скорее всего закажу МК и установлю на плату. В нете смотрел много БП в основном на ПИКах, но там МК только делает замеры напряжения, тока и т. д... А сам БП управляется с помощью переменного резистора (если на основе компютерного БП)

Я уже сделал подобный, все отлично работает, регулируется выходное напряжение от 2,5 до 18 вольт. Но дури у него немеренно! если от него запитать, например фотоапарат, а в нем где нибуть будет КЗ - то он его просто уничтожит! (сгорят дорожки на плате и все что попадется на пути).

А так выставил бы нужных 3,6 вольта и сделал ограничение по току например в 400 мА. И если ток превысит заданный - МК убавит напряжение, чтобы ток не превышал заданный или вырубит полностью в завивимости от выбранного режима. Еще можно будет заряжать любые акумуляторы выставив нужный ток, можно будет реализовать таймер заряда и даже контроль напряжения заряжаемого акумулятора.

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

А чем вас не устраивает регулировка напряжения посредством переменного резистора ?

Устанавливаете датчик тока , вводите режимы тока и делаете защитное отключение , в случае чего.

А при КЗ напруга и так подает почти до нуля а ток подскакивает под потолок.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

"Важен сам процесс" - для меня - достаточно веская причина, можно только приветствовать это желание :)

Вот один из вариантов на атмеге8 и более новая версия на 164, однако там Basic, брр :)

http://avr.ru/ready/contr/power/power

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

ПС Хотя щас малось придется поднатаскаться в аналоге, достался осцилл старенький C1-94 (1972 гв), придется подшаманить малость, фронты заваливает, подлечим немного ;)

 

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

kisoft пишет:

Вот один из вариантов на атмеге8 и более новая версия на 164, однако там Basic, брр :)

http://avr.ru/ready/contr/power/power

Ну да... Серьезный подход! Возьму на заметку. Спасибо.

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

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

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

Програмка у меня получилась следующая:

#include <LiquidCrystal.h>;
LiquidCrystal lcd(12, 10, 11, 5, 4, 3, 2);
 
 // задаем константы
const int down = 7;    
const int up =  13;    
int mig = 0; //0 стоим 1 плюс 2 минус
float counter = 12.0; // переменная хранит заданное напряжение
void setup() { 
  pinMode (9, OUTPUT);  
  pinMode(down, INPUT);  
  pinMode(up, INPUT);  
  digitalWrite(up, 1); // поддерживаем еденицу на входах
  digitalWrite(down, 1);
 analogWrite (9, 47);  //устанавливаем напряжение для контраста дисплея
lcd.begin(16, 2); 

}
void loop() {
  // считываем значения с входа регулятора
  boolean regup = digitalRead(up);
  boolean regdown = digitalRead(down);
  lcd.setCursor (0, 1);
  if(regup==0 && regdown==1) mig = 1; // крутится в сторону увеличения
  if(regdown==0 && regup==1) mig = 2; // крутится в сторону уменшения
  if(!regup & !regdown){ //момент для переключения
    
    if (mig==1) counter = counter+0.1; //добавляем
    if(mig==2) counter = counter-0.1; //уменшаем
    mig = 0; //сбрасываем указатель направления
    
  }
  lcd.print("U = ");
  lcd.print (counter);
  lcd.print ("  ");
}

зы 9 вывод используется для подачи напряжения через RC фильтр на регулятор контраста дисплея (третий контакт)

Я программировал в основном на PHP. Под ардуино только второй день. Может чего глупого наделал в коде? Но в любом случае все что задумал работает. http://youtu.be/ygCTpvuxGZY

 

Процес идет, удовольствие получаю :)

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

>>Сегодня из обломков старого музыкального центра выдрал регулятор громкости, точнее такой себе датчик который имеет три вывода, крутится на все 360 градусов любое колличество оборотов. Поймал себя на мысле что даже незнаю как оно называется.<<

Энкодер. Он же валкодер.

По программе. Что бросается в глаза так это отсутствие хоть какой то защиты от дребезга (все таки механика). 

Переменная mig обнуляется постоянно , в общем цикле. Я бы сделал обнуление по событию.

Как то так 



if(regup==0 && regdown==0) mig = 0;

Добавьте команду lcd.clear(); Тоже по какому либо событию.

Я конечно не знаю какой именно у вас энкодер, но его программный опрос мне не нравится.

 

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Вот, начиркал схему, судя по результатах эмуляции все должно работать...

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Чуваак, если ты всё это сделаешь с максимальным КПД ты мне сильно упростишь жизнь 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Недостатком схемы является то, что мощный транзистор работает в аналоговом режиме - греться будет "по-полной". Я бы вообще убрал первый операционник, поставил бы ключ p-n-p или p-канальный полевик, управление которого - ключ на npn-транзисторе. А потом уже можно и сглаживать, можно RC, но лучше LC фильтром.

Это если нужен КПД... А эта схема кроме недостатков имеет и плюсы - низкий коэффициент пульсаций.

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

AlexFisher пишет:

Недостатком схемы является то, что мощный транзистор работает в аналоговом режиме - греться будет "по-полной". Я бы вообще убрал первый операционник, поставил бы ключ p-n-p или p-канальный полевик, управление которого - ключ на npn-транзисторе. А потом уже можно и сглаживать, можно RC, но лучше LC фильтром.

Это если нужен КПД... А эта схема кроме недостатков имеет и плюсы - низкий коэффициент пульсаций.

Все верно. Но уже начал делать по аналоговой схеме. Меня просто не очень волнует КПД :). Но если кому нужно будет высокий КПД то переделывать много не нада будет, да и прошивка тоже должна подойти.

Перерь по продвижению проекта.

Целый вечер промучился с регулятором напряжения, ничего не получалось... Виной тому был ОС F4558. В нете писали, что аналог LM358. Но оказалось что F4558 вообще вела себя непонятно как... Думал нерабочая, но другая вела себя точно так же неадекватно... Купил LM358 все стало на места. Выходное напрядение можна было регулировать заряжая/розряжая конденсатор RC филтрта, дотрагиваясь одной рукой к минусу или плюсу, а другой к входу управления. Очень прикольно :)

Схему немного переделал, сейчас она выгледит как-то так:

В основном изменений коснулась часть контроля тока. эта схема более точная, но оказалось две проблемы. 
Первая в том, что при больших нагрузках или КЗ на контрольном выходе напряжение может превысить 5 вольт (1А = 1В). Естественно МК будет при превышении максимального тока (у меня это будет 4А) понижать выходное напряжение или выключать, но кратковременный импульс все же может попасть на Ардуино. Кто нибуть знает сколько может выдержать анаголовый вход ардуино? В общем контроль тока я пока что не подкулючал, а замерял только тестером...

И вторая проблема: При уменьшении напряжения на выходе БП транзистор Q2 может открытся и не закрыватся до выключения, в результате на выходе БП поддерживается некоторое напряжение, которое (насколько я понял) проходит из выхода ОУ, R9, Q2, R10, R6... и на контрольном выходе тока тоже присутствует высокое напряжение... Это заметил еще при эмулировании, но как-то надеялся что в реале не повторится, но не тут то было.

Продолжение следует...

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

...Добавил в схему реле. которое включает/выключает питание всего этого устройства, и управляется через МК. Оно будет отключать питание при превышении тока в 4,5А. Проверено практически. При КЗ отключает моментально (ну так по крайней мере мной так воспринемается) Ничего не сгорело. Этим была решена первая проблема.

Вторую проблему решил путем увеличения минимального выходного напряжения с 0 до 0.1 В и увиличением сопротивления резистора R9 до 9,1кОм.

Разработал в sprint layout плату и заказал её изготовление (впервые в жизни :). Обойдется где-то в 50 грн. Со стороны деталей будет вставлятся и плата Ардуино. Со стороны дорожек будет разьем для подключения дисплея, энкодер, две кнопки, два светодиода... Будет такой себе "Бутерброд", но за то минимум проводов. 

Пока все. Жду плату.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Как ты реализовал управление током? не ну напряжение это понятно - ШИМ, ну а ток?

Скетчом поделится не хочешь?

Как закончишь фотк сделай парочку, интересно же. Лабораторный блок питания с регулировкой напряжения и тока - вещь полезная в хозяйстве...

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Ну так ток, и напряжение величины прямопропорциональные - тоесть уменьшая напряжение уменшается и ток. Например: выставлено напряжение 10 вольт и ограничение тока в 1А. Если ток в нагрузке не превышает заданого значения - напряжение держится тоже на заданом, если превышает - уменьшаем напряжение, чтобы ток оставался на заданом уровне.

Скетч еще не готов до конца (тем более на заказанной плате выводы ардуино некоторые будут менятся) сделал только регулировку/отображение напряжения, отображение тока в нагрузке, и защиту от КЗ. Когда будет более-менее полная версия - обязательно выложу и скетч и подробные фото.

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

А какую микруху будешь использовать как мозги? АТмега8?

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Может это не рационально, но будет использоватся плата ардуино уно, а не отдельный МК. 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Не вижу криминала. Плату всегда можно снять, потестить что-нибудь другое, потом залить скетч и поставить обратно. Еще можно сделать управление от компа и регистрацию работы на компе.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Ты только главное постарайся вписаться в 7-8 килобайт и использовать 3 вывода под ШИМ , думаю перенести на ATmega 8 не будет проблемой.

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Наконец несколько дней назад мне пришла заказанная плата для проэкта. Все детали установил, все заработало! Осталось написать функциональный скетч, под это все дело. На плате установлены две кнопки (для управления настройками и т. д. Одна, я так планирую будет кнопка "настройка" а другая "выход" и переключение иформации на дисплее). Сами установки будут выбиратся тем же валкодером что и установка напряжения (такой себе multjog). И еще добавил два светодиода (красный и синий) один для индикации сосояния "ухода в защиту" другой думаю будет сигнализировать о стабилизации тока.

Пока выкладываю пару фоток, чуть позже выложу тот скетч, что уже написал.

http://uaimage.com/gallery/aa4a469d

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Текущий скетч:

#include <LiquidCrystal.h>;
//void upp();
LiquidCrystal lcd(11, 9, 5, 4, 3, 2); //rs, e, d4, d5, d6, d7

 // задаем константы
const int down = 10;    //выход валкодера 1/2
const int up =  8;    //выход валкодера 2/2
const int pwm = 6;  //выход ШИМ 
const int power = 7; //управление релюхой
long previousMillis = 0;        // храним время последнего обновления дисплея
long interval = 500;           // интервал
int mig = 0; //0 стоим 1 плюс 2 минус (чтобы знать в какую сторону крутим валкодер)
float level = 10; //"уровень" ШИМ сигнала

float counter = 10; // переменная хранит заданное напряжение
void setup() { 
  
  pinMode(down, INPUT);  
  pinMode(up, INPUT);  
  pinMode(power, OUTPUT);
  pinMode(pwm, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);
  analogWrite(pwm, 0); //пока на выход не подаем напряжение
  digitalWrite(up, 1); // поддерживаем еденицу на входах от валкодера
  digitalWrite(down, 1);
  lcd.begin(16, 2); 

digitalWrite(power, 1); //включаем реле
}


void uup(){ //валкодер +
   if(counter<15.0) { 
    counter = counter+0.1;//добавляем
   }
}

void udn(){ //валкодер -
   if(counter>0.1)counter = counter-0.1; //убавляем
   if(counter<0.1) counter = 0.1;
}

void loop() {
  
  float Iout = analogRead(A0) * (5.0 / 1023.0); // узнаем ток в нагрузке
  if (Iout>4.1 | level == 255) // условия защиты
  /*
  (Вырубаем если ток превышает заданный,
  или ШИМ по каким либо причинам зашкалил)
  */
 {
   digitalWrite(power, 0); //вырубаем реле
   //выводим инфу
   lcd.clear();
   lcd.print("[ >> ERROR! << ]");
   lcd.setCursor (0, 1);
   lcd.print("    overload");
   
   //зажигаем красный светодиод
   digitalWrite(A4, 1);   
   level = 0; //убираем ШИМ сигнал
   delay(5000); //ждем некоторое время
   digitalWrite(power, 1); //включаем реле
   digitalWrite(A4, 0); //гасим светодиод
   lcd.clear();//очищаем дисплей
 }
  
  // считываем значения с входа валкодера
  boolean regup = digitalRead(up);
  boolean regdown = digitalRead(down);
  
  if(regup<regdown) mig = 1; // крутится в сторону увеличения
  if(regup>regdown) mig = 2; // крутится в сторону уменшения
  if(!regup & !regdown){ //момент для переключения
  
    if (mig==1) uup();//+
    if(mig==2) udn(); //-
    
    mig = 0; //сбрасываем указатель направления
    
  }

float Ucorr = -0.0835; //коррекция напряжения
float Uout = analogRead(A1) * ((5.0 + Ucorr) / 1023.0) * 5.0; //узнаем напряжение на выходе
/*
Сравниваем напряжение на выходе с установленным,
и принимаем меры..
Тоесть увиличиваем или уменшаем переменную для ШИМ
сигнала на значение отклонения...
например, при разнице в 0.5 вольта
изменяем переменную level на 0.5
Знаю, что выход ШИМ воспринимает только целые значения от 0 до 255
но такой подход позволяет более четко стабилизировать выходное напряжение
Тоесть не реагировать на незначительные погрешности, и 
Реско изменять ШИМ при большой разници заданого и реального напряжения
*/
if(Uout>counter){
  float raz = Uout - counter;
  level = level - raz;
}
if(Uout<counter){
  float raz = counter - Uout;
  level = level + raz;
}
if(level<0) level = 0;
if(level>255) level = 255;

analogWrite(pwm, ceil(level)); //подаем нужный сигнал на ШИМ выход


  lcd.setCursor (0, 1);
  lcd.print("  U/set:");
 
 if(counter<10) lcd.print(" "); //добавляем пробел, если нужно, чтобы не портить картинку
  lcd.print (counter,1); //выводим установленное значение напряжения
  lcd.print ("V ");

  
  unsigned long currentMillis = millis();
  
  /*проверяем не прошел ли нужный интервал, если прошел то
  выводим реальные значения на дисплей*/
  if(currentMillis - previousMillis > interval) {
    // сохраняем время последнего обновления
    previousMillis = currentMillis;  
   lcd.setCursor (0, 0);
 lcd.print("U=");
 if(Uout<9.99) lcd.print(" ");
  lcd.print(Uout,2);
  lcd.print("V I=");
  lcd.print(Iout, 2);
  lcd.print("A ");
  }
}

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

6 Кило, отлично, на мегу 8-ю должен уместится.

Схему, печатную плату и другие детали проэкта когда выложишь? :)

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Над скетчем сейчас еще работаю... пишу менюшку уже 7 кило, будет побольше, надеюсь не на много.

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

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Выложы что есть, может местние радиолюбители тебе помогуть с коекакими-то нюансами...

7 ещё норм, было бы неплохо если бы ты вписался в 7.5 кб.

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

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Как обстоят дела с проектом?

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

 

HWman пишет:

Как обстоят дела с проектом?

Сейчас небыло свободного времени чтобы завершить. Но проект практически готов. Внес несколько мелких изменений в схему. Даже разок заряжал автомобильный АКБ :) (током 4А). Если выходное напряжение относительно большое - то силовой транзистор практически не греется (что логично). Осталось собрать все в красивую коробочку, и чуть-чуть подправить программу. В качестве источника питания использую БП от факса. Но его немножко маловато. Во время зарядки АКБ в нем очень нагрелось все что могло. Но он справился и остался жив :). Скорее всего буду использовать компютерный БП. 

Вот нашел скетч последней версии: 

#include <LiquidCrystal.h>;
//void upp();
LiquidCrystal lcd(11, 9, 5, 4, 3, 2); //rs, e, d4, d5, d6, d7

 // задаем константы
const int down = 10;    //выход валкодера 1/2
const int up =  8;    //выход валкодера 2/2
const int pwm = 6;  //выход ШИМ 
const int power = 7; //управление релюхой
long previousMillis = 0;        // храним время последнего обновления дисплея
long interval = 500;           // интервал
int mig = 0; //0 стоим 1 плюс 2 минус (чтобы знать в какую сторону крутим валкодер)
float level = 10; //"уровень" ШИМ сигнала
int mode = 0;//режим (0 обычный, спабилизация тока, защита по току)
float Ioutmax = 1.0; //заданный ток
int set = 0; //(настройки: 0 напряжение, 1 режим, 2 ток)
int knopka_a = 0;
int knopka_b = 0;
float counter = 10; // переменная хранит заданное напряжение
void setup() { 
  
  pinMode(down, INPUT);  
  pinMode(up, INPUT);  
  pinMode(12, INPUT); 
  pinMode(13, INPUT); 
  pinMode(power, OUTPUT);
  pinMode(pwm, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);
  analogWrite(pwm, 0); //пока на выход не подаем напряжение
  digitalWrite(up, 1); // поддерживаем еденицу на входах от валкодера
  digitalWrite(down, 1);
   digitalWrite(12, 1);
    digitalWrite(13, 1);
  lcd.begin(16, 2); 

digitalWrite(power, 1); //включаем реле
}


void uup(){ //валкодер +
  if(set==0){
     if(counter<15.0) { 
      counter = counter+0.1;//добавляем
     }
  }
  if(set==1){
   mode = mode+1;
   if(mode>2) mode=2;
   
}
  if(set==2){
   Ioutmax = Ioutmax+0.05;
   if(Ioutmax>4) Ioutmax=4;
   
}
}

void udn(){ //валкодер -
if(set==0){
   if(counter>0.1)counter = counter-0.1; //убавляем
   if(counter<0.1) counter = 0.1;
}
if(set==1){
   mode = mode-1;
   if(mode<0) mode=0;
   
}  
if(set==2){
   Ioutmax = Ioutmax-0.05;
   if(Ioutmax<0.05) Ioutmax=0.05;
   
}
}

void loop() {
  
  float Iout = analogRead(A0) * (5.0 / 1023.0); // узнаем ток в нагрузке
  if ((Iout>4.8 | level == 255) & set!=3) // условия защиты
  /*
  (Вырубаем если ток превышает заданный,
  или ШИМ по каким либо причинам зашкалил)
  */
 {
   digitalWrite(power, 0); //вырубаем реле
   //выводим инфу
   lcd.clear();
   lcd.print("[ >> ERROR! << ]");
   lcd.setCursor (0, 1);
   lcd.print("    overload");
   
   //зажигаем красный светодиод
   digitalWrite(A4, 1);   
   level = 0; //убираем ШИМ сигнал
   delay(5000); //ждем некоторое время
   digitalWrite(power, 1); //включаем реле
   digitalWrite(A4, 0); //гасим светодиод
   lcd.clear();//очищаем дисплей
   set=0;
 }
  
  // считываем значения с входа валкодера
  boolean regup = digitalRead(up);
  boolean regdown = digitalRead(down);
  
  if(regup<regdown) mig = 1; // крутится в сторону увеличения
  if(regup>regdown) mig = 2; // крутится в сторону уменшения
  if(!regup & !regdown){ //момент для переключения
  
    if (mig==1) uup();//+
    if(mig==2) udn(); //-
    
    mig = 0; //сбрасываем указатель направления
    
  }

float Ucorr = -0.0835; //коррекция напряжения
float Uout = analogRead(A1) * ((5.0 + Ucorr) / 1023.0) * 5.0; //узнаем напряжение на выходе
/*
Сравниваем напряжение на выходе с установленным,
и принимаем меры..
Тоесть увиличиваем или уменшаем переменную для ШИМ
сигнала на значение отклонения...
например, при разнице в 0.5 вольта
изменяем переменную level на 0.5
Знаю, что выход ШИМ воспринимает только целые значения от 0 до 255
но такой подход позволяет более четко стабилизировать выходное напряжение
Тоесть не реагировать на незначительные погрешности, и 
Реско изменять ШИМ при большой разници заданого и реального напряжения
*/

if(mode==0 | mode==1){

if(Uout>counter){
  float raz = Uout - counter;
  level = level - raz;
}
if(Uout<counter){
  float raz = counter - Uout;
  level = level + raz;
}

if(mode==1&&Iout>Ioutmax){
   digitalWrite(power, 0); //вырубаем реле
   //выводим инфу
   /*lcd.clear();
   lcd.print("[ >> ERROR! << ]");
   lcd.setCursor (0, 1);
   lcd.print("    overload");
   */
   //зажигаем красный светодиод
   digitalWrite(A4, 1);   
   level = 0; //убираем ШИМ сигнал
   set=3;
   //lcd.clear();//очищаем дисплей
}
}else{ //режим стабилизации тока

if(Iout>Ioutmax){
  float raz = (Iout - Ioutmax)*10;
  level = level - raz;
  if(level<1) level=1;
  if(Uout<1){
    digitalWrite(power, 0); //вырубаем реле
     //зажигаем красный светодиод
   digitalWrite(A4, 1);   
   level = 0; //убираем ШИМ сигнал
   set=4;
  }
   //зажигаем синий светодиод
   digitalWrite(A5, 1); 
}else{
digitalWrite(A5, 0);
  if(Uout>counter){
  float raz = Uout - counter;
  level = level - raz;
}
if(Uout<counter){
  float raz = counter - Uout;
  level = level + (raz / 1
  0);
  //if(level>254) level=254;
}
}
}

if(level<0) level = 0;
if(level>255) level = 255;



analogWrite(pwm, ceil(level)); //подаем нужный сигнал на ШИМ выход


if (digitalRead(12)==0 && knopka_b==0) { // нажата ли кнопка б
knopka_b = 1;
set = set+1; if(set>2) {//вырубаем защиту
level = 0;
digitalWrite(power, 1); //врубаем реле
digitalWrite(A4, 0);  


  set = 0;
  
}

lcd.clear();
}
if(digitalRead(12)==1&&knopka_b==1) knopka_b = 0;

if(set==0){
  lcd.setCursor (0, 1);
  lcd.print("U/set:");
 
 if(counter<10) lcd.print(" "); //добавляем пробел, если нужно, чтобы не портить картинку
  lcd.print (counter,1); //выводим установленное значение напряжения
  lcd.print ("V ");

  
  unsigned long currentMillis = millis();
  
  /*проверяем не прошел ли нужный интервал, если прошел то
  выводим реальные значения на дисплей*/
  if(currentMillis - previousMillis > interval) {
    // сохраняем время последнего обновления
    previousMillis = currentMillis;  
   lcd.setCursor (0, 0);
 lcd.print("U=");
 if(Uout<9.99) lcd.print(" ");
  lcd.print(Uout,2);
  lcd.print("V I=");
  lcd.print(Iout, 2);
  lcd.print("A ");
  }
  if(set==1){//выбор режима
    lcd.setCursor (0, 1);
    lcd.print("U/set:");
  }
}
    if(set==1){//выбор режима
     lcd.setCursor (0, 0);
 lcd.print("MENU");
   lcd.setCursor (0, 1);
 lcd.print("mode: ");
  if(mode==0)  lcd.print("normal          ");//режим (0 обычный, спабилизация тока, защита по току)
 if(mode==1)  lcd.print("shutdown  ");
 if(mode==2)  lcd.print("drop      ");
  }
      if(set==2){//настройка тока
     lcd.setCursor (0, 0);
 lcd.print("MENU");
   lcd.setCursor (0, 1);
 lcd.print("I out max: ");
 lcd.print(Ioutmax);
 lcd.print("A");
  }
  if(set==3){//защита. вывод инфы
     lcd.setCursor (0, 0);
 lcd.print("Shutdown!        ");
   lcd.setCursor (0, 1);
 lcd.print("Iout");
  lcd.print(">Imax(");
 lcd.print(Ioutmax);
 lcd.print("A)");
  }
    if(set==4){//защита. вывод инфы критическое падение напряжения
     lcd.setCursor (0, 0);
 lcd.print("Shutdown!        ");
   lcd.setCursor (0, 1);
 lcd.print("Uout < 1.0V   ");

  }
}

 

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

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

axill
Offline
Зарегистрирован: 05.09.2011

TheGupic пишет:

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

думаю это в вашей задаче будет самое простое )) - писать и читать eeprom

а что за фильтр в итоге поставили на выходе? по-моему напрашивается LC, а не RC фильтр. Если есть возможность то измерьте и поделитесь по форме напряжения на выходе если есть осциилограф или какой-либо анализатор

АКБ большие колебания проглотит, а вот например схему на МК отлаживать - тут требования будут куда серьезнее

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

фильтр только RC (как на схеме, перед базой транзистора). Осцилографа нет. Все приборы которые подключал работают отлично (портативный телевизор, МР3 плейер и т. п.). Если бы были сильные помехи - думаю в первую очередь колбасило бы цифрового тестера - а он напряжение отображает ровно без глюков и скачков...

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

а чего не взяли для силовой части БП от компа, там все очень красиво управляется с помощью МК, есть защиты и т.п. + в инете уже все разжовано

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Тестирование что-то показало? Может какие-то мелкие баги или недочёты?

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Привет всем, непрошло и года как я вернулся ))))

Вот недавно продолжил работу над проектом. Сделал сохранение параметров по кнопочке (чтобы после выключения->включения все ставало на свои места:) 

Детальнешое тестирование показало некие скачи в связи с относительно небольшим диапазонов ШИМ выхода (0-255) и поэтому в большинстве случаев на выходе присутствуют небольшие скачки, например когда значение 155 маловато, а 156 уже многовато для поддержания точно заданого напряжения на выходе, вот оно и колбасится между этими значениями. Програмно избавится не удается. Разве что сделать небольшой допуск погрешности на выходе (+/- 0,05 В) но как-то не очень серьезно задаеш 12,0 В а на выходе 12,05 В :) Зачем тогда вообще было использовать микроконтроллер... Сейчас думаю как можно использовать два ШИМ выхода, чтобы увеличить точность управления выходным транзистором, может кто-то уже решал подобные задачи - подскажите как лучше реализовать. 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013
TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Не выходит... Импульсы еще больше... частоту указывал разную но не помогает...

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Попробуйте добавить конденсатор на 100-220 мкФ между пинами AVCC и GND контроллера, таким образом шумы АЦП сведутся к минимуму.

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

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

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Привет TheGupic, как дела с проектом?

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Привет всем. Пропал я не окончательно и вот Вам результат:

 

https://www.youtube.com/watch?v=dwOmQUercxk&feature=youtu.be

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

А файлы проекта выгружать будете?

art100
Offline
Зарегистрирован: 09.03.2014

TheGupic пишет:

Привет всем. Пропал я не окончательно и вот Вам результат:

 

https://www.youtube.com/watch?v=dwOmQUercxk&feature=youtu.be

Я конечно в этом ни бумбум. Но В ардуине есть ШИМ на 1024 шага. А вот чем он занят библиотекой енкодера или индикатора это вам думаю покопатся видней будет. Мне пока стандартных примеров и ШИМ-а на 255 хватало повеселится http://arduino.ru/forum/proekty/diskovyi-nomer-nabiratel-regulyator-paya.... Если пробьетесь к этому ШИМ-у критичите.

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Если я не ошибаюсь в моей ардуине есть только шимы 255 (8 бит), а 1024 (10 битный) есть в ардуино мега.

Но я уже придумал как использовать еще один шим для "точной подстройки" путем управления усилением ОУ. При емуляции в суперской проге MultiSim  создал cхему. Все должно работать. Скоро опубликую окончательную схему и найду скеч... 

TheGupic
TheGupic аватар
Offline
Зарегистрирован: 17.02.2013

Начеркал схему...

 

Piccy.info - Free Image Hosting

art100
Offline
Зарегистрирован: 09.03.2014

TheGupic пишет:

Если я не ошибаюсь в моей ардуине есть только шимы 255 (8 бит), а 1024 (10 битный) есть в ардуино мега.

Но я уже придумал как использовать еще один шим для "точной подстройки" путем управления усилением ОУ. При емуляции в суперской проге MultiSim  создал cхему. Все должно работать. Скоро опубликую окончательную схему и найду скеч... 

atmega328

таймер 0 8 бит

таймер 1 16 бит вроде 9 нога по умолчанию

таймер 2 8 бит

попробуйте тут почитать как библиотечка TimerOne.h можно ШИМ-ы http://www.pobot.ru/topic/show/154 вопрос не занят ли уже 16 битный таймер Индикатор Енкодер ...

тут http://forum.amperka.ru/threads/ШИМ-с-16кГц-управляемый-кнопками.2234/page-2

void setup(){
TCCR1A = B11110010;
TCCR1B = B00011001;

https://code.google.com/p/arduino-timerone/

Эта библиотека-это коллекция программ для настройки 16-битный аппаратный Таймер называется Timer1 на ATmega168/328. Есть 3 аппаратных таймеров, имеющихся на Чип, и они могут быть настроены различными способами для достижения различных функций. Развитие этой библиотеки началось с простого способа быстро и легко установить период ШИМ или частоты, но вырос до включения таймера переполнения обработки прерываний и других особенностей.

Для документации см. arduino площадка странице: http://arduino.cc/playground/Code/timer1

так что сами смотрите свободен ли Timer1 16bit

Я это не проверял но официальная библиотечка существует.

#include <TimerOne.h>
 
void setup() 
{
  // Initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards
  pinMode(13, OUTPUT);    
  
  Timer1.initialize(100000); // set a timer

Может вам просто прикрутить официальную библиотечку и дрыгать ногой такой конструкцией

void pwm(char pin, int duty, long microseconds=-1);

и вот оно счастье :)

смотрю этот ТаймерВань недавно на Due и Leonardo обкатали значит живет трясинка ;) TimerOne-r11.zip

если высмотришь что по умолчанию конфликтуют #include <TimerOne.h> #include <LiquidCrystal.h> кричи

 
art100
Offline
Зарегистрирован: 09.03.2014

TheGupic пишет:

Начеркал схему...

я в этом не разбираюсь но по видимому вы енкодеровсми медленными прерываниями загрузили шустрый timer1 9-ой ногой

вычитывать даташит надо

согласен любое програмное обеспечение компенсирует аппаратное несовершенство

Если вы аппаратно нашли как там какой-то ОУ трясти, может и не стоит вчитываться в таймеры и енкодеры и шимы на амегах. Вроде по тексту у всех начиная с 168-ых 16бит таймер есть. Но для упрощения кода мало кто разгоняет его выше 8 битового 255. Я играясь и зная точно дальше не вчитывался. 

  //PWM-----------------------------------------------------------------------------
  if(PowerTmp==1){ digitalWrite(RELE1,HIGH); lcd.setCursor(0,1); lcd.print("220v = ON  "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==2){ analogWrite (RELE1,  25); lcd.setCursor(0,1); lcd.print("220v = 20% "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==3){ analogWrite (RELE1,  50); lcd.setCursor(0,1); lcd.print("220v = 30% "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==4){ analogWrite (RELE1,  75); lcd.setCursor(0,1); lcd.print("220v = 40% "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==5){ analogWrite (RELE1, 100); lcd.setCursor(0,1); lcd.print("220v = 50% "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==6){ analogWrite (RELE1, 125); lcd.setCursor(0,1); lcd.print("220v = 60% "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==7){ analogWrite (RELE1, 150); lcd.setCursor(0,1); lcd.print("220v = 70% "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==8){ analogWrite (RELE1, 175); lcd.setCursor(0,1); lcd.print("220v = 80% "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==9){ analogWrite (RELE1, 200); lcd.setCursor(0,1); lcd.print("220v = 90% "); lcd.setCursor(11,1);  lcd.print(number);}//
  if(PowerTmp==0){ digitalWrite(RELE1, LOW); lcd.setCursor(0,1); lcd.print("220v = OFF "); lcd.setCursor(11,1);  lcd.print(number);}//
  //PWM-----------------------------------------------------------------------------

Вам вроде актуальнее. Полвольта туда полвольта сюда заряд идет заряд не идет как я понимаю.