Пакет импульсов на Timer2

dm128
Offline
Зарегистрирован: 10.08.2018

Имеем: Pro Mini 3,3 8МГц
Задача получать на выходе пакеты импульсов в противофазе на двух ногах. N импульсов выдали, пауза на M импульсов.

Подходит только таймер2, т.к есть регистр принудительной установки выходов FOC.

Пишем код

//Пример Timer2 импульсы пакетом по 3 через 9 пропусков
int period_count = 0;

void setup() {
  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  timer2_init();
}

void timer2_init() { // Запуск таймера
  cli();
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
  TCCR2A = (0 << COM2A1) | (1 << COM2A0) | (0 << COM2B1) | (1 << COM2B0) | 0        | 0        | (1 << WGM21) | (0 << WGM20);
  TCCR2B = (0 << FOC2A ) | (1 << FOC2B ) | 0         | 0         | (0 << WGM22) | (0 << CS22 ) | (1 << CS21 ) | (1 << CS20 );
  OCR2A = 50;
  OCR2B = 50;
  TIMSK2 = 1 << OCIE2A;
  sei();
}

ISR(TIMER2_COMPA_vect) {
  cli();
  if (period_count == 3) {   //  Отключаем ноги
    TCCR2A = (0 << COM2A1) | (0 << COM2A0) | (0 << COM2B1) | (0 << COM2B0) | 0        | 0        | (1 << WGM21) | (0 << WGM20);
  }
  else if (period_count ==  12) { //  Подключаем ноги
    TCCR2A = (0 << COM2A1) | (1 << COM2A0) | (0 << COM2B1) | (1 << COM2B0) | 0        | 0        | (1 << WGM21) | (0 << WGM20);
    period_count = 0;
  }
  period_count++;
  sei();
}

void loop() {
}

На выходе получаем искомый результат, в данном примере для простоты три импульса прошли, ноги отключились, пока 9 холостых не пройдет и на счетчике 12 ноги включаются обратно.

Вопрос1: после отключения ног, если она была в нуле, появляется выброс на несколько мкс. Почему?

Вопрос2: если прошивать не как 3.3 а 5 В, появляется выброс до следующего прерывания. Чудо?

 

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

dm128, вы в курсе, что команда типа:   регистр = (0 << имя бита);    и   | 0     не имеет никакого смысла? Они конечно не мешают, но  из-за цепочки таких команд код становится длиннее и хуже читаем. Короче приходится напрягать глаза, что бы среди бесполезных нулей увидеть где вы там единички прописали. Предлагаю сначала окультурить код :)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тут не согласен. Зато так видно назначение всех флагов. На код все равно не влияет, но мне, например, так читать легче.

В смысле, когда все нули и единицы прописаны, а не только единицы.

================

ЗЫ: 2ТС: подтяни к земле свои выходы резистором. Это не "чудо", это просто выход контроллера ;).

=====================

ЗЗЫ: ДимаХ! У ТС режим СТС (010) и оба выхода в тогль режиме.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Ну тогда программа работает именно так, как написана :) -Таймер поднимает свою аппаратную ногу, а потом в прерывании она резко опускается, отсюда выброс в несколько µS. Вывод -CTC mode не подходит.

dm128
Offline
Зарегистрирован: 10.08.2018

В регистре приведены все значения, писать и читать проще.
Повторюсь, при прошивке того же чипа вместо 3В 8Мгц указываем 5В 16МГц и выброс длится целое прерывание. Почему такая разница?

К земле подтянуто на 11К

dimax пишет:

Ну тогда программа работает именно так, как написана :) -Таймер поднимает свою аппаратную ногу, а потом в прерывании она резко опускается, отсюда выброс в несколько µS. Вывод -CTC mode не подходит.

Если посмотреть в код, видно, что на третьем импульсе меняется режим таймера, его ноги перестанут быть подключенными на следующем прерывании.
Как с учетом этого факта можно воспринять ваш комментарий? Где видно, что нога резко опускается? Почему при прескалере даже много большем, b111 выброс появляется реже, не каждый импульс, но появляется?

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

dm128, вот вам эти строчки читать проще, а мне тяжелее. Вы же написали этот код не для себя , а  для тех, кто будет читать ваш пост. Нужно уважать желание людей, которые вам отвечают. Можно было сделать вариант без нолей.

Мой ответ очень прост, т.к. основан на том, что в данном режиме прерывание совершается уже после того, как произошло изменение состояния аппаратной ноги, а не перед этим. Поэтому  вы видете выброс в момент отключения бит управления ногой. Надеюсь это достаточно понятно. Самый простой способ обойти эту проблему -дёргать ногами программно, в прерывании. Более трудный -попробовать осуществить всё тоже самое в другом режиме таймера.

dm128
Offline
Зарегистрирован: 10.08.2018

//Пример Timer2 импульсы пакетом по 3 через 9 пропусков
int period_count = 0;

void setup() {
  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  timer2_init();
}

void timer2_init() { // Запуск таймера
  cli();
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
  TCCR2A = ((1 << COM2A0) | (1 << COM2B0)  | (1 << WGM21) );
  TCCR2B = ( (1 << FOC2B )  | (1 << CS22 ) | (1 << CS21 ) | (1 << CS20 );
  OCR2A = 50;
  OCR2B = 50;
  TIMSK2 = 1 << OCIE2A;
  sei();
}

ISR(TIMER2_COMPA_vect) {
  cli();
  if (period_count == 3) {   //  Отключаем ноги
    TCCR2A = ( (1 << WGM21));
  }
  else if (period_count ==  12) { //  Подключаем ноги
    TCCR2A = ((1 << COM2A0) | (1 << COM2B0) | (1 << WGM21));
    period_count = 0;
  }
  period_count++;
  sei();
}

void loop() {
}

Здесь именно нюанс в изменении состояний флагов регистра. Приведенные значения расположенны в том порядке, что описаны в даташите.
В таком виде сложнее понять, что произошло. Но не вопрос.

dm128
Offline
Зарегистрирован: 10.08.2018

Программно - виден джиттер, не подходит. Пробовал прямым управлением портом регистра.
Выброс виден в 4 импульсе, после прерывания.
Прерывание  не идет после изменения состояния ног - оно формируется совпадением счетчика с регистром и этот сигнал на waveform генератор идет. Ладно, прерывание могло застрять в своей схеме...

Пробовал делать ноги через Clear OC2A/B on Compare Match, не помогло. Как и принудительное задание FOC в ноль.

В последнем примере праскалер в 111, на Нано тоже видны выбросы, просто реже. Если есть логика, то она должа быть в каждом импульсе.
А теперь представим, что мы останавливаем шаговый двигатель и с некоторой вероятностью проходит левый импульс.

Как в принципе останавливают таймер, чтоб его ноги ушли в нули, чтоб с Н-моста снять напряжение в нагрузке?
Пусть это не СТС, а шим, возможно проблема и там есть. Если это не СТС режим, шим не позволяет менять период и управлять FOC.
Первый таймер занят, можно не рассматривать.
Какие остались варианты?

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

dm128, к сожалению не распологаю временем для глубокого погружения в тему. Думаю стоит попытаться развить программный вариант, джиттер будет в любом случае, но можно его попробовать минимизировать до приемлемого уровня.  Ещё можно решить вопрос внешней логикой, тут вообще огромный простор для фантазии. Можно генерить только один канал, а второй канал сделать инверсией первого. И из прерывания подавать сигнал разрешения/запрещения на дополнительную логику, которая будет корректно всем управлять. И наконец можно взять stm32, с гораздо более широкими возможностями настройки таймеров.

dm128
Offline
Зарегистрирован: 10.08.2018

Варианты всегда есть. Фильтром и порогом убрал импульс. И уже на стм пошел.
Если это аппаратный баг, можно сколь угодно долго лечить 3д принтеры и cnc, собранные на 328 чипе.

Arhat109-2
Онлайн
Зарегистрирован: 24.09.2015

А если не только отключать ноги от таймера, но ещё и дергать их ручками в 0, прямо таже, сразу в прерывании?

dm128
Offline
Зарегистрирован: 10.08.2018

Тогда это будет начало 4 импульса, можно добавить иф на первую позицию. Но что-то мне говорит, что пока первые команды обработают мы, ноги закрывать будет поздно.

Arhat109-2
Онлайн
Зарегистрирован: 24.09.2015

Я честно говоря не очень понял о каком джиттере идет речь .. дело в том, что даташита на 328-ю у меня нет, а в даташите на 2560 практически прямо как у Вас указано, что "типа так надо делать" .. исправлено? Какие-нибудь errata на эту тему есть, искали?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ТС, уважаемый! Ты меня прости, но ты как-то странно кодишь.

Ты поставил прескелер в 32 и считаешь до 50. Имеем 8000КГц/32/50 = 5КГц.

То есть ты генеришь тоггль на 5 КГц, следовательно сама частота - 2500Гц. И тебе чего-то не хватает, Джиттер какой-то на такой частоте ты находишь? время исполнения одной команды 125нс и это тебе как-то мешает на частоте 2500Гц?

Вызывай по прерыванию обрабортчик и одной командой выставляй ноги в противофазе. Одной командой (1 такт = 125 нс) - если на одном порту выберешь ноги.

------------------

Как вариант - напиши, что именно ты хочешь получить на осцилографе, я предложу тебе работающий вариант. Тот, что выбрал ты  - с использованием FOC, слишком вычурно, ИМХО.

И ты хорошо ли понимашь, что ты делаешь? У тебя режим тогль, то есть три прерывания - это ОДИН "импульс"  это 0-1-0, потом 9 пропусков - 101010101, далее снова 010. То есть так должно быть в идеале, в соответствии с даташитом.

 

dm128
Offline
Зарегистрирован: 10.08.2018

Увы, с такого варианта я начал и были хорошо заметны отличия импульсов по ширине в пакете.
Команда может и 125 нс, но байт код на выходе со сравнением if получается, что влияет существенно. А прескейлер 32 обеспечивает нужный диапазон - 50 частный случай, плавает от 30 до 70.

Странно кодишь - отметаем, здесь и кода-то нет. Есть настройка таймера согласно даташиту и смена настроек таймера в прерывани, опять же по даташиту. И работает все по даташиту. Кроме одного но - не каждый раз возникают выбросы. Поэтому и пишу в аппаратную ветку.

Про хорошо ли я понимаю, что делаю даже смешно читать. Да, делаю что по даташиту, в соответствии с техзаданием; понимаю, что делаю и нахожусь в светлом уме и трезвой памяти. И поверь, с 80-х собрал много импульсных генераторов на всякой рассыпухе. С процами и без. pic взять или stm не вопрос, так и сделаю. 
Но глюк 328 чипа останется с вами.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

dm128, я же вам объяснил уже -нет тут никакого глюка ,  таймер поднимает ногу, вы её в прерывании резко опускаете -отсюда короткий импульс в пару микросекунд.  За прошедшие 3 дня можно было уже любой вариант решения реализовать, из тех, что я предлогал.

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

Попробовал их любопытства сделать программно - вообще никах проблем. Идеальные пачки.

 


void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
TCCR2A = (1 << WGM21) ;
TCCR2B =   (1 << CS22 ) | (1 << CS21 );
OCR2A = 50;
TIMSK2 = 1 << OCIE2A;
}

ISR(TIMER2_COMPA_vect) {
static uint8_t tic;
tic=(tic&15)+1;
  switch(tic){
    case 1: PORTD&= ~((1<<PD3)|(1<<PD4));break;
    case 8:  PORTD= PORTD&0xe7|8; break;
   default: if (tic>8){ PORTD^= (1<<PD3)|(1<<PD4);} 
  }

}

void loop() {}