Управление мощностью ТЭНа

  • В этой теме 422 ответа, 52 участника, последнее обновление 3 года сделано Андрей.
Просмотр 15 сообщений - с 256 по 270 (из 422 всего)
  • Автор
    Сообщения
  • #46495
    Dark
    Участник
    • Ответов: 864
    @dark

    Может быть тогда деление заменить на умножение, можно прилично по времени съэкономить)

    Да! Я с виду шут, но в душе король, и ни кто как я не может...

    #46498
    Petrozelikaps
    Участник
    • Ответов: 540
    @petrozelikaps

    акты считать приходится

    вот это молодец ))

    #46512
    Sergey_r
    Участник
    • Ответов: 2934
    @serjrv

    Может быть тогда деление заменить на умножение, можно прилично по времени съэкономить)

    Надо посмотреть набор команд на данный проц, возможно и стоит. Я просто в основном с PIC контроллерами работаю, там и умножение и деление на аппаратном уровне. Уходит 1 такт проца на умножение (16 бит * 16 бит) и 18 на деление (32 бита / 16 бит). А вот от переменных float постараюсь точно уйти в критичных местах. Я же просто торопился перед отпуском, оптимизацией еще не занимался. А так надо в живую на реальной нагрузке проверить, если будет “плясать” в пределах 1% мощности это думаю не критично.
    Еще, как вариант, добиться деления кратному 2^n, тогда сдвигом битов можно делить, с умножением та же песня только сдвигаем в другую сторону. И это я кстати в коде использую, просто не везде.

    #46514
    Dark
    Участник
    • Ответов: 864
    @dark

    Порядка 5-6 мкс с каждой операции можно уменьшить.

    Умножение и сложение где-то 0.7мкс деление и степень на порядок и ещё чуток больше.

    Оптимально деление на умножение, степень тоже на умножение.

    Ещё с float поиграться можно. Там где-то 10-11мкс на операции съэкономить можно.

    По коду очень сложно от if избавиться. Но буду ещё смотреть.

    Да! Я с виду шут, но в душе король, и ни кто как я не может...

    #46519
    Sergey_r
    Участник
    • Ответов: 2934
    @serjrv

    Деление на 2 и на 4 переделаю на битовый сдвиг, чет только сейчас внимание обратил что ступил. Float тоже не проблема убрать. А там еще посмотрим.

    #46520
    Dark
    Участник
    • Ответов: 864
    @dark

    Так кажется понял как предыдущий кусок кода на case перевести завтра на бросаю, а то с телефона сижу

    Да! Я с виду шут, но в душе король, и ни кто как я не может...

    #46573
    Dark
    Участник
    • Ответов: 864
    @dark

    Ну вот как то так конечно не море времени сокращается но все же.

    Было:
    frecuence = 1 / (tmpCalcTMR1 * 0.000001); // считаем герцы для отображения
    if (frecuence > 48 && frecuence < 52) frecuence = 50;
    else if (frecuence > 58 && frecuence < 62) frecuence = 60;

    Стало:
    switch (frecuence) {
    case 48:
    case 49:
    case 50:
    case 51:
    case 52:frecuence = 50;
    break;
    case 58:
    case 59:
    case 60:
    case 61:
    case 62:frecuence = 60;
    break;
    }
    Тут если все нормально удастся сократить от 0.3 до 1.4 мкс

    Было:
    // расчет мощности от заданных процентов
    userPowerSet = ((uint32_t)powerMax * (uint32_t)triacPercentIn) / 100;
    стало
    // расчет мощности от заданных процентов
    userPowerSet = ((uint32_t)powerMax * (uint32_t)triacPercentIn) * 0.01; // минус 5 мкс

    Было:
    // Опрос энкодера
    ISR (TIMER2_COMPA_vect) {
    if (*portInputRegister(digitalPinToPort(11)) & 8) encoder_CLK = 1;
    else encoder_CLK = 0;
    if (*portInputRegister(digitalPinToPort(9)) & 2) encoder_DT = 1;
    else encoder_DT = 0;

    if ((!encoder_CLK) && (encoder_CLK_prev)) {
    if (encoder_DT) encoder_Data++;
    else encoder_Data–;
    }
    encoder_CLK_prev = encoder_CLK;
    if (dotRX < 255) dotRX++;
    }

    Стало:
    ISR (TIMER2_COMPA_vect) {
    switch (*portInputRegister(digitalPinToPort(11)) & 8){
    case 0: encoder_CLK = 1;
    break;
    case 1:encoder_CLK = 0;
    break;
    }
    switch (*portInputRegister(digitalPinToPort(9)) & 2){
    case 0: encoder_DT = 1;
    break;
    case 1:encoder_DT = 0;
    break;
    }
    if ((!encoder_CLK) && (encoder_CLK_prev)) {
    switch (encoder_DT) {
    case0: encoder_Data++;
    break;
    case 1: encoder_Data–;
    break;
    }
    }
    encoder_CLK_prev = encoder_CLK;
    if (dotRX < 255) dotRX++;
    }
    Тут если я прав, должны чуток сократить от 1.2 мкс и может чуть больше.
    Было:
    EEPROM.get(0, powerMax);
    if (powerMax > 9000 && (powerMax % 50) != 0) powerMax = 3000;
    stepOnePercent = powerMax / 100;
    calcTMR1pr = 18500;
    tmr1_pr = 18500;
    Стало:
    EEPROM.get(0, powerMax);
    if (powerMax > 9000 && (powerMax % 50) != 0) powerMax = 3000;
    stepOnePercent = powerMax * 0.01; //выиграли где-то 5 мкс.
    calcTMR1pr = 18500;
    tmr1_pr = 18500;
    Тут спорный код
    if (ADC_Done_U == 1) {
    VoltageIn = (float)(sqrt(VoltageIn / countU)) * VoltageCoeff;
    VoltageOnIn = (float)(sqrt(VoltageOnIn / countU)) * VoltageCoeff;
    // сглаживание
    Voltage = Voltage – (Voltage >> 2) + (VoltageIn >> 2);
    VoltageOn = VoltageOn – (VoltageOn >> 2) + (VoltageOnIn >> 2);

    ADC_Done_U = 0;
    VoltageIn = 0;
    VoltageOnIn = 0;
    countU = 0;
    }
    if (ADC_Done_I == 1) {
    CurrentIn = (float)(sqrt(CurrentIn / countI)) * CurrentCoeff;
    // сглаживание
    if (CurrentIn >= 10) Current = Current – (Current >> 2) + (CurrentIn >> 2);
    else Current = 0;

    CurrentOut = (float)Current / 100.0;
    Power = ((uint32_t)Current * VoltageOn) / 100;

    ADC_Done_I = 0;
    CurrentIn = 0;
    countI = 0;

    // расчет коррекции угла открытия симистора
    if (Power > userPowerSet) delta = (Power – userPowerSet) / stepOnePercent;
    else delta = (userPowerSet – Power) / stepOnePercent;
    delta <<= 4; // умножаем на 16
    if (Power < userPowerSet) {
    if (tmr1_pr >= (10 + delta)) tmr1_pr -= delta;
    else if (tmr1_pr >= (10 + delta/2)) tmr1_pr -= delta/2;
    else if (tmr1_pr >= (10 + delta/4)) tmr1_pr -= delta/4;
    else if (tmr1_pr > 10) tmr1_pr–;
    }
    else if (Power > userPowerSet) {
    if (tmr1_pr <= (calcTMR1pr + delta)) tmr1_pr += delta;
    else if (tmr1_pr <= (calcTMR1pr + delta/2)) tmr1_pr += delta/2;
    else if (tmr1_pr <= (calcTMR1pr + delta/4)) tmr1_pr += delta/4;
    else if (tmr1_pr < calcTMR1pr) tmr1_pr++;
    }

    U_I = 0;
    }
    я бы так:
    if (ADC_Done_U == 1) {
    VoltageIn = (float)(sqrt(VoltageIn / countU)) * VoltageCoeff;
    VoltageOnIn = (float)(sqrt(VoltageOnIn / countU)) * VoltageCoeff;
    // сглаживание
    Voltage = Voltage – (Voltage >> 2) + (VoltageIn >> 2);
    VoltageOn = VoltageOn – (VoltageOn >> 2) + (VoltageOnIn >> 2);

    ADC_Done_U = 0;
    VoltageIn = 0;
    VoltageOnIn = 0;
    countU = 0;
    }
    if (ADC_Done_I == 1) {
    CurrentIn = (float)(sqrt(CurrentIn / countI)) * CurrentCoeff;
    // сглаживание
    if (CurrentIn >= 10) Current = Current – (Current >> 2) + (CurrentIn >> 2);
    else Current = 0;

    CurrentOut = (float)Current *0.01;
    Power = ((uint32_t)Current * VoltageOn) * 0.01; //Суммарно сократили бы на 9-11 мкс

    ADC_Done_I = 0;
    CurrentIn = 0;
    countI = 0;

    // расчет коррекции угла открытия симистора
    if (Power > userPowerSet) delta = (Power – userPowerSet) / stepOnePercent;
    else delta = (userPowerSet – Power) / stepOnePercent;
    delta <<= 4; // умножаем на 16
    if (Power < userPowerSet) {
    if (tmr1_pr >= (10 + delta)) tmr1_pr -= delta;
    else if (tmr1_pr >= (10 + delta/2)) tmr1_pr -= delta/2;// Тут я бы заменил по простому на умножение и на всех операциях бы сократили где-то на 20-40 мкс
    else if (tmr1_pr >= (10 + delta/4)) tmr1_pr -= delta/4;
    else if (tmr1_pr > 10) tmr1_pr–;
    }
    else if (Power > userPowerSet) {// Думаю от этого if можно избавиться
    if (tmr1_pr <= (calcTMR1pr + delta)) tmr1_pr += delta;
    else if (tmr1_pr <= (calcTMR1pr + delta/2)) tmr1_pr += delta/2;
    else if (tmr1_pr <= (calcTMR1pr + delta/4)) tmr1_pr += delta/4;
    else if (tmr1_pr < calcTMR1pr) tmr1_pr++;
    }

    U_I = 0;
    }

    Ну как-то так

    Да! Я с виду шут, но в душе король, и ни кто как я не может...

    #46578
    Sergey_r
    Участник
    • Ответов: 2934
    @serjrv

    Это не критично, т.к. выполняем только один раз при старте:
    frecuence = 1 / (tmpCalcTMR1 * 0.000001); // считаем герцы для отображения
    if (frecuence > 48 && frecuence < 52) frecuence = 50;
    else if (frecuence > 58 && frecuence < 62) frecuence = 60

    Эти места:
    else if (tmr1_pr <= (calcTMR1pr + delta/2)) tmr1_pr += delta/2;
    else if (tmr1_pr <= (calcTMR1pr + delta/4)) tmr1_pr += delta/4;
    уже заменил так:
    else if (tmr1_pr <= (calcTMR1pr + (delta>>1))) tmr1_pr += (delta>>1);
    else if (tmr1_pr <= (calcTMR1pr + (delta>>2))) tmr1_pr += (delta>>2);

    Далее по расчетам с float, было:
    CurrentIn = (float)(sqrt(CurrentIn / countI)) * CurrentCoeff;
    Сделал:
    CurrentIn = ((uint32_t)(sqrt(CurrentIn / countI)) * CurrentCoeff) >> 7; в данном случае просто множитель CurrentCoeff будет равен не 6.32 а целочисленный 809 которое сдвигом поделим на 128, т.е. 809/128=6.32

    С энкодером почти согласен, только вот это:
    case 0: encoder_CLK = 1;
    break;
    case 1: encoder_CLK = 0;
    break;
    заменим на битовые операции вместо присвоения, еще скорость возрастет (по крайней мере = 1 точно вместо двух операций на asm будет одна, главное переменную при старте обнулить):
    case 0: encoder_CLK | = 0x01;
    break;
    case 1: encoder_CLK &= ~0x01;
    break;
    с переменной encoder_DT аналогично.

    По поводу /100 или *0.01 не знаю, надо смотреть что там GCC генерит при этом.

    #46579
    Dark
    Участник
    • Ответов: 864
    @dark

    Вот этот кусок

    }
    else if (Power > userPowerSet) {// Думаю от этого if можно избавиться
    if (tmr1_pr <= (calcTMR1pr + delta)) tmr1_pr += delta;
    else if (tmr1_pr <= (calcTMR1pr + delta/2)) tmr1_pr += delta/2;
    else if (tmr1_pr <= (calcTMR1pr + delta/4)) tmr1_pr += delta/4;
    else if (tmr1_pr < calcTMR1pr) tmr1_pr++;
    }

    Думаю перед ним надо где-то поставить <= вместо < иначе при равенстве может быть глюк, хотя это я бы просто поставил чтобы застраховаться. Все понял, тяжело чужой код править. (

    Да! Я с виду шут, но в душе король, и ни кто как я не может...

    #46583
    Sergey_r
    Участник
    • Ответов: 2934
    @serjrv

    Вот этот кусок

    Я этот кусок уже переделал, выше пример привел, сдвиг вместо деления.

    А так да, в чужом коде тяжко ковыряться )))

    #46587
    Dark
    Участник
    • Ответов: 864
    @dark

    Вот этот кусок } else if (Power > userPowerSet) {// Думаю от этого if можно избавиться if (tmr1_pr <= (calcTMR1pr + delta)) tmr1_pr += delta; else if (tmr1_pr <= (calcTMR1pr + delta/2)) tmr1_pr += delta/2; else if (tmr1_pr <= (calcTMR1pr + delta/4)) tmr1_pr += delta/4; else if (tmr1_pr < calcTMR1pr) tmr1_pr++; } Думаю перед ним надо где-то поставить <= вместо < иначе при равенстве может быть глюк, хотя это я бы просто поставил чтобы застраховаться. Все понял, тяжело чужой код править. (

    Этот кусок, мне спокойно спать не дает. По хорошему, расчет delta/2 и /4 за проверку в две переменные закинуть, но тут палка о двух концах двумя переменными большой кусок памяти оттяпать можем, но зато чуток в if-ах скорость увеличим.

    Да! Я с виду шут, но в душе король, и ни кто как я не может...

    #46588
    Dark
    Участник
    • Ответов: 864
    @dark

    Вот этот кусок

    Я этот кусок уже переделал, выше пример привел, сдвиг вместо деления. А так да, в чужом коде тяжко ковыряться )))

    Будем ждать нового кода, чтобы сказать свое радостное фи )

    Да! Я с виду шут, но в душе король, и ни кто как я не может...

    #46634
    Sergey_r
    Участник
    • Ответов: 2934
    @serjrv

    Будем ждать нового кода, чтобы сказать свое радостное фи )

    Так твое “фи” всегда подстегивает дальше подумать, но это не страшно, говори )))
    Завтра силовой блок окультурю в коробок, и в воскресенье испытаю в живую, и на старой прошивке, и на подправленной, с совместными идеями.

    #46655
    Dark
    Участник
    • Ответов: 864
    @dark

    Хотелось бы посмотреть на сколько скорость измениться. Датчик htwc004 кажется так на ac1050 заменить можно, а то монтаж разный получается

    Да! Я с виду шут, но в душе король, и ни кто как я не может...

    #46657
    Mantis
    Участник
    • Ответов: 1279
    @mantis

    Ага только сегодня думал за чем он на проводах нужен.

    modern distiller, разрушаем "каноны")
    https://vk.com/club173629256
    Я хочу синего джина, я хочу чёрного рома....

Просмотр 15 сообщений - с 256 по 270 (из 422 всего)
  • Для ответа в этой теме необходимо авторизоваться.