Хочу выложить проект, но вот куда?

vde69
Offline
Зарегистрирован: 10.01.2016

хочу выложить проект контролера муфельной печи, есть 2 проблеммы

1. В проекте есть PDF файлы (графики, статистика, методики, схемы)

2. Скетч разделен на 7 файлов, по этому выкладывать надо зип директории

 

здесь можно выкладывать только картинки :(

inspiritus
Offline
Зарегистрирован: 17.12.2012

Сделайте архив на ядиске, сюда положите ссылку и коммениы.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

vde69 пишет:

хочу выложить проект контролера муфельной печи, есть 2 проблеммы

1. В проекте есть PDF файлы (графики, статистика, методики, схемы)

2. Скетч разделен на 7 файлов, по этому выкладывать надо зип директории

 

здесь можно выкладывать только картинки :(

onedrive.live.com
www.dropbox.com

*как там в 90-х, друг из прошлого?

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

Переводите пдф в картинку, картинку выкладываете в пост. Отдельные файлы скетчей помещаете каждый под свой спойлер. Кому надо - откроют, кому не надо - мимо пройдут. Как это сделать, рассказано в соответствующих "приклееных" темах.

vde69
Offline
Зарегистрирован: 10.01.2016

это будет очень много... один скетч сейчас примерно 20 000 символов, плюс 3..5 фото, плюс 2..3 графика плюс таблицы и описание еще с несколькими картинками

Serg5
Offline
Зарегистрирован: 16.03.2016

vde69 пишет:

это будет очень много... один скетч сейчас примерно 20 000 символов, плюс 3..5 фото, плюс 2..3 графика плюс таблицы и описание еще с несколькими картинками

я тоже думаю, что многовато как то насекомых надо избавиться от них http://dezin24.com/dezinfektsiya вызвал спецов все сделали быстро , теперь дома как в раю.

vde69
Offline
Зарегистрирован: 10.01.2016

попробую тут, заодно может кто ошибок и опечаток найдет :)

ВНИМАНИЕ - это тестовая версия !!!!

файл term.ino :

// ---------------------------------------------------------
// управление муфельной печью модуль "term"
//
// состав проекта:
// Arduino R3 UNO
// LCD 1602 Keypad shield
// MAX6675 Module + K Type Thermocouple Sensor for Arduino
// UN3F SLA-05VDC-SL-A 5V 30A Relay Module For Arduino
//
// версия среды Arduino 1.5.2
// 
// автор vde69@mail.ru (с), процедуры главного алгоритма
// ---------------------------------------------------------

// добавляем необходимые библиотеки

#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <util/delay.h>

// общие настройки
const int TIME_GET_THERMOMETR = 1000; // время шага опроса термодатчиков
const int TIME_GET_ERROR      = 1000; // время шага диагностики ошибок
const int TIME_ANIME          = 300;  // время шага анимации
const int TIME_RUN            = 100;  // время шага расчета действий по включению/выключению нагрузки
const int TIME_STAB           = 2000; // время расчета в режиме стабилизации (при открытом муфеле)
const int BUTTON_TIME         = 20;   // время между нажатием и отпусканием (устранение дребезга)
const int BUTTON_TIME_LONG    = 5000; // время перевода в режим SETUP
const int TERM_LIMIT          = 1100; // предельная температура контролера, установить температуру выше нельзя, при реальном превышении будет издавать звук
const byte TERM_GRADIENT      = 5;    // допустимый градиент температуры (от установленой), влияет на процесс калибровки, рекомендуется от 5 до 20 (5 - самая точная калибрвка)

// статусы нажатых кнопок, определить несколько нажатых кнопок одновременно - нельзя
const int BUTTON_RIGHT  = 1;     // 0   < 100
const int BUTTON_UP     = 2;     // 148 < 200
const int BUTTON_DOWN   = 3;     // 338 < 400
const int BUTTON_LEFT   = 4;     // 515 < 600
const int BUTTON_SELECT = 5;     // 750 < 800
const int BUTTON_NONE   = 0;     // 1023

// статусы режимов работы
const byte STATUS_STOP  = 1;     // отображаем текущую и установленую температуру, 
                                 // установленую температуру можно редактировать, 
                                 // нагрузка не включается 
                                 // переход возможен в статусы RUN и SETUP
                             
const byte STATUS_RUN   = 2;     // отображаем текущую и установленую температуру, 
                                 // установленую температуру нельзя редактировать, 
                                 // нагрузка включается для поддержания установленой температуры
                                 // переход возможен только в статус STOP

const byte STATUS_SETUP = 3;     // отображаем линейку настройки и вариант выхода STOP/START 
                                 // линейку и вариант выхода можно редактировать, 
                                 // нагрузка не включается, текущая температура отображается
                                 // переход возможен только статус STOP или SETUP_RUN

const byte STATUS_SETUP_RUN = 4; // отображаем линейку выполнения настройки контроллера, текущий этап
                                 // нагрузка включается для определения параметров калибровки, текущая температура отображается
                                 // переход возможен только в статус SETUP

const byte STATUS_ERROR = 5;     // отображаем описание ошибки, 
                                 // нагрузка не включается, текущая температура отображается
                                 // переход возможен только в статус STOP

// --------------------------------------------------------
// объявления для индикаторов и кнопок управления
//

LiquidCrystal lcd(8, 9, 4, 5, 6, 7 );

// переменные для поддержки циклов анимации
unsigned long time_anime = 0;
unsigned long time_anime_new = 0;
int step_anime = 0;

// переменные для поддержки циклов клавиатуры
unsigned long time_button = 0;
unsigned long time_button_new = 0;

// переменные для поддержки циклов опроса датчиков
unsigned long time_temp = 0;
unsigned long time_temp_new = 0;

// переменные для поддержки циклов включения/выключения нагревателя и расчетов
// обработка проходит в 10 степов, общее длинна всех степов TIME_RUN - милисекунд
unsigned long time_run = 0;
unsigned long time_run_new = 0;

// переменные для контроля, изменения и отображения температур
// конкретные значения могут переустанавливатся (из сохраненых в памяти) при старте системы 
int term_set = 0;             // установленая температура
int term_set_display = 0;     // установленая температура выведеная на дисплей
int term_set_new = 0;         // новая установленая температура
int term_real = 0;            // текущая температура полученая от датчиков
int term_real_display = 0;    // текущая температура выведеная на дисплей
int term_real_new = 0;        // новая температура полученая от датчиков

// переменные для поддержки клавиатуры и экрана
int button = BUTTON_NONE;     // текущаяя нажатая клавиша
int button_new = BUTTON_NONE; // новое значение нажатой клавиши
boolean FlagCursor = false;   // кеширующий флаг обозначающий, что включен режим курсора "Blink"

// переменные для поддержки статусов контроллера
byte mode = STATUS_STOP;      // текущий статус работы контролера
int edit_term = 0;            // номер знака редактирования у установленой температуры, 1...4-знаки, 0-не редактируется

// переменные для общения с термопарой 
int thermoDO  = 17; // А3 он же SO
int thermoCS  = 16; // A2
int thermoCLK = 15; // A1 он же SCK

// переменные для реле
int heatCTRL = 18;  // A4

// переменные для динамика
int beepCTRL = 19;  // A5

// переменные для расчетов
int r_pow;                    // текущий коэффициэнт (сотая доля процента, 10000 = 100%) относительной мощность для поддержания планируемой температуры
int r_term;                   // текущий перебег (градусы), время перебега при нагреве до планируемой температуры со 100% мощностью
int r_dt;                     // время цикла on/off сек
int r_step;                   // время шага хранения истории сек (для апроксимации поддержания температуры)

// дополнительные коэффициэнты (сотая доля процента, 10000 = 100%) 
int rk_pow;                     
int rk_term;   

boolean mode_heat = false;          // флаг показывающий включена или нет нагрузка
unsigned long time_heat_start = 0;  // время последнего включения нагрузки
unsigned long time_heat_stop = 0;   // время последнего отключения нагрузки

// структуры которые хранят примерные таблицы тепловых характеристик
int ar_temp[10]       = {100,  200,  300,  400,  500,  600,  700,  800,  900,  1000};    // температуры градусы
int ar_pow[10]        = { 3,    6,   12,   25,   40,   50,   55,   60,   65,   75};      // мощность процент
int ar_tep[10]        = {22,   20,   20,   20,   20,   20,   20,   20,   20,   20};      // температура перебега
int ar_dt[10]         = {20,   20,   20,   20,   20,   20,   20,   20,   20,   20};      // время цикла on/off нагрузки сек
int ar_step[10]       = {130,  25,   25,   25,   25,   25,   25,   25,   25,   25};      // время перебега температуры (инерционность) сек
int ar_setup[10]      = { 2,    2,    2,    2,    2,    2,    2,    2,    2,    2};      // резерв для вычислений при выполнения SETUP 
byte ar_setup_scr[10] = { 0,    0,    0,    0,    0,    0,    0,    0,    0,    0};      // признаки для обновления на экране элементов массива ar_setup

byte setup_step;

// переменные для расчетов

// переменные используемые только при калибровке, пишу сюда, что-бы были доступны для логов
unsigned long time_setup_t1; // время достижения калибровочной температуры, или время запуска нагрева на втором этапе калибровки 
unsigned long time_setup_t2; // время достижения калибровочной температуры, или время запуска нагрева на втором этапе калибровки 
int term_setup_max;          // максимальная температура (поиск перебега)
int pow_setup_max;           // минимальная мощность на которой проявился перегрев
int pow_setup_min;           // максимальная мощность на которой проявился недогрев
int pow_setup;               // текущая мощность
byte step_run;               // текущий режим калибровки
                             //   0 - нет
                             //   1 - первичный разогрев 
                             //   2 - поиск перебега
                             //   3 - остываение ниже градиента
                             //   4 - вторичный разогрев для поиска оптимальной мощности поддержания температуры
                             // текущий режим работы
                             //   0 - ожидание стабилизации
                             //   1 - первичный разогрев 
                             //   2 - ожидание остывания до текущей температуры
                             //   3 - поддержание температуры

// переменные для ошибок
int Error_Term;              // температура на которой зафиксирована ошибка
int Error_Number;            // номер ошибки
unsigned long time_error;    //время последнего опроса ошибок


//*************************************************************************************************
// процедура инициализации контролера
//*************************************************************************************************
void setup()
{ 
  int i;

  Serial.begin(9600);  

  LogSerial(0);  
  
  // читаем сохраненные значения в энергонезависимой памяти
  // первые 2 байта - сигнатура формата, для нашего проекта возьмем значение "T1", что равнозначно числу 21469
  // при изменении физического местоположения сохраняемых значений идентификатор следует изменить
  // при изменении идентификатора (и физического места данных), чтение производится не будет
  // что будет равносильно полному заливки скетча в новый контроллер

  i = Get_signature();
  if (i != 21469) {
    // перезапишем все сохраняемые параметры
    LogSerial(1); 
    i = 21469;
    Set_signature(i);
    Set_term_set(term_set);
    for (byte i1=0; i1 <= 9; i1++) {
      Set_temp(i1,  ar_temp[i1]);
      Set_pow(i1,   ar_pow[i1]);
      Set_tep(i1,   ar_tep[i1]);
      Set_dt(i1,    ar_dt[i1]);
      Set_step(i1,  ar_step[i1]);
      Set_setup(i1, ar_setup[i1]);
    }  
  }
  // теперь читаем все параметры из энергонезависимой памяти
  // читаем установленую температуру
  i = Get_term_set(); term_set = i; term_set_display = i; term_set_new = i;

  // читаем структуры
  for (byte i1=0; i1 <= 9; i1++) {
    ar_temp[i1]  = Get_temp (i1);
    ar_pow[i1]   = Get_pow  (i1);
    ar_tep[i1]   = Get_tep  (i1);
    ar_dt[i1]    = Get_dt   (i1);
    ar_step[i1]  = Get_step (i1);
    ar_setup[i1] = Get_setup(i1);
  }  
  LogSerial(2); 
 
 // инициализируем модуль контролера термопары
 
  pinMode(thermoCS, OUTPUT);
  pinMode(thermoCLK, OUTPUT); 
  pinMode(thermoDO, INPUT);
  
  digitalWrite(thermoCS, HIGH);
  delay(500);

  // инициализируем порт реле
  pinMode(heatCTRL, OUTPUT); 
  off_Relay();
 
  // инициализируем экран, у нас 16 символов и 2 строки            
  lcd.begin(16, 2); 
  lcd.noCursor();

  screen_out(true, true, true); 
  Beep(1);
  
  LogSerial(3);
}

//*************************************************************************************************
// главный цикл
//*************************************************************************************************
void loop() {
  unsigned long time_loop_new;  
  unsigned long time_pause;     
  int button_temp;              
  
  time_loop_new = millis();     // получим время начала цикла
 
  // --------------------------------------------------------------------------------------------
  // обработка управления кнопками, должена идти как можно ближе к началу цикла
  button_temp = getPressedButton();
  if (button_new != button_temp) {
    // изменилось состояние клавиатуры, запомним время и новое состояние
    button_new = button_temp;
    time_button_new = time_loop_new;
  }

  time_pause = getDelayTime(time_button_new, time_loop_new);
  if (time_pause <= BUTTON_TIME) { 
    // ожидание минимальной паузы
  }
  else {
    if (button_new != button) {
      // сотояния клавиатуры изменилось, минимальная пауза выдержана
      if (button_new == BUTTON_NONE) { 
        // кнопка отпущена
        // вызовем обработчик, при этом расчитаем время нажатие от события нажатия а не от нового события отпускания  
        OnKeyUp (button, getDelayTime(time_button, time_button_new));  
      }
      else if (button != BUTTON_NONE) { 
        // кнопка нажата, пока обработчик этого события мне не нужен, 
        // по тому, что кнопка SELECT обрабатывается по таймеру двумя разными способами        
        // здесь ничего не делаем, код оставляю для расширения в других проектах
      }
      else { 
        // смена нажатой кнопки на другую, пока обработчик этого события мне не нужен      
        // по тому, что мы работаем не по событию нажатия, а по событию отжатия
        // здесь ничего не делаем, код оставляю для расширения в других проектах
      }      
      // изменения клавиатуры отработаны, теперь запомним новое состояние
      time_button = time_loop_new; 
      button = button_new;
    }  
    else if ((button_new == button) && (button != BUTTON_NONE)) {
      // есть какая-то зажатая кнопка
      if ((button == BUTTON_SELECT) && (time_pause >= BUTTON_TIME_LONG)) { 
        // кнопка SELECT нажата достаточно долго для перехода в режим SETUP  
        // в текущем проекте это пока не нужно, мы пойдем другим путем и будем передовать время удержания в событие отжатия кнопки
        // здесь ничего не делаем, код оставляю для расширения в других проектах, 
        // но, все-же,  напомним звуком, что кнопка зажата или это ошибка...
        Beep(2);
      }
    }   
  }
  

  // --------------------------------------------------------------------------------------------
  // получение актуальной температуры
  time_pause = getDelayTime(time_temp, time_loop_new);
  if (time_pause > TIME_GET_THERMOMETR) { 
    time_temp = time_loop_new;
    term_real_new = readCelsius(); 
  }

  // --------------------------------------------------------------------------------------------
  // поиск и обработка ошибок
  time_pause = getDelayTime(    time_error, time_loop_new);
  if (time_pause > TIME_GET_ERROR) { 
    time_error = time_loop_new;

    // включение пищалки динамика
    if (   term_real_new > TERM_LIMIT
        || mode == STATUS_ERROR) { 
      Beep(2); 
    }
    
    if (mode == STATUS_RUN) {
      // ошибки при работе
      if (  term_real_new < -100            // ошибка термопары
         || term_real_new > (term_set + 50) // перегрев на 50 градусов
         || term_real_new > TERM_LIMIT) {   // общий перегрев 
        mode = STATUS_ERROR;
        Error_Term = term_real_new;
        Error_Number = 1;      
        off_Relay();
        screen_out(true, true, true);
      }
    }
    else if (mode == STATUS_SETUP_RUN) {
      // ошибки при калибровке
      if (  term_real_new < -100            // ошибка термопары
         || term_real_new > TERM_LIMIT) {   // общий перегрев 
        mode = STATUS_ERROR;
        Error_Term = term_real_new;
        Error_Number = 1;      
        off_Relay();
        screen_out(true, true, true);
      }
    }
    
  }

  // --------------------------------------------------------------------------------------------
  // расчет параметров для включения и выключения разогрева
  time_pause = getDelayTime(time_run, time_loop_new);
  if (time_pause > TIME_RUN) {
    time_run = time_loop_new;
    Run(time_loop_new);
  }
  
  // --------------------------------------------------------------------------------------------
  // обновление экрана, это последнее...
  time_pause = getDelayTime(time_anime, time_loop_new);
  if (time_pause > TIME_ANIME) {
    time_anime = time_loop_new;
    screen_out(true, false, false);
  }
  else {
    screen_out(false, false, false);
  }
}

 

файл Screen_out.ino :

//*************************************************************************************************
// процедура выводит все параметры и оформление на экран
//   anime - вызывает перерисовку анимации в зависимости он значения переменных time_anime, time_anime_new, step_anime
//   face  - вызывает перерисовку надписей и прочих статических значений в зависимости от текущего режима контролера
//   force - параметр для явного обновления всего экрана вне зависимости от остальных параметров
//           true - полностью обновляет все параметры
//           false - обновляет только измененые параметры
//*************************************************************************************************
void screen_out(boolean anime, boolean face, boolean force)
{
  byte ii;
  
  // строка 1: 
  // текущая температура выводится всегда в колонках 12,13,14,15
  // оформление текущей температувы выводится всегда в колонках 10,11,16
  term_real_display = OutNumber(term_real_display, term_real_new, 11, 0, 4, force);
  if (force || face) {
    PrintLcd("t:", 9, 0);
    PrintLcd("c", 15, 0);
  }
 
  //------------------------------------------------------- 
  if (mode == STATUS_STOP) {
    // строка 1:
    // анимацию не выводим, вместо анимации выводим оформление в колонках 1,2,3,4,5,6,7,8,9
    if (force || face) {
      PrintLcd("=STOP=   ", 0, 0);
    }
    
    // строка 2:
    // установленая температура выводится в колонках 12,13,14,15
    // оформление выводим в колонки 1,2,3,4,5
    // оформление установленой температувы выводится в колонки 6,7,8,9,10,11,16
    term_set_display = OutNumber(term_set_display, term_set_new, 11, 1, 4, force);
    if (force || face) {
      PrintLcd("     ", 0, 1);
      PrintLcd("SET T:", 5, 1);
      PrintLcd("c", 15, 1);
    }

    // установка курсора во вторую строку редактируемого поля
    if (edit_term == 0) {
      if (FlagCursor == true) {
        lcd.noBlink();
        FlagCursor = false;
      }
    }
    else { 
      lcd.setCursor(10 + edit_term, 1);
      if (FlagCursor != true) { 
        lcd.blink();
        FlagCursor = true;
      }
    }
  }
  //------------------------------------------------------- 
  else if (mode == STATUS_RUN) {
    
    // строка 1:
    // очистим поле для анимации в колонках 1,2,3,4,5,6,7,8,9
    if (force || face) {
      PrintLcd("         ", 0, 0);
    }

    // анимацию выводим в первую строку
    if (anime == true) {
      // делаем шаг анимации
      if (step_anime < 3) { step_anime = step_anime + 1; }
      else { step_anime = 0; }
      // выводим текущий шак на экран
      if (step_anime == 0)      { PrintLcd("|", 0, 0); }
      else if (step_anime == 1) { PrintLcd("/", 0, 0); }
      else if (step_anime == 2) { PrintLcd("-", 0, 0); }
      else                      { PrintLcd("-", 0, 0); }
    }

    // строка 2:
    // установленая температура выводится в колонках 12,13,14,15
    // оформление выводим в колонки 1,2,3,4,5
    // оформление установленой температувы выводится в колонки 6,7,8,9,10,11,16
    term_set_display = OutNumber(term_set_display, term_set_new, 11, 1, 4, force);
    if (force || face) {
      PrintLcd("     ", 0, 1);
      PrintLcd("    T:", 5, 1);
      PrintLcd("c", 15, 1);
    }
  }

  //------------------------------------------------------- 
  else if (mode == STATUS_SETUP) {
    // строка 1:
    // анимацию не выводим, вместо анимации выводим оформление в колонках 1,2,3,4,5,6,7,8,9
    if (force || face) {
      PrintLcd(" =SETUP= ", 0, 0);
    }

    // строка 2:
    if (force || face) {
      PrintLcd("                ", 0, 1);
      for (byte ii=0; ii <= 9; ii++) {
        if      (ar_setup[ii] == 0)  { PrintLcd("_", ii + 3, 1); }
        else if (ar_setup[ii] == 1)  { PrintLcd("o", ii + 3, 1); }
        else if (ar_setup[ii] == 2)  { PrintLcd("O", ii + 3, 1); }
        ar_setup_scr[ii] = 0;
      }  
    }
    else {
      for (byte ii=0; ii <= 9; ii++) {
        if (ar_setup_scr[ii] == 1) {
          if      (ar_setup[ii] == 0) { PrintLcd("_", ii + 3, 1); }
          else if (ar_setup[ii] == 1) { PrintLcd("o", ii + 3, 1); }
          else if (ar_setup[ii] == 2) { PrintLcd("O", ii + 3, 1); }
        }
        ar_setup_scr[ii] = 0;
      }  
    }  
    
    // установка курсора во вторую строку редактируемого поля
    if (edit_term == 0) {
      if (FlagCursor == true) {
        lcd.noBlink();
        FlagCursor = false;
      }
    }
    else { 
      lcd.setCursor(2 + edit_term, 1);
      if (FlagCursor != true) { 
        lcd.blink();
        FlagCursor = true;
      }
    }
  }
  
  //------------------------------------------------------- 
  else if (mode == STATUS_SETUP_RUN) {
    // строка 1:
    // очистим поле для анимации в колонках 1,2,3,4,5,6,7,8,9
    if (force || face) {
      PrintLcd("   SETUP ", 0, 0);
    }

    // анимацию выводим в первую строку
    if (anime == true) {
      // делаем шаг анимации
      if (step_anime < 3) { step_anime = step_anime + 1; }
      else { step_anime = 0; }
      // выводим текущий шак на экран
      if (step_anime == 0)      { PrintLcd("|", 0, 0); }
      else if (step_anime == 1) { PrintLcd("/", 0, 0); }
      else if (step_anime == 2) { PrintLcd("-", 0, 0); }
      else                      { PrintLcd("-", 0, 0); }
    }

    // строка 2:
    if (force || face) {
      PrintLcd("                ", 0, 1);
      for (byte ii=0; ii <= 9; ii++) {
        if      (ar_setup[ii] == 0)  { PrintLcd("_", ii + 3, 1); }
        else if (ar_setup[ii] == 1)  { PrintLcd("o", ii + 3, 1); }
        else if (ar_setup[ii] == 2)  { PrintLcd("O", ii + 3, 1); }
        ar_setup_scr[ii] = 0;
      }  
    }
    else {
      for (byte ii=0; ii <= 9; ii++) {
        if (ar_setup_scr[ii] == 1) {
          if      (ar_setup[ii] == 0) { PrintLcd("_", ii + 3, 1); }
          else if (ar_setup[ii] == 1) { PrintLcd("o", ii + 3, 1); }
          else if (ar_setup[ii] == 2) { PrintLcd("O", ii + 3, 1); }
        }
        ar_setup_scr[ii] = 0;
      }  
    }  
  }
  
  
  //------------------------------------------------------- 
  else if (mode == STATUS_ERROR) {
    // строка 1:
    // анимацию не выводим, вместо анимации выводим оформление в колонках 1,2,3,4,5,6,7,8,9
    if (force || face) {
      PrintLcd("=ERROR= ", 0, 0);
    }

    // строка 2:
    // температура ошибки выводится в колонках 12,13,14,15
    // оформление выводим в колонки 1,2,3,4,5
    // оформление температуры ошибки температувы выводится в колонки 6,7,8,9,10,11,16
    term_set_display = OutNumber(Error_Term, Error_Term, 3, 1, 4, force);
    if (force || face) {
      PrintLcd("         T:", 0, 1);
      PrintLcd("c", 15, 1);
    }
  }
}

 

файл Run.ino :

//*************************************************************************************************
// процедура расчитывает разогрев и включает, отключает нагрузку
//*************************************************************************************************
void Run(unsigned long time_loop_new) {
  int temp_pow;
  int i;   
  int i1;  
  
  //--------------------------------------------------------------------
  if (mode == STATUS_RUN) {
    
    if (step_run == 0) {
      // ожидание стабилизации температуры, предотвращает перегрев нагревателей при открытом муфеле
      off_Relay();
      if (getDelayTime(time_heat_start, time_loop_new) < TIME_STAB) {
        if (   (term_real_new > (term_setup_max + TERM_GRADIENT * 2)) 
            || (term_real_new < (term_setup_max - TERM_GRADIENT * 2))) { 
              
          // температура скачет
          time_heat_start = time_loop_new;
        }
      }
      else {
        step_run = 1;
      }
    }
    else if (step_run == 1) {
      // разогрев с мощностью 100%
      if (term_real_new < (term_set - r_term)) {
        on_off_heat(10000, r_dt * 1000, time_loop_new);
      }
      else {
        time_heat_start = time_loop_new;
        time_setup_t1 = time_loop_new;
        step_run = 2;
      }
    }
    else if (step_run == 2) {
      // ожидание остывания до текущей температуры
      if (term_real_new >= term_set) { 
        off_Relay(); 
      }
      else { 
        time_heat_start = time_loop_new;
        time_setup_t1 = time_loop_new;
        step_run = 3;
      }
    }
    else if (step_run == 3) {
      // поддержание температуры 
      if (term_real_new > (term_set + TERM_GRADIENT)) {
        // явный перегрев, идем к предыдущему шагу
        step_run = 2;
      }
      else if (  (getDelayTime(time_heat_start, time_loop_new) < (1000.0 * r_dt))     // не закончен малый цикл on-off отсчитаного от времени включения реле
              || (getDelayTime(time_setup_t1, time_loop_new) < (1000.0 * r_step)))  { // или не прошло время перебега
              
        on_off_heat(100 * r_pow + rk_pow, r_dt * 1000, time_loop_new);
      }
      else {
        // тут все равно попали мы в диапазон или нет, все равно вносим корректор...
        
        temp_pow = 1.0 * (term_set / term_real_new) * (100 * r_pow + rk_pow);
        rk_pow = (100 * r_pow) - temp_pow;
        time_setup_t1 = time_loop_new;
        on_off_heat(100 * r_pow + rk_pow, r_dt * 1000, time_loop_new);
        LogSerial(5);
      }
    }
    else { off_Relay(); }
  }
  
  //--------------------------------------------------------------------
  else if (mode == STATUS_SETUP_RUN) {
    // выбор полки калибровки
    // надо проверить может мы отстали... проверяем всегда, без учета степов 
    for (byte i=setup_step; i <= 9; i++) {
      setup_step = i;            
      if (ar_setup[setup_step] != 2) {
        break; // все нормально, можно идти дальше (выходим из цикла)
      }
    } 
    
    if (setup_step == 9) {
      if (ar_setup[setup_step] == 2) {
        // это конец калибровки, переходим в режим SETUP 
        mode = STATUS_SETUP; 
        edit_term = 0;
        off_Relay();
        Beep(1);             
        // после изменения режима нужно полностью обновить экран
        screen_out(true, true, true);
        LogSerial(2);
        return;
      }
    }

    // полка выбрана, идем дальше теперь собственно этапы калибровки
    
    if (step_run == 1) {
      // этап 1. - разогрев до температуры полки 
      if (term_real_new < ar_temp[setup_step]) {
        // до температуры калибровки еще не дошли, греем дальше и запоминаем время
        on_off_heat(10000, ar_dt[setup_step] * 1000, time_loop_new);
        time_setup_t1 = time_loop_new;
      }
      else { 
        off_Relay();
        step_run = 2; 
        LogSerial(7);
      }
    }
    else if (step_run == 2) {
      // этап 2. - ожидание потолка перебега
      off_Relay();
      if (term_real_new >= (term_setup_max-1)) {
        // идет перебег, нагрев нужно выключить, и запомнить температуру (-1 это на дребезг темппературы)
        if (term_real_new > term_setup_max) { 
          term_setup_max = term_real_new; 
          time_setup_t2 = time_setup_t1;
        }
      }
      else {
        // начали остывать, температура опустилась ниже максимума на 2 градуса, реальное время - середина между time_setup_t2 и time_setup_t1
        // пишем результаты
        if (ar_tep[setup_step] != (term_setup_max - ar_temp[setup_step])) {
          ar_tep[setup_step] = term_setup_max - ar_temp[setup_step];
          Set_tep(setup_step,  ar_tep[setup_step]);     // пишем температуру перебега
        }
        
        i = getDelayTime(time_setup_t1, time_loop_new) / 1000;
        i1 = getDelayTime(time_setup_t2, time_loop_new) / 1000;
        i = (i + i1) / 2;
        if (ar_step[setup_step] != i) {
          ar_step[setup_step] = i;
          Set_step(setup_step,  ar_step[setup_step]);
        }

        ar_setup[setup_step] = 1;
        ar_setup_scr[setup_step] = 1;
        Set_setup(setup_step, ar_setup[setup_step]);
        pow_setup_max = 100; 
        pow_setup_min = 0;
        pow_setup = 0;
        
        step_run = 3;
        LogSerial(8); 
      }    
    }
    else if (step_run == 3) {
      // этап 3. - остывание ниже градиента
      off_Relay();
              
      if (term_real_new <= (ar_temp[setup_step] - TERM_GRADIENT)) {
        // остыли, будущую мощность выберем как среднюю между pow_setup_max и pow_setup_min 
        pow_setup = (pow_setup_min + pow_setup_max) / 2;
        
        // запомним время перехода в 4 режим
        time_setup_t1 = time_loop_new;
        
        // нагрев был выключен, значит запуск этапа 4 нужно начинать со старта
        mode_heat = true;
        time_heat_start = time_loop_new;
        on_Relay();
        
        step_run = 4;
        LogSerial(9); 
      }
    } 
    else if (step_run == 4) {
      // этап 4. - нагреваем с выбраной ранее мощностью
      
      if (term_real_new > (ar_temp[setup_step] + TERM_GRADIENT)) {
        // явный перегрев, идем к предыдущему шагу
        off_Relay();
        pow_setup_max = pow_setup;
        step_run = 3;
      }
      else if (  (getDelayTime(time_heat_start, time_loop_new) < (1000.0 * ar_dt[setup_step]))     // не закончен малый цикл on-off отсчитаного от времени включения реле
              || (getDelayTime(time_setup_t1, time_loop_new) < (2000.0 * ar_step[setup_step])))  { // или не прошло двойное время перебега
              
        on_off_heat(pow_setup * 100, ar_dt[setup_step] * 1000, time_loop_new);
      }
      else if (   ((pow_setup_max - pow_setup_min) == 1)                        // разница между режимами перегрева и негорева 1%, дальше оптимизировать нечего
              ||  (term_real_new >= (ar_temp[setup_step] - TERM_GRADIENT))) {   // или мы попали в диапазон градиента 
        // мощность подобрана правильно
        // этап 2 завершен, пишем результаты
        if (ar_pow[setup_step] != (pow_setup)) {
          ar_pow[setup_step] = pow_setup;
          if (ar_pow[setup_step] > 100) {ar_pow[setup_step] = 100;}
          
          Set_pow(setup_step,  ar_pow[setup_step]);
        }
        
        ar_setup[setup_step] = 2;
        ar_setup_scr[setup_step] = 1;
        Set_setup(setup_step, ar_setup[setup_step]);
        step_run = 1; // по сколько этот этап мы прошли, следующий идем с первого шага
        
        LogSerial(10); 
      }
      else {
        // это недогрев,  меняем параметры и продолжаем
        pow_setup_min = pow_setup;
        pow_setup = (pow_setup_min + pow_setup_max) / 2;
        time_setup_t1 = time_loop_new;
        step_run = 3;
      }
    }
    else { off_Relay(); }
  }  
  //--------------------------------------------------------------------
  else { off_Relay(); }
}

 

файл other.ino :

// ---------------------------------------------------------
// вспомогательные процедуры
// ---------------------------------------------------------

//*************************************************************************************************
// процедура включает и выключает нагрев в зависимости от необходимой мощности
//   p       - относительной мощность сотые доли % (допустимые значения от 0 до 10 000)
//   dt      - общее время одного цикла вкл/выкл (в мсек, допустимые значения от 0 до 32 767), это время делется пропорционально параметра "p" 
//             100% мощность этого времени не должно приводить к перебегу температуры выше разумной погрешности, 
//             по этому общее время одного цикла должно расчитыватся заранее.
//   t       - текущее время
//*************************************************************************************************

void on_off_heat(int p, int dt, unsigned long t) 
{
  unsigned long t1 = 1;
  
  if (p >= 9900) {
    // 99% мощности считаем как 100% в целях сохранения ресурса реле
    mode_heat = true;
    time_heat_start = t;    
    on_Relay();
  }
  else if (p <= 100) {
    // 1% мощности считаем 0% в целях сохранения ресурса реле
    mode_heat = false;
    time_heat_stop = t;    
    off_Relay();
  }
  else if (mode_heat == true) {
    // идет нагрев, нужно проверить может стоит остановится
    t1 = t1*dt/100*p/100;
    if (getDelayTime(time_heat_start, t) >= t1) {
      mode_heat = false;
      time_heat_stop = t;    
      off_Relay();
    }
  }
  else if (mode_heat == false) {
    // идет охлаждение, нужно проверить может стоит запустится
    t1 = t1*dt/100*(100-p/100);
    if (getDelayTime(time_heat_stop, t) >= t1) {
      mode_heat = true;
      time_heat_start = t;    
      on_Relay();
    }
  }
}


void on_Relay() 
{
    //Serial.println("on reley"); 
    digitalWrite(heatCTRL, HIGH);
}

void off_Relay() 
{
    //Serial.println("off reley"); 
    digitalWrite(heatCTRL, LOW);
}


//*************************************************************************************************
// процедура выводит на экран число и возвращает новое значение
//   num     - текущее значение числа
//   new_num - новое значение числа
//   col     - номер позиции в строке экрана для вывода
//   line    - номер строки экрана для вывода
//   count   - количество символов на экране для вывода
//   force   - параметр для явного обновления
//*************************************************************************************************
int OutNumber(int num, int new_num, byte col, byte line, byte count, boolean force)
{
  String stringOne;
  int str_l;

  if (force || (new_num != num)) {
    num = new_num;
    stringOne = String(num);
    str_l = count - stringOne.length();
    for (int i=1; i <= str_l; i++){
      stringOne = String(" ") + stringOne;
    }
    PrintLcd(stringOne, col, line);
  }
  return num;
}

//*************************************************************************************************
// процедура возвращает значение нажатой клавиши на клавиатуре
//*************************************************************************************************
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;
  }
  else if (buttonValue >= 800){
    return BUTTON_NONE;
  }
   
  return BUTTON_NONE;
}

//*************************************************************************************************
// процедура сравнивает два времени и возвращает разницу в виде числа, учитывает переход времени через 0
//   start_time - начальное время
//   end_time - конечное время
//
// !!!! процедура чуствительна к разрядности исполняемого кода !!!!
// !!!! процедура может работать неправильно при двойном переходе времени через 0 !!!!
//*************************************************************************************************
unsigned long getDelayTime(unsigned long start_time, unsigned long end_time)
{
  unsigned long result;
  if (start_time <= end_time) {
    result = end_time - start_time;
  }
  else {
    result = 4294967295 - end_time + start_time;
  }
  return result;
}

//*************************************************************************************************
// процедура увеличивает или умеьшает значение разряда числа 
//   num - начальное число
//   count - максимальная разрядность числа
//   nb - номер разряда, считам с лево на право, например: num=2, count=4, nb=2 считаем разряд указаный "X" 0X02. Результат увеличения будет число 102. 
//   inc - флаг увеличение/уменьшения, если true - то увеличиваем
//*************************************************************************************************
int ChangeValue(int num, int count, int nb, boolean inc) {
  int result;
  String stringOne; 
  int str_l;
  int sim;  

  // сначала добьем нулями разрядность  
  stringOne = String(num);
  str_l = count - stringOne.length();
  for (int i=1; i <= str_l; i++){
    stringOne = String("0") + stringOne;
  }

  // теперь изменяем нужный разряд
  sim = int(stringOne.charAt(nb-1));
  if ((inc == true) && (sim < 57)) { sim = sim + 1; }
  else if ((inc == false) && (sim > 48)) { sim = sim - 1; }

  // запаковываем обратно в число
  stringOne.setCharAt(nb-1, char(sim));
  result = stringOne.toInt();
  return result;
}

//*************************************************************************************************
// процедура выводит на экран заранее подготовленую строку, при этом выключает режим "Blink"
//   str     - строка или String для вывода
//   col     - номер позиции в строке экрана для вывода
//   line    - номер строки экрана для вывода
//*************************************************************************************************
void PrintLcd(String str, int col, int line)
{
 if (FlagCursor == true) { 
    lcd.noBlink();
    FlagCursor = false;
  }
  lcd.setCursor(col, line);
  lcd.print(str);
}

//*************************************************************************************************
// процедура читает из энерго независимой памяти двухбйтовое число
//   num - идентификатор памяти (номер двухбайтного слова)
//*************************************************************************************************
int ReadInt(int num)
{
  byte a;
  byte b;
  int result;
  
  a = int(EEPROM.read(num * 2));
  b = int(EEPROM.read(num * 2 + 1));   
  result = a * 255 + b;

  return result;
}

//*************************************************************************************************
// процедура записывает в энерго независимую память двухбйтовое число
//   num - идентификатор памяти (номер двухбайтного слова)
//   value - записываемое значение
//*************************************************************************************************
void WriteInt(int num, int value)
{
  byte a;
  byte b;
  
  b = value % 255;   
  a = (value - b) / 255;
  EEPROM.write(num * 2, a);
  EEPROM.write(num * 2 + 1, b);
  Beep(4); // сделано для выявления безконтрольной записи и снижения ресурса EEPROM
}

//*************************************************************************************************
// процедура проверяет новую установленую температуру и сохраняет ее
//*************************************************************************************************
void set_term_set()
{
  if (term_set_new > TERM_LIMIT) { term_set_new = TERM_LIMIT; }

  if (term_set_new != term_set) {
    // применяем новую температуру и запоминаем ее
    term_set = term_set_new;
    Set_term_set(term_set);
  }
}

//*************************************************************************************************
// две процедуры, для получения данных с термопары
//*************************************************************************************************
double readCelsius() {

  uint16_t v;

  digitalWrite(thermoCS, LOW);
  _delay_ms(1);

  v = spiread();
  v <<= 8;
  v |= spiread();

  digitalWrite(thermoCS, HIGH);

  if (v & 0x4) {
    // uh oh, no thermocouple attached!
    //return NAN; 
    return -101;
  }
  v >>= 3;

  return v*0.25;
}

byte spiread() { 
  int i;
  byte d = 0;

  for (i=7; i>=0; i--)
  {
    digitalWrite(thermoCLK, LOW);
    _delay_ms(1);
    if (digitalRead(thermoDO)) {
      //set the bit to 0 no matter what
      d |= (1 << i);
    }

    digitalWrite(thermoCLK, HIGH);
    _delay_ms(1);
  }

  return d;
}

//*************************************************************************************************
// процедура получает апромиксированое значение по температуре из эталонных массивов
//   NumParam - номер массива, 1 - ar_pow, 2 - ar_tep, 3 - ar_dt, 4 - ar_step
//   Term - температура к которой нужно получить значение
//*************************************************************************************************
int GetParamProc(byte NumParam, int Term){
  int ir = 0;
  byte ii;
  byte i1;
  byte i2;

  // найдем индексы
  i1 = 0;
  for (byte ii=0; ii <= 9; ii++) {
    if (ar_temp[ii] > Term) {
      ii = ii - 1;
      break;
    }
  }  
  
  if (ii <= 0) {
    i1 = 0;
    i2 = 1;
  }
  else if (ii >=9) {
    i1 = 8;
    i2 = 9;
  }
  else {
    i1 = ii;
    i2 = ii + 1;
  }

  // в i1 и i2 лежат индексы для массивов, начинаем апромиксацию 
  if (NumParam == 1) { ir = ar_pow[i1] + 1.0 * (Term - ar_temp[i1]) * (ar_pow[i2] - ar_pow[i1]) / (ar_temp[i2] - ar_temp[i1]); }
  if (NumParam == 2) { ir = ar_tep[i1] + 1.0 * (Term - ar_temp[i1]) * (ar_tep[i2] - ar_tep[i1]) / (ar_temp[i2] - ar_temp[i1]); }
  if (NumParam == 3) { ir = ar_dt[i1]  + 1.0 * (Term - ar_temp[i1]) * (ar_dt[i2]  - ar_dt[i1])  / (ar_temp[i2] - ar_temp[i1]); }
  if (NumParam == 4) { ir = ar_step[i1]+ 1.0 * (Term - ar_temp[i1]) * (ar_step[i2]- ar_dt[i1])  / (ar_temp[i2] - ar_temp[i1]); }
  
  return ir;
}

//*************************************************************************************************
// процедуры, для записи и получении всех данных EEPROM 
// собраны здесь для единообразного адресного хранения и визуализации карты использования EEPROM, 
// адреса в двух байтовом виде (1 - это два байта с физическим адресом 2 и 3)
//*************************************************************************************************

// ------------------- чтение -------------------
int Get_signature()    { return ReadInt(0); }                    // 0 - сигнатура
int Get_term_set()     { return ReadInt(1); }                    // 1 - установленая температура
                                                                 // 2...9 - резерв
int Get_temp(int Num) { return ReadInt(Num+10); }                // 10..19 - массив калибровочных температур
int Get_pow(int Num)  { return ReadInt(Num+20); }                // 20..29 - массив мощности поддержания температуры
int Get_tep(int Num)  { return ReadInt(Num+30); }                // 30..39 - массив температур инерционности
int Get_dt(int Num)   { return ReadInt(Num+40); }                // 40..49 - массив времени цикла on/off 
int Get_step(int Num) { return ReadInt(Num+50); }                // 50..59 - массив времени инерционности 
int Get_setup(int Num){ return ReadInt(Num+60); }                // 60..69 - массив флагов калибровки
                                                                 // 70..99 - резерв
                                                                 // 100..511 - свободно 

// ------------------- запись -------------------
int Set_signature(int value)        { WriteInt(0, value); }      // 0 - сигнатура
int Set_term_set(int value)         { WriteInt(1, value); }      // 1 - установленая температура
                                                                 // 2...9 - резерв
void Set_temp(int Num, int value)  { WriteInt(Num+10, value); }  // 10..19 - массив калибровочных температур
void Set_pow(int Num, int value)   { WriteInt(Num+20, value); }  // 20..29 - массив мощности поддержания температуры
void Set_tep(int Num, int value)   { WriteInt(Num+30, value); }  // 30..39 - массив температур инерционности
void Set_dt(int Num, int value)    { WriteInt(Num+40, value); }  // 40..49 - массив времени цикла on/off 
void Set_step(int Num, int value)  { WriteInt(Num+50, value); }  // 50..59 - массив времени инерционности 
void Set_setup(int Num, int value) { WriteInt(Num+60, value); }  // 60..69 - массив флагов калибровки
                                                                 // 70..99 - резерв
                                                                 // 100..511 - свободно 

 

файл OnKeyUp.ino :

//*************************************************************************************************
// обработчик вызывается при отпускании кнопки клавиатуры
//   key - кнопка которая была отпущена
//   pressing - время которое кнопка была нажата
//*************************************************************************************************
void OnKeyUp (int key, unsigned long pressing)
{
  int i ;
  
  if (key == BUTTON_SELECT) { 
    // реализуем переход режима работы контроллера
    
    // ******************** переход в режим RUN ********************
    if (mode == STATUS_STOP && pressing < BUTTON_TIME_LONG) {
      
      // перед стартом применим (и сохраним) установленую температуру
      set_term_set(); 
      mode = STATUS_RUN; 
      
      // иницилизируем дефолтные параметры расчета
      r_pow  = GetParamProc(1, term_set);   
      r_term = GetParamProc(2, term_set);   
      r_dt   = GetParamProc(3, term_set);   
      r_step = GetParamProc(4, term_set);   
      
       // дополнительные коэффициенты (плюсуются к основным) 
      step_run = 0;
      time_heat_start = millis();
      rk_pow = 0;                     

      LogSerial(6);
      Beep(3);     
    }
    
    // ******************** переход в режим SETUP ********************
    else if (  (mode == STATUS_STOP && pressing >= BUTTON_TIME_LONG) 
            || (mode == STATUS_SETUP_RUN)) {
      mode = STATUS_SETUP; 
      off_Relay(); 
      edit_term = 0;
    }
    
    // ******************** переход в режим STOP ********************
    else if (  (mode == STATUS_ERROR) 
            || (mode == STATUS_RUN)  
            || (mode == STATUS_SETUP && pressing < BUTTON_TIME_LONG)) { 
      mode = STATUS_STOP; 
      off_Relay(); 
      edit_term = 0;
      Error_Term = 0;
      Error_Number = 0;      
    }
    
    // ******************** переход в режим SETUP_RUN ********************
    else if ((mode == STATUS_SETUP) && (pressing >= BUTTON_TIME_LONG)) { 
      // перед калибровкой применим (и сохраним) установленую линейку порогов
      for (byte i=0; i <= 9; i++) {
        if (Get_setup(i) != ar_setup[i]) { Set_setup(i, ar_setup[i]); } 
      }  
      
      mode = STATUS_SETUP_RUN; 
      step_run = 1;
      term_setup_max = 0;
      pow_setup_max = 100;
      edit_term = 0;
      setup_step = 0;
      Beep(3);     
    }
    
    // после изменения режима нужно полностью обновить экран
    screen_out(true, true, true);
  }
  else if (key == BUTTON_RIGHT) { 
    if (mode == STATUS_STOP) {
      // переключаем редактируемый разряд установленой температуры
      if (edit_term >= 4) { edit_term = 0; }
      else { edit_term = edit_term + 1; }

      if (term_set_new > TERM_LIMIT) { term_set_new = TERM_LIMIT; }
      screen_out(false, false, false);   
    }
    else if (mode == STATUS_SETUP) {
      if (edit_term >= 10) { edit_term = 0; }
      else { edit_term = edit_term + 1; }
      
      screen_out(false, false, false);   
    }
  }
  else if (key == BUTTON_LEFT) { 
    if (mode == STATUS_STOP) {
      // переключаем редактируемый разряд установленой температуры
      if (edit_term == 0) { edit_term = 4; }
      else { edit_term = edit_term - 1; }
      
      if (term_set_new > TERM_LIMIT) { term_set_new = TERM_LIMIT; }
      screen_out(false, false, false);  
    }
    else if (mode == STATUS_SETUP) {
      if (edit_term == 0) { edit_term = 10; }
      else { edit_term = edit_term - 1; }
      
      screen_out(false, false, false);   
    }
  }
  else if (key == BUTTON_UP) { 
    if ((mode == STATUS_STOP) && (edit_term != 0)) {
      // мы редактируем текущий разряд установленой температуры
      term_set_new = ChangeValue(term_set_new, 4, edit_term, true);
      if (term_set_new > TERM_LIMIT) { term_set_new = TERM_LIMIT; }
    }
    else if (mode == STATUS_SETUP) {
      switch (ar_setup[edit_term - 1]) { 
        case 0:  ar_setup[edit_term - 1] = 2; break; 
        case 1:  ar_setup[edit_term - 1] = 2; break; 
        case 2:  ar_setup[edit_term - 1] = 0; break; 
      } 
     ar_setup_scr[edit_term - 1] = 1;
    }
  }
  else if (key == BUTTON_DOWN) { 
    if ((mode == STATUS_STOP) && (edit_term != 0)) {
      // мы редактируем текущий разряд установленой температуры
      term_set_new = ChangeValue(term_set_new, 4, edit_term, false);
      if (term_set_new > TERM_LIMIT) { term_set_new = TERM_LIMIT; }
    }
    else if (mode == STATUS_SETUP) {
      switch (ar_setup[edit_term - 1]) { 
        case 0:  ar_setup[edit_term - 1] = 2; break; 
        case 1:  ar_setup[edit_term - 1] = 0; break; 
        case 2:  ar_setup[edit_term - 1] = 0; break; 
      }  
     ar_setup_scr[edit_term - 1] = 1;
    }
  }
}

 

файл LogSerial.ino :

//*************************************************************************************************
// процедура выводит в порт лог глобальных переменных, собрано здесь для удобства включения/отключения
// и уменьшения текстов основной программы, Num - номер вызова лога
//*************************************************************************************************
void LogSerial(byte Num) {
  int i;  
  
//  if (false) {
  if (true) {
    
    switch (Num) { 
      case 0: 
        Serial.print("=debug (setup.Start)="); 
        Serial.println(); 
        
        break; 
        
      case 1: 
        Serial.print("=debug (setup.FORMAT)="); 
        Serial.println(); 
        
        break; 
        
      case 2: 
        Serial.print("=debug (setup.ActualTable)="); 
        Serial.println(); 
        for (byte i=0; i <= 9; i++) {
          Serial.print("i: ");    Serial.print(i); 
          Serial.print(", ar_temp: ");  Serial.print(ar_temp[i]); 
          Serial.print(", ar_pow: ");   Serial.print(ar_pow[i]); 
          Serial.print(", ar_tep: ");   Serial.print(ar_tep[i]); 
          Serial.print(", ar_dt: ");    Serial.print(ar_dt[i]); 
          Serial.print(", ar_step: ");  Serial.print(ar_step[i]); 
          Serial.print(", ar_setup: "); Serial.print(ar_setup[i]); 
          Serial.println(); 
       }  
       
       break; 
        
      case 3: 
        Serial.print("=debug (setup.setup)= Complete."); 
        Serial.println(); 
        
        break; 
        
      case 4: 
        Serial.print("=debug (Run.RunStep_1)="); 
        Serial.print(" term_set: ");       Serial.print(term_set); 
        Serial.print(", term_real_new: "); Serial.print(term_real_new); 
        Serial.println(); 
  
        break; 
        
      case 5: 
        Serial.print("=debug (Run.RunStep_2)="); 
        Serial.print(", rk_pow: ");     Serial.print(rk_pow); 
        Serial.println(); 
 
        break; 
        
      case 6: 
        Serial.print("=debug (OnKeyUp.Start)="); 
        Serial.print(" term_set: "); Serial.print(term_set); 
        Serial.print(", r_pow: ");   Serial.print(r_pow); 
        Serial.print(", r_term: ");  Serial.print(r_term); 
        Serial.print(", r_dt: ");    Serial.print(r_dt); 
        Serial.print(", r_step: ");  Serial.print(r_step); 
        Serial.println(); 
    
        break; 
        
      case 7: 
        Serial.print("=debug (Run.Setup.1)="); 
        Serial.print(" setup_step: ");            Serial.print(setup_step); 
        Serial.print(", term_real_new: ");        Serial.print(term_real_new); 
        Serial.println(); 
        
        break; 

      case 8: 
        Serial.print("=debug (Run.Setup.2)="); 
        Serial.print(" setup_step: ");            Serial.print(setup_step); 
        Serial.print(", ar_tep[setup_step]: ");   Serial.print(ar_tep[setup_step]); 
        Serial.print(", ar_step[setup_step]: ");  Serial.print(ar_step[setup_step]); 
        Serial.println(); 

        break; 
        
      case 9: 
        Serial.print("=debug (Run.Setup.3)="); 
        Serial.print(" setup_step: ");            Serial.print(setup_step); 
        Serial.print(", term_real_new: ");        Serial.print(term_real_new); 
        Serial.println(); 

        break; 
         
      case 10: 
        Serial.print("=debug (Run.Setup.End)="); 
        Serial.print(" setup_step: ");            Serial.print(setup_step); 
        Serial.print(", term_real_new: ");        Serial.print(term_real_new); 
        Serial.print(", ar_pow[setup_step]: ");   Serial.print(ar_pow[setup_step]); 
        Serial.println(); 
    
        break; 
    } 
  }
}

 

файл Beep.ino :

//*************************************************************************************************
// процедура выводит на динамик звуки, сделана здесь, для удобства
//   Num - номер программы
//         0 - нет звуков,
//         1 - включение контроллера, 
//         2 - ошибка, 
//         3 - старт нагрева, 
//         4 - звук записи в EEPROM, 
//*************************************************************************************************
void Beep(byte Num) {

  switch (Num) { 
    case 0: 
      // нет звуков
      noTone(beepCTRL);
      break; 
    case 1: 
      // включение контроллера
      tone(beepCTRL, 1000);
      delay(500);
      tone(beepCTRL, 4000, 500);
      break; 
      
    case 2: 
      // ошибка,
      tone(beepCTRL, 6000, 150);
      break; 
      
    case 3: 
      // старт нагрева,
      tone(beepCTRL, 300, 1000);
      break; 

    case 4: 
      // запись в EEPROM,
      tone(beepCTRL, 300, 100);
      break; 
      
  } 
}

 

vde69
Offline
Зарегистрирован: 10.01.2016

Калибровка моей печи

Схема

nevkon
Offline
Зарегистрирован: 20.01.2015

Подпишусь на тему. Интересно увидеть фотографии печки.

vde69
Offline
Зарегистрирован: 10.01.2016

фото ниже, но пока еще есть ошибки в программе...

 

 

 

 

 

 

 

 

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

А для чего печка?

vde69
Offline
Зарегистрирован: 10.01.2016

Duino A.R. пишет:
А для чего печка?

печь до 1100 с,

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

vde69
Offline
Зарегистрирован: 10.01.2016

рабочий вариант выложил сюда http://arduino.ru/forum/proekty/kontroller-mufelnoi-pechi

сабж можно закрывать :)