Тайме обратного хода для паяльной станции

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Доброго времени суток!

Собрал таймер кухонный по этой схеме http://mk90.blogspot.fr/2009_06_01_archive.html

Работает замечательно. Но он не подходит для моих нужд. Я новичок не шар. в программировании. Умею только повторять чужие проекты.

Нашел в скетче чтобы первоначальное время было не 0000 а свое. Мне нужно чтобы он астоматически стартовал без нажатия на кнопки и при старте на какой нибудь вывод подавал лог 1. после окончания таймера лог.0 для включения реле.

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

вот. скетч. что тут нужно переделать. заранее спасибо!

/* кухонный таймер */

#define SEG_NUM 4 // total digits in a display

#define BUTT_NUM 2 // total buttons number

#define delayms 1 // time for displaying one digit, ms

#define p_buzz 8

// управление дисплеем

byte latch[SEG_NUM] = {0,0,0,0}; // защелка состояний

boolean flash_all = true; // мигание

boolean flash_dots = false;

byte s_pin[SEG_NUM]; // пины общих катодов

byte l_pin[8]; // мап пинов на сегменты знакоместа

byte d_map[10]; // память знакогенератора

// State Machines

typedef enum { E_WAIT=0, E_SETUP, E_STARTED, E_ALARMED} fsm_type;

fsm_type state = E_WAIT;

typedef enum { NO_EVENT=0, KEY1_PRESSED, KEY2_PRESSED, KEY12_PRESSED, KEYS_CHANGED} key_press_type;

int key_event = NO_EVENT;

byte b_pins[BUTT_NUM] = {10,9};

boolean b_changed[BUTT_NUM] = {false,false};

int b_state[BUTT_NUM] = {HIGH,HIGH};

// машина состояний таймера

word timer_delay = 0; // задержка, на которую программируется таймер

boolean started = false; // таймер запущен

boolean alarmed = false; // включен акустический сигнал

unsigned long t_start; // засечка времени старта

unsigned long t_stop; // засечка времени останова

// машина состояния кнопок

unsigned long button_timeout; // засечка последнего времени изменения кнопок

void setup() {

s_pin[0] = 4;

s_pin[1] = 5;

s_pin[2] = 6;

s_pin[3] = 7;

 

l_pin[0] = 3; // a

l_pin[1] = 17; // b

l_pin[2] = 19; // c

l_pin[3] = 15; // d

l_pin[4] = 14; // e

l_pin[5] = 2; // f

l_pin[6] = 18; // g

l_pin[7] = 16; // dot

 

for (byte i=0;i<SEG_NUM;i++) {

pinMode(s_pin[i],OUTPUT);

digitalWrite(s_pin[i],LOW);

}

for (byte i=0;i<8;i++) pinMode(l_pin[i],OUTPUT);

 

d_map[0] = 0b00000010; // 0

d_map[1] = 0b10011110; // 1

d_map[2] = 0b00100100; // 2

d_map[3] = 0b00001100; // 3

d_map[4] = 0b10011000; // 4

d_map[5] = 0b01001000; // 5

d_map[6] = 0b01000000; // 6

d_map[7] = 0b00011110; // 7

d_map[8] = 0b00000000; // 8

d_map[9] = 0b00001000; // 9

// кнопки

for (byte i=0;i<BUTT_NUM;i++) {

pinMode(b_pins[i],INPUT);

digitalWrite(b_pins[i],HIGH); // enable pull-up R

}

//

pinMode(p_buzz,OUTPUT);

digitalWrite(p_buzz,LOW);

// Serial.begin(38400);

}

void set_digit(byte d) {

byte i=0;

for (byte mask=0x80;mask!=1;mask>>=1)

digitalWrite(l_pin[i++],(d_map[d]&mask) ? HIGH : LOW );

}

void indicate() {

if (!flash_all || (flash_all && (millis() % 1000UL > 200))) {

digitalWrite(l_pin[7], (!flash_dots || (flash_dots && (millis() % 1000UL > 500))) ? LOW : HIGH);

for (byte k=0;k<SEG_NUM;k++) {

digitalWrite(s_pin[k],HIGH);

set_digit(latch[k]);

delay(delayms);

digitalWrite(s_pin[k],LOW);

}

}

}

void set_display(unsigned long secs) {

latch[3] = secs % 10;

if (secs > 9) {

latch[2] = (secs % 60) / 10;

}

else latch[2] = 0;

if (secs > 59) {

latch[1] = (secs / 60) % 10;

}

else latch[1] = 0;

if (secs > (60*10 -1) ) {

latch[0] = secs / 600;

} else latch[0] = 0;

}

void update_time() {

unsigned long t_now = millis();

if (state == E_STARTED) {

if (t_now >= t_stop) {

set_display(timer_delay);

flash_all = true;

flash_dots = false;

alarmed = true;

state = E_ALARMED;

} else set_display((t_stop - t_now) / 1000UL);

} else set_display(timer_delay);

}

void update_alarm() {

digitalWrite(p_buzz, (alarmed && (millis() % 2000UL > 999)) ? HIGH : LOW);

}

int get_key_event() {

for (int i=0;i<BUTT_NUM;i++) {

b_changed[i]=false;

int bread = digitalRead(b_pins[i]);

if (bread != b_state[i]) {

b_changed[i]=true;

b_state[i]=bread;

}

}

if (b_changed[0] || b_changed[1]) {

if ( (b_state[0] == LOW) && (b_state[1] == LOW)) return KEY12_PRESSED;

else if ( (b_state[0] == LOW) && b_changed[0]) return KEY1_PRESSED;

else if ( (b_state[1] == LOW) && b_changed[1]) return KEY2_PRESSED;

else return KEYS_CHANGED;

} else

return NO_EVENT;

}

void update_buttons() {

int evt = get_key_event();

 

switch (evt) {

case NO_EVENT: {

if (state == E_SETUP) {

if ( timer_delay && ((millis() - button_timeout) > 5000) ) {

t_start = millis();

t_stop = t_start + (unsigned long)timer_delay*1000UL;

flash_all = false;

flash_dots = true;

started = true;

state = E_STARTED;

}

}

return;

} break;

case KEY1_PRESSED: {

if (state == E_WAIT) state = E_SETUP;

button_timeout = millis();

if (state == E_SETUP)

timer_delay+=(timer_delay>599?600:60);

} break;

case KEY2_PRESSED: {

if (state == E_WAIT) state = E_SETUP;

button_timeout = millis();

if (state == E_SETUP) {

if (timer_delay < 60) timer_delay = 0;

else timer_delay-=(timer_delay>(15*60-1)?300:60);

}

} break;

case KEY12_PRESSED: {

if (state == E_WAIT) state = E_SETUP;

button_timeout = millis();

if (state == E_SETUP) {

timer_delay=0;

}

} break;

case KEYS_CHANGED: {

if (state == E_WAIT) state = E_SETUP;

button_timeout = millis();

if (state == E_ALARMED) {

alarmed = false;

state = E_WAIT;

}

} break;

}

}

void loop() {

indicate();

update_time();

update_alarm();

update_buttons();

}

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Сдесь ставится первоначальное время

word timer_delay = 0; // задержка, на которую программируется таймер

Sky-DiGGeR
Offline
Зарегистрирован: 19.01.2015

Друг, ну ты хоть расскажи, разобрался ли с автозапуском таймера этого кода? А то я уже неделю в этот код втыкаюсь над этой же задачей. Чую ещё чуть чуть и Си уже выучу..))

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

Sky-DiGGeR
Offline
Зарегистрирован: 19.01.2015

Разобрался я с автозапуском!

Добавил условие (строки 155-161), что таймер стартует через 10 секунд после подачи питания, но не будет автостартовать если контроллер проработал без сброса больше 30 сек ( т.е. автостарт работает только первый раз)

switch (evt) {
    case NO_EVENT: { 
      if (state == E_WAIT && millis() > 10000UL && millis() < 30000UL) {
        t_start = millis();
          t_stop = t_start + (unsigned long)timer_delay*1000UL;
          flash_all = false;
          flash_dots = true;
          started = true;
          state = E_STARTED;
      if (state == E_SETUP) {
        if ( timer_delay && ((millis() - button_timeout) > 5000) ) {
          t_start = millis();
          t_stop = t_start + (unsigned long)timer_delay*1000UL;
          flash_all = false;
          flash_dots = true;
          started = true;
          state = E_STARTED;
        }
      }
      }
      return; 

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

void update_alarm() {
  digitalWrite(p_buzz, (alarmed /* && (millis() % 2000UL > 999)*/) ? HIGH : LOW);
}

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

Ну и осталось разобраться с подключением дисплеев с общим катодом

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Sky-DiGGeR,  Доброго времени суток!

С кодом я не разобрался. Только почему прога стартует через 10 секунд не понятно? Нужно сократить время хотя бы до 3-х секунд. 10 это много

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Еще вопрос. Под рукойнет ардуино т.к. на работе нахожусь. Прога работает так я правильно понял: при подаче питания проходит 10 секунд и начинается обратный отсчет. на D8 появляется лог. 1 для включения реле. после оканчания отсчета чтобы запустить нужно нажать на резет или переподать напругу

Sky-DiGGeR
Offline
Зарегистрирован: 19.01.2015

Gavrilov_S пишет:

Нужно сократить время хотя бы до 3-х секунд. 10 это много

мне надо было именно столько , можешь подправить тут 10000 на 3000, и будет стартовать через 3 сек.

     if (state == E_WAIT && millis() > 10000UL && millis() < 30000UL) {

Gavrilov_S пишет:

Прога работает так я правильно понял: при подаче питания проходит 10 секунд и начинается обратный отсчет. на D8 появляется лог. 1 для включения реле. после оканчания отсчета чтобы запустить нужно нажать на резет или переподать напругу

Нет, на D8  появляется лог 1 только после отработки времени обратного отсчёта и висит там пока таймер мигает всеми цифрами в ожидании команды. В принципе сделать так чтобы пока работает таймер, на D8 висела лог1, тоже не сложно:

void update_alarm() {
   digitalWrite(p_buzz, (started ) ? HIGH : LOW); // лог1 пока таймер запущен
}

но тогда надо ещё добавить одну строку в секции void update_time()

void update_time() {
  unsigned long t_now = millis();    
  if (state == E_STARTED) {
    if (t_now >= t_stop) {
      set_display(timer_delay);
      flash_all = true;
      flash_dots = false;
      alarmed = true;
      started = false;
      state = E_ALARMED;
    } else set_display((t_stop - t_now) / 1000UL);
  } else set_display(timer_delay);
}

такой вариант я не проверял натурно, но логически всё должно работать )

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Спасибо за труд! Завтра притащу ардуино и проверю.

Такие штуки хочу еще установить на лампочки освещения и на элетромоторы насосов. От забывчивости. Но их буду делать без дисплея и кнопок. буду использовать только выход и пущу  на симистор.

Sky-DiGGeR
Offline
Зарегистрирован: 19.01.2015

Вообще, если тебе надо просто задержку выключения органзовать после умпульсного включения питания, например по кнопке без фиксации и не нужны никакие дисплеи с цифирками, то это очень легко и быстро организуется на таймере NE555. Схем в инете море, собираются на коленке за 15 минут и настройка задержки простым подбором R C , по формуле 1.1 * R (МОм) * С (мкФ) = t (сек)

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Про NE555 я знаю. На нем много че собирал. Она она мне не подходит. в некоторых местах мне нужна все же индикация процесса. Прошивать прогу буду в мега 8 контроллеры. памяти должно хватить. Их уже заказал на алиэкспрессе

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Проверил код. Все работает! Сам стартует через 10 секунд. На D8 появляется после старта 4,5вольт лог 1.

Но вот не разобрался с автостартом так и. чтобы он стартовал не через 10 секунд а через 3.

Sky-DiGGeR
Offline
Зарегистрирован: 19.01.2015

Чтобы стартовала через 3 сек, вот тут:

switch (evt) {
    case NO_EVENT: { 
      if (state == E_WAIT && millis() > 10000UL && millis() < 30000UL) {
        t_start = millis();
          t_stop = t_start + (unsigned long)timer_delay*1000UL;
          flash_all = false;
          flash_dots = true;
          started = true;
          state = E_STARTED;
      if (state == E_SETUP) {
        if ( timer_delay && ((millis() - button_timeout) > 5000) ) {
          t_start = millis();
          t_stop = t_start + (unsigned long)timer_delay*1000UL;
          flash_all = false;
          flash_dots = true;
          started = true;
          state = E_STARTED;
        }
      }
      }
      return; 

Надо сделать вот так:

switch (evt) {
    case NO_EVENT: { 
      if (state == E_WAIT && millis() > 3000UL && millis() < 30000UL) {
        t_start = millis();
          t_stop = t_start + (unsigned long)timer_delay*1000UL;
          flash_all = false;
          flash_dots = true;
          started = true;
          state = E_STARTED;
      if (state == E_SETUP) {
        if ( timer_delay && ((millis() - button_timeout) > 5000) ) {
          t_start = millis();
          t_stop = t_start + (unsigned long)timer_delay*1000UL;
          flash_all = false;
          flash_dots = true;
          started = true;
          state = E_STARTED;
        }
      }
      }
      return; 

 

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Еще олин вопрос. После отсчитывания временя чтобы он не показывал установленное а 0000 показывал что нужно менять?

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Все разобрался с временем автозапуска: if (state == E_WAIT && millis() > 1000UL && millis() < 30000UL) {

тут 1000 поставил 1 секунду

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Все отлично работает. Жаль только буззера нет по окончании работы

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Собрал 3 устройства.

Один на защиту насоса на гидроаккумулятор. поставил на 3.5 минут.

ВТорой. На душевую кабинку и тепличку на 30 минут.

Третий в баню. на 14 минут.

1

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Добрый день!

Добрые люди, от Вас снова нужна помощь.

Купил я приблуду TM1637 СВЕТОДИОДНЫЙ Дисплей Модуль Для arduino 7 Сегмент 4 Бит https://ru.aliexpress.com/item/Free-shipping-4-digital-display-with-adjustable-brightness-LED-module-clock-Point-Accessories-Blocks-for-arduino/32243608784.html?spm=2114.13010608.0.0.WWDPGf&detailNewVersion=&categoryId=541

Хочу на таймер поставить этот дисплей. т.к. он по 2 проводам управляется. Помогите с кодом плиз. С меня пиво!

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Еще одна хотелочка. Чтобы по окончании отсчета раз 5 пропищала пищалка. у меня есть со встроенным генератором на 5В. На любую свободную ногу

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014
/* кухонный таймер */
 
#define SEG_NUM 4 // total digits in a display
 
#define BUTT_NUM 2 // total buttons number
 
#define delayms 1 // time for displaying one digit, ms
 
#define p_buzz 8
 
// управление дисплеем
 
byte latch[SEG_NUM] = {0,0,0,0}; // защелка состояний
 
boolean flash_all = true; // мигание
 
boolean flash_dots = false;
 
byte s_pin[SEG_NUM]; // пины общих катодов
 
byte l_pin[8]; // мап пинов на сегменты знакоместа
 
byte d_map[10]; // память знакогенератора
 
// State Machines
 
typedef enum { E_WAIT=0, E_SETUP, E_STARTED, E_ALARMED} fsm_type;
 
fsm_type state = E_WAIT;
 
typedef enum { NO_EVENT=0, KEY1_PRESSED, KEY2_PRESSED, KEY12_PRESSED, KEYS_CHANGED} key_press_type;
 
int key_event = NO_EVENT;
 
byte b_pins[BUTT_NUM] = {10,9};
 
boolean b_changed[BUTT_NUM] = {false,false};
 
int b_state[BUTT_NUM] = {HIGH,HIGH}; 

// машина состояний таймера
 
word timer_delay = 900; // задержка, на которую программируется таймер
 
boolean started = false; // таймер запущен
 
boolean alarmed = false; // включен акустический сигнал
 
unsigned long t_start; // засечка времени старта
 
unsigned long t_stop; // засечка времени останова
 
// машина состояния кнопок
 
unsigned long button_timeout; // засечка последнего времени изменения кнопок
 
void setup() {
 
s_pin[0] = 4; 
s_pin[1] = 5; 
s_pin[2] = 6; 
s_pin[3] = 7; 

 
l_pin[0] = 3; // a 
l_pin[1] = 17; // b
l_pin[2] = 19; // c
l_pin[3] = 15; // d
l_pin[4] = 14; // e
l_pin[5] = 2; // f 
l_pin[6] = 18; // g
l_pin[7] = 16; // dot
 
  
for (byte i=0;i<SEG_NUM;i++) {
 
pinMode(s_pin[i],OUTPUT);
 
digitalWrite(s_pin[i],LOW);
 
}
 
for (byte i=0;i<8;i++) pinMode(l_pin[i],OUTPUT);
 
d_map[0] = 0b00000010; // 0
d_map[1] = 0b10011110; // 1
d_map[2] = 0b00100100; // 2
d_map[3] = 0b00001100; // 3 
d_map[4] = 0b10011000; // 4
d_map[5] = 0b01001000; // 5
d_map[6] = 0b01000000; // 6
d_map[7] = 0b00011110; // 7
d_map[8] = 0b00000000; // 8
d_map[9] = 0b00001000; // 9
 
// кнопки
 
for (byte i=0;i<BUTT_NUM;i++) {
 
pinMode(b_pins[i],INPUT);
 
digitalWrite(b_pins[i],HIGH); // enable pull-up R
 
} 

// 

pinMode(p_buzz,OUTPUT);
 
digitalWrite(p_buzz,LOW); 

// Serial.begin(38400);
 
}
 
void set_digit(byte d) {
 
byte i=0;
 
for (byte mask=0x80;mask!=1;mask>>=1) 

digitalWrite(l_pin[i++],(d_map[d]&mask) ? HIGH : LOW );
 
}
 
void indicate() {
 
if (!flash_all || (flash_all && (millis() % 1000UL > 200))) {   //1000UL > 200
 
digitalWrite(l_pin[7], (!flash_dots || (flash_dots && (millis() % 1000UL > 500))) ? LOW : HIGH); 

for (byte k=0;k<SEG_NUM;k++) {
 
digitalWrite(s_pin[k],HIGH);
 
set_digit(latch[k]);
 
delay(delayms);
 
digitalWrite(s_pin[k],LOW);
 
}
 
}
 
}
 
void set_display(unsigned long secs) {
 
latch[3] = secs % 10;
 
if (secs > 9) {
 
latch[2] = (secs % 60) / 10;
 
}
 
else latch[2] = 0;
 
if (secs > 59) {
 
latch[1] = (secs / 60) % 10;
 
}
 
else latch[1] = 0;
 
if (secs > (60*10 -1) ) {
 
latch[0] = secs / 600;
 
} else latch[0] = 0;
 
}
 
void update_time() {
 
unsigned long t_now = millis(); 

if (state == E_STARTED) {
 
if (t_now >= t_stop) {
 
set_display(timer_delay);
 
flash_all = true;
 
flash_dots = false;
 
alarmed = true;

 started = false; ////////
 
state = E_ALARMED;
 
} else set_display((t_stop - t_now) / 1000UL);
 
} else set_display(timer_delay);
 
}
 
 
 
/// A L A R M

void update_alarm() {

 // digitalWrite(p_buzz, (alarmed /* && (millis() % 2000UL > 999)*/) ? HIGH : LOW);
   digitalWrite(p_buzz, (started ) ? HIGH : LOW); // лог1 пока таймер запущен

}

int get_key_event() {
 
for (int i=0;i<BUTT_NUM;i++) {
 
b_changed[i]=false;
 
int bread = digitalRead(b_pins[i]);
 
if (bread != b_state[i]) {
 
b_changed[i]=true;
 
b_state[i]=bread;
 
}
 
}
 
if (b_changed[0] || b_changed[1]) {
 
if ( (b_state[0] == LOW) && (b_state[1] == LOW)) return KEY12_PRESSED;
 
else if ( (b_state[0] == LOW) && b_changed[0]) return KEY1_PRESSED;
 
else if ( (b_state[1] == LOW) && b_changed[1]) return KEY2_PRESSED;
 
else return KEYS_CHANGED;
 
} else 

return NO_EVENT;
 
}
 
void update_buttons() {
 
int evt = get_key_event();
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 
switch (evt) {
 
// АВТОСТАРТ
case NO_EVENT: { 
if (state == E_WAIT && millis() > 1000UL && millis() < 30000UL) {  // ТУТ ЗАДЕРЖКА 10000UL && millis() < 30000UL) 10СЕК., ТУТ СТАРТ СРАЗУ 1000UL && millis() < 30000UL 

        t_start = millis();

          t_stop = t_start + (unsigned long)timer_delay*1000UL; //1000 не трогать это значение
          flash_all = false;
 flash_dots = true;
started = true;
state = E_STARTED;
}

if (state == E_SETUP) {
 
if ( timer_delay && ((millis() - button_timeout) > 5000) ) {
 
t_start = millis();
 
t_stop = t_start + (unsigned long)timer_delay*1000UL;
 
flash_all = false;
 
flash_dots = true;
 
started = true;
 
state = E_STARTED;
 
}
 
}
 
return; 

} break;
 
case KEY1_PRESSED: {
 
if (state == E_WAIT) state = E_SETUP;
 
button_timeout = millis(); 

if (state == E_SETUP) 

timer_delay+=(timer_delay>599?600:60);
 
} break;
 
case KEY2_PRESSED: {
 
if (state == E_WAIT) state = E_SETUP;
 
button_timeout = millis(); 

if (state == E_SETUP) {
 
if (timer_delay < 60) timer_delay = 0;
 
else timer_delay-=(timer_delay>(15*60-1)?300:60);
 
} 

} break;
 
case KEY12_PRESSED: {
 
if (state == E_WAIT) state = E_SETUP;
 
button_timeout = millis(); 

if (state == E_SETUP) {
 
timer_delay=0;
 
}
 
} break;
 
case KEYS_CHANGED: {
 
if (state == E_WAIT) state = E_SETUP;
 
button_timeout = millis(); 

if (state == E_ALARMED) {
 
alarmed = false;
 
state = E_WAIT; 

}
 
} break; 

} 

}
 
void loop() {
 
indicate();
 
update_time();
 
update_alarm();
 
update_buttons();
 
}

 

Gavrilov_S
Offline
Зарегистрирован: 13.11.2014

Добрый день!

Как переделать программу по общие аноды??? дисплеи кончились с катодами :(