Коммутация Arduino и твердотельного реле
- Войдите на сайт для отправки комментариев
Втр, 21/01/2014 - 13:24
Добрый день!
Есть задача - управлять твердлотельным реле с фазовой регуляцией с помошью ШИМ ардуины.
проблемы:
1. Ардуина на выходе дает 5 в. а для коммутации надо 10 в.
2. ШИМ надо преобразовать в постоянное напряжение.
то есть из ШИМ ардуины надо сделать 0-10 вольт постоянного напряжения.
есть задумка такого плана
не ясны конкретные значения сопротивлений и конденсатора и какой конкретно усилитель взять
http://yadi.sk/d/X1rPEChdGSvnL
это схемка, назнаю как вставить в сообщение :)
Если не секрет, о каком конкретно реле идёт речь??
http://www.kippribor.ru/TTR/Serii-HD-xx44VA-HD-xx2210U-HD-xx25LA-TTR
вот о таком. управление напряжением
Я тоже нечто аналогичное собирался пробывать (преобразователь шим-ток), но ещё не успел. Попробуйте R1 3,3k ,C1 0,1 , R2 4,7k , R3 10k, вместо R3 лучше подстроечник на 15 к взять, что б напряжение точно 10 вольт выставить при максимальном входном. И паралельно R3 желательно конденсатор антивозбудный 0,01..0,1. Опер любой пойдёт, lm358 например. Запитать его от 12 вольт.
http://habrahabr.ru/post/112665/
вот здесь например есть расчет этих сопротивлений где усиление равно 1+деление r3 на r2
тоесть в моем случае это должно быть 1+1 т.к. 10 в 2 раза больше пяти. значит r2=r3
про подстроечник хорошая идея, но тут масса нюансов начиная от плавания напряжения в сети до отсутствия необходимости полного открытия фазы на реле. в общем эта погрешность будет программно компенсирована, все равно рабочий диапазон будет в пределах 4-7 вольт.
буду пробовать. спасибо
вы про HD-xx22.10U ? Та которая управляется напряжением 0-10в
если ток потребления реле не большой (из описания не ясно), сделать из шима 0-10 в довольно просто - берем транзистор + два резистора + конденсатор и делаем выходной повторитель с RC фильтром. Транзистор лучше MOSFET с логическим уровнем, например irlml2402 - исток на GND, затвор через 10-100 ом на PWM выход ардуино, сток через резистор 1к на +10В. Выходной фильтр резистор 100-500 ом. (одна сторона к стоку, вторая к конденсатору), конденсатор 1-100мкф. (+ на второй резистор с другой стороны от стока, - на GND).
да, ток небольшой.
а можно схемку? и характеристики фильтра
насколько я понимаю эта идея такова -
из шим 0-5 делаем шим 0-10 а потом уже сглаживаем, правильно?
Такой же формы SSR, купленные у китайцев, управляются прямо с ноги ардуины через небольшой резистор. У них заявлено управление 3-32 вольта.
Такой же формы SSR, купленные у китайцев, управляются прямо с ноги ардуины через небольшой резистор. У них заявлено управление 3-32 вольта.
вы упустили то, что реле выше управляет напряжением в нагрузке, а ваше - нет
вы упустили то, что реле выше управляет напряжением в нагрузке, а ваше - нет
Значит это не "твердотельное реле", а "диммер" на триаке, или тиристоре. Реле по своему определению не может управлять напряжением в нагрузке.
Здесь нет противоречия. Диммер такое же реле, только со своей логикой включения-выключения
но это не суть, нет смысла спорить
да, ток небольшой.
а можно схемку? и характеристики фильтра
насколько я понимаю эта идея такова -
из шим 0-5 делаем шим 0-10 а потом уже сглаживаем, правильно?
да, правильно. Схема простая, проще некуда. Если сами нарисуете, то здесь подскажем, если вдруг где ошибетесь
да, ток небольшой.
а можно схемку? и характеристики фильтра
насколько я понимаю эта идея такова -
из шим 0-5 делаем шим 0-10 а потом уже сглаживаем, правильно?
да, правильно. Схема простая, проще некуда. Если сами нарисуете, то здесь подскажем, если вдруг где ошибетесь
ок. в выходные поковыряю. спасибо.
По сути меня интересует решение где на выходе получится более линейный постоянный ток. если это зависит только от RC фильтра тогда действительно пофигу. хотя на первый взгляд стоимость решений примерно одинаковая, но вжечь полевик в процессе гораздо проще :)
Есть вот такие Dimmer модули по 350руб.
Для работы с Arduino к нему есть скетч
Его схема
это несомненно прекрасное устройство!
но для меня не подходит
во первых как я понимаю тут реализован переход через 0 программно и мне это не кажется правильным, поскольку у ардуины есть и другие задачи, пусть даже он реализован через прерывание.
а во вторых у меня на другом конце муфельная печь :)
Вместо ШИМ можно использовать цифровой потенциометр, а после него усилитель напряжения на два.
а во вторых у меня на другом конце муфельная печь :)
Тогда PID вам в руки и барабан на шею!
http://playground.arduino.cc//Code/PIDLibraryRelayOutputExample
объясните пожалуйста как это реализовать в виде схемы?
а во вторых у меня на другом конце муфельная печь :)
Тогда PID вам в руки и барабан на шею!
http://playground.arduino.cc//Code/PIDLibraryRelayOutputExample
О! спасибо, я и не знал :)
попробую прикрутить, правда думаю пид пиду не товарищь :)
меня честно говоря во всей этой истории не столько пид интересует (благо есть аппаратные решения из китая за 700 рублей вместе с термопарой) сколько плавный разогрев. почему то эта функция сильно удорожает контроллеры...примерно в пять раз :)
плюсом к тому у нас печь не очень любит максимальные напряжения, особенно холодная, поэтому и приросло тут реле с фазовой регуляцией.
когда у нагревателя большая инерция (а у печки могу предположить масса и инерция к нагреву присутствуют) то "плавное" регулирование по сути не дает никаких преимуществ
Оно конечно наверно полезнее нагреватели на холодной когда у них низкое сопротивление разогревать пониженным напряжением. С другой стороны они как правило расчитаны как раз на то, чтобы их просто врубили в розетку так что это забота сверх положенного.
Вам там выше модуль предлагали и вы смутились, что ваш МК и так будет занят работой. Вот можете еще мой вариант посомтреть - там всю "грязную" работу делате tiny13 http://arduino.ru/forum/proekty/spi-modul-upravleniya-moshchnostyu-setev...
"Плавный" разогрев, вернее его эмуляцию, можно сделать просто- плавно повышая среднюю
мощьность нагревателя регулируя скважность- 30 секунд греем- 60 не греем - вот вам и 33% мощьности.
Или 3 секунды- 6 секунд (или минут). Для нагревателя подойдёт.
А теплоёмкость нагревателя будет всё это сглаживать.
Зато простое SSR с Zero Crossing и выходной пин без резистора прямо на SSR .
Но прийдётся выяснить, хотя-бы примерно, период для этго "ШИМ"а
вы про HD-xx22.10U ? Та которая управляется напряжением 0-10в
если ток потребления реле не большой (из описания не ясно), сделать из шима 0-10 в довольно просто - берем транзистор + два резистора + конденсатор и делаем выходной повторитель с RC фильтром. Транзистор лучше MOSFET с логическим уровнем, например irlml2402 - исток на GND, затвор через 10-100 ом на PWM выход ардуино, сток через резистор 1к на +10В. Выходной фильтр резистор 100-500 ом. (одна сторона к стоку, вторая к конденсатору), конденсатор 1-100мкф. (+ на второй резистор с другой стороны от стока, - на GND).
вот наваял
но мне кажется первый вариант, вами предложенный даст инвертирование фазы...а нам это не надо.
будет ли работать по второму варианту?
Вторая схема не даст желаемых десять вольт на выходе, т.к. это истоковый повторитель. А вот первая вполне работоспособна. Инвертирование фазы думаю можно компенсировать программно. Кстати транзисторы можно использовать и n-p-n.
Вторая схема не даст желаемых десять вольт на выходе, т.к. это истоковый повторитель. А вот первая вполне работоспособна. Инвертирование фазы думаю можно компенсировать программно. Кстати транзисторы можно использовать и n-p-n.
инвертировать самим транзистором, т.е. когда ардуина дает ноль он будет открытым?
какой конкретно взять транзистор?
Когда Ардуина даёт "ноль" - транзистор заперт. Т.е. на его коллекторе будет напряжение 10В. Когда Ардуина даёт "единицу" (+5 В) транзистор открывается, т.е. коллектор замыкается с эмиттером - на коллекторе 0 В. Происходит инвертирование логического сигнала - если на Ардуине "ноль", то на коллекторе "единица". Транзисторы n-p-n: КТ315, КТ503, КТ3102 - с любой буквой. Из импортных: BC817 и много других (под рукой не имею справочника). Напишите какие есть в наличии - подскажу.
Есть неочевидный ньюанс схемы: когда контроллер не инициализирован или завис с логическим нулём на выходе - Вы имеете на выходе схемы (коллекторе) 10В. Поэтому, если Вы управляете чем-то мощьным, нужно применить схемотехнику похитрее.
Когда Ардуина даёт "ноль" - транзистор заперт. Т.е. на его коллекторе будет напряжение 10В. Когда Ардуина даёт "единицу" (+5 В) транзистор открывается, т.е. коллектор замыкается с эмиттером - на коллекторе 0 В. Происходит инвертирование логического сигнала - если на Ардуине "ноль", то на коллекторе "единица". Транзисторы n-p-n: КТ315, КТ503, КТ3102 - с любой буквой. Из импортных: BC817 и много других (под рукой не имею справочника). Напишите какие есть в наличии - подскажу.
я имел ввиду взять полевик с другой проводимостью, чтобы при нуле он был открыт.
Если взять полевой транзистор с другой проводимостью, то учитывая, что исток будет на +10 В, напряжение открывания должно быть в диапазоне 5 ...10 В. Искать именно такие транзисторы мне думается не правильно и затруднительно.
Инвертировать програмно это значит не analogWrite(value), а analogWrite(255-value)
вам нужна первая схема. В цепи истока резистор надо уменьщить до 100 ом
и еще надо импедарс реле уточнить, 1к в RC фильтре может быть многовато если импеданс меньше 10ком
чтобы побороть зависшую ардуину можно активировать вотчдог, правда для некоторых ардуин это требует замены бутлоадера. Не вижу проблем со схемой 1, от нуля с инверсией ее проще строить, чем от плюса без инверсии. Ардуина зависнуть может как с нулем на выходе так и с единицей
Извиняюсь, но в цепи истока транзистора первой схемы резистора нет. "Схемотехника похитрее" предполагает надёжное отключение нагрузки не зависимо от уровня, на выводе "зависшей" Ардуины.
Хотел одно написать, написал другое. Речь про резистор между МК и затвором
это..
в общем извернулся я так- от ардуины идет на повторитель уровня 561уп4 из нее RC 1 ком и 10мкф.
проблема такая - из повторителя выходит 9 вольт (я питаю его 9 вольтами) а после фильтра уже 7 вольт.
то есть я ставлю шим 255, а по факту реле недооткрыто.
чего делать как спасаться?
Логично, ведь реле не святым духом питается, есть некий потребляемый ток, и напряжение падает на резисторе. Фильтр нужно ставить перед вашей микрухой.
Логично, ведь реле не святым духом питается, есть некий потребляемый ток, и напряжение падает на резисторе. Фильтр нужно ставить перед вашей микрухой.
не вижу логики, оно и там будет падать. все равно получится что я даю 125 шим а напряжение будет меньше половины.
dedov, вход микросхемы не должен создавать нагрузки, и падать будет только в соответствии с ШИМ. И при 255 попугаях с меги должно быть максимально напряжение. Кстати RC-цепочка у вас на 15герц получилась, немножко перебор. Тьфу ты, забыл что это логический чип... Ставьте операционник вобщем )
dedov, вход микросхемы не должен создавать нагрузки, и падать будет только в соответствии с ШИМ. И при 255 попугаях с меги должно быть максимально напряжение. Кстати RC-цепочка у вас на 15герц получилась, немножко перебор. Тьфу ты, забыл что это логический чип... Ставьте операционник вобщем )
микросхема то это логика. она аналог не понимает.
[/quote]
микросхема то это логика. она аналог не понимает.
[/quote]
Эх, в начале темы у вас была чудесная проверенная схема на опере , и зачем вас на альтернативы потянуло? :)
Схема в посте #1 действительно подходит для Вашей проблемы. R2 = R3 = 10 кОм. Интегрирующая цепочка R1, C1 как в посте #23. Получится интегратор без инвертирования с коэффициентом усиления +2. А возможно применить эмиттерный повторитель после интегрирующей цепочки (транзистор n-p-n и резистор, например КТ315 и R=10 кОм.
прикрутил пид из библиотеки как выше писали :) работает но глючит скотина :)
например была температура выше заданной, он нифига не понял и врубил на полную :)
да нет, похоже корректно работает, была проблема в том что в пид библиотеке переменные дабл а у меня внутренняя логика на инт. сделал все дабл стало вроде работать. тестирую, если кому надо выложу скетч.
http://youtu.be/WoZN3bRBY7k
Выглядит интересно. Выложите скетч, будет полезно проанализировать на досуге.
// include the library code: #include <LiquidCrystal.h> #include <OneWire.h> #include <DallasTemperature.h> #include <Wire.h> // pid #include <PID_v1.h> //Define Variables we'll be connecting to double Setpoint, Input, Output=80; //Define the aggressive and conservative Tuning Parameters double aggKp=4, aggKi=0.2, aggKd=1; double consKp=1, consKi=0.05, consKd=0.25; //Specify the links and initial tuning parameters PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT); // initialize the library with the numbers of the interface pins LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Data wire is plugged into pin 2 on the Arduino #define ONE_WIRE_BUS 2 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); int relayPin = 11; // здесь висит реле // объявляем переменные текущ темп double tc = 1 ; // желаемая температура double tl = 50 ; // всякие рабочие переменные double tlnew ; long keytime ; long curtime ; long keydo ; int power = 255 ; // мощность реле // гистерезис int dt = 2 ; // Нажатые кнопки int button; const int BUTTON_NONE = 0; const int BUTTON_RIGHT = 1; const int BUTTON_UP = 2; const int BUTTON_DOWN = 3; const int BUTTON_LEFT = 4; const int BUTTON_SELECT = 5; int getPressedButton() { int buttonValue = analogRead(0); // считываем значения с аналогового входа(A0) if (buttonValue < 100) { return BUTTON_RIGHT; } else if (buttonValue < 200) { return BUTTON_UP; } else if (buttonValue < 400){ return BUTTON_DOWN; } else if (buttonValue < 600){ return BUTTON_LEFT; } else if (buttonValue < 800){ return BUTTON_SELECT; } return BUTTON_NONE; } //функция регулирования температуры void regTemperature() { // оценка температуры delay(750); sensors.requestTemperatures(); // Send the command to get temperatures tc = sensors.getTempCByIndex(0) ; if( (tl-tc)>dt ) // если разница температур больще гистерезиса { analogWrite(relayPin, power); Serial.print(power); // врубаем реле } else // если в диапазоне { analogWrite(relayPin, power-100); // вырубаем реле Serial.println("L"); } Serial.println(tc); Serial.println(tl); } // установка температуры с клавиатуры void setTemperature() { tlnew=tl ; // вводим внутреннюю временную переменную температуры keytime = millis(); keydo = millis(); //выводим на дисплей заданное значение температуры lcd.begin(16,2); lcd.setCursor(0, 0); lcd.print(" Setting temp "); lcd.setCursor(7, 1); lcd.print(tlnew); delay(2000); //Опрашиваем клавиатуру, если нажата клавиша Up увеличиваем //значение на 1, если Down – уменьшаем на 1 //Если нажаты клавиши Select или Right или больше 6 секунд ничего не нажато – цикл опроса прерывается //Задержки введены для борьбы с дребезгом, если клавиши срабатывают //четко – можно уменьшить время задержек или вообще их убрать do { button = getPressedButton(); if (button==2){tlnew++;delay(200);lcd.setCursor(7, 1);lcd.print(tlnew); keytime = millis();} if (button==3){tlnew--;delay(200);lcd.setCursor(7, 1);lcd.print(tlnew); keytime = millis();} curtime = millis(); if ((curtime-keydo)>2000){calculatePIDoutput(); keydo = millis();} // каждые 2 секунды вызываем терморегуляцию чтобы ничего не сгорело пока мы кнопки тыкаем Serial.print(tlnew); Serial.println("DONE"); } while (button!=5 && button!=1 && (curtime-keytime)<6000); delay(200); Serial.print((curtime-keytime)); //По клавише Select – созраняем //По клавише Right – просто выходим if (button==5) { tl=tlnew ; } if (button==1) { ; } } void calculatePIDoutput() { Input = tc ; Setpoint = tl ; double gap = abs(Setpoint-Input); //distance away from setpoint if(gap<3) { //we're close to setpoint, use conservative tuning parameters myPID.SetTunings(consKp, consKi, consKd); } else { //we're far from setpoint, use aggressive tuning parameters myPID.SetTunings(aggKp, aggKi, aggKd); } myPID.Compute(); analogWrite(relayPin,Output); Serial.print(tc); Serial.println("DONE"); Serial.print(tl); Serial.println("DONE"); Serial.print("pid"); Serial.println("DONE"); Serial.print(Output); Serial.println("DONE"); } void setup() { // set up the LCD's number of columns and rows: lcd.begin(16, 2); // Print a message to the LCD. lcd.print("current temp"); // start serial port Serial.begin(9600); Serial.println("Dallas Temperature IC Control Library Demo"); // Start up the library sensors.begin(); pinMode(relayPin, OUTPUT); // pid //initialize the variables we're linked to Input = tc ; Setpoint = tl ; //turn the PID on myPID.SetMode(AUTOMATIC); } void loop() { // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus Serial.print("Requesting temperatures..."); sensors.requestTemperatures(); // Send the command to get temperatures tc = sensors.getTempCByIndex(0) ; Serial.println("DONE"); Serial.print("Temperature for Device 1 is: "); Serial.print(tc); // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire // set the cursor to column 0, line 1 // (note: line 1 is the second row, since counting begins with 0): // set up the LCD's number of columns and rows: lcd.begin(16, 2); // Print a message to the LCD. lcd.print("current "); lcd.print("t="); //печатаем текущую температуру lcd.print(tc); lcd.setCursor(0, 1); // print the number of seconds since reset: lcd.print(" tl="); //печатаем желаемую температуру lcd.print(tl); lcd.print(" "); //печатаем желаемую температуру lcd.print(Output); //regTemperature(); // вызываем терморегуляцтю calculatePIDoutput(); button = getPressedButton(); // опрашиваем клавиатуру // если нажата селект то вызываем функцию установки нового значения if ( button==5 ) {delay(200);setTemperature();} delay(50); }Немного правильнее будет работать с клавиатурой вот так :
int getPressedButton(){ int buttonValue = analogRead(0); // считываем значения с аналогового входа(A0) if (buttonValue > 1000) { return BUTTON_NONE;} // сразу выходим пропуская все последующие сравнения else if (buttonValue < 100) { return BUTTON_RIGHT; } else if (buttonValue < 200) { return BUTTON_UP; } else if (buttonValue < 400) { return BUTTON_DOWN; } else if (buttonValue < 600) { return BUTTON_LEFT; } else if (buttonValue < 800) { return BUTTON_SELECT; } return BUTTON_NONE; // на всякий случай....... }А вообще почитайте классику жанра:
http://alxarduino.blogspot.com/
P.S. Куда пропал Леший ? Никто не видел? Я волнуюсь !
Вожусь с пидом. выход на обыное SSR реле. на прямую с ножки Arduino.
Стандартный пример из библиотеки PID
PID_RelayOutput
нормально не работает. Логика работает, но на ножку ардуины не выдаёт полного напряжения., соответственно реле не срабатывает. поставил диод еле светится. на глаз процентов 25.
Пробовал на Mega, Leonardo и chipKit Max 23
результат одинаков.
Может кто сталкиавлся?
/******************************************************** * PID RelayOutput Example * Same as basic example, except that this time, the output * is going to a digital pin which (we presume) is controlling * a relay. the pid is designed to Output an analog value, * but the relay can only be On/Off. * * to connect them together we use "time proportioning * control" it's essentially a really slow version of PWM. * first we decide on a window size (5000mS say.) we then * set the pid to adjust its output between 0 and that window * size. lastly, we add some logic that translates the PID * output into "Relay On Time" with the remainder of the * window being "Relay Off Time" ********************************************************/ #include <PID_v1.h> #define RelayPin 6 //Define Variables we'll be connecting to double Setpoint, Input, Output; //Specify the links and initial tuning parameters PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT); int WindowSize = 5000; unsigned long windowStartTime; void setup() { windowStartTime = millis(); //initialize the variables we're linked to Setpoint = 100; //tell the PID to range between 0 and the full window size myPID.SetOutputLimits(0, WindowSize); //turn the PID on myPID.SetMode(AUTOMATIC); } void loop() { Input = analogRead(0); myPID.Compute(); /************************************************ * turn the output pin on/off based on pid output ************************************************/ if(millis() - windowStartTime>WindowSize) { //time to shift the Relay Window windowStartTime += WindowSize; } if(Output < millis() - windowStartTime) digitalWrite(RelayPin,HIGH); else digitalWrite(RelayPin,LOW); }Ногу RelayPin надо задать на выход через параметр pinmode
Ногу RelayPin надо задать на выход через параметр pinmode
Спасибо работает.
не совсем понимаю разницу почеру разные форма обявления так драматически влияет на работу.
Всмысле "форма обявления" ? Вывод необходимо запрограммировать на выход чтобы им что-то можно было управлять . Без этой команды digitalWrite просто вкл/выкл подтягивающий резистор