срезать каждый 20 импульс

RizONE
Offline
Зарегистрирован: 22.03.2018

Доброе

допустим на 13й пин приходит пакет из 50-ти импульсов частотой 3 кГц, нужно продублировать их на 14й пин, но убрав каждый 20й и 33й. Как их посчитать я понимаю, а вот как выводить соблюдая ту же входную частоту? в  голове только вариант типа

digitalWrite(14, HIGH);
delay(1000);
digitalWrite(14, LOW);
delay(1000);
 

но это не правильно

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Головоломка, однако. Интервал увеличится, а частота должна остаться прежней.

nik182
Offline
Зарегистрирован: 04.05.2015

А импульсы чистые? Дребезг на фронте есть? Если нет то какие проблемы - считываете  в цикле состояние ноги и проверяете изменилось или нет, если изменилось то считаете в отдельном счетчике количество изменений и выдаёте на выходную ногу тот же уровень что и на входной ноге кроме изменения номер 40 и 41 и 66 и 67.       

RizONE
Offline
Зарегистрирован: 22.03.2018

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

А почему читать в цикле, я думал лучше отрабатывать по прерыванию, нет? Так даже легче будет: пришел фронт импульса, делаешь сразу digitalWrite(14, HIGH); ждешь нужный тайминг и digitalWrite(14, LOW); и заного ловишь прерывание. Конечно нужно заранее подсчитать буду ли я попадать в нужный интервал по частоте импульсов...

У меня вопрос был больше в другом: есть ли какой другой вариант кроме записи в регистр хай и лоу для имитации импульсов на выходе?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Ловить в прерывании оба фронта и лишние пропускать ...

Писать напрямую а регистр без digitalWriye ...

rkit
Offline
Зарегистрирован: 23.11.2016

digitalWrite(14, digtalRead(13));

Например

ssss
Offline
Зарегистрирован: 01.07.2016

RizONE пишет:

Доброе

допустим на 13й пин приходит пакет из 50-ти импульсов частотой 3 кГц, нужно продублировать их на 14й пин, но убрав каждый 20й и 33й.

Да как два пальца... Берете СТМ32... любой копеечный... 030... к примеру... заводите сигнал на вход таймера... выход таймера настраиваете как OD... и соединяете его с входом таймера через резистор... Таймер настраиваете на старт по фронту на  входе... в режиме one pulse... период выставляете чуть больше чем "от первого входного импульса до 20го импульса... а длительность от "чуть раньше 20го импульса до чуть больше чем заканчивается 20й импульс"... т.е. по сути вы просто вырезаете 20й импульс... Т.к. в таймерах СТМ32 регистры имеют пребуфер... то можно уже во время вырезания 20го импульса загнать данные для выррезания 33го импульса... Заюзав другой таймер как таймаут... получаете полухардварное решение... Добавив ДМА... получите полностю хардварное решение... МК будет полностью свободен... для решения других задач...

RizONE
Offline
Зарегистрирован: 22.03.2018

спасибо за идеи! завтра буду пробовать.

RizONE
Offline
Зарегистрирован: 22.03.2018
const int ReadPin = 2;
const int OutPin =  3;
volatile int buttonState = 0;
int counter = 0;


void setup() {
  pinMode(OutPin, OUTPUT);
  pinMode(ReadPin, INPUT);
  attachInterrupt(0, pin_ISR, CHANGE);
}

void loop() {
  // put your main code here, to run repeatedly:

}

void pin_ISR() {
  buttonState = digitalRead(ReadPin);
  if (counter > 50) counter = 0;
  if (counter != 20 && counter != 33) {
    digitalWrite(OutPin, buttonState);
  }
  if (buttonState == HIGH) counter ++;
}

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

RizONE пишет:

const int ReadPin = 2;
const int OutPin =  3;
volatile int buttonState = 0;
int counter = 0;


void setup() {
  pinMode(OutPin, OUTPUT);
  pinMode(ReadPin, INPUT);
  attachInterrupt(0, pin_ISR, CHANGE);
}

void loop() {
  // put your main code here, to run repeatedly:

}

void pin_ISR() {
  buttonState = digitalRead(ReadPin);
  if (counter > 50) counter = 0;
  if (counter != 20 && counter != 33) {
    digitalWrite(OutPin, buttonState);
  }
  if (buttonState == HIGH) counter ++;
}

 

Очень достойно, хотя нет - надо использовать оператор ИЛИ в строке 21. Не, дурак - все правильно.

Опять нет - не выходит циклического вызова подпрограммы pin_ISR(). В луп ее надо

b707
Offline
Зарегистрирован: 26.05.2017

RizONE - у вас прерывание по изменению, оно будет срабатывать дважды на каждый импульс, и соответственно 20-й по счетчику сигнал - это только десятый импульс

и еще - проверьте, все ли вы описали как volatile, что меняется в прерывании

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

b707 пишет:

RizONE - у вас прерывание по изменению, оно будет срабатывать дважды на каждый импульс, и соответственно 20-й по счетчику сигнал - это только десятый импульс

и еще - проверьте, все ли вы описали как volatile, что меняется в прерывании

А нахера прерывания на килогерцы? А если надо очень быстро - то считывайте из портов. Без разной херни типа проверок.

RizONE
Offline
Зарегистрирован: 22.03.2018

mykaida пишет:

Опять нет - не выходит циклического вызова подпрограммы pin_ISR(). В луп ее надо

почему? При каждом изменении хай/лоу будет срабатывать подпрограмма

mykaida]</p> <p>[quote=b707 пишет:

RizONE - у вас прерывание по изменению, оно будет срабатывать дважды на каждый импульс, и соответственно 20-й по счетчику сигнал - это только десятый импульс

и еще - проверьте, все ли вы описали как volatile, что меняется в прерывании

почему? у меня ж там счетчик меняется только при приходе хай т.е. на импульс один раз. Хотя ISR срабатывает дважды

RizONE
Offline
Зарегистрирован: 22.03.2018

mykaida пишет:

А нахера прерывания на килогерцы? А если надо очень быстро - то считывайте из портов. Без разной херни типа проверок.

да я точно частоту входящих импульсов не знаю...

b707
Offline
Зарегистрирован: 26.05.2017

RizONE пишет:

почему? у меня ж там счетчик меняется только при приходе хай т.е. на импульс один раз. Хотя ISR срабатывает дважды

да, сорри.

а счетчик все же стоит сделать волатильным...

RizONE
Offline
Зарегистрирован: 22.03.2018

Если кто знает хороший мануал про работу с прерываниями через

EIMSK  =  (1<<INT0));
EICRA  =  (1<<ISC01) | (1<<ISC00) | (1<<ISC11) | (0<<ISC10);

был бы благодарен, а то поиск заводит вообще в непонятные дебри

RizONE
Offline
Зарегистрирован: 22.03.2018

b707 пишет:

а счетчик все же стоит сделать волатильным...

Ок

b707
Offline
Зарегистрирован: 26.05.2017

RizONE пишет:

Если кто знает хороший мануал про работу с прерываниями через

лучший мануал - это даташит контроллера

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

digital read / write внутри прерывания - жуткая жуть

RizONE
Offline
Зарегистрирован: 22.03.2018

Komandir пишет:

digital read / write внутри прерывания - жуткая жуть

как будет правильнее подскажите или пример кода покажите

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
Kakmyc
Offline
Зарегистрирован: 15.01.2018

Счётчик частоты и скважности ШИМ тут есть в темах.
Ищущий, да обрящет.
Останется только пересчитать и вывести их с учётом выбрасывания ненужных.

nik182
Offline
Зарегистрирован: 04.05.2015

Дело было вечером... Без прерываний получилось.

const int ReadPin = 2;
const int OutPin =  3;
int buttonState;
int counter = 0;
int oldState;

void setup() 
{
  pinMode(OutPin, OUTPUT);
  pinMode(ReadPin, INPUT);
  buttonState = oldState = digitalRead(ReadPin);
}

void loop()
{
  while (buttonState == oldState )  buttonState = digitalRead(ReadPin);
  if (!(counter == 40 || counter == 41 || counter == 66 || counter == 67)) digitalWrite(OutPin, buttonState);
  oldState = buttonState;
  counter++;
  if (counter > 67) counter=0;
}