Помогите вычислить ширину импульса!

miboss
Offline
Зарегистрирован: 29.09.2015
Здравствуйте!
Не могу точно вычислить ширину.
Имеется Nano, с нее подается шим сигнал на Uno в радиусе 1000-2000 мкс с шагом 1 мкс.
Требуется точное считывание вплоть до 1 шага для продвижения действий дальше.
 
1. Пробовал через pulsein, 
плюсы: изменение по 1 шагу (1 мкс); 
минусы: даже при голом коде ширина ~ (995-1985), при наличии Serial порта и его загруженности ширина резко падает, в чем причина и откуда такая зависимость я пока не понимаю, так же само значение держится нестабильно и постоянно дергается.
 
Код с pulsein:
int pin = 2;
unsigned long duration;
void setup()
{
  pinMode(pin, INPUT);
}
void loop()
{
duration = pulseIn(pin, HIGH);
}

 

 
2. Через прерывания: 
плюсы: измеряется точно, почти нет помех, Serial порт не влияет, не мешает программе;
минусы: собственно главный, ради чего все и замышлялось, минимальный шаг = 4 мкс.
 
Код с прерыванием:
#define pin 2
volatile unsigned long ChannelIn;

void setup() {

  pinMode(pin, INPUT);
  attachInterrupt(digitalPinToInterrupt(pin), calcChannel, CHANGE);

}

void calcChannel()
{
  static unsigned long Start;

  if(digitalRead(pin))
  {
    Start = micros();  
  }
  else
  {
    ChannelIn = (unsigned long)(micros() - Start);
  }
}

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

 

 
3. Так же нашел нечто непонятное:
int pin = 2;
unsigned long duration;
unsigned long v1 = 0;
unsigned long v2 = 0;
unsigned long itog = 0;
void setup()
{
  pinMode(pin, INPUT);

}

void loop()
{
duration = pulseIn(pin, HIGH);
while (digitalRead(pin) == LOW);
v1 = micros();
while (digitalRead(pin) == HIGH);
v2 = micros();
itog = v2-v1;
}

 

Собственно "itog" показывает значения как и во 2 случае с прерываниями, вроде бы просто и отлично, но опять же минимальный шаг 4 мкс все перекрывает.
Самое непонятное, что работает только с "pulsein", без него выдает ахинею.
 
Сам новичок и буду рад любой помощи.
nik182
Offline
Зарегистрирован: 04.05.2015

Вы представляете что такое фронт импульса? Можете посчитать какой у вас? А посмотреть в реале? Это я к тому, что надо ставить реальные задачи. Что бы получить точность 1 микросекунду нужна схемотехника. Нужны правильные линии передачи и согласованные входные - выходные сопротивления. У вас всё это обеспечено? Если нет, то добится такой точности невозможно. С точки зрения програмирования, такую точность может обеспечить только режим захвата таймера. Не прерывание и не pulseIn.

miboss
Offline
Зарегистрирован: 29.09.2015

Так я же писал, что pulsein вроде как выдает точность в 1 мкс, но по неизвестным мне причинам жестко проседает.

Фронт импульса на подъем ~0.017 мкс, на спад ~ 0.018 мкс.

Расскажите, пожалуйста, поподробнее про режим захвата, первый раз слышу.

SLKH
Offline
Зарегистрирован: 17.08.2015

miboss пишет:

...........
2. Через прерывания: 
плюсы: измеряется точно, почти нет помех, Serial порт не влияет, не мешает программе;
минусы: собственно главный, ради чего все и замышлялось, минимальный шаг = 4 мкс.
 
Код с прерыванием:
#define pin 2
volatile unsigned long ChannelIn;

void setup() {

  pinMode(pin, INPUT);
  attachInterrupt(digitalPinToInterrupt(pin), calcChannel, CHANGE);

}

void calcChannel()
{
  static unsigned long Start;

  if(digitalRead(pin))
  {
    Start = micros();  
  }
  else
  {
    ChannelIn = (unsigned long)(micros() - Start);
  }
}

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

 

 
3. Так же нашел нечто непонятное:
int pin = 2;
unsigned long duration;
unsigned long v1 = 0;
unsigned long v2 = 0;
unsigned long itog = 0;
void setup()
{
  pinMode(pin, INPUT);

}

void loop()
{
duration = pulseIn(pin, HIGH);
while (digitalRead(pin) == LOW);
v1 = micros();
while (digitalRead(pin) == HIGH);
v2 = micros();
itog = v2-v1;
}

 

Собственно "itog" показывает значения как и во 2 случае с прерываниями, вроде бы просто и отлично, но опять же минимальный шаг 4 мкс все перекрывает.
Самое непонятное, что работает только с "pulsein", без него выдает ахинею.
 
Сам новичок и буду рад любой помощи.

Читаем букварь: "На 16MHz платах Ардуино (Duemilanove и Nano) функция micros() имеет разрешение 4 микросекунды (возвращаемое значение всегда кратно 4)."

Волшебник
Offline
Зарегистрирован: 22.12.2016
nik182
Offline
Зарегистрирован: 04.05.2015

Из мануала

20.9. Input Capture Unit
The Timer/Counter1 incorporates an Input Capture unit that can capture external events and give them a
time-stamp indicating time of occurrence. The external signal indicating an event, or multiple events, can
be applied via the ICP1 pin or alternatively, via the analog-comparator unit. The time-stamps can then be
used to calculate frequency, duty-cycle, and other features of the signal applied.