Очередная паяльная станция

Bolotov75
Offline
Зарегистрирован: 15.06.2018

???.... ну ничего тогда не понимаю... так не может быть(.. ну никак не выходит по формуле такое как у Вас. Я рассчитал и на практике так и выходит. 220v, 2 шт 2Вт 30к резисторы, фактический ток 14мА. 220/15000=0,0146, 3,2 Вт, все сходится. а по Вашим данным токи мизер.... что то тут не так)

YURSA
YURSA аватар
Offline
Зарегистрирован: 28.09.2017

Bolotov75 пишет:

YURSA, и еще вопросик. не подскажите по поводу вопросов в #2685

По поводу вопроса №1 пока сказать ни чего не могу

Вопрос№2 как мне кажется так и должно быть

Bolotov75
Offline
Зарегистрирован: 15.06.2018

Вот и я не могу понять на в1. что это может быть, почему у меня фен в таймер уходит, геркон не виноват т.к. сигнал от него я временно отсек, да и при норм. работе при съеме с подставки должен включится на нагрев... а тут нет ведет себя как на подставке и все тут))))) приходится кнопкой по новой запускать. а на 100% скорости вента все норм)))... магнитные бури на луне виноваты)

alex1978
alex1978 аватар
Offline
Зарегистрирован: 09.09.2017

Скорее на Солнце!!! ))) У меня частенько такая фигня, пол дня ковыряюсь, нихрена не работает. В конце концов плюну на все, и в ящик заброшу. Через какое-то время вернусь, включаю, все блин работает. ))) Какого хрена надо было??? Магия!!! И вспышки на Солнце!!! )))

Oleg_D
Offline
Зарегистрирован: 13.06.2018

Il86md
Откройте архив Руслана, там найдёте схему на 2 термопары. Можете выдрать и на отдельную платку приспособить. Было бы желание.

Bolotov75
Если сомневаетесь, ставьте 20 - 22к 2вт, за глаза. Всё будет работать в штатном режиме. У меня на 0.5 Вт и то без радиатора сколько проработали. Потом жалко стало, намазал термопастой и пилепил сверху радиатор.
По поводу магнитных бурь: разберите фен, замените геркон, или удалите. Посмотрите как будет себя вести. Больше нечему на таймер влиять. Проверьте кабеля внутри фена.
У китайцев до 100 осуждает и ничего, работает. 70гр. это вообще ни о чём. Не парьтесь.

il86md
Offline
Зарегистрирован: 22.11.2017

Oleg_D пишет:
il86md пишет:

HELP ребята куда еще залезть щупом?

 

.... Иногда его притягивали 10к к 5в. ....

походу внутренняя подтяжка с причудой, а ведь когда-то меня предупреждали не надейся на внутренние подтяжки, припаял 12Kom к линии ZC и втрой конец припаял к +5вольт микроконтроллера...

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

Спасибо Oleg_D почему сразу поленился проверить вот же ж

Спасибо разработчику Олегу)

Bolotov75
Offline
Зарегистрирован: 15.06.2018

ВСЕ!!!...Закончил я свою станцию!)))) Получилось довольно неплохо (в моем понимании), мелкие доработки остались, но это мелочи. Итог: генераторам этого проекта и всех доработок и конструкторов и помощникам огромное СПАСИБО!!! Вкратце, что у меня получилось. Не буду рисовать схем, т.к. их уже тут столько было (и моя не сильно от них отличется), делал из того, что быто доступно. И так: 

1. Arduino pro mini 5V, 16 MHz

2. LCD 16x2

3. Транс. тор. 50 Вт. 220-25-9.

4. Корпус 170х130х60 (ШхГхВ)

6. Фен 700Вт

7. Паяльник 50Вт 24В (фен и паяльник китайский)

Станция состоит из 4 плат и LCD 16х2: силовая (65х65), (220 в. ZC, симистор, БП 24 в, реле 24 в, и вся оптика), мозги (80х35), (про мини, БП 5 в.), ОУ (35х40), (там все стандартно на 2 термопары LM358),  кнопки управления (80х12).

В силовом блоке отказался от транзисторов на реле защиты (РС817 и так по токам тянет), ZC 220в. РС814 (2 резюка в параллель по 2 Вт , 24к (ток 18 мА (с меньшим током небыло стабильности), и 1к подтяжка к 5 в. на транзисторе (с бОльшим резистором не работало(( ).

Про мини, БП 5 в., бузер, и разъемы размещены на плате размером с платку LCD (земечательный бутер получился))), переназначил некоторые пины под свою разводку.

Вот вроде и все)))) если интересно, можно и фото выложить (только я тут первый раз, боюсь не так  что нить напакостить))))

kret.a.v@gmail.com
Offline
Зарегистрирован: 14.07.2017

не плохо былобы прикрепить архив с Вашими наработками (схемы, печатки , прошивка, и тхт с описанием проделанных процессов настроек)

заранее спасибо

k0l1an
Offline
Зарегистрирован: 21.08.2018

Добрый день, изготовил ПС на схеме Руслана, с небольшими изменениями(реле) ОУ использовал mcp6022 (Rail-to-Rail Input/Output, 10 MHz Op Amps)

есть вопрос по заземлению, к чему подключать корпус паяльника и фена, я паяльник подключил к "-" 24в, фен на заземление 220В.?!

проблемма в следующем, не корректно работает канал фена, температура меняется при нагреве термопары(ростет). На ZC 4,6В и импульсы присутствуют(вечером осцилограммы приложу). Сначала не набералась пемпература, оставалась на уровне комнатной, не отключая ардуино подал на 3023 через 1КОм 5В, температура наберается, и после поддерживается. Сейчас температура набирается, но очень медленно, также вечером приложу осцилограммы на D8.

в какую сторону копать?!

k0l1an
Offline
Зарегистрирован: 21.08.2018

Сигнал ZC деление 2В

Начало нагрева(D8)

спустя минуту нагрева(D8) на табло 100*(+/-) задана температура 250*

il86md
Offline
Зарегистрирован: 22.11.2017

k0l1an пишет:

спустя минуту нагрева(D8) на табло 100*(+/-) задана температура 250*

вот вот такое и я видел пока не припаял резистор на d3 вход кросзеро (перепаивал каждый элемент замерял параметры на тестере уже был психоз)) ), пост выше паяй и потом проверяй, только температуру более 200 не ставь при отладке, а то у меня резко раскалился фен когда подпаял резюк и все наладилось после регулировки усилителя 

k0l1an
Offline
Зарегистрирован: 21.08.2018

Немного решилась проблемма, как и предполагалось, причина программная, фен работает, пока нет насадок, посему не спешу калибровать,
мне немного не ясен алгоритм роботы станции... 

допустим я ставлю на фене температуду 130* и он падает в ошибку, !6 температуру не берет. стоит поставить температуру 300* он тут же набирает, и стабилизируется. Работа на температуре до 200* актуальна, потому мне нужна помощь!!!

выставил

float max_power = map(SetHotAirT, min_hotair_temp, max_hotair_temp, 35.0, 60.0);

вроде как лучьше, но 120* не взял, очень медленно набирает температуру

AleksBAM
Offline
Зарегистрирован: 13.09.2014

Кто проверял в работе прошивку 1.6.1 с энкодером. Буду переделавать паяльную станцию, так вот думаю поставить энкодер из набора ардуина.

Буду переделывать из за наводак на плате. Перекладывать провода. Возможно экранировать. А так работает норм. Спасибо автору.  

snag
Offline
Зарегистрирован: 29.05.2015

Я собирал, с энкодером. Мозги на 328-м (не ардуино) со стандартной обвязкой. Работает отлично, мне так удобней, чем кнопки. Конденсаторы ставить!

Для управления использовался обработчик dimax-a. Здесь есть его тема. У меня валкодер без платки, разница с народным (из набора ардуино) - два импульса за щелчок. Разные значения будут при вызове прерывания. В теме по обработчику все это есть.

k0l1an
Offline
Зарегистрирован: 21.08.2018

Привет, я собрал с двумя енкодерами, залил прошивку от Spinne, для двух энкодеров, не понравилать работа, кнопка фена при зажатии включает фен и тут же отключает.

В итоге, взял скетч 1.6.1. вкинул туда еправление 2-мя енкодерами, и переписал обработку нажатий кнопок
теперь работает так=>

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

2енкодер, короткое нажатие включает фен, во включенном состоянии короткое нажатие перебрасует флажок на регулировку оборотов>температура фена. Длинное нажатие отключает фен и устанавливает флажок на регулировку температуры.
При выключенном фене, можно регулировать только температуру.

ПС. Если кого-то интересует скетч на 2 енкодера, пишите, выложу.
ПС2. так же прошу помочь мне с робой канала фена, сейчас работает, но с изменением max_power  65.0, 180.0

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

void CalctImpulseControl() {
    ots = (uint16_t)(acos(HAPower / 100.0 - 1.0) * 9950.0 / 3.14);
}

/* HotAir PI regulator */
void HA_PI() {
    int err = SetHotAirT - GetHotAirT;
    float tmp_power = Kp * err + Ki * integral;
    float max_power = map(SetHotAirT, min_hotair_temp, max_hotair_temp, 65.0, 180.0);
    if (tmp_power < max_power && tmp_power > 0.0) {
        integral += err;
    }
    HAPower = constrain(tmp_power, 0.0, max_power);
    CalctImpulseControl();

 

yuraanapa
Offline
Зарегистрирован: 31.05.2017

k0l1an пишет:

ПС. Если кого-то интересует скетч на 2 енкодера, пишите, выложу.

 

 

Конечно выкладывайте,очень интересно

yuraanapa
Offline
Зарегистрирован: 31.05.2017

del

AleksBAM
Offline
Зарегистрирован: 13.09.2014

Возможно это оговаривалось,  но хочу ещё раз спросить.  Резистор и светодиод на выводе  D13 обязательно выпаивать.

alex1978
alex1978 аватар
Offline
Зарегистрирован: 09.09.2017

Нет, не обязательно.

k0l1an
Offline
Зарегистрирован: 21.08.2018

резюк с d13 снял, допилю немного, протестирую и выложу, обязательно, прошу помощи в настройке фена, скажите где и какие осцилограммы снять?? на стандартном скетче не корректно работает фен, ставлю 200* а он до 100 догревает и вырубается в защиту. Более менее работает, только с изменением выше.

il86md
Offline
Зарегистрирован: 22.11.2017

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

плата от автора, прошивка 1.6.1

а еще вот такой косяк на бисплее вылазиет (после сборки такого не было) при нажатии кнопок. питание от usb пробовал теже яйца

Oleg_D
Offline
Зарегистрирован: 13.06.2018

Звук задумывался одинаковой громкости что для фена, что для паяльника. Замерьте потребление бипера, подключившись вместо джампера Тестером. Если больше 20мА, желательно пустить через транзистор. Поищите в теме, уже обсуждалось как повысить громкость.
По дисплею: проверьте проводку подключения дисплея, возможны плохой контакт или наводки на проводах. Замените их при необходимости. Возможно перепутаны sda scl. На кнопки поставьте кандёры в параллель, на 0.1 uF

AleksBAM
Offline
Зарегистрирован: 13.09.2014

Какой энкодер использовали.

k0l1an
Offline
Зарегистрирован: 21.08.2018

AleksBAM пишет:

Какой энкодер использовали.

самий дешевий, з гайочкою) близько 1$

k0l1an
Offline
Зарегистрирован: 21.08.2018

Доброй ночи, более менее настроил паялку, чтобы выложить исходник, есть над чем работать, но и текущий вариант роботоспособен.
Собрал на плате от Руслана(2.2) нужно перерезать дороги помеченные красным(d11, d13, a1, a2), в разрыв 
впаять разисторы 10К(между ардуино и разьемом), так же резисторами 10К нужно подтянуть выводы энкодера к +5В, на схеме указал. Выводы дуины (d11, d13, a1, a2) подтянуть к земле кондерами 10-100nf(у меня 100). Должен быть выпаян резистор или led на дуине, который на d13 и 470ом на плате не ставь(что на d13 идет)
Буззер обязательно пасивный, на 5В подключи, резистор 470 замени на 160
d13, d11 энкодер2 (фен), a0 кнопка энкодер2. a1, a2 энкодер1 (паяльник), a0 кнопка энкодер1.
Эенкодер может быть 2х типов :
1.  1-щелчек - 1импульс (1>0) - для норм роботы должно быть что-то типо if (n2 == 40 || n2 == 36)
2. 1-щелчек - 2импульса (1>0>1), типо так. У меня такие (были самые дешевые). мой скеч под такой.
Есть на 3 импульса, я таких пока не видил.
Вот тестовый скеч для проверки энкодера, если ваш не корректно работает, или срабатывает через щелчек.

#include <EEPROM.h>
#include <CyberLib.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Bounce2.h>
#include <avr/io.h>
#include <avr/interrupt.h>

volatile int enc;
volatile int enc2;

void setup() // процедура setup
{
  Serial.begin(9600);

  pinMode(11, INPUT_PULLUP);//enc2
  pinMode(13, INPUT_PULLUP);//enc2
  pinMode(15, INPUT_PULLUP);//enc1
  pinMode(16, INPUT_PULLUP);//enc1
  PCICR = (1 << PCIE0) | (1 << PCIE1); //разрешить прерывание
  PCMSK0 = (1 << PCINT3); //выбрать вход на котором сработает прерывание
  PCMSK1 = (1 << PCINT9); //выбрать вход на котором сработает прерывание

}
/* Enkoder */ //открыть монитор порта и потехоньку повращать в разные стороны
              //энкодеры, значения записать в блокнот, набрать калькуляторе програмиста
              //перевести в бинарный, посмотреть какие биты изменяются, поменять n и n2
ISR (PCINT1_vect) {
  byte n = PINC; //в монитор порта посмотрел, биты выставил на n, закоментируй
 enc=n; //в монитор порта посмотрел, биты выставил на n, закоментируй
  /* //в монитор порта посмотрел, биты выставил на n, розкоментируй
  byte n = PINC & 15; // узнать значение суммы битов PC0 и PС1
  if (n == 13 || n == 14) {enc++ }
  if (n == 12 || n == 15) {enc-- }
  */
}

ISR (PCINT0_vect) {
  byte n2 = PINB; //в монитор порта посмотрел, биты выставил на n2, закоментируй 
  enc2=n2; //в монитор порта посмотрел, биты выставил на n2, закоментируй
 /*//в монитор порта посмотрел, биты выставил на n, розкоментируй
  byte n2 = PINB & 40; // узнать значение суммы битов PC0 и PС1
  if (n2 == 40 || n2 == 36) {enc2++ }
  if (n2 == 32 || n2 == 44) {enc2-- }
  */
}


void loop() // процедура loop
{

  Serial.println(enc);
  Serial.println("and");
  Serial.println(enc2);
  Serial.println("/////////////////////");
  delay (500);
}

Чуть не забыл, так и не понял, чего не догревает фен, измени строку

  float max_power = map(SetHotAirT, min_hotair_temp, max_hotair_temp, 65.0, 180.0);
на 
    float max_power = map((float)SetHotAirT, min_hotair_temp, max_hotair_temp, 10.0, 60.0);
Управление паялкой:
* кнопка Е1 -короткое - вкл паяльник и сброс таймера(если активен)
--длинное отключает паяльник
* кнопка Е2 -короткое - вкл фен и сброс таймера(если активен), когда включен фен, переключае обототы и температуру
--длинное отключает фен
*енкодер 1 регулирует температуру паяльника
*енкодер 2 регулирует температуру фена(в любом состоянии), и обороты(только когда включен фен)
****Установи  пасивный буззер!!!!)))) одновременно нажми кнопка Е1  и кнопка Е2 и активируй ночной режим))), на дисплее появиться [*](запоминается)
Вроде бы все, И да, все сделанно на 1.6.1. сам лично тестирую, кто сделает, отпишите.
код для энкодера брал здесь, наверное надо указать первоисточник)))
http://arduino.ru/forum/apparatnye-voprosy/ispolzuem-enkoder?page=4#comment-160475
Если ты дочитал, то вот мой исходник, если есть какие-то проблеммы, то не сердись, это я впервый раз код пишу)))
Фух, все. тестируем)))
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                    Soldering Station v 1.6.1              */
/*                        coded by OlegK                     */
/* arduino.ru/forumy/proekty/ocherednaya-payalnaya-stantsiya */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <EEPROM.h>
#include <CyberLib.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Bounce2.h>
#include <avr/io.h>
#include <avr/interrupt.h>

/* it's fuckin' magic! */
#if 1
__asm volatile ("nop");
#endif

/* Options */

/* if you need to create themperature diagramm then uncomment it */
//#define NEED_GRAPH

/* if used not rail-to-rail OPA, then uncomment it */
//#define LM358

/* if used passive busser, then uncomment it */
#define PASSIVE_BUZZER

/* if you want deactivate additional protection, then COMMENT it */
#define HA_ADV_PROT_ON
#define S_ADV_PROT_ON

/* if used LCD 1602, then uncomment it */
//#define LCD_1602

/* Soldering iron - if you want to remove the digit jumps, then uncomment it */
//#define SOLDER_DIGIT_JUMPS_REMOVE

/* Hot Air - if you want to remove the digit jumps, then uncomment it */
//#define HOTAIR_DIGIT_JUMPS_REMOVE

/* if you want soldering iron soft start, then uncomment it */
//#define SOLDER_SOFT_START

/* if you want to activate soldering iron off-timer only on stand, then uncomment it */
#define SOLDER_TIMER_ON_STAND

/* End options */

#define FIRMWARE_VERSION "1.6.1"

#ifdef LCD_1602
LiquidCrystal_I2C lcd(0x3F, 16, 2);
#else
LiquidCrystal_I2C lcd(0x3F, 20, 4);
#endif

/* Degree symbol */
uint8_t degree[8] = {
  B01100,
  B10010,
  B10010,
  B01100,
  B00000,
  B00000,
  B00000,
  B00000
};

/* Arrow symbol */
uint8_t arrow[8] =  {
  B00000,
  B00100,
  B00010,
  B11111,
  B00010,
  B00100,
  B00000,
  B00000
};

/* mode selector */

#define  modeHotAir 2
#define  modeFanPWM 3

int nmBut = 0 ;
long nmMillis = 0;
boolean nkey1 = false ;
boolean nkey2 = false;
boolean need_S_countdown = false;
byte selected_Mode = modeHotAir;
byte HA_countdown = 1;
byte S_countdown = 1;
uint16_t HA_sleeptime = 10;
uint16_t S_sleeptime = 10;
uint16_t Graph_count = 0;
uint32_t Enc_ButtonPressTime = 0;
uint32_t Enc2_ButtonPressTime = 0;
boolean Enc_ButtonState, Enc2_ButtonState;

byte Count;
uint16_t Duration, Interval;

char bspace[ ] = "    ";

#define pinBuzzer 12
#define pinFanPwm 6
#define pinSolderPwm 5

#define min_solder_temp 100
#define max_solder_temp 400
#define min_hotair_temp 20.0
#define max_hotair_temp 450.0
#define min_rpm 30
#define max_rpm 100
#define min_nightmod 1000
#define max_nightmod 2000
#define default_temp 280
#define default_rpm 50
#define default_nightmod 1000

/* Buttons */
#define sw_HA 10
#define sw_S 9

#define e_button 17 //pin A1 button
#define e2_button 14 //pin A0 button2
#define e_dir 15    //pin A2 enc_a
#define e_step 16   //pin A3 enc_b
#define e2_dir 11    //pin D13 enc2_a
#define e2_step 13   //pin D11 enc2_b

/* Bounce killers */
Bounce swHotAir = Bounce();
Bounce swSolder = Bounce();
Bounce SolderOnButton = Bounce();
Bounce HotAirOnButton = Bounce();

/* Hot Air */

/* states */
#define st_stop 0
#define st_work 1
#define st_pause 2
#define st_protection 3
//#define st_lowpower 4

byte hotair_state = st_stop;

volatile uint16_t ots = 9990;
volatile float HAPower = 0.0;
uint16_t GetHotAirT = 0;
uint16_t SetHotAirT = 100;
uint16_t nightmod = 1000;
byte SetHotAirRPM = 100;
boolean HA_temp_stable = false;
boolean need_Cooling = true;
boolean scr_blink = false;

byte ha_error = 0;
boolean HA_prot_beep = false;
boolean ha_f1 = false;
boolean ha_f2 = false;
uint32_t prevHAcontrol;

/* HA PI regulator */
#define Kp 1.0
#define Ki 0.003
int integral = 0;

/* Soldering iron */
uint16_t GetSolderT = 0;
uint16_t SetSolderT = 100;
boolean S_temp_stable = false;
boolean SolderON = false;
boolean SolderProtect = false;
int SPower = 0;
//byte solder_state = st_stop;

byte s_error = 0;
uint32_t prevScontrol;
boolean S_prot_beep = false;
boolean s_f1 = false;
boolean s_f2 = false;

/* Solder P regulator */
#define sKp 50

uint16_t last_HotAirT, last_SolderT, last_nightmod;
byte last_RPM;


/********************************************* MAIN PROCEDURES *********************************************/

void setup() {


  pinMode(3, INPUT_PULLUP); //Zero cross pin
  D5_Out; //pinSolder
  D5_Low;
  D4_Out; //pinSolderProt
  D4_Low;
  D7_Out; //pinHotAirProt
  D7_Low;
  D8_Out; //pinHotAir
  D8_Low;
  D12_Out; //pinBuzzer
  D12_Low;
  ButtonsSetup();
#ifdef NEED_GRAPH
  Serial.begin(9600);
#endif

  lcd.begin();
  lcd.backlight();
  lcd.createChar(0, degree);
  lcd.createChar(1, arrow);
  Splash();
  MemRead();
  delay_ms(500);
  initDisplay();
  attachInterrupt(1, ZC, FALLING);
}
void loop() {
  ScanButtons();
  /* Off-timer for HotAir, countdown with 1 min */
  static uint32_t prevHAmillis = millis();
  if (hotair_state == st_pause) {
    if (millis() - prevHAmillis > 60000) {
      prevHAmillis = millis();
      if (HA_countdown > 1) {
        HA_countdown--;
        if (HA_countdown == 1) {
          Beep(100);    //Beep, if 1 minute left
        }
      } else {
        hotair_state = st_stop;
        Beep(200);
      }
    }
  } else {
    prevHAmillis = millis();
  }

  /* Off-timer for Solder, countdown with 1 min */
  static uint32_t prevSmillis = millis();
  if (need_S_countdown) {
    if (millis() - prevSmillis > 60000) {
      if (S_countdown > 1) {
        S_countdown--;
        if (S_countdown == 1) {
          Beep(100);    //Beep, if 1 minute left
        }
      } else {
        MemSolder();
        need_S_countdown = false;
        SolderON = false;
        Beep(200);
      }
      prevSmillis = millis();
    }
  } else {
    prevSmillis = millis();
  }

  /* Update LCD with 500ms interval */
  static uint32_t prevDisplayMillis = millis();
  static boolean blink_state = true;
  if (millis() - prevDisplayMillis > 500) {
    scr_blink = ! scr_blink;
    prevDisplayMillis = millis();
    DisplayUpdate(blink_state);
    blink_state = !blink_state;

    /* Send data to Serial port */
#ifdef NEED_GRAPH
    if (SolderON || hotair_state == st_work) {
      Graph_count++;
      //Serial.print(Graph_count);
      //Serial.print(";");
    } else {
      Graph_count = 0;
    }
    if (SolderON && hotair_state != st_work) {
      Serial.println(GetSolderT);
    } else if (!SolderON && hotair_state == st_work) {
      Serial.println(GetHotAirT);
    }
#endif
  }

  WorkWithHotAir();
  WorkWithSolder();
}

/* HotAir working procedure */
void WorkWithHotAir() {

  /* Read the thermocouple value */
#ifdef LM358
  GetHotAirT = getOversampled_HA();
#else
  GetHotAirT = getOversampled_HA() >> 1;
#endif

  switch (hotair_state) {
    case st_stop: {
        HotAirOff();
        Cooling();
        break;
      }

    case st_work: {
        /* Set the cooler rpm (convert from 30-100% to 80-255 PWM) */
        analogWrite(pinFanPwm, map(SetHotAirRPM, min_rpm, max_rpm, 80, 255));

        ha_error = HADoProtect();

        /* Turn ON protection relay */
        if (ha_error == 0) D7_High;

        /* Themperature PI regulator */
        HA_PI();

        /* If themperature was stable for 100 times (+/-2 degrees), then signalize about it */
        int delta = ABS(SetHotAirT, GetHotAirT);
        static byte HAgood;
        if (!HA_temp_stable) {
          if (delta < 3) {
            HAgood++;
            if (HAgood == 100) {
              Beep(50);
              delay_ms(200);
              Beep(50);
              HAgood = 0;
              HA_temp_stable = true;
            }
          } else {
            HAgood = 0;
          }
        } else {
          if (delta > 5) {
            HA_temp_stable = false;
          }
        }
        break;
      }

    case st_pause: {
        HAPower = 0.0;
        HA_temp_stable = false;
        CalctImpulseControl();
        Cooling();
        ha_error = HADoProtect();
        break;
      }

    case st_protection: {
        need_Cooling = true;
        break;
      }

  } //switch (state)
}

/* Solder working procedure */
void WorkWithSolder() {

  /* Read the thermoresistor value */
  //GetSolderT = A6_Read >> 1;
#ifdef LM358
  GetSolderT = getOversampled_S();
#else
  GetSolderT = getOversampled_S() >> 1;
#endif

  if ( SolderON ) {
    s_error = SDoProtect();

    /* Turn ON relay */
    if (s_error == 0) D4_High;

    /* themperature P regulator */
    S_P();

    /* If themperature was stable for 200 times loop (+/- 2 degrees) then signalize about it */
    uint16_t delta = ABS(SetSolderT, GetSolderT);
    static byte Sgood;
    if (!S_temp_stable) {
      if (delta < 3) {
        Sgood++;
        if (Sgood == 200) {
          Beep(50);
          delay_ms(200);
          Beep(50);
          //Sgood = 0;
          S_temp_stable = true;
        }
      } else {
        Sgood = 0;
      }
    } else {
      if (delta > 5) {
        S_temp_stable = false;
      }
    }
  } else {
    SolderOff();
    need_S_countdown = false;
    S_countdown = 1;
  }
}

/***************************************** END OF MAIN PROCEDURES ******************************************/



/****************************************** PROTECTION & ON-OFF ********************************************/

/* HotAir protection */
byte HADoProtect() {

  /* ------------------------------------------------------------------------------------------------------- */

  /* Crytical protection: high overheat or thermocouple value is not valid or wire break */
  if (GetHotAirT > max_hotair_temp + 20) {
    HAProtectionOut();
    return 1;
  }

  /* ------------------------------------------------------------------------------------------------------- */

  /* Crytical protection: thermocouple value is not valid or wires short circuit */
  if (GetHotAirT < 10) {
    HAProtectionOut();
    return 2;
  }

  /* ------------------------------------------------------------------------------------------------------- */

#ifdef HA_ADV_PROT_ON

  /* Overheat protection */
  if (ha_f1 && GetHotAirT > SetHotAirT + 20) {
    ha_f1 = false;
    HAProtectionOut();
    return 3;
  }

  if (ha_f2 && GetHotAirT < SetHotAirT + 15) {
    ha_f1 = true;
    ha_f2 = false;
  }

  /* ------------------------------------------------------------------------------------------------------- */

  /* Deviation themperature protection +/- 10 degrees */
  //if (HA_temp_stable) {
  //ha_f3 = true;
  //}
  //
  //if (ha_f3) {
  //if (GetHotAirT > SetHotAirT + 10) {
  //HAProtectionOut();
  //return 4;
  //}
  //
  //if (GetHotAirT < SetHotAirT - 10) {
  //HAProtectionOut();
  //return 5;
  //}
  //}

  /* ------------------------------------------------------------------------------------------------------- */



  /* Advanced protection: the themperature falls down/not changed & power > 0 */
  /* & */
  /* Advanced protection: the themperature rise up & power < 0 */
  static byte t_cnt = 0;
  static byte t_cnt2 = 0;
  static boolean ha_ctrl = true;
  if (!HA_temp_stable) {
    static uint16_t prev_t;
    if (ha_ctrl) {
      prev_t = GetHotAirT;
      ha_ctrl = false;
      prevHAcontrol = millis();
    }

    if (!ha_ctrl && millis() - prevHAcontrol > 1000) {
      ha_ctrl = true;

      if (HAPower > 0.0) {

        /* themperature falls or not changed */
        if (prev_t >= GetHotAirT && GetHotAirT < SetHotAirT) {
          t_cnt++;
          if (t_cnt == 7) {
            HAProtectionOut();
            t_cnt = 0;
            return 6;
          }
        } else t_cnt = 0;

      } else { //HAPower == 0.0

        /* themperature rise */
        if (prev_t < GetHotAirT && GetHotAirT > SetHotAirT) {
          t_cnt2++;
          if (t_cnt2 == 7) {
            HAProtectionOut();
            t_cnt2 = 0;
            return 7;
          }
        } else t_cnt2 = 0;
      }
    }
  } else {
    prevHAcontrol = millis();
    t_cnt = 0;
    t_cnt2 = 0;
    ha_ctrl = true;
  }

#endif

  /* ------------------------------------------------------------------------------------------------------- */

  /* if everything is OK */
  return 0;
}

/* Solder protection */
byte SDoProtect() {

  /* ------------------------------------------------------------------------------------------------------- */

  /* Crytical protection: high overheat or thermoresistor value is not valid or wire break */
  if (GetSolderT > max_solder_temp + 20) {
    SProtectionOut();
    return 1;
  }

  /* ------------------------------------------------------------------------------------------------------- */

  /* Crytical protection: thermoresistor value is not valid or wires short circuit */
  if (GetSolderT < 10) {
    SProtectionOut();
    return 2;
  }

  /* ------------------------------------------------------------------------------------------------------- */

#ifdef S_ADV_PROT_ON

  /* Overheat protection */
  if (s_f1 && GetSolderT > SetSolderT + 20) {
    s_f1 = false;
    SProtectionOut();
    return 3;
  }

  if (s_f2 && GetSolderT < SetSolderT + 15) {
    s_f1 = true;
    s_f2 = false;
  }

  /* ------------------------------------------------------------------------------------------------------- */

  /* Deviation themperature protection +/- 10 degrees */
  //if (S_temp_stable) {
  //s_f3 = true;
  //}
  //
  //if (s_f3) {
  //if (GetSolderT > SetSolderT + 10) {
  //SProtectionOut();
  //return 4;
  //}
  //Not required for soldering iron
  //if (GetSolderT < SetSolderT - 10) {
  //SProtectionOut();
  //return 5;
  //}
  // }

  /* ------------------------------------------------------------------------------------------------------- */



  /* Advanced protection: the themperature falls down/not changed & power > 0 */
  /* & */
  /* Advanced protection: the themperature rise up & power < 0 */
  static byte t_cnt = 0;
  static byte t_cnt2 = 0;
  static boolean s_ctrl = true;
  if (!S_temp_stable) {
    static uint16_t prev_t = 0;
    if (s_ctrl) {
      prev_t = GetSolderT;
      s_ctrl = false;
      prevScontrol = millis();
    }

    if (!s_ctrl && millis() - prevScontrol > 1000) {
      s_ctrl = true;

      if (SPower > 0) {
        /* themperature falls or not changed */
        if (prev_t >= GetSolderT && GetSolderT < SetSolderT) {
          t_cnt++;
          if (t_cnt == 10) {
            SProtectionOut();
            t_cnt = 0;
            return 6;
          }
        } else t_cnt = 0;
      } else { //SPower == 0
        /* themperature rise */
        if (prev_t < GetSolderT && GetSolderT > SetSolderT) {
          t_cnt2++;
          if (t_cnt2 == 10) {
            SProtectionOut();
            t_cnt2 = 0;
            return 7;
          }
        } else t_cnt2 = 0;
      }
    }
  } else {
    prevScontrol = millis();
    t_cnt = 0;
    t_cnt2 = 0;
    s_ctrl = true;
  }

#endif

  /* ------------------------------------------------------------------------------------------------------- */

  /* everything is OK */
  return 0;
}

/* Solder full off */
void SolderOff() {
  analogWrite(pinSolderPwm, 0);
  D5_Low;
  D4_Low;
  resetSolderStablePoint();
  if (S_prot_beep) {
    S_prot_beep = false;
    Beep(1000);
    MemSolder();
  }
}

/* HotAir full off */
void HotAirOff() {
  HAPower = 0.0;
  D8_Low;
  delay_ms(10);
  D7_Low;
  hotair_state = st_stop;
  resetHotAirStablePoint();
  if (HA_prot_beep) {
    HA_prot_beep = false;
    Beep(1000);
    MemHotAir();
  }
}

/* Cooling the heater until the temperature is below 50 degrees */
void Cooling() {
  if (GetHotAirT >= 50 && need_Cooling) {
    analogWrite(pinFanPwm, 255);
  } else {
    analogWrite(pinFanPwm, 0);
    need_Cooling = false;
  }
}

/* internal procedure */
void set_ha_f() {
  boolean a = SetHotAirT >= GetHotAirT;
  ha_f1 = a;
  ha_f2 = !a;
}

/* internal procedure */
void set_s_f() {
  boolean a = SetSolderT >= GetSolderT;
  s_f1 = a;
  s_f2 = !a;
}

/* Solder protection */
void SProtectionOut() {
  SolderProtect = true;
  S_prot_beep = true;
  SolderON = false;
  SolderOff();
}

/* HotAir protection out */
void HAProtectionOut() {
  analogWrite(pinFanPwm, 255);
  HA_prot_beep = true;
  HotAirOff();
  hotair_state = st_protection;
}

/****************************************** END OF PROTECTION & ON-OFF *************************************/



/************************************************ OTHER ROUTINES *******************************************/

/* Read integer value */
int EEPROM_int_read(int addr) {
  byte raw[2];
  for (byte i = 0; i < 2; i++) {
    raw[i] = EEPROM.read(addr + i);
  }
  int &num = (int&)raw;
  return num;
}

/* Write integer value */
void EEPROM_int_write(int addr, int num) {
  byte raw[2];
  (int&)raw = num;
  for (byte i = 0; i < 2; i++) {
    EEPROM.write(addr + i, raw[i]);
  }
}

/* Read last parameters from memory */
void MemRead() {
  SetSolderT = EEPROM_int_read(0);
  if (SetSolderT < min_solder_temp || SetSolderT > max_solder_temp)  {
    SetSolderT = default_temp;
    last_SolderT = SetSolderT;
  }
  SetHotAirT = EEPROM_int_read(4);
  if (SetHotAirT < min_hotair_temp || SetHotAirT > max_hotair_temp) {
    SetHotAirT = default_temp;
    last_HotAirT = SetHotAirT;
  }
  SetHotAirRPM = EEPROM_int_read(8);
  if (SetHotAirRPM < min_rpm || SetHotAirRPM > max_rpm) {
    SetHotAirRPM = default_rpm;
    last_RPM = SetHotAirRPM;
  }
  nightmod = EEPROM_int_read(12);
  if (nightmod == min_nightmod || nightmod == max_nightmod) {
    nightmod = nightmod;
    last_nightmod = nightmod;
  } else {
    nightmod = default_nightmod;
    last_nightmod = nightmod;
  }
}

/* Write last used solder themperature to memory */
void MemSolder() {
  if (last_SolderT != SetSolderT) {
    EEPROM_int_write(0, SetSolderT);
    last_SolderT = SetSolderT;
  }
}

/* Write last used HotAir themperature and fan r.p.m. to memory */
void MemHotAir() {
  if (last_HotAirT != SetHotAirT) {
    EEPROM_int_write(4, SetHotAirT);
    last_HotAirT = SetHotAirT;
  }
  if (last_RPM != SetHotAirRPM) {
    EEPROM_int_write(8, SetHotAirRPM);
    last_RPM = SetHotAirRPM;
  }
}

/* Sound procedure */
void Memnightmod() {
  if (last_nightmod != nightmod) {
    EEPROM_int_write(12, nightmod);
    last_nightmod = nightmod;
  }
}


void Beep(uint16_t duration) {
#ifdef PASSIVE_BUZZER
  tone(pinBuzzer, nightmod, duration);
#else
  D12_High;
  delay_ms(duration);
  D12_Low;
#endif
}

/* HotAir oversampling function */
//uint16_t getOversampled_HA() {
//uint32_t tmp = 0;
//for (byte z = 0; z < 64; z++) {
//tmp +=  A7_Read;
//}
//return tmp >> 6;
//}

uint16_t getOversampled_HA() {
  uint32_t tmp = 0;
  for (byte z = 0; z < 128; z++) {
    tmp +=  A7_Read;
  }
  return tmp >> 7;
}

/* Solder oversampling function */
uint16_t getOversampled_S() {
  uint32_t tmp = 0;
  for (byte z = 0; z < 64; z++) {
    tmp +=  A6_Read;
  }
  return tmp >> 6;
}

/* Get absolute difference function */
uint16_t ABS(uint16_t a, uint16_t b) {
  if (a > b) {
    return (a - b);
  }
  return (b - a);
}

/****************************************** END OF OTHER ROUTINES ******************************************/



/*************************************** TRIAC CONTROL & AUTOMATHIC ****************************************/

/* Zero cross INT1 */
void ZC() {
  StartTimer1(HeaterOn, ots);
  RestartTimer1();
}

/* Triac open impulse */
void HeaterOn() {
  StopTimer1();
  if (HAPower > 0.0) {
    D8_High;
    delay_us(30);
  }
  D8_Low;
}

/* Calculate triac on delay */
void CalctImpulseControl() {
  ots = (uint16_t)(acos(HAPower / 100.0 - 1.0) * 9950.0 / 3.14);
}

/* HotAir PI regulator */
void HA_PI() {
  int err = SetHotAirT - GetHotAirT;
  float tmp_power = Kp * err + Ki * integral;
  float max_power = map(SetHotAirT, min_hotair_temp, max_hotair_temp, 65.0, 180.0);
  if (tmp_power < max_power && tmp_power > 0.0) {
    integral += err;
  }
  HAPower = constrain(tmp_power, 0.0, max_power);
  CalctImpulseControl();
}


#ifdef SOLDER_SOFT_START
/* Solder P regulator with soft start */
void S_P() {
  int TempPower = sKp * (SetSolderT - GetSolderT + 1);
  byte maxPower = 255;
  if (GetSolderT < 100) {
    maxPower = 100;
  }
  SPower = constrain(TempPower, 0, maxPower);
  analogWrite(pinSolderPwm, SPower);
}
#else
/* Solder P regulator */
void S_P() {
  int TempPower = sKp * (SetSolderT - GetSolderT + 1);
  SPower = constrain(TempPower, 0, 255);
  analogWrite(pinSolderPwm, SPower);
}
#endif

/************************************* END OF TRIAC CONTROL & AUTOMATHIC ***********************************/



/**************************************** INTERFACE CONTROLS & TIMERS **************************************/


/* Scan buttons */
void ScanButtons() {

  /* HotAir stand switch */
  if (swHotAir.update() && hotair_state != st_stop) {
    if (swHotAir.fell()) {
      hotair_state = st_pause;
      need_Cooling = true;
      resetHotAirCountown();
    } else {
      if (hotair_state == st_pause) {
        hotair_state = st_work;
        integral = 0;
        set_ha_f() ;
      }
    }
    Beep(50);
  } else if (hotair_state == st_work && D10_Read == LOW) {
    D7_High;
    hotair_state = st_pause;
    need_Cooling = true;
    resetHotAirCountown();
  }

#ifdef SOLDER_TIMER_ON_STAND

  /* Solder stand switch - only on stand */
  if (swSolder.update()) {
    if (swSolder.fell() && SolderON) {
      if (!need_S_countdown) {
        Activate_S_countdown();
        Beep(50);
      }
    }

    if (swSolder.rose())  {
      if (need_S_countdown) {
        need_S_countdown = false;
        Beep(50);
      }
    }
  }


#else

  /* Solder stand switch simple check user activity */
  if (swSolder.update() && SolderON) {
    resetSolderCountdown();
    Beep(50);
  }

#endif // SOLDER_TIMER_ON_STAND


  /* Encoder1 short & long button press */
  /* Solder "on-off" button */

  if (SolderOnButton.update()) {
    if (SolderOnButton.read()) {
      Enc_ButtonState = false;
    } else {
      if (!SolderON) {
        SolderON = true;
        SolderProtect = false;

#ifdef SOLDER_TIMER_ON_STAND
        if (!D9_Read) Activate_S_countdown();
#else
        Activate_S_countdown();
#endif

        Graph_count = 0;
        resetSolderStablePoint();
        set_s_f();
      } else {

        resetSolderCountdown();
      }
      Enc_ButtonState = true;
      Enc_ButtonPressTime = millis();

      Beep(50);
    }

    nkey1 = false;
  }

  if  (Enc_ButtonState) {

    if ( millis() - Enc_ButtonPressTime >= 1000 ) { //long press
      Enc_ButtonPressTime = millis();
      if (SolderON) {
        SolderON = false;
        resetSolderStablePoint();
        MemSolder();
        Beep(200);
      }
    }
    nkey1 = true;
  }

  /* Encoder2 button short and long press */

  /* HotAir "on-off" button */

  if (HotAirOnButton.update()) {
    if (HotAirOnButton.read()) {
      Enc2_ButtonState = false;
    } else {
      if (hotair_state == st_work || hotair_state == st_pause) {
        (selected_Mode < modeFanPWM) ? (selected_Mode++) : (selected_Mode = modeHotAir);
      } else {
        if (hotair_state != st_work) {
          hotair_state = st_work;
          Graph_count = 0;
          selected_Mode = modeHotAir;
          need_Cooling = true;
          resetHotAirStablePoint();
          set_ha_f();
          integral = 0;
        } else {
          resetHotAirCountown();
        }
      }
      Enc2_ButtonState = true;
      Enc2_ButtonPressTime = millis();


      Beep(50);
    }
    nkey2 = false;
  }

  if  (Enc2_ButtonState) {
    if ( millis() - Enc2_ButtonPressTime >= 1000 ) { //long press
      Enc2_ButtonPressTime = millis();
      resetHotAirStablePoint();
      if (hotair_state == st_work || hotair_state == st_pause) {
        hotair_state = st_stop;
        need_Cooling = true;
        MemHotAir();
        selected_Mode = modeHotAir;
        Beep(200);
      }
      nkey2 = true;
    }
  }

  //NightMode
  if (nkey1 == true && nkey2 == true) {
    if (millis() - nmMillis   >=  1)
    {
      nmMillis  = millis();
      nmBut ++;
    }
    else
    {
      nmBut  = 0;
    }
    if (nmBut >= 100)
    {
      if (nmBut <= 130)
      {
        if (nightmod == 1000) {
          nightmod = 2000;
          nmBut = nmBut + 50;
          Beep(100);
        } else {
          if (nightmod == 2000) {
            nightmod = 1000;
            nmBut = nmBut + 50;
            Beep(100);
          }
        }
      }
    }
  }
  else {
    nmBut  = 0;
  }
}

/* Enkoder */
ISR (PCINT1_vect) {
  byte n = PINC & 15; // узнать значение суммы битов PC0 и PС1
  if (n == 13) {
    if (SetSolderT < max_solder_temp) {
      SetSolderT += 5;
    }
    set_s_f();
    resetSolderStablePoint();
    resetSolderCountdown();
    Beep(50);
  }
  if (n == 15) {
    if (SetSolderT > min_solder_temp) {
      SetSolderT -= 5;
    }
    set_s_f();
    resetSolderStablePoint();
    resetSolderCountdown();
    Beep(50);
  }
}

ISR (PCINT0_vect) {
  byte n = PINB & 40; // узнать значение суммы битов PC0 и PС1
  if (n == 40) {
    switch (selected_Mode) {
      case modeHotAir:
        if (SetHotAirT < max_hotair_temp) {
          SetHotAirT += 5;
        }
        break;
      case modeFanPWM:
        if (SetHotAirRPM < max_rpm) {
          SetHotAirRPM += 5;
        }
        break;
    }

    if (selected_Mode > 1) {
      set_ha_f();
      integral = 0;
    }
    Beep(50);
  }


  if (n == 32) {
    switch (selected_Mode) {
      case modeHotAir:
        if (SetHotAirT > min_hotair_temp) {
          SetHotAirT -= 5;
        }
        break;
      case modeFanPWM:
        if (SetHotAirRPM > min_rpm) {
          SetHotAirRPM -= 5;
        }
        break;
    }

    if (selected_Mode > 1) {
      set_ha_f();
      integral = 0;
    }
    Beep(50);
  }


}

/* Buttons initialise */

void ButtonsSetup() {
  pinMode(sw_HA, INPUT_PULLUP);
  swHotAir.attach(sw_HA);
  swHotAir.interval(50);

  pinMode(sw_S, INPUT_PULLUP);
  swSolder.attach(sw_S);
  swSolder.interval(50);

  pinMode(e_button, INPUT_PULLUP);//enc button
  SolderOnButton.attach(e_button);
  SolderOnButton.interval(5);

  pinMode(e_dir, INPUT_PULLUP);   //pin enc_a
  pinMode(e_step, INPUT_PULLUP);  //pin enc_b

  pinMode(e2_button, INPUT_PULLUP);//enc2 button
  HotAirOnButton.attach(e2_button);
  HotAirOnButton.interval(5);

  pinMode(e2_dir, INPUT_PULLUP);   //pin enc2_a
  pinMode(e2_step, INPUT_PULLUP);  //pin enc2_b

  PCICR = (1 << PCIE0) | (1 << PCIE1); //разрешить прерывание
  PCMSK0 = (1 << PCINT3); //выбрать вход на котором сработает прерывание
  PCMSK1 = (1 << PCINT9); //выбрать вход на котором сработает прерывание

}

/* internal procedure */
void resetHotAirStablePoint() {
  HA_temp_stable = false;
}

/* internal procedure */
void resetSolderStablePoint() {
  S_temp_stable = false;
}

/* Reset HotAir countdown */
void resetHotAirCountown() {
  HA_countdown = HA_sleeptime;
}

/* Reset Solder countdown */
void resetSolderCountdown() {
  S_countdown = S_sleeptime;
}

/* Activate Solder countdown procedure */
void Activate_S_countdown() {
  need_S_countdown = true;
  S_countdown = S_sleeptime;
}

/**************************************** INTERFACE CONTROLS & TIMERS **************************************/



/************************************************* DISPLAY *************************************************/

/* "Hello" screen */
void Splash() {
  lcd.clear();
#ifdef LCD_1602
  lcd.setCursor(0, 0);
  lcd.print(F("Soldering Station"));
  lcd.setCursor(6, 1);
#else
  lcd.setCursor(2, 1);
  lcd.print(F("Soldering Station"));
  lcd.setCursor(7, 2);
#endif
  lcd.print(F("v "));
  lcd.print(FIRMWARE_VERSION);
}

/* Set LCD design */
void initDisplay() {
  lcd.clear();
#ifdef LCD_1602

#else
  lcd.setCursor(11, 0);
  lcd.print(F("Set"));

  lcd.setCursor(16, 0);
  lcd.print(("Act"));

  lcd.setCursor(0, 1);
  lcd.print(F("Solder"));

  lcd.setCursor(0, 2);
  lcd.print(F("HotAir"));

  lcd.setCursor(0, 3);
  lcd.print(F("FanRPM"));
#endif
}

/* Update LCD */
void DisplayUpdate(boolean blink_state) {

#ifdef LCD_1602

  lcd.setCursor(0, 0);
  lcd.print(bspace);
  lcd.setCursor(0, 0);

  if (SolderProtect) {
    lcd.print(F("!"));
    lcd.print(s_error);
  } else if (need_S_countdown) {
    if (blink_state) lcd.print(S_countdown);
  } else if (SolderON) {
    (S_temp_stable) ? (lcd.print(F(" *"))) : (lcd.print(F(" :")));
  }

  lcd.setCursor(3, 0);
  lcd.print(bspace);
  lcd.setCursor(3, 0);
  lcd.print(SetSolderT);
  lcd.write((byte)0);

  byte pos;
  uint16_t s_view_t;

  if (GetSolderT > 505) {
    lcd.setCursor(8, 0);
    lcd.print(F("---"));
  } else {
    uint16_t s_view_t;
#ifdef SOLDER_DIGIT_JUMPS_REMOVE
    (S_temp_stable) ? (s_view_t = SetSolderT) : (s_view_t = GetSolderT);
#else
    s_view_t = GetSolderT;
#endif
    pos = GetPos(s_view_t);
    lcd.setCursor(8, 0);
    lcd.print(bspace);
    lcd.setCursor(8 + pos, 0);
    lcd.print(s_view_t);
  }
  lcd.write((byte)0);

  lcd.setCursor(0, 1);
  lcd.print(bspace);
  lcd.setCursor(0, 1);

  switch (hotair_state) {
    case st_stop: {
        break;
      }

    case st_work: {
        if (HA_temp_stable) {
          lcd.print(F(" *"));
        } else {
          lcd.print(F(" :"));
        }
        break;
      }

    case st_pause: {
        if (blink_state) lcd.print(HA_countdown);
        break;
      }

    case st_protection: {
        lcd.print(F("!"));
        lcd.print(ha_error);
        break;
      }

  }

  pos = GetPos(SetHotAirT);
  lcd.setCursor(3, 1);
  lcd.print(bspace);
  lcd.setCursor(3 + pos, 1);
  lcd.print(SetHotAirT);
  lcd.write((byte)0);

  if (GetHotAirT > 505) {
    lcd.setCursor(8, 1);
    lcd.print(F("---"));
  } else {
    uint16_t ha_view_t;
#ifdef HOTAIR_DIGIT_JUMPS_REMOVE
    (HA_temp_stable) ? (ha_view_t = SetHotAirT) : (ha_view_t = GetHotAirT);
#else
    ha_view_t = GetHotAirT;
#endif
    pos = GetPos(ha_view_t);
    lcd.setCursor(8, 1);
    lcd.print(bspace);
    lcd.setCursor(8 + pos, 1);
    lcd.print(ha_view_t);
  }
  lcd.write((byte)0);

  lcd.setCursor(13, 1);
  lcd.print(bspace);
  lcd.setCursor(13, 1);

  pos = GetPos(SetHotAirRPM);
  if (need_Cooling && hotair_state != st_work) {
    lcd.print(F("100%"));
  } else {
    lcd.setCursor(13 + pos, 1);
    lcd.print(SetHotAirRPM);
    lcd.print(F("%"));
  }

  lcd.setCursor(2, 0);
  lcd.print(F(" "));
  lcd.setCursor(2, 1);
  lcd.print(F(" "));
  lcd.setCursor(12, 1);
  lcd.print(F(" "));

  switch (selected_Mode) {
    case modeSolder: {
        lcd.setCursor(2, 0);
        break;
      }

    case modeHotAir: {
        lcd.setCursor(2, 1);
        break;
      }

    case modeFanPWM: {
        lcd.setCursor(12, 1);
        break;
      }
  }
  lcd.write((byte)1);

#else //LCD2004

  lcd.setCursor(6, 1);
  lcd.print(bspace);
  lcd.setCursor(7, 1);

  if (SolderProtect) {
    lcd.print(F("!"));
    lcd.print(s_error);
  } else if (need_S_countdown) {
    if (blink_state) lcd.print(S_countdown);
  } else if (SolderON) {
    (S_temp_stable) ? (lcd.print(F(" *"))) : (lcd.print(F(" :")));
  }

  lcd.setCursor(11, 1);
  lcd.print(bspace);
  lcd.setCursor(11, 1);
  lcd.print(SetSolderT);
  lcd.write((byte)0);

  byte pos;
  uint16_t s_view_t;

  if (GetSolderT > 505) {
    lcd.setCursor(16, 1);
    lcd.print(F("---"));
  } else {
    uint16_t s_view_t;
#ifdef SOLDER_DIGIT_JUMPS_REMOVE
    (S_temp_stable) ? (s_view_t = SetSolderT) : (s_view_t = GetSolderT);
#else
    s_view_t = GetSolderT;
#endif
    pos = GetPos(s_view_t);
    lcd.setCursor(16, 1);
    lcd.print(bspace);
    lcd.setCursor(16 + pos, 1);
    lcd.print(GetSolderT);
  }
  lcd.write((byte)0);

  lcd.setCursor(6, 2);
  lcd.print(bspace);
  lcd.setCursor(7, 2);

  switch (hotair_state) {
    case st_stop: {
        break;
      }

    case st_work: {
        if (HA_temp_stable) {
          lcd.print(F(" *"));
        } else {
          lcd.print(F(" :"));
        }
        break;
      }

    case st_pause: {
        if (blink_state) lcd.print(HA_countdown);
        break;
      }

    case st_protection: {
        lcd.print(F("!"));
        lcd.print(ha_error);
        break;
      }

  }

  pos = GetPos(SetHotAirT);
  lcd.setCursor(11, 2);
  lcd.print(bspace);
  lcd.setCursor(11 + pos, 2);
  lcd.print(SetHotAirT);
  lcd.write((byte)0);

  if (GetHotAirT > 505) {
    lcd.setCursor(16, 2);
    lcd.print(F("---"));
  } else {
    uint16_t ha_view_t;
#ifdef HOTAIR_DIGIT_JUMPS_REMOVE
    (HA_temp_stable) ? (ha_view_t = SetHotAirT) : (ha_view_t = GetHotAirT);
#else
    ha_view_t = GetHotAirT;
#endif
    pos = GetPos(ha_view_t);
    lcd.setCursor(16, 2);
    lcd.print(bspace);
    lcd.setCursor(16 + pos, 2);
    lcd.print(ha_view_t);
  }
  lcd.write((byte)0);

  lcd.setCursor(11, 3);
  lcd.print(bspace);
  lcd.setCursor(11, 3);

  pos = GetPos(SetHotAirRPM);
  if (need_Cooling && hotair_state != st_work) {
    lcd.print(F("100%"));
  } else {
    lcd.setCursor(11 + pos, 3);
    lcd.print(SetHotAirRPM);
    lcd.print(F("%"));
  }

  for (byte z = 1; z < 4; z++) {
    lcd.setCursor(10, z);
    lcd.print(F(" "));
  }

  lcd.setCursor(10, selected_Mode);
  lcd.write((byte)1);

  if (nightmod == 1000) {
    lcd.setCursor(0, 0);
    lcd.print(F("\xA2\x2A\xA3"));
  } else {

    lcd.setCursor(0, 0);
    lcd.print(F("\xA2\xA0\xA3"));
  }

#endif

}

/* Get print position */
byte GetPos(uint16_t number) {
  if (number >= 100) {
    return 0;
  } else if (number < 10) {
    return 2;
  }
  return 1;
}

/*********************************************** END OF DISPLAY ********************************************/

 

 

Sergey2018
Offline
Зарегистрирован: 05.09.2018

Добрый день. 

Уважаемый OlegK, уважаемые форумчане.

Хочу собрать такю станцию, у меня вопрос по трансформатору питания.

Есть в магазине транформаторы на кольце:

1.  ТТП100 (2х12В, 3.7А)

2. ТТП100 (2х25В, 1.8А)

3. ТТП-60 (2х12В, 2.2А)

4. ТТП120 (2х18В, 3.0А)

Какой выбрать?  Надеюсь на ваш совет и опыт (у меня его пока немного). 

 

 

alex1978
alex1978 аватар
Offline
Зарегистрирован: 09.09.2017

Вообще 100Вт за глаза. У меня на 80Втном бублике нормально работает. Так что бери первый и сматывай часть одной вторички.
В Питере есть дядька, мотает трансы на бублике на заказ, я у него для усилка заказывал. У него объявление на Авито есть, если надо могу ссылку кинуть. Только когда дома буду.

Sergey38
Offline
Зарегистрирован: 23.02.2017

Sergey2018, второй берите (необходимо 24В), а вторую вторичку смотайте (на 5В)...

alex1978
alex1978 аватар
Offline
Зарегистрирован: 09.09.2017

Со вторым трансом после выпрямителя будет порядка 30 вольт.

alex1978
alex1978 аватар
Offline
Зарегистрирован: 09.09.2017

А вообще, сколько стоят трансы в магазине?

Oleg_D
Offline
Зарегистрирован: 13.06.2018

Выбор в порядке возрастания геморроя:
4
2
1
3 - не годится
Я бы выбрал 4, если разница в цене не существенна.

Sergey2018
Offline
Зарегистрирован: 05.09.2018

Спасибо за ответ.

Это чип и дип. Они стоят до 1500 руб. и зависят от мощности.

1- 1450 руб.

2-1440 руб.

3- 1030 руб.

4- 1520 руб.

Я мало имею опыта по линейным блокам питани, поэтому и задавал вопрос. Помню что после выпрямителеля напряжение больше должно быть в 1,14 раза.

Тогда если взять 2х18 вольт, то напряжение поднимется до 21. Этого мало.

alex1978, что Вы думаете по этому вопросу?

В теории мне нужен транс с выходным напряжением не более 20 вольт. Так?  Взять ТТП120 (2х18В, 3.0А), правда цена в 1500 кусается, домотать, потом расчет сделаю намотав 10 витков и замерив получившеевя напряжение, полагаю это порядка 30-50 витков. Как вы думаете? Или может быть альтернативный вариант?

Посоветуйте пожалуйста.

Sergey2018
Offline
Зарегистрирован: 05.09.2018

Извините, не в 1,14 а в 1,41

alex1978
alex1978 аватар
Offline
Зарегистрирован: 09.09.2017

Я заказывал у дядьки из Питера транс для усилка. 80Вт, две вторички по 18В. Обошёлся в 1300р. вместе с доставкой. Зато никакого гемороя, подключил и всё работает. С 18В вторички выходит 23,7В. На паялке у меня стоит такойже транс с одной вторичкой на 18В. На него домотал ещё одну на 5В. Всё работает.

Oleg_D
Offline
Зарегистрирован: 13.06.2018

18*1.41=25.4, что очень хорошо подходит, с учётом падения . Для 5 в лучше смотать вторую обмотку. Если этого не делать и понизить через lm7812- LM7805, получите лишнюю печку.
Пс. Можете на мотать сверху доп обмотку для 5в, никто этого не запрещает.

Sergey2018
Offline
Зарегистрирован: 05.09.2018

А можно намотать еще одну обмотку, включить в противофазе и погасить определенное количество вольт? Только танс после этого греться не будет?

Секешфехервар
Секешфехервар аватар
Offline
Зарегистрирован: 06.09.2018

Здравствуйте подскажите пожалуйста можно ли ипользовать 328 в дип корпусе ?

Секешфехервар
Секешфехервар аватар
Offline
Зарегистрирован: 06.09.2018

И если можно то куда перекинуть А6, А7 ?

Oleg_D
Offline
Зарегистрирован: 13.06.2018

Конечно. Пины только переназначте в скетче как Вам удобно,  пин D3 (прерывание) можно только поменять на пин 2. Программатор у Вас есть, подозреваю. PWM пины D6 и D7 на любой из D3, D9, D10, D11. Смотрите распиновку, там все расписано.

ПС . В дип корпусе аналоговых входов меньше. А6 и А7 на нано можно переназначить только на аналоговые пины в дип - это с А0 по А5. Можете перекинуть пару кнопок на цыфровой пин.

Секешфехервар
Секешфехервар аватар
Offline
Зарегистрирован: 06.09.2018

Сорян туплю....

SERG_K
Offline
Зарегистрирован: 06.08.2017

SERG_K
Offline
Зарегистрирован: 06.08.2017

Удалена

SERG_K
Offline
Зарегистрирован: 06.08.2017

Добрый день. Смоделировал в Компасе для платы Руслана и китайского б/п. Жду предложения по дизайну. Печать на 3D принтере, как закончу, если кому надо, выложу файлы. Размер 150x150x65

Sergey2018
Offline
Зарегистрирован: 05.09.2018

SERG_K, красиво, мне очень понравилось.

А это чисто мое мнение:

1. Угол наклона дисплея нужно изменить, читать информацию будет не удобно (угол обзора мал).

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

3. Выключатель установлен близко к разъему, не удобно. Я бы сделал его на задней панели или в центре.

P.S.  Жалко что не могу пока купить принтер.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

OlegK пишет:

Простая софтина для снятия графиков тут. (#1153) Требуется NET Framework 4.0

Спасибо за программу. Реально помогла настроить ПИД, тоже паяльник делаю

kalapanga
Offline
Зарегистрирован: 23.10.2016

SERG_K пишет:

Добрый день. Смоделировал в Компасе для платы Руслана и китайского б/п. Жду предложения по дизайну. Печать на 3D принтере, как закончу, если кому надо, выложу файлы. Размер 150x150x65

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

SERG_K
Offline
Зарегистрирован: 06.08.2017

Спосибо за предложения, угол наклона дисплея меня тоже немного смущает, просто хотелось сделать его более плоским. Насчет растояния от паяльника до жала там растояние достаточное и площадка под паяльником поварачивается.Насчет теплового экрана хорошая идея можно подумать как его там разместить. Выключатель, если увеличить высоту можно и на заднюю панель перенести. Просто вся задняя стенка занята б/п, стоит вертикально.

3D принтер собирал сам. После того как собрал станцию пост 1722 понял, что для наших самоделок нужены нормальные корпуса.

SERG_K
Offline
Зарегистрирован: 06.08.2017

SERG_K
Offline
Зарегистрирован: 06.08.2017

Секешфехервар
Секешфехервар аватар
Offline
Зарегистрирован: 06.09.2018

Намутил основную платку размер 65×85мм . деталюхи с алика уже два месяца идут либо по новой надо заказывать... С сотки получается фото не вставить ?