Например TDA7294

Форум РадиоКот • Просмотр темы - Программное изменение яркости вакуумно-люминисцентных ламп
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Вс июл 27, 2025 21:39:36

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 36 ]  1,  
Автор Сообщение
Не в сети
 Заголовок сообщения: Программное изменение яркости вакуумно-люминисцентных ламп
СообщениеДобавлено: Ср авг 11, 2021 15:58:25 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 33
Зарегистрирован: Чт ноя 08, 2012 22:28:05
Сообщений: 794
Откуда: Ижевск
Рейтинг сообщения: 0
Всем здравствуйте!

Пытаюсь реализовать следующий эффект: при смене цифр одна плавно гаснет, вторая плавно появляется.

С общей регулировкой яркости проблем вообще нет. Все красиво, нормально. Алгоритм общей регулировки такой

Код:
// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)                 

    switch (a) {                                             
            case 0:
                    Cathode_0_on ();
                    print (a1);
                    break;
            case 1:
                    Cathode_1_on ();
                    print (a2);
                    break;               
            case 2:
                    Cathode_2_on ();
                    print (a3);
                    break;
            case 3:
                    Cathode_3_on ();
                    print (a4);
                    break;
            case 4:
                    Cathode_4_on ();
                    print (a5);
                    break; 
            case 5:
                    Cathode_5_on ();
                    print (a1);
                    break;
    }
    a++;
    if (a == 6) {a = 0;}                                       
}               

// Timer2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)                   
{
    all_off ();
    off_segments ();   
}



Далее путем подбора OCR2 меняется яркость.

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

1) Добавлял переменную B в прерывании, делал так:

Код:
if (b < bright1) {зажигать} else {не зажигать}


полная фигня, лампа моргает, засветы и прочие артефакты

2) Пробовал выполнять переключения ламп в прерывании, а зажигать сегменты в основной программе, она же типа быстрее. Получалась тоже фигня с засветами и мерцаниями.

Очень прошу помощи, уже не помню сколько раз возвращался к вопросу и так и не осилил (


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 16:56:02 
Друг Кота
Аватар пользователя

Карма: 50
Рейтинг сообщений: 1395
Зарегистрирован: Пт авг 28, 2009 21:34:30
Сообщений: 7306
Откуда: 845-й км.
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
https://www.radiokot.ru/forum/viewtopic ... 0#p3875550 <-- вот описание моей реализации для ГРИ.

Если вы не можете запрячь под это дело DMA, то можете добавить просто прерывание по сравнению таймера и по прерыванию по переполнению показываете новую цифру, а по прерыванию сравнения - старую.

Когда я делал такую штуку на светодиодах, там заметил, что чтобы яркость спадала/возрастала линейно, ШИМ должен изменяться по экспоненциальному закону. Но если разом гасить и зажигать другую цифру - ничего не получится, поэтому ШИМ меняем просто линейно.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 17:03:12 
Друг Кота
Аватар пользователя

Карма: 81
Рейтинг сообщений: 1377
Зарегистрирован: Пн май 11, 2009 14:15:00
Сообщений: 3059
Откуда: СПб
Рейтинг сообщения: 2
Медали: 1
Мявтор 3-й степени (1)
С тех пор, как мне захотелось совместить регулировку яркости с плавной сменой цифр, я стал делать так:

Каждый разряд при динамической индикации обрабатывается не 1 раз, а 16 (частота, соответственно, также увеличена в 16 раз). Выводятся цифры, хранящиеся в двумерном массиве - по 16 элементов массива на разряд. Чтобы получить плавную смену цифр, например, поменять 5 на 6, нужно с некоторым интервалом заполнять массив (в данном разряде) следующими наборами значений:
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
6 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5
6 6 6 5 5 5 5 5 5 5 5 5 5 5 5 5
...
6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5
6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6

Заполнение я делаю не в прерывании, а в main(), при помощи программного таймера, отсчитывающего интервалы времени для шагов плавной смены.

Такой алгоритм позволяет очень легко реализовать и другие эффекты, например, не "перетекание" одной цифры в другую, а плавное погасание старой цифры и резкое зажигание новой (это делается записью в массив специального кода, соответствующего пустому разряду).

P.S. Эх, пока я это всё писал, uldemir меня опередил.
Но, к слову, я использую описанный алгоритм на прерываниях в AVR без всяких DMA. И всё прекрасно работает, поскольку код в прерываниях сделан максимально компактным - просто выводится цифра из массива.

Добавлено after 6 minutes 17 seconds:
Re: Программное изменение яркости вакуумно-люминисцентных ламп
uldemir писал(а):
Если вы не можете запрячь под это дело DMA, то можете добавить просто прерывание по сравнению таймера и по прерыванию по переполнению показываете новую цифру, а по прерыванию сравнения - старую

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

_________________
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 17:15:32 
Друг Кота
Аватар пользователя

Карма: 50
Рейтинг сообщений: 1395
Зарегистрирован: Пт авг 28, 2009 21:34:30
Сообщений: 7306
Откуда: 845-й км.
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
*Trigger* писал(а):
Такой вариант плохо совмещается с регулировкой яркости, к сожалению. Я по началу так и делал, а потом захотелось регулировать яркость, и пришлось от такого способа отказаться.
А если использовать два канала сравнения? один для яркости, другой для эффекта? Или у AVR нет таймеров с несколькими каналами захвата/сравнения?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 17:33:48 
Друг Кота
Аватар пользователя

Карма: 81
Рейтинг сообщений: 1377
Зарегистрирован: Пн май 11, 2009 14:15:00
Сообщений: 3059
Откуда: СПб
Рейтинг сообщения: 1
Медали: 1
Мявтор 3-й степени (1)
Такие таймеры в AVR есть. Тут дело в другом. Пусть есть, скажем, 8-разрядный таймер. На полной яркости прерывание, где гасятся все разряды, возникает, например, при значении 240 в счётном регистре (чтобы сформировать паузу между разрядами). А на минимальной яркости пусть будет где-нибудь 80. Тогда при максимальной яркости менять значение в регистре сравнения того канала, где меняется старая цифра на новую, нужно в диапазоне 0...239, а на минимальной - в диапазоне 0...79. Если будет, например, 16 шагов при смене цифр, то придётся рассчитывать значение регистра сравнения для канала, где переключается цифра, исходя из текущего значения яркости. На полной яркости будет один набор значений, на минимальной - другой, где-то посередине - ещё один.
На мой взгляд, это неудобно. Лишние расчёты. И ещё нужно следить за тем, чтобы значение в регистре сравнения для гашения изменялось не абы когда, а только в определённые моменты времени, чтобы прерывания не поменялись местами.

Ну и гибкость у такого решения невелика. Вариант с 16 "проходами" одного разряда позволяет очень легко реализовать и всякие другие эффекты.

_________________
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 18:14:51 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 33
Зарегистрирован: Чт ноя 08, 2012 22:28:05
Сообщений: 794
Откуда: Ижевск
Рейтинг сообщения: 0
К сожалению пока я не понимаю... DMA в атмеге8 вряд ли найдется, может вам не сложно будет кусок кода набросать? Что проще, перетекание одной цифры в другую или плавное гашение одной и розжиг другой? Допустим для начала всего одну цифру секунд плавно гасим, затем зажигаем новую.

Подойдет и на каком-нибудь условном языке.

Идею с массивом я понял, но никак не дойдет, как это будет в виде алгоритма выглядеть, хватит ли 8 МГц на это? Среда в принципе любая, но codevision с его PORTx.y = z понятнее была бы )
---

Усиленно перечитываю, вроде потихоньку что то доходит, но все равно пока еще не очень, буду благодарен за пример кода

Вот как я представил себе это. Есть сомнения на счет t, что там будет происходить, если общая яркость понижена, что то мне подсказывает что где то фигня, поправьте пожалуйста )

Код:
unsigned char digit1 [16] = {1, 1, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
unsigned char t = 0;

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)                 
{
    switch (a) {                                             
            case 0:
                    Cathode_0_on ();
                    print (digit [t]);
                    break;
            case 1:
                    Cathode_1_on ();
                    print (a2);
                    break;               
            case 2:
                    Cathode_2_on ();
                    print (a3);
                    break;
            case 3:
                    Cathode_3_on ();
                    print (a4);
                    break;
            case 4:
                    Cathode_4_on ();
                    print (a5);
                    break;
            case 5:
                    Cathode_5_on ();
                    print (a1);
                    break;
    }
    a++;
    t++;
    if (t > 15) t = 0;
    if (a == 6) {a = 0;}                                       
}               

// Timer2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)                   
{
    all_off ();
    off_segments ();   
}


Вернуться наверх
 
Распродажа паяльного оборудования ATTEN!
Паяльные станции, паяльники и аксессуары по самой выгодной цене.

По промокоду radiokot скидка 10%
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 18:38:30 
Друг Кота
Аватар пользователя

Карма: 81
Рейтинг сообщений: 1377
Зарегистрирован: Пн май 11, 2009 14:15:00
Сообщений: 3059
Откуда: СПб
Рейтинг сообщения: 1
Медали: 1
Мявтор 3-й степени (1)
Вот слегка адаптированный код из программы реальных часов (правда, на ГРИ, но тут особой разницы нет):
Спойлер
Код:
uint8_t display_buffer_raw[DIGITS][BRIGHT_STEPS];
uint8_t digit_counter = 0;
uint8_t bright_step_counter = 0;
uint8_t digit_mask = (1 << 0);

void id1_output(uint8_t n){
  if(n >= 10)
    return;

  n = id1_decode_table[n];

  CLR_PORT(ID1_A);
  CLR_PORT(ID1_B);
  CLR_PORT(ID1_C);
  CLR_PORT(ID1_D);

  if(n & (1 << 0))
    SET_PORT(ID1_A);
  if(n & (1 << 1))
    SET_PORT(ID1_B);
  if(n & (1 << 2))
    SET_PORT(ID1_C);
  if(n & (1 << 3))
    SET_PORT(ID1_D);
}

ISR(TIMER1_COMPA_vect){
  uint8_t symbol;

  if(bright_step_counter >= BRIGHT_STEPS)
    return;

  symbol = display_buffer_raw[digit_counter][bright_step_counter];
  id1_output(symbol);

  if(symbol < 10){
    switch(digit_counter){
    case 0:
      SET_PORT(ANODE_0);
      break;
    case 1:
      SET_PORT(ANODE_1);
      break;
    case 2:
      SET_PORT(ANODE_2);
      break;
    case 3:
      SET_PORT(ANODE_3);
      break;
    }
  }
}

ISR(TIMER1_COMPB_vect){
  if(++bright_step_counter == BRIGHT_STEPS_WITH_SAFE_PAUSE){
    bright_step_counter = 0;
    digit_mask <<= 1;
    if(++digit_counter == DIGITS){
      digit_counter = 0;
      digit_mask = (1 << 0);
    }
  }

  CLR_PORT(ANODE_0);
  CLR_PORT(ANODE_1);
  CLR_PORT(ANODE_2);
  CLR_PORT(ANODE_3);
}

soft_timer_t display_change_effect_timer; //структура "программного таймера", который позволяет отсчитывать заданные интервалы времени

uint8_t display_buffer[DIGITS]; //новые (текущие) состояния разрядов
uint8_t display_buffer_old[DIGITS]; //старые состояния разрядов

//функция вызывается в основном цикле
void display_routine(void){
  uint8_t i, j;
  uint16_t step_duration;
  uint8_t steps;

  if(display_state.change_effect == NO_EFFECT ||
     display_state.change_effect_step == 0){
    for(i = 0; i < DIGITS; i++)
      for(j = 0; j < BRIGHT_STEPS; j++){
        display_buffer_raw[i][j] = display_buffer[i];
      }
  }
  else{
    switch(display_state.change_effect){
    case SOFT_CHANGE: //обычная плавная смена (одновременное погасание и зажигание)
      for(i = 0; i < DIGITS; i++)
        for(j = 0; j < BRIGHT_STEPS; j++)
          if(j < display_state.change_effect_step ||
             !(display_state.change_effect_flags & (1 << i))){
            display_buffer_raw[i][j] = display_buffer[i];
          }
          else{
            display_buffer_raw[i][j] = display_buffer_old[i];
          }
      steps = SOFT_CHANGE_STEPS;
      step_duration = SOFT_CHANGE_STEP_DURATION;
      break;

    case SEMI_SOFT_CHANGE: //плавное погасание, резкое зажигание
      for(i = 0; i < DIGITS; i++)
        for(j = 0; j < BRIGHT_STEPS; j++)
          if(display_state.change_effect_flags & (1 << i)){
            if(j < display_state.change_effect_step){
              display_buffer_raw[i][j] = ' ';
            }
            else{
              display_buffer_raw[i][j] = display_buffer_old[i];
            }
          }
          else{
            display_buffer_raw[i][j] = display_buffer[i];
          }
      steps = SEMI_SOFT_CHANGE_STEPS;
      step_duration = SOFT_CHANGE_STEP_DURATION;
      break;

    case SOFT_OFF_ON_CHANGE: //плавное погасание, плавное зажигание
      for(i = 0; i < DIGITS; i++)
        for(j = 0; j < BRIGHT_STEPS; j++)
          if(display_state.change_effect_flags & (1 << i)){
            if(j >= display_state.change_effect_step){
              display_buffer_raw[i][j] = display_buffer_old[i];
            }
            else if(j + SOFT_OFF_ON_CHANGE_STEPS - BRIGHT_STEPS + 1 < display_state.change_effect_step){
              display_buffer_raw[i][j] = display_buffer[i];
            }
            else{
              display_buffer_raw[i][j] = ' ';
            }
          }
          else{
            display_buffer_raw[i][j] = display_buffer[i];
          }
      steps = SOFT_OFF_ON_CHANGE_STEPS;
      step_duration = SOFT_OFF_ON_CHANGE_STEP_DURATION;
      break;

    case ROTATE_CHANGE: //смена с прокруткой, без каких-либо плавностей
      for(i = 0; i < DIGITS; i++)
        for(j = 0; j < BRIGHT_STEPS; j++)
          if(display_state.change_effect_flags & (1 << i)){
            display_buffer_raw[i][j] = (display_buffer_old[i] + display_state.change_effect_step) % 10;
          }
          else{
            display_buffer_raw[i][j] = display_buffer[i];
          }
      steps = ROTATE_CHANGE_STEPS;
      step_duration = ROTATE_CHANGE_STEP_DURATION;
      break;

    default:
      break;
    }

    //по истечении интервала времени - следующий шаг смены цифр
    if(soft_timer_finished(&display_change_effect_timer)){
      if(++display_state.change_effect_step == steps + 1){
        display_state.change_effect_step = 0;
        for(i = 0; i < DIGITS; i++)
          display_buffer_old[i] = display_buffer[i];
        display_state.change_effect_flags = 0;
      }
      else{
        soft_timer_start(&display_change_effect_timer, step_duration); //перезапуск программного таймера
      }
    }
  }
}


Тут нет определения некоторых переменных и структур, а также присутствует много макросов типа SET_PORT(). Также тут нет кода, определяющего факт смены цифр, устанавливающего биты в display_state.change_effect_flags и запускающего цикл смены. Надеюсь, без этого всего принцип всё равно будет понятен.

_________________
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 18:49:47 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 139
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1478
Рейтинг сообщения: 0
Как то так.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 18:52:39 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 33
Зарегистрирован: Чт ноя 08, 2012 22:28:05
Сообщений: 794
Откуда: Ижевск
Рейтинг сообщения: 0
Попробую для себя главное выделить...

Спойлер
Код:

// Прерывание таймера 1 по совпадению, с чем? Он 16 битный... Можно ли использовать как у меня, таймер 2 по совпадению и гасить по переполнению?
ISR(TIMER1_COMPA_vect){
  uint8_t symbol;

  if(bright_step_counter >= BRIGHT_STEPS) // число градаций яркости? Если пробежали весь массив, то уходим из прерывания, почему так? Что будет если не уйти?
    return;

  symbol = display_buffer_raw[digit_counter][bright_step_counter]; // выбираем цифру из массива массивов цифр, так? Получается двумерный массив, в строках идут цифры, 16 значений, которые пишем в лампу?
  id1_output(symbol); // цифру в порт, так?

  if(symbol < 10){ // Если цифра от 0 до 10, то зажечь порт, если нет, не зажигать порт, верно?
    switch(digit_counter){
    case 0:
      SET_PORT(ANODE_0);
      break;
    case 1:
      SET_PORT(ANODE_1);
      break;
    case 2:
      SET_PORT(ANODE_2);
      break;
    case 3:
      SET_PORT(ANODE_3);
      break;
    }
  }
}

// Совпадение таймера со вторым значением?
ISR(TIMER1_COMPB_vect){

  // зачем это? Не пойму что делает этот кусочек,
  if(++bright_step_counter == BRIGHT_STEPS_WITH_SAFE_PAUSE){
    bright_step_counter = 0;
    digit_mask <<= 1;
    if(++digit_counter == DIGITS){
      digit_counter = 0;
      digit_mask = (1 << 0);
    }
  }

  // гасим все цифры? Но почему 4, в часах 4 лампы?
  CLR_PORT(ANODE_0);
  CLR_PORT(ANODE_1);
  CLR_PORT(ANODE_2);
  CLR_PORT(ANODE_3);
}


Вытянет ли 8 МГц все это? Проверять в железе смогу только завтра начать...

Где у вас происходит изменение bright_step_counter ?

if(++bright_step_counter == BRIGHT_STEPS_WITH_SAFE_PAUSE){

увидел, но весь смысл кусочка не понимаю пока


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 19:10:40 
Друг Кота
Аватар пользователя

Карма: 81
Рейтинг сообщений: 1377
Зарегистрирован: Пн май 11, 2009 14:15:00
Сообщений: 3059
Откуда: СПб
Рейтинг сообщения: 1
Медали: 1
Мявтор 3-й степени (1)
Таймер 16-битный, но используется в режиме Fast PWM, TOP = OCR1A. Это сделано для того, чтобы можно было произвольно менять частоту динамической индикации. По некоторым причинам в тех часах это было нужно.
Можно использовать 8-битный, но тоже в режиме Fast PWM (выходы OC** при этом включать не нужно). Этот режим хорош тем, что значения в регистрах сравнения буферизуются - новое значение загружается при переполнении таймера, поэтому не получится так, что в регистр сравнения записывается значение, меньшее, чем текущее значение в счётном регистре, и прерывания по совпадению не пропускаются. Первое прерывание в коде заменяется на прерывание по переполнению (тут зажигаем разряд), второе - по совпадению (тут всё гасим). Можно, конечно, и наоборот, но тогда при увеличении OCR яркость будет снижаться.

Вот это:
Код:
if(bright_step_counter >= BRIGHT_STEPS)
    return;

и это:
Код:
  if(++bright_step_counter == BRIGHT_STEPS_WITH_SAFE_PAUSE){
    bright_step_counter = 0;
    digit_mask <<= 1;
    if(++digit_counter == DIGITS){
      digit_counter = 0;
      digit_mask = (1 << 0);
    }
  }

служит для создания дополнительной паузы при переключении разрядов. Так пришлось сделать для подавления паразитной засветки. Для ВЛИ, думаю, это не актуально.
BRIGHT_STEPS_WITH_SAFE_PAUSE = BRIGHT_STEPS + 1. Поэтому в конце отображения каждого разряда, когда bright_step_counter == BRIGHT_STEPS, одно прерывание, где должен был бы зажечься разряд, пропускается (именно поэтому там return). Можно убрать первый кусочек и заменить во втором BRIGHT_STEPS_WITH_SAFE_PAUSE на BRIGHT_STEPS, тогда будет обычный алгоритм, который я описывал ранее.

Во втором кусочке инкрементируется текущая градация яркости, а когда все градации пройдены - номер разряда. На digit_mask не обращайте внимания, надо было мне её из кода убрать. Это переменная с "бегущей единицой", которая использовалась для десятичных точек и мигания разрядов.

Дальше Вы всё написали верно - выбираем цифру из массива, выводим в порт (в данном случае - на К155ИД1), зажигаем нужный разряд. Потом гасим. 4 цифры - для сокращения числа строк в примере. Можно и больше сделать. :)

На 8 МГц всё это прекрасно работает. Число градаций яркости было даже не 16, а 20. Частота переполнений таймера была 135 * 20 * 4 Гц. Это соответствует обычной динамической индикации, где частота импульсов на каждый разряд равна 135 Гц.

_________________
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 19:23:41 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 33
Зарегистрирован: Чт ноя 08, 2012 22:28:05
Сообщений: 794
Откуда: Ижевск
Рейтинг сообщения: 0
Вот накидал своё, так правильно будет? Не полезет ли косяков при изменении OCR2?

Как я думаю, 6я цифра должна гореть менее чем на пол яркости, цифра 10, переданная в print заставляет его гасить все сегменты.

Спойлер
Код:


#include <mega8.h>
#include <delay.h>

#include <show_num.h>

unsigned char a = 0;   

unsigned char digits [6][16] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
};
   
// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)                 

    switch (a) {                                             
            case 0: print (digits [0][t]);
                    PORTC.4 = 0;
                    break;
            case 1: print (digits [1][t]);
                    PORTC.3 = 0;
                    break;               
            case 2: print (digits [2][t]);
                    PORTC.0 = 0; 
                    break;
            case 3: print (digits [3][t]);
                    PORTC.1 = 0;
                    break;
            case 4: print (digits [4][t]);
                    PORTC.2 = 0;
                    break; 
            case 5: print (digits [5][t]);
                    PORTD.3 = 0;
                    break;
    }
    a++;   
    t++;
    if (t > 5) t = 0;
    if (a == 6) {a = 0;}                                       
}               

// Timer2 output compare interrupt service routine
interrupt [TIM2_COMP] void timer2_comp_isr(void)                   
{
    off_setki ();
    off_segments ();   
}


void main(void)
{
DDRB=0b11111111;
PORTB=0x00;

DDRC=0b11011111;
PORTC=0x00;

DDRD=0b11111011;
PORTD=0x00;


// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: Fast PWM top=0xFF
// OC2 output: Disconnected
// Timer Period: 0,256 ms
ASSR=0<<AS2;
TCCR2=(1<<PWM2) | (0<<COM21) | (0<<COM20) | (1<<CTC2) | (0<<CS22) | (1<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(1<<OCIE2) | (1<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);


#asm ("sei");

OCR2 = 250;

while (1)  {     

    }   
}



Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 19:30:21 
Друг Кота
Аватар пользователя

Карма: 81
Рейтинг сообщений: 1377
Зарегистрирован: Пн май 11, 2009 14:15:00
Сообщений: 3059
Откуда: СПб
Рейтинг сообщения: 1
Медали: 1
Мявтор 3-й степени (1)
Почти правильно. Нужно подправить инкремент a и t:
Код:
    t++;
    if (t > 15){
        t = 0;
        a++;
        if (a == 6)
            a = 0;
    }


print(), кстати, можно вынести за switch, используя a как индекс массива. Можно оставить, как сейчас, это, вроде бы, должно даже выполняться быстрее.

И учтите, что при OCR2 = 250 и предделителе таймера 8 на выполнение прерывания по совпадению есть всего 6 * 8 = 48 тактов.

Изменять OCR в режиме Fast PWM можно как угодно, но нужно следить, чтобы не было слишком больших и слишком маленьких значений. Иначе код в прерываниях не успеет выполниться, и следующее прерывание будет сдвинуто во времени.

_________________
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.


Последний раз редактировалось *Trigger* Ср авг 11, 2021 20:29:04, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 19:43:17 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 33
Зарегистрирован: Чт ноя 08, 2012 22:28:05
Сообщений: 794
Откуда: Ижевск
Рейтинг сообщения: 0
Если так сделать, мне кажется будет довольно сильно моргать с делителем 8... Вы таймер настраиваете без делителя? Или лучше действительно делать на таймере0 с двумя совпадениями и подбирать эти совпадения так, чтобы не слишком лагало и мерцало? Без делителя мне кажется, контроллер только и будет висеть в прерываниях постоянно )


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 19:48:12 
Друг Кота
Аватар пользователя

Карма: 81
Рейтинг сообщений: 1377
Зарегистрирован: Пн май 11, 2009 14:15:00
Сообщений: 3059
Откуда: СПб
Рейтинг сообщения: 1
Медали: 1
Мявтор 3-й степени (1)
А если так не делать, то получается что-то странное вместо нормального алгоритма. Хотя, можете попробовать. Даже интересно, что получится.

В том варианте, который предложил я, частота импульсов на каждый разряд (в терминах обычной динамической индикации) будет 8 000 000 / 8 / 256 / 6 / 16 = 40,7 Гц. Я мерцание с такой частотой вижу, но это всё индивидуально. В телевидении 25 Гц, и никто не жалуется. :)

Собственно, это была одна из причин, по которой я использовал таймер с двумя каналами совпадения.

Без делителя будет трудно уложить прерывания в ограниченное время выполнения.

_________________
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 11, 2021 19:52:12 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 33
Зарегистрирован: Чт ноя 08, 2012 22:28:05
Сообщений: 794
Откуда: Ижевск
Рейтинг сообщения: 1
Что то похожее я уже делал и тут не то чтобы мерцало как телевизор... Там скорее 5-6 Гц частота была )) что весьма печалило, однако это уже кое что новое, чем делал я.

Большое спасибо за помощь и подсказки, в ближайшее время доберусь до собранных часов и попробую, а то уже очень много времени этот процесс с места не двигается, а все мои личные попытки провальны (
---

Проверил в железе... и все работает, сколько возился с этим, даже не предполагал что все на столько просто, капец...
---

К сожалению на частоте 8 МГц при делителе 1000 8 ощутимо мерцает, без делителя все адски лагает, так как постоянно висит в прерывании. Буду либо таймером0 делать, либо ставить кварц )


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Пн авг 23, 2021 21:29:53 
Говорящий с текстолитом
Аватар пользователя

Карма: 33
Рейтинг сообщений: 148
Зарегистрирован: Вс июн 24, 2012 16:07:00
Сообщений: 1588
Откуда: Лен.Обл.
Рейтинг сообщения: 0
Я делал просто - использовал BAM-модуляцию. Хранится текущая цифра и следующая. Дальше при выводе на единичный бит значения счётчика выводится одна цифра, а на нолик другая. Когда счётчик досчитал, одна цифра заменяется на другую.

Вложение:
IN12Clock V6 (with thermo).zip [724.96 KiB]
Скачиваний: 91


Код:
volatile uint8_t Digit[4]={0,0,0,0};//текущие отображаемые цифры
volatile uint8_t NewDigit[4]={0,0,0,0};//новые отображаемые цифры
volatile uint8_t ChangeDigitCounter[4]={0,0,0,0};//счётчик перехода от старых к новым цифрам

//----------
//обработчик вектора прерывания таймера T0 (8-ми разрядный таймер) по переполнению
//----------
ISR(TIMER0_OVF_vect)
{
 //выполняем плавное зажигание/погасание цифр с импользованием BAM (binary amplitude modulation)
 static uint8_t weight=0;//вес разряда
 
 uint8_t mask=0;
 
 mask=(1<<weight);
 TCNT0=0xff-mask;
 weight++;
 if (weight==5) weight=0;
 
 uint8_t digit[4]={Digit[0],Digit[1],Digit[2],Digit[3]};
 static bool new_digit[4]={false,false,false,false};
 
 for(uint8_t n=0;n<4;n++)
 {
  if (ChangeDigitCounter[n]==0) Digit[n]=NewDigit[n];//цифра сменилась
  if (ChangeDigitCounter[n]&mask) new_digit[n]=false;
                             else new_digit[n]=true;
  if (new_digit[n]==true) digit[n]=NewDigit[n];
 }
 
 OUTPUT_OutputDigit(digit);
}





//----------
//обработчик вектора прерывания таймера T2 (8-ми разрядный таймер) по переполнению
//----------
ISR(TIMER2_OVF_vect)
{
 //таймер вызывается 122.0703125 раза в секунду

 TCNT2=0;
 KEYBOARD_Scan();
 SENSOR_DecrementEnabledDataCounter();
 
 static uint8_t tick=0;
 
 tick++;
 if (tick==122)//прошла секунда (примерно)
 {
  if (CathodeCleaningCounter>0) CathodeCleaningCounter--;
  tick=0;
 }
 
 if ((tick&0x01)!=0) return;
 
 for(uint8_t n=0;n<4;n++)
 {
  if (ChangeDigitCounter[n]>0) ChangeDigitCounter[n]--;
 }
}



Собственно, когда надо сменить цифры, делается так:

Код:
 for(uint8_t n=0;n<4;n++)
 {
  if (NewDigit[n]!=set_digit[n]) ChangeDigitCounter[n]=0x1f;
  NewDigit[n]=set_digit[n];
 }



Тут, правда, есть нюанс. У меня статическая индикация. И я не трачу МК на развёртку показаний.

_________________
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Ср авг 25, 2021 07:52:28 
Друг Кота
Аватар пользователя

Карма: 27
Рейтинг сообщений: 33
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Сообщений: 6296
Откуда: Ukraine
Рейтинг сообщения: 0
Kotto, вопрос еще актуален ?
сам алгоритм плавной смены вы понимаете ?

_________________
Tell Me The Truth


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Пн авг 30, 2021 07:13:15 
Опытный кот
Аватар пользователя

Карма: 8
Рейтинг сообщений: 33
Зарегистрирован: Чт ноя 08, 2012 22:28:05
Сообщений: 794
Откуда: Ижевск
Рейтинг сообщения: 0
FreshMan, простите за долгий ответ, был в отпуске. По алгоритму триггера получилось вроде, но вот прямо конкретно реализовать алгоритм полностью с заполнением массива еще не делал, сегодня завтра начну. В целом, на 8 МГц мерцание заметно, если вблизи находиться, но если чуть отойти, то уже не особо.

Сам алгоритм вроде понял, а вот БАМ я когда то пытался осилить для управления ргб светодиодами, теми, что не ws2812, раз сто статьи по ней прочитал, так и не дошло (


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Пн авг 30, 2021 09:26:54 
Опытный кот
Аватар пользователя

Карма: -14
Рейтинг сообщений: -98
Зарегистрирован: Ср дек 01, 2010 00:38:15
Сообщений: 882
Откуда: Харьков
Рейтинг сообщения: 0
глядя на такой чудо-код:
Спойлер
da-nie писал(а):
ISR(TIMER0_OVF_vect)
{
 //выполняем плавное зажигание/погасание цифр с импользованием BAM (binary amplitude modulation)
 static uint8_t weight=0;//вес разряда
 
 uint8_t mask=0;
 
 mask=(1<<weight);
 TCNT0=0xff-mask;
 weight++;
 if (weight==5) weight=0;
 
 uint8_t digit[4]={Digit[0],Digit[1],Digit[2],Digit[3]};
 static bool new_digit[4]={false,false,false,false};
 
 for(uint8_t n=0;n<4;n++)
 {
  if (ChangeDigitCounter[n]==0) Digit[n]=NewDigit[n];//цифра сменилась
  if (ChangeDigitCounter[n]&mask) new_digit[n]=false;
                             else new_digit[n]=true;
  if (new_digit[n]==true) digit[n]=NewDigit[n];
 }
 
 OUTPUT_OutputDigit(digit);
}
руки так и тянутся...
Код:
ISR(TIMER0_OVF_vect) {
    //выполняем плавное зажигание/погасание цифр с импользованием BAM (binary amplitude modulation
    static uint8_t mask = 1;
    TCNT0 = 0xff - mask;
    mask <<= 1;
    if (mask == (<< 5)) mask = 1;

    uint8_t digind[4];

    for (uint8_t n = 0; n < 4; n++) {
        if (ChangeDigitCounter[n] == 0) Digit[n] = NewDigit[n]; //цифра сменилась
        digind[n] = (ChangeDigitCounter[n] & mask) ? Digit[n] : NewDigit[n];
    }

    OUTPUT_OutputDigit(digind);

_________________
ohmycode!
primuss3.com


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Программное изменение яркости вакуумно-люминисцентных ла
СообщениеДобавлено: Пн авг 30, 2021 09:54:28 
Друг Кота
Аватар пользователя

Карма: 27
Рейтинг сообщений: 33
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Сообщений: 6296
Откуда: Ukraine
Рейтинг сообщения: 1
Kotto, предлагаю вам реализовать более легкий , на мой взгляд, метод реализации регулировки яркости индикаторов на 2-м таймере атмеги8 с кварцем на 16МГц (не пожалейте на него денег :)) )
Изображение
алгоритм следующий:
- в прерыванию по сравнению мы зажигаем ту или иную лампу
- в преывании по переполнению гасятся все лампы

если данная информация вас заинтересовала, прошу лайкнуть и мы не спеша продолжим дальше наше увлекательное путешествие в удивительный мир знаний :tea:

_________________
Tell Me The Truth


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 36 ]  1,  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y