Минимальная доза энергии в одну полуволну... Или "выкусывание" энного количества полуволн. Будет ли разница меду простым релейным с мостовой схемой для датчика (плюс усиление сигнала рассогласования) и таким решением... Т.е. есть ли смысл в усложнении?
Ламинатор FGK-230
- Реклама
Так в данном случае релейный вариант не особо от обычного регулятора на паре операционных усилителей по результатам отличаться будет...
Минимальная доза энергии в одну полуволну... Или "выкусывание" энного количества полуволн. Будет ли разница меду простым релейным с мостовой схемой для датчика (плюс усиление сигнала рассогласования) и таким решением... Т.е. есть ли смысл в усложнении?

Минимальная доза энергии в одну полуволну... Или "выкусывание" энного количества полуволн. Будет ли разница меду простым релейным с мостовой схемой для датчика (плюс усиление сигнала рассогласования) и таким решением... Т.е. есть ли смысл в усложнении?
Собрал.
https://cloud.mail.ru/public/23WU/xmHzhCLv5
В работе.
https://cloud.mail.ru/public/sxE8/8bcUbNAuF
Подбирать оптимальную температуру для плат буду позже.
https://cloud.mail.ru/public/23WU/xmHzhCLv5
В работе.
https://cloud.mail.ru/public/sxE8/8bcUbNAuF
Подбирать оптимальную температуру для плат буду позже.
Кот:
Код: Выделить всё
//------------------------
//
// Регулировка температуры ламинатора (или подобного прибора) в диапазоне 25-220°С
// Massaraksh7 17.07.2026
//
//------------------------
#include <EEPROM.h>
#include <math.h>
#include <avr/pgmspace.h>
//---таблица кодов температуры от 0 до 220°С для термистора NTC 100k B3950
const int ntc[221] ={1009,1008,1007,1007,1006,1005,1004,1003,1002,1001,1000,999,997,996,995,994,992,991,989,988,986,984,983,981,
979,977,975,973,971,969,966,964,962,959,957,954,951,949,946,943,940,937,933,930,927,923,920,916,912,908,905,901,896,892,888,884,
879,875,870,865,860,855,850,845,840,835,830,824,819,813,807,802,796,790,784,778,772,766,759,753,747,740,734,727,721,714,707,701,
694,687,680,674,667,660,653,646,639,632,625,618,611,604,597,590,583,576,569,562,556,549,542,535,528,521,515,508,501,495,488,481,
475,468,462,456,449,443,437,430,424,418,412,406,400,395,389,383,377,372,366,361,355,350,345,340,335,329,324,319,315,310,305,300,
296,291,287,282,278,274,269,265,261,257,253,249,245,241,238,234,230,227,223,220,216,213,209,206,203,200,197,194,191,188,185,182,
179,176,174,171,168,166,163,161,158,156,153,151,149,146,144,142,140,138,136,134,132,130,128,126,124,122,120,119,117,115,113,112,
110,108,107,105,104};
int ttemp; //---Целевое значение температуры
int seg7; //---Счётчик сегментов
int rate; //---Режим =0-работа, =1-программирование
int val_to_show; //---Значение, которое показываетя на индикатореЮ в зависимости от режима
float lastval; //---Последнее сглаженное значение температуры
int countr; //---Счётчик
int btn1; //---Счётчик кнопки prog
int btn2; //---Счётчик кнопки -
int btn3; //---Счётчик кнопки +
int load; //---Управление нагрузкой
float kf_exp=0.9; //---Коэффициент экспоненциального фильтра
double integral = 0.0; //---Накопление интегральных данных
double prevError = 0.0; //---Предыдущая разница
double prevTemp = 0.0; //---Предыдущая температура
const int outMin = 0; //---Ограничения
const int outMax = 255; //---по выходу
//---Коэффициенты для ПИД-регулятора
float kf_p=10.0;
float kf_i=0.028; // 0.023 циклилось на 146-147-148, 0,033 - 151-152
float kf_d=305.0;
//---Индикация одной цифры
void drawDigit(int dig) {
PORTD &= 3;
PORTB &= 0xFC;
switch (dig)
{
case 0: PORTD |= 0x7C; PORTB |= 2; break;
case 1: PORTD |= 4; PORTB |= 2; break;
case 2: PORTD |= 0x74; PORTB |= 1; break;
case 3: PORTD |= 0x54; PORTB |= 3; break;
case 4: PORTD |= 0x0C; PORTB |= 3; break;
case 5: PORTD |= 0x58; PORTB |= 3; break;
case 6: PORTD |= 0x78; PORTB |= 3; break;
case 7: PORTD |= 0x14; PORTB |= 2; break;
case 8: PORTD |= 0x7C; PORTB |= 3; break;
case 9: PORTD |= 0x5C; PORTB |= 3; break;
case 10: break;
}
if (rate |= 0) PORTD |= (1 << 7);
}
//---Выбор номера разряда
void setNumber(int n) {
PORTB |= 0x1C;
switch (n)
{
case 0: PORTB &= ~4;break;
case 1: PORTB &= ~8;break;
case 2: PORTB &= ~16;break;
}
}
//---Показать температуру на индикаторе
void showValue(int seg){
int n;
switch (seg)
{
case 0: n=val_to_show / 100; if (n==0) n=10; break;
case 1: n=(val_to_show / 10) % 10; break;
case 2: n=val_to_show % 10; break;
}
drawDigit(n); setNumber(seg);
}
//--Основной цикл 256 Гц
void setTimer0() {
cli();
TCCR0A = (1 << WGM01);
TCCR0B = 0;
TCCR0B |= (1 << CS02) | (1 << CS00); // 16000000/1024=15625
OCR0A = 61; // 15625/61 ~ 256
TIMSK0 |= (1 << OCIE0A);
sei();
}
//---Читать целевую температуру из EEPROM
void readTTemp() {
int eeaddr=0;
ttemp = EEPROM.read(eeaddr);
if (ttemp==255)
{
ttemp=100;
writeTTemp();
}
}
//---Записать целевую температуру в EEPROM
void writeTTemp() {
int eeaddr=0;
EEPROM.write(eeaddr,ttemp);
}
//
//---Бинарный поиск значения температуры в массиве кодов
//
float BinarySearch(int code) {
int amin,amax,amid,i;
float t;
amax = 220; amin = 0;
//---Бинарный поиск
while (amax>amin)
{
amid = (amin+amax)/2;
if (code==ntc[amid]) return(amid);
if (code>ntc[amid]) amax=amid; else amin = amid+1;
}
//---Точного значения не нашли, интерполяция
if (code>ntc[amid]) amid--;
if (amid<0) return(0);
if (ntc[amid]==ntc[amid+1]) return(amid);
t = amid+(code-ntc[amid])/(ntc[amid+1]-ntc[amid]);
return(t);
}
//---Читать код с NTC100k и применить экспоненциальное сглаживание
void ReadAndSmooth() {
int code;
float tval;
code = analogRead(A5); //
tval = BinarySearch(code);
prevTemp=lastval;
lastval = tval*kf_exp+lastval*(1-kf_exp);
}
//---ПИД-регулятор
int PID (void){
double error = ttemp - lastval;
//---Интегральная часть
integral += error;
const double integralMax = 5000.0;
if (integral > integralMax) integral = integralMax;
if (integral < -integralMax) integral = -integralMax;
//---Дифференциальная часть
double derivative = (error - prevError);
prevError = error;
double output = kf_p * error + kf_i * integral + kf_d * derivative;
//---Ограничение выхода
if (output > outMax) output = outMax;
else if (output < outMin) output = outMin;
return (int)output;
}
//---Установки
void setup() {
//-Порты
DDRB=0x3F;PORTB=0x00;
DDRD=0xFC;PORTD=0x00;
DDRC=0x01;PORTC=0x1A;
//--Нач. значения
integral=0;
prevError=0;
prevTemp=0;
val_to_show = 0;
seg7=0;rate=0;countr=0;lastval=0;
btn1=0;btn2=0;btn3=0;load=0;
readTTemp();
val_to_show=777;
//---Запуск таймера
setTimer0();
}
//--256 Гц - основной цмкл
ISR(TIMER0_COMPA_vect) {
byte inp;
//---показать одну из цифр
showValue(seg7);
seg7++;if (seg7>=3)seg7=0;
//---Программирование целевой температуры
if (rate == 1)
{
val_to_show = ttemp;
inp = PINC; if (!(inp & (1 << PC3))) btn2++; else btn2=0;
inp = PINC; if (!(inp & (1 << PC4))) btn3++; else btn3=0;
inp = PINC; if (!(inp & (1 << PC1))) btn1++; else btn1=0;
if (btn1>=256) {btn1=0;writeTTemp();rate=0;return;}
if (btn2>=25) {btn2=0;if (ttemp>=25)ttemp--;val_to_show = ttemp;}
if (btn3>=25) {btn3=0;if (ttemp<=220)ttemp++;val_to_show = ttemp;}
return;
}
//---считывание кода 1 раз в секунду
countr++;
if (countr==256)
{
countr=0;
ReadAndSmooth();
val_to_show=lastval;
if (rate==0) val_to_show = lastval;
//---ПИД-регулятор
load = PID();
}
//---Вход в режим программирования целевой температуры
inp = PINC; if (!(inp & (1 << PC1))) btn1++; else btn1=0;
if (btn1>=256) {btn1=0;rate=1;}
//--- Реализация расчёта ПИД
if (countr==0){PORTB |= (1<<PB5);PORTC |= (1 << PC0);}
if (countr>=load){PORTB &= ~(1<<PB5); PORTC &= ~(1 << PC0);}
}
void loop() {
while(1){};
}- Реклама
На счёт скорости протяжки- про ЛУТ не скажу, а вот для фоторезиста -
https://static.chipdip.ru/lib/387/DOC018387106.pdf
https://static.chipdip.ru/lib/387/DOC018387106.pdf
Спойлер
Два прохода, один раз медью вверх, другой раз медью вниз.
160°С
https://cloud.mail.ru/public/7QYx/BjrmN1y9X
180°С
https://cloud.mail.ru/public/jky5/tumHMFdts
200°С
https://cloud.mail.ru/public/AioA/WkDn9rLhg
210°С
https://cloud.mail.ru/public/Q1r7/b5MBaK7YH
160°С
https://cloud.mail.ru/public/7QYx/BjrmN1y9X
180°С
https://cloud.mail.ru/public/jky5/tumHMFdts
200°С
https://cloud.mail.ru/public/AioA/WkDn9rLhg
210°С
https://cloud.mail.ru/public/Q1r7/b5MBaK7YH
215°С, 4 прохода. По-моему, уже перебор местами.
https://cloud.mail.ru/public/qpSg/wfyvVTD2R
https://cloud.mail.ru/public/qpSg/wfyvVTD2R
Massaraksh7 писал(а): Сб июл 18, 2026 22:53:20 Два прохода, один раз медью вверх, другой раз медью вниз.
210°С
https://cloud.mail.ru/public/Q1r7/b5MBaK7YH
Так, может, 4 прохода много?Massaraksh7 писал(а): Вс июл 19, 2026 01:14:35 215°С, 4 прохода. По-моему, уже перебор местами.
https://cloud.mail.ru/public/qpSg/wfyvVTD2R
Или 215°С много. Проверю.
Ну, вообще- 5 градусов - непонятно, много или мало.
У меня, например, для прикатки фоторезиста- (по встроенному индикатору температуры) 95 градусов- мало, а 100 градусов- много.
У меня, например, для прикатки фоторезиста- (по встроенному индикатору температуры) 95 градусов- мало, а 100 градусов- много.
Ну вот, 210°С, 4 прохода, почти идеально.
https://cloud.mail.ru/public/14vr/nNFXZqGwm
https://cloud.mail.ru/public/14vr/nNFXZqGwm
Проверил, интереса ради, релейный вариант, как без гистерезиса, так и с ним.BOB51 писал(а): Пт июл 17, 2026 19:35:00 Так в данном случае релейный вариант не особо от обычного регулятора на паре операционных усилителей по результатам отличаться будет...
Есть. Температура плавает на ±3-5-7 °С (и чем больше инерционность объекта, тем выше), а это может повлиять на качество перевода рисунка.
В случае же ПИД температура стоит ровно, сколько нужно, если правильно подобрать коэффициенты. Правда, при прохождении платы температура падает (нагреватель отдаёт ей тепло), но нужно просто подождать, пока она восстановится (секунд 10-30, в зависимости от размера платы), и тогда пихать следующий проход.
Собственно и требовалось учитывать как температуру, так и скорость прокатки и толщину (плюс свойства) материала для платки.
А это, в свою очередь, требует управления скоростью привода валов и, вероятно, бесконтактного датчика температуры поверхности платы (плюс коррекция на теплоотдачу в окружающую среду - исходная температура платки до валов ламинатора)...
Хорошая задачка для тренировки мозгов.
На практике для мелкосерийного еще оправдано, для одной платки в месяц - уже под вопросом.
А для ленивых (типа меня) и дырчатые заготовки с "паутинкой" проволочками вполне достаточны...
Вот так из лени (да ЖАБЫ) и деградируем помаленьку, теряя интерес к самоделкам.
Датчики у ламинатора удобно оборачивать кусочком пленки от нагревательного блока копириовалок типа кенона FC200 - обычно на сервисе порванных в избытке было... а далее ставим прижатым через ту пленку к резине вала, чтоб и скользил не "протираясь" и температуру точнее показывал (та пленка в термоблоке копировального аппарата напрямую между нагревателем и бумагой пробегает хорошей теплопередачей и износостойкостью обладает)... Но то так давно было... Сейчас может и бесконтактное чего попридумывали...

А это, в свою очередь, требует управления скоростью привода валов и, вероятно, бесконтактного датчика температуры поверхности платы (плюс коррекция на теплоотдачу в окружающую среду - исходная температура платки до валов ламинатора)...
Хорошая задачка для тренировки мозгов.
На практике для мелкосерийного еще оправдано, для одной платки в месяц - уже под вопросом.
А для ленивых (типа меня) и дырчатые заготовки с "паутинкой" проволочками вполне достаточны...
Вот так из лени (да ЖАБЫ) и деградируем помаленьку, теряя интерес к самоделкам.
Датчики у ламинатора удобно оборачивать кусочком пленки от нагревательного блока копириовалок типа кенона FC200 - обычно на сервисе порванных в избытке было... а далее ставим прижатым через ту пленку к резине вала, чтоб и скользил не "протираясь" и температуру точнее показывал (та пленка в термоблоке копировального аппарата напрямую между нагревателем и бумагой пробегает хорошей теплопередачей и износостойкостью обладает)... Но то так давно было... Сейчас может и бесконтактное чего попридумывали...
Угу. У меня ещё с юношеского возраста с регулярностью примерно раз в 5-7 лет возникает обострение интереса к электронным поделкам, длится короткий период, а потом снова затухает... до следующего цикла.BOB51 писал(а): Пн июл 20, 2026 14:12:25 Вот так из лени (да ЖАБЫ) и деградируем помаленьку, теряя интерес к самоделкам.


