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

Тема в разделе "Глядите, что я сделал", создана пользователем Jalnin, 2 ноя 2012.

Статус темы:
Закрыта.
  1. bamik

    bamik Нерд

    Проблем с адресацией не будет, если вычислять длину переменных. Я пару-тройку страниц назад накидывал кусок на эту тему.
     
  2. Добрый день. Предлагаю на дисплее выводить собственную кириллицу(об этом ниже). Функция lcd.createChar(7, bukva_G); позволяет создать с ограничением до 8 пользовательских символов выводимых на экран. Можно обойти так #5(http://arduino.ru/forum/obshchii/lcd-1602-i-russkie-simvoly) то есть вывести символы, ЗАТЕМ очистить экран и вывести новые. Такие буквы как H P M X E Y O A K C B - заглавные(в верхнем регистре) латиница, поэтому есть смысл выводить все только заглавными. Более подробно в ссылке и код приведен

    У себя делал так: создал вначале символы которые пригодятся в коде
    Код (C++):
    uint8_t  bukva_G[8]   ={B11111,B10001,B10000,B10000,B10000,B10000,B10000,B00000,}; // Буква "Г"
    uint8_t  bukva_D[8]   = {B01111,B00101,B00101,B01001,B10001,B11111,B10001,B00000,}; // Буква "Д"
    uint8_t  bukva_ZH[8]  = {B10101,B10101,B10101,B11111,B10101,B10101,B10101,B00000,}; // Буква "Ж"
    uint8_t  bukva_L[8]   = {B00011,B00111,B00101,B00101,B01101,B01001,B11001,B00000,}; // Буква "Л"
    uint8_t bukva_CH[8] = {B10001, B10001, B10001, B01111, B00001, B00001, B00001}; // Буква "Ч"
    uint8_t bukva_IY[8] = {B10101, B10001, B10001, B10011, B10101, B11001, B10001}; // Буква "Й"
    uint8_t bukva_IYI[8] = {B10001, B10001, B10001, B11001, B10101, B10101, B11001}; // Буква "Ы"
    uint8_t  bukva_I[8]   = {0x11, 0x13, 0x13, 0x15, 0x19, 0x19, 0x11}; // Буква "И"
    uint8_t  bukva_P[8]   = {0x1F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; // Буква "П"
    uint8_t bukva_Mz[8] = {0x10, 0x10, 0x10, 0x1E, 0x11, 0x11, 0x1E}; // Буква "Ь"
    uint8_t tochki[8] = {B0, B00000, B0, B0, B0, B0, B10101};
    Далее уже прямо в коде создавал те которые буду выводить до очистки(смены) экрана
    Запись "HACTPO\4K\2" надеюсь понятна - \4 и \2 собственные симовлы

    Код (C++):
    case MAIN_MENU:  /***************** Главное меню ***************/

          flag = 0; // опускаем флаг

          setString(ButtonModecount); // включаем отображение стрелки выбора меню

          lcd.createChar(2, bukva_I); // создает символ И
          lcd.createChar(3, bukva_CH); // создает символ Ч
          lcd.createChar(4, bukva_IY); // создает символ Й
          lcd.createChar(5, bukva_IYI); // создает символ Ы
          lcd.createChar(6, bukva_Mz);      // Создаем символ Ь

          lcd.setCursor(1, 0); // 1 строка
          lcd.print(F("PY\3HO\4")); //РУЧНОЙ
          lcd.setCursor(1, 1); // 2 строка
          lcd.print(F("ABTOMAT\2\3ECK\2\4")); // АВТОМАТИЧЕСКИЙ
          lcd.setCursor(1, 2); // 3 строка
          lcd.print(F("HACTPO\4K\2")); /НАСТРОЙКИ
          lcd.setCursor(1, 3); // 4 строка
          lcd.print(F("*****")); // ПК

          break;
     
    Удобно для этого перед выводом, создать функцию с генерацией букв и сделать ее вызов после очистки экрана

    Код (C++):
    void ExitCurMenu() {
      lcd.createChar(1, bukva_Mz); // создает символ
      lcd.createChar(2, bukva_I); // создает символ
      lcd.createChar(3, bukva_IYI); // создает символ
      lcd.createChar(4, bukva_IY); // создает символ
      lcd.setCursor(1, 1);
      lcd.print(F("COXPAH\2T\1 \2 B\3\4T\2")); // СОХРАНИТЬ И ВЫЙТИ
    }
     

    Вложения:

    Последнее редактирование: 12 май 2018
  3. bamik

    bamik Нерд

    Эти дисплеи в своей таблице имеют русские буквы, но они находятся не на "своих" местах. Поэтому достаточно сделать кодирующую таблицу, через которую и пропускать выводимый текст.
     
  4. Дисплеи МЭЛТ имеют в своем составе кириллицу, в китайских то что зашито заводом изготовителем тем и пользоваться. В моем (китай)нет кириллицы проверял. Это касается LCD1602, LCD2004 т д
    Проверьте #13
     
    Последнее редактирование: 12 май 2018
  5. bamik

    bamik Нерд

    С аналогового входа считываются целочисленные значения от 0 до 1023. С внешних АЦП аналогично. Это уже мы затем преобразуем полученное число в напряжение, температуру и т.д. В угоду нашего восприятия. Но для логики нет разницы какое значение использовать. Преобразование - это всего лишь масштаб. Преобразование требуется делать только при выводе на экран.
     
  6. bamik

    bamik Нерд

    Да, ты прав. все грустно.
    Код (C++):
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x27, 20, 4);
    int currentRow = 0;
    int currentCol = 0;

    void setup() {

    // put your setup code here, to run once:

    }

    void loop() {
    lcd.begin();
    //lcd.init(); // В некоторых вариантах библиотеки такая команда инициализации.
    lcd.backlight();
      lcd.clear();
    for (int letter = 0; letter <= 255; letter++) {
    lcd.setCursor(currentCol, currentRow-1);
    lcd.print(char(letter));
    currentCol++;
        if (currentCol > 20){
            currentCol = 0;
           if (currentRow < 3 ){
            currentRow++;
            }
          else {
            delay(8000);
            lcd.clear();
            currentRow = 0;          
          }
        }
      }

    }
    Вот код для проверки.
     
  7. SNMar4enko

    SNMar4enko Нерд

    Русификация китайского дисплея - не такое и без проблемное дело.
    В скетче много моментов когда что-то пишется поверх написанного. Своих генерируемых символов максимум 8. Мы можем динамически менять их все. Это расширяет их количество. Неплохо. Но я скажу следующее - я поначалу несколько раз попадался в случае отсутствия очистки экрана:
    lcd.clear();
    если надпись, написанная с использованием сгенерированных символов осталась на экране LCD а мы меняем их на новые то тут же на экране написанное сообщение тоже отображается по новому - не смотря на то что мы практически не переписывали. Так учитывайте при написании кода.

    Теперь по ПИДу: если бы у нас был один ПИД регулятор - может быть и хватило скорости опроса ПИД. Но у нас два нагревателя и два ПИДа. Исходя из формулы расчета ПИД получается что для аналогичного регулирования при увеличении шкалы ПИД выходного сигнала нужно увеличить все коэффициенты ПИД в тоже количество раз. При уменьшении аналогично уменьшить. Не забывайте об этом когда будете подбирать коэффициенты ПИД. Теперь взглянем на примеры от человека написавшего используемую нами библиотеки.
    Код (C++):
    double Kp=2, Ki=5, Kd=1;
    PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
    при этом шкала &Output от 0 до 255.
    При пересчете на шкалу 100 получаем Kp=0.8, Ki=2, Kd=0.4;
    Если для целочисленого ПИДа то можно округлить к примеру так:
    Kp=1, Ki=2, Kd=0.5; - первая составляющая берем просто ошибку, второй +2 или -2 значения мощности последний перед сложением делим на 2. Как вам такая идея?
    Или так?
    Код (C++):
    void pid()
    {
    error=set_temp-temp;
    I+=error;
    I+=error;
    set_pwm=(error+I-(pre_error-error)/2);

    pre_error=error;
    }
    Да таких ПИД нужно 2, и еще нужно ограничение ввести. Чтобы правильно регулировало все переменные кроме set_pwm должны быть double. Получим ли выигрыш неизвестно. ведь ограничивать нужно set_pwm и I
     
    Последнее редактирование: 12 май 2018
  8. SNMar4enko, добрый день Можете разъяснить по коду, зачем по условию выводятся символы "+" или "-". Какой в них смысл?
    Код (C++):
    case REFLOW_STATE_IDLE:
         TopStart = false;
         currentStep = 1;
         counter = 0;
         setpointRamp = 0;

         flag = 0;         //после остановки профиля сбрасываем флаг
         DimmerUP=220;
         DimmerDOWN=220;

          //Update whole screen only once
          if (updateScreen) {
            //Настройка экрана в режиме ожидания
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("IDLE ");
            lcd.setCursor(0, 1);
            lcd.print("Pr  ");
            lcd.setCursor(5, 0);
            lcd.write(byte(1));
            lcd.setCursor(5, 1);
            lcd.write(byte(2));
            lcd.write(byte(2));

            updateScreen = false;
          }
          lcd.setCursor(2, 1);
          lcd.print(currentProfile, HEX);

          if (temperatureStep[profileSteps-2]<181) {lcd.print("+");
          lcd.write(byte(2));}
          else {lcd.print("-");
          lcd.write(byte(2));}

          lcd.setCursor(7, 0);
          lcd.print(temperatureStep[profileSteps-1]);
          lcd.write(byte(0));
          lcd.setCursor(7, 1);
          lcd.print(SP2);
          lcd.write(byte(0));

          lcdTemp();
    И еще это правильный перевод стадий профиля? Надеюсь что допустимо
    Код (C++):
    const char string_6[] PROGMEM = "STEPS"; // ШАГИ
    const char string_7[] PROGMEM = "DWELL: "; // ВРЕМЯ ВЫДЕРЖКИ
    const char string_8[] PROGMEM = "PWR  "; // МОЩНОСТЬ
    const char string_9[] PROGMEM = "RAMP: "; // СКОРОСТЬ РОСТА
    const char string_10[] PROGMEM = "TARGET:"; // КОНТРОЛ. ТОЧКА
    И если не затруднит зачем вы переменную pwr_BOTTOM ограничили значением 200, а не 100?
    Код (C++):
    case REFLOW_STATE_MENU_BOTTOM_PWR:
     
          if (updateScreen)
          {
       
            lcd.setCursor(0, 1);
            lcd.print("Bottom PWR:     ");    
            updateScreen = false;
          }
          lcd.setCursor(12, 1);  
          lcd.print(pwr_BOTTOM/2);
          lcd.print("%");
     
     
     
         if (pwr_BOTTOM<=199)
          {  
          lcd.setCursor(15,1);
          lcd.print(" ");
          }
           if (pwr_BOTTOM<=19)
          {  
          lcd.setCursor(14,1);
          lcd.print("  ");
          }
     
           if (upSwitchState == HIGH && ( millis() - ms_button)>100)
          {
            ms_button =  millis();
            pwr_BOTTOM = pwr_BOTTOM + 1;
            if (pwr_BOTTOM >= 200)
            {
              pwr_BOTTOM = 200;
            }
          }
    Смотрю вашу последнюю версии с сайта http://radioservice.at.ua
     
    Последнее редактирование: 12 май 2018
  9. SNMar4enko

    SNMar4enko Нерд

    + свинцовый профиль.
    - безсвинцовый профиль, определяются по предпосленему шагу - по его температуре.

    - для первых шагов время стабилизации в контрольной точке, на последнем шаге время пайки. возможно парой слов так и правильней. (Пауза удержания температуры контрольной точки).
    - все просто - ограничение мощности регулируется с точностью 0.5 процента, хотя на индикаторе не сделано отображение. По последним рассуждениям - нужно убавлять, ведь большее значение замедляет время установки ПИД.
     
    Последнее редактирование: 12 май 2018
    Aleksander1997 нравится это.
  10. Dmitrysh

    Dmitrysh Гуру

    Не связано напрямую одно с другим. Тут надо подумать...
    Нет, когда мы меняем выходные значения, допустим методом SetOutputLimits, ничего не пересчитывается, просто максимум выходного сигнала ограничивается 100 усл.ед. Коэффициенты при прочих равных условиях зависят только от нагревателей и среды.
     
  11. Dmitrysh

    Dmitrysh Гуру

    Вот самая главная и правильная мысль! Отсюда надо плясать.
     
  12. Dmitrysh

    Dmitrysh Гуру

    Наша библиотека ПИД медленная, надо её переписывать по целочисленную математику.
     
  13. vector99

    vector99 Гик

    По поводу двух ПИД. Могу предложить такой способ: включили нижний нагреватель, дождались когда плата достигла уставки, подождать некоторое время зафиксировать выходную мощность и отключить нижний ПИД. Затем включаем верхний ПИД, тогда за всё время пайки контроллёр расчитывает только один ПИД
     
    SOLOway нравится это.
  14. Dmitrysh

    Dmitrysh Гуру

    разумный вариант, но надо придумать чем будем поддерживать температуру низа от её большого выбега или провала.
     
  15. SOLOway

    SOLOway Гуру

    Для НИ не критична температура в 1-5*С, как и увеличение времени самого преднагрева на 0,5-2 мин. Там интервал от 120 до 160 для Pb+ и от 140 до 185 для Pb-. Из-за различий в размерах и теплоемкости плат мы при фиксированной мощности получим лишь небольшие изменения времени преднагрева - не критичные. Не будет больших колебаний там.
    Да и надо определиться с типом нагревателей в НИ: безинерционные/сильноинерционные и в зависимости от этого построить таблицу мощностей на "средних" платах...
    Важно избежать бросков мощности и излишне быстрого прироста температуры на нагревателях.
    Количество шагов профиля придется увеличивать, если мы желаем успевать за подлостями производителей чипов - комбайны требуют сложных профилей, точного соблюдения параметров шагов и изменений конструкции ВИ - классические формы ВИ не справляются из-за особенностей распространения теплового излучения (как, впрочем, и иных видов волн)...
     
    Последнее редактирование: 12 май 2018
  16. SNMar4enko

    SNMar4enko Нерд

    Почему нет? разве время на сложение, умножение и т д кучи 4 байтных чисел с послледующим ограничением не занимает время ..... и вроде писали что
    - выжимает даже 73 - по началу ПИД опрашивается только для низа - что тут думать

    - полносттью под целочисленную не получится, если ошибка будет меньше 0.5 градусов ПИД ничего не будет пересчитывать. Диффиринциальная сотавлящая вообще потяряется. Да и уже 3 последних страницы твердим об этом, все согласны и я уже предлегал пример выше
    Код (C++):
    void pid()
    {
    error=set_temp-temp;
    I+=error;
    I+=error;
    set_pwm=(error+I-(pre_error-error)/2);

    pre_error=error;
    }
    - здесь мы избавляемся от кучи умножений, делений, сум .....в крайнем случае можно копию библиотеки PID_v1 испортить чтобы код не переписывать в скетче

    - я в своем скетче установленной верхней мощностью ограничиваю окно выходного сигнала ПИД - так вот при более сильном ограничении - уменшается шкала ПИД - а мы не забываем что установившийся режим ПИД устанавливается в хужем случае за количество циклов опроса ПИД равное количеству выходных делений. Если их меньше то быстрей формируется ПИД установившийся. Если нагреватель мощный и ограничение мощности не влияет на нагрев то пропорциональная коректировка коэффициентов ПИД влияет аналогично на время установки ПИД.

    Еще - низ можно регулировать только по ШИМ - без ПИД. Делать это так - в настройках ставим ограничение мощности низа - когда включаем нагрев можно мощность посекундно разогнать до установленоного ограничения. Температуру мерять датчиком и когда достигнет тех же 150 градусов - включить верх.
     
    Последнее редактирование: 12 май 2018
  17. Dmitrysh

    Dmitrysh Гуру

    Над этим мы подискутируем попозже и придем к консенсусу. Тема интересная и обширная.
    Давайте посмотрим приведенный вами код
    Код (C++):
    void pid()
    {
    error=set_temp-temp;
    I+=error;
    I+=error;
    set_pwm=(error+I-(pre_error-error)/2);

    pre_error=error;
    }
    И сравним с нашим
    Код (C++):
    bool PID::Compute()
    {
     
          double error = *mySetpoint - input; //это error
          double dInput = (input - lastInput); //это pre_error-error
          outputSum+= (ki * error); //интегральная составляющая
       
          if(outputSum > outMax) outputSum= outMax;
          else if(outputSum < outMin) outputSum= outMin; //ограничиваем накопленный интеграл

            double output;
           output = kp * error;   //пропорциональная составляющая
               
          output += outputSum - kd * dInput; //это выход ПИД

            if(output > outMax) output = outMax;   //это ограничение ПИД
          else if(output < outMin) output = outMin;
            *myOutput = output;

           lastInput = input;  //это pre_error=error;
            return true;
       }

    }
    Не замечаете сходства?
     
  18. Dmitrysh

    Dmitrysh Гуру

    А кто нибудь пробовал не разгонять а притормозить ПИД?
     
    SOLOway нравится это.
  19. Dmitrysh

    Dmitrysh Гуру

    А отсюда поподробней, откуда такая теория?
     
  20. bamik

    bamik Нерд

    А кто-нибудь догадался посмотреть код целочисленного ПИДа, который я скидывал? AVR211.
    Там все по уму сделано. И все очень понятно. Есть ограничители по разрядности. По-умолчанию ограничено 16 битами. Но можно сделать 8 бит. Выход - в процентах в виде от -100% до +100%. Но это условности. На самом деле это число типа int. Можно переделать на byte. И поправить проверку на нижние значения вычислений.
    Вот как-то так:
     

    Вложения:

    • IAR_byte.zip
      Размер файла:
      96,8 КБ
      Просмотров:
      278
    Последнее редактирование: 13 май 2018
Статус темы:
Закрыта.