ИК паяльная станция на Arduino Mega 2560. Доработка скетча "ARS_v2_Lilium_JSN"

Тема в разделе "Arduino & Shields", создана пользователем Jalnin, 2 ноя 2012.

  1. Jalnin

    Jalnin Нуб

    Важные ссылки темы.

    От @SOLOway :

    В теме такие ветки ведутся: #2454
    для UNO/NANO/ProMini (на 328p) + LCD2004 +2xMAX6675 в постах #1619 и #1917
    для UNO/NANO/ProMini (на 328p) +LCD1602+2xMAX6675+ZCC в посте #1967 и #2194
    очень неплохой ZCC в посте #1587 и #1589
    самодельная резистивная клавиатура в посте #568
    для ProMini AtMega168p / 16MHz / 5v и LCD1602A+ 1xMAX6675 (только канал ВИ! Термостол независимый, какой есть под рукою!) в постах #2184, #2882
    практическая попытка настройки ПИД на станции в посте #2328
    для UNO & TFT SPI 2.4"+2xMAX6675+ZCC в постах #2373, #2374, #2378, #2380
    Простенький термостат для низа от mvm_ksaa: #2509 и #2513
    Как включить режим "только термостол" #1584
    Как проверить ZCC если нет осциллографа: #2592
    Схема простого проверенного многими ZCC: #2595
    Схема подключений для Mega2560+tft3.2" в релизах @Dmitrysh: #2627
    Тем, кто будет платы реле 4х-канальные покупать: #572
    Вместо платы с реле 4х-канальной можно так делать: #2670, #2683
    как бюджетно сделать стойки для установки платы на станцию со стеклокерамикой или алюминиевыми плитами: #2712
    полезный блокнотик ардуинщика закреплен в посте #2959
    Отдельный проект @Leonid0071 здесь: #2980 и плейлист его проекта
    https://www.youtube.com/playlist?list=PLJ1YPXoM_BzWV-Z7Csv4WUm-mzmUgkxxd

    От @Watashi :

    MEGA2560 + TFT 3.5" 480x320 + 2*MAX6675 + PC(опция) + энкодер + сенсор + RTC
    Контроллер паяльной станции собран на базе Arduino MEGA2560 + TFT 3.5" 480x320 с резистивным сенсором и часами RTC на основе модуля DS3231.
    В качестве датчиков температуры используются термопары типа К с микросхемами MAX6675.
    Для управления используется аналоговая клавиатура, сенсор экрана и энкодер. Управлять можно как по отдельности так и в комбинации.
    Можно выводить графики температур на компьютер (PC опция).
     
    Последнее редактирование модератором: 10 окт 2019
    xake и SOLOway нравится это.
  2. vector99

    vector99 Гик

    В просторах интернета нашёл контролёр для управления паяльной станции https://instructables.info/infrakrasnaya-payalnaya-stantsiya-svoimi-rukami/
    Немного почитав информации в интернете, изменил скетч под дисплей с модулем I2C, включил внутренние подтягивающие резисторы, и прошивка загрузилась в ардуинку. Вроди-бы всё заработало, но есть тут такие нестыковки которые могут убить пациента.

    Код (C++):
    [code]
          startTemp = tc1;// нужно как-то привязать к начальной температуре на каждом этапе
             
         
          lcd.setCursor(16, 1);
          lcd.print(currentStep);
          lcd.setCursor(8, 3);
          lcd.print(SP2);
          //ramp rate counter
          if ((currentMillis - previousMillis) > 1000 * rampRateStep[currentStep - 1]) { //seconds counter

            previousMillis = currentMillis;
            counter = counter + 1;
            setpointRamp = counter + startTemp;
            lcd.setCursor(8, 2);
            lcd.print("   ");      
            lcd.setCursor(8, 2);
            lcd.print(setpointRamp);
            lcd.print("  ");
            Setpoint1 = setpointRamp;

     
    А именно строка
    Код (C++):
     startTemp = tc1
    явно неправильна. Нужно "startTemp" привязать к начальной температуре на каждом этапе нагрева, а не мониторить её постоянно, потому как нет нагрева с нужной нам скоростью.
    В программировании я полный "0"!
    ARS_v2_Lilium_JSN_max6675.zip- это оригинальный код
    ARDUINO REWORK V1.2.zip- а это изменённый мной код
    Ещё при настройке параметров не сохраняются значения роста температуры если они с запятой, сбрасывается на нули.
    Прошу Вашей помощи!!!
     

    Вложения:

  3. vector99

    vector99 Гик

    Проблему роста температуры решил простым умножением коэффициентов на 4
    Код (C++):

            rampRateStep[editStep] = rampRateStep[editStep] + 1.;
            delay(25);
            if (rampRateStep[editStep] >= 12.)  //(только целые числа) максимальная скорость роста температуры делённая на 4
            {
              rampRateStep[editStep] = 12.;  //(только целые числа) максимальная скорость роста температуры делённая на 4
            }
          }
          if (downSwitchState == HIGH)
          {
            rampRateStep[editStep] = rampRateStep[editStep] - 1.;
            delay(25);
            if (rampRateStep[editStep] <= 1.)  //(только целые числа) минимальная скорость роста температуры делённая на 4
            {
              rampRateStep[editStep] = 1.;  //(только целые числа) минимальная скорость роста температуры делённая на 4
            }

     
    Код (C++):

          if ((currentMillis - previousMillis) > 4000 / rampRateStep[currentStep - 1]) { //seconds counter

     
    а для корректного отображения на дисплее
    Код (C++):
    lcd.print(rampRateStep[editStep] / 4);
    ограничил скорость роста температуры максимум 3 градуса в секунду, минимум 0,25 градуса
     

    Вложения:

  4. vector99

    vector99 Гик

    Решил проблему со считыванием стартовой температурой. Теперь при старте профиля температура считывается с термопары один раз.
    Код (Text):

          if (currentStep == 1 && flag == 0){
            startTemp = tc1;
            flag = 1;
          }    
          if (currentStep >1 && flag == 1){
            flag = 0;
            startTemp = temperatureStep[currentStep - 2];      
            flag = 1;
          }

     
    Флаги сбрасываются после остановки или завершении профиля.
    Код (Text):

          if (cancelSwitchState == HIGH)
          {
            currentStep = 1;
            counter = 0;
            setpointRamp = 0;
            flag = 0;         //после отановки профиля сбрасываем флаг
            reflowStatus = REFLOW_STATUS_OFF;
            reflowState = REFLOW_STATE_IDLE;
            updateScreen = true;
          }

     
    Код (Text):

    if (counter == dwellTimerStep[currentStep - 1]) {
            counter = 0;
            setpointRamp = 0;
            if (profileSteps == currentStep) {
              currentStep = 1;
              flag = 0;   //после завершения профиля сбрасываем флаг
              reflowState = REFLOW_STATE_COMPLETE;
            }
            else {          
              currentStep++;
              reflowState = REFLOW_STATE_STEP_RAMP;          
            }
          }

     
     

    Вложения:

  5. vector99

    vector99 Гик

    Продолжим вносить изменения. Теперь после остановки нагрева и повторном запуске, профиль продолжится с текущей температуры. Тоесть если недогрели, то можно остановить пайку, внести изменения и продолжить дальше.
    Код (Text):

          if (flag == 0){
            startTemp = tc1;
            flag = 1;
          }
          if (startTemp > temperatureStep[currentStep -1]){
            for (x=1; startTemp > temperatureStep[currentStep - 1];currentStep++){
              x++;
            }
          }
          if (currentStep > x && flag == 1){
            flag = 0;
            startTemp = temperatureStep[currentStep - 2];      
            flag = 1;
          }

     
    Максимальное время перехода на следующий шаг сократил до 100 секунд, т.к 1000 секунд это слишком много.
     

    Вложения:

    Последнее редактирование: 22 дек 2016
  6. Darev

    Darev Нуб

    Спасибо огромное. Ваши корректировки прекрасно работают, станция прям ожила. Какие PID-ы у Вас вышли при наладке
     
  7. vector99

    vector99 Гик

    Станция в стадии разработки. Поэтому наладка контроллёра идёт на лампочке, а пиды настраивать надо на готовой станции. Поэтому пидами даже не заморачивался. В планах сделать вход в меню по долгому нажатию на "ОК", убрать одну кнопку.
     
  8. vector99

    vector99 Гик

    С прошедшими праздниками всех!
    В очередной версии я сделал вход в "МЕНЮ" по долгому нажатию (3 секунды) на кнопку "ОК".
    Заодно защиту от дребезга контактов сделал через "millis()" вместо "delay()" (все 4 кнопки)
    Код (Text):

    //фиксируем момент нажатия кнопки "ОК" + защита от дребезга
          if (okSwitchState == HIGH && !button_state && ( millis() - ms_button)>100)
          {
            ms_button =  millis();
            button_state = true;
            button_long_state = false;
          }
    //держим "ОК" 3секунды и заходим в меню настроек    
          if (okSwitchState == HIGH && !button_long_state && ( millis() - ms_button)>3000)
          {
            button_long_state = true;
            button_state = false;
            reflowState = REFLOW_STATE_MENU_STEPS;
            //update next screen
            updateScreen = true;
          }
    //включаем пайку, кнопка сработает после отпускания "ОК"    
          if (okSwitchState == LOW && button_state && ( millis() - ms_button)>100)
          {      
            ms_button =  millis();
            button_state = false;
            tone(buzzerPin, 1045, 500);  //звуковой сигнал при старте профиля
            //update next screen
            updateScreen = true;
            curCount = 0;
            nextRead2 = millis();
            reflowStatus = REFLOW_STATUS_ON;
            reflowState = REFLOW_STATE_STEP_RAMP;
          }

     
    Отключил бузер при нажатии на кнопки, пищит только при приветствии, старте и завершении профиля.
    И немного раскомментировал скетч. Т.К. эта версия с 4-мя кнопками записил как "ARDUINO REWORK v1.3"
     

    Вложения:

  9. xake

    xake Нерд

    в этом контроллере можно включить только нижний подогрев, например, на 90 градусов?
     
  10. vector99

    vector99 Гик

    Если подключить низ к "6" пину на ардуино и удалить в скече это условие "(tc2 >= (Setpoint2-10))&&" в самом конце скетча.
    Код (Text):

    //верхний нагреватель включится ели температура "низа" достигнет (уснановленной минус 10 градусов)  
        if ((tc2 >= (Setpoint2-10))&&(Output1> millis() - windowStartTime )) digitalWrite(RelayPin1, HIGH);

     
    то низ будет отрабатывать профиль начиная с комнатной температуры до какой Вам надо (максимум 250 градусов) с заданной скоростью.
    Смотря для каких целей Вы хотите приспособить этот контроллёр. Решения могут быть разные.
     
    Последнее редактирование: 19 янв 2017
    Docent38rus и xake нравится это.
  11. xake

    xake Нерд

    создать профиль только преднагрев
     
  12. vector99

    vector99 Гик

    для пайки BGA, SMD, или запекания паяльной маски? если не секрет!
     
  13. xake

    xake Нерд

    преднагрев платы для замены разъема, например
     
  14. vector99

    vector99 Гик

    Ну в таком случае, предложенный выше вариант наверное самый оптимальный.
     
  15. xake

    xake Нерд

    проще тумблером :)
     
  16. vector99

    vector99 Гик

    По своей природе датчик МАХ6675 немного шумит (показания прыгают туда сюда), соответственно ПИДу тяжело ловить оптимальное значение. Поэтому решил его немного стабилизировать. Добавил в скетч "Фильтр Калмана" (во избежании критики, это наверное сильно упрощённый вариант, и таковым его может и трудно назвать). Возможно можно было и проще сделать, но работает неплохо.
    Код (Text):

    // переменные для калмана "ВЕРХНЕГО" нагревателя
    float varTerm1 = 0.25;  // среднее отклонение (ищем в excel)
    float varProcess1 = 0.025; // скорость реакции на изменение (подбирается вручную)
    float Pc1 = 0.0;
    float G1 = 0.0;
    float P1 = 1.0;
    float Xp1 = 0.0;
    float Zp1 = 0.0;
    float Xe1 = 0.0;

    // переменные для калмана "НИЖНЕГО" нагревателя
    float varTerm2 = 0.25;  // среднее отклонение (ищем в excel)
    float varProcess2 = 0.025; // скорость реакции на изменение (подбирается вручную)
    float Pc2 = 0.0;
    float G2 = 0.0;
    float P2 = 1.0;
    float Xp2 = 0.0;
    float Zp2 = 0.0;
    float Xe2 = 0.0;
    // переменные для калмана

     
    Код (Text):

            Input1 = filter1(thermocouple1.readCelsius());
            Input2 = filter2(thermocouple2.readCelsius());

     
    Код (Text):

      float filter1(float val_1) {  //функция фильтрации показений "Верхней" термопары
      Pc1 = P1 + varProcess1;
      G1 = Pc1/(Pc1 + varTerm1);
      P1 = (1-G1)*Pc1;
      Xp1 = Xe1;
      Zp1 = Xp1;
      Xe1 = G1*(val_1-Zp1)+Xp1; // "фильтрованное" значение
      return(Xe1);
    }
      float filter2(float val_2) {  //функция фильтрации показений "Нижней" термопары
      Pc2 = P2 + varProcess2;
      G2 = Pc2/(Pc2 + varTerm2);
      P2 = (1-G2)*Pc2;
      Xp2 = Xe2;
      Zp2 = Xp2;
      Xe2 = G2*(val_2-Zp2)+Xp2; // "фильтрованное" значение
      return(Xe2);
      }

     
    Теперь показания ведут себя вот так,
    90-100 градусов.jpg остывание.jpg комнатная.jpg нагрев.jpg
    (красная - реальные показания, желтая - отфильтрованные)
    Не совсем плавно, но более спокойно.
     

    Вложения:

    Последнее редактирование: 23 янв 2017
  17. uagreen

    uagreen Нуб

    А под нано переделать возможно?
     
  18. vector99

    vector99 Гик

  19. dredivan

    dredivan Нуб

    как приятно что скетч для MAX6675 который я выложил в интернет получил другую жизнь. А с коэффициентами P I D кто-то разбирался?
     
  20. vector99

    vector99 Гик

    пробовал на лампочке P=8, I=0.1, D=1
    вылет за уставку не более 2х градусов. как в боевых условиях будет неизвестно