Не получается установить длительность импульса

Здравствуйте! Помогите разобраться. Мне на выходе нужен импульс с длительностью 2uS. В программе задаю 2uS, смотрю осликом там 5uS. Что я делаю не так. Сильно не пинайте, Только учусь. Спасибо.
"const int outputPin = 5; // Пин для выходного сигнала
const float Vavg = 1.5; // Среднее значение напряжения

void setup() {
pinMode(outputPin, OUTPUT); // Установка пина в режим вывода
}

void loop() {
digitalWrite(outputPin, HIGH); // Устанавливаем выходной пин в HIGH
delayMicroseconds(2); // Задержка в 2 микросекунды

digitalWrite(outputPin, LOW); // Устанавливаем выходной пин в LOW
delayMicroseconds(15); // Задержка в 15 микросекунд

delayMicroseconds(2000 / (55 * 2) - 17); // Рассчитываем и задаем задержку для достижения цикла в 18 микросекунд

// Повторяем цикл с указанной Duty+
for (int i = 0; i < 12; i++) {
digitalWrite(outputPin, HIGH);
delayMicroseconds(2);
digitalWrite(outputPin, LOW);
delayMicroseconds(2); // Изменяем задержку на 2 микросекунды
delayMicroseconds(2000 / (55 * 2) - 17);
}

// Повторяем цикл с указанной Duty-
for (int i = 0; i < 88; i++) {
digitalWrite(outputPin, HIGH);
delayMicroseconds(2);
digitalWrite(outputPin, LOW);
delayMicroseconds(2); // Изменяем задержку на 2 микросекунды
delayMicroseconds(2000 / (55 * 2) - 17);
}

// Рассчитываем и задаем задержку для достижения указанного среднего значения напряжения
int delayTime = (int)((Vavg / 5.0) * (2000 / (55 * 2) - 17));
delayMicroseconds(delayTime);
}
‘’’

Вы не так вставляете код. Почитайте что написано в пустом окне сообщения, до того, как Вы ставите туда свои нетленки. Это для Вас написано - зря игнорируете.

С чего? Почему Вас нельзя пинать за косяки?

Так и учитесь! Читайте, что Вам пишут! Или “чукча не читатель”?

Спасибо Евгений помогли)))

И все остальные также помогут. Вы, похоже, не поняли: до тех пор, пока Вы не вставите код как положено, его никто читать не будет.

Да ну? А что ж код не поправили? Обратный апостроф - это тот, который на букве ё, а не абы какой. И должно быть ровно три в начале и три в конце. А не как придется.

const float Vavg = 1.5; // Среднее значение напряжения

void setup() {
  pinMode(outputPin, OUTPUT); // Установка пина в режим вывода
}

void loop() {
  digitalWrite(outputPin, HIGH); // Устанавливаем выходной пин в HIGH
  delayMicroseconds(2); // Задержка в 2 микросекунды
  
  digitalWrite(outputPin, LOW); // Устанавливаем выходной пин в LOW
  delayMicroseconds(15); // Задержка в 15 микросекунд
  
  delayMicroseconds(2000 / (55 * 2) - 17); // Рассчитываем и задаем задержку для достижения цикла в 18 микросекунд
  
  // Повторяем цикл с указанной Duty+
  for (int i = 0; i < 12; i++) {
    digitalWrite(outputPin, HIGH);
    delayMicroseconds(2);
    digitalWrite(outputPin, LOW);
    delayMicroseconds(2); // Изменяем задержку на 2 микросекунды
    delayMicroseconds(2000 / (55 * 2) - 17);
  }
  
  // Повторяем цикл с указанной Duty-
  for (int i = 0; i < 88; i++) {
    digitalWrite(outputPin, HIGH);
    delayMicroseconds(2);
    digitalWrite(outputPin, LOW);
    delayMicroseconds(2); // Изменяем задержку на 2 микросекунды
    delayMicroseconds(2000 / (55 * 2) - 17);
  }
  
  // Рассчитываем и задаем задержку для достижения указанного среднего значения напряжения
  int delayTime = (int)((Vavg / 5.0) * (2000 / (55 * 2) - 17));
  delayMicroseconds(delayTime);
}```
Так

Для такой задержки скорее всего придется обратиться к аппаратным таймерам и управлением портов побитно напрямую.
Смотреть:

  • управление портами ардуино через регистры
  • arduino прерывания по таймеру

Не совсем так. В конце надо три апострофа отдельной строкой писать. Исправьте.

Вы о какой задержке говорите, у Вас их много. В строка 8-11 Или в строка 18-21? Или ещё где?

Может, раз уж такая беда возникла, оставить одну и отладить как следует? Тогда понятнее будет что и как искать.

const float Vavg = 1.5; // Среднее значение напряжения

void setup() {
  pinMode(outputPin, OUTPUT); // Установка пина в режим вывода
}

void loop() {
  digitalWrite(outputPin, HIGH); // Устанавливаем выходной пин в HIGH
  delayMicroseconds(2); // Задержка в 2 микросекунды
  
  digitalWrite(outputPin, LOW); // Устанавливаем выходной пин в LOW
  delayMicroseconds(15); // Задержка в 15 микросекунд
  
  delayMicroseconds(2000 / (55 * 2) - 17); // Рассчитываем и задаем задержку для достижения цикла в 18 микросекунд
  
  // Повторяем цикл с указанной Duty+
  for (int i = 0; i < 12; i++) {
    digitalWrite(outputPin, HIGH);
    delayMicroseconds(2);
    digitalWrite(outputPin, LOW);
    delayMicroseconds(2); // Изменяем задержку на 2 микросекунды
    delayMicroseconds(2000 / (55 * 2) - 17);
  }
  
  // Повторяем цикл с указанной Duty-
  for (int i = 0; i < 88; i++) {
    digitalWrite(outputPin, HIGH);
    delayMicroseconds(2);
    digitalWrite(outputPin, LOW);
    delayMicroseconds(2); // Изменяем задержку на 2 микросекунды
    delayMicroseconds(2000 / (55 * 2) - 17);
  }
  
  // Рассчитываем и задаем задержку для достижения указанного среднего значения напряжения
  int delayTime = (int)((Vavg / 5.0) * (2000 / (55 * 2) - 17));
  delayMicroseconds(delayTime);
}

Хорошо переделаю

А каково назначение этой задержки?
Что-то в коде куча странных операторов и комментариев, которые заставляют подозревать. что задержка - не самоцель.

Вы чего добиться “в целом” хотите? Может этого можно достичь и без точных микросекундных интервалов?

delayMicroseconds здесь не прокатит, т.к. у неё 4 мкс разрешение, а вот либовская _delay_us вполне.

Задача получить на выходе 5 пина прямоугольный импульс с частотой 50 килогерц, длительность 2 микросекунды .

Беда ещё и в том, что сам по себе delay может и точно отмеряет, но ещё и манипуляции выводом digitalWrite отнимают неприлично много времени.между установкой 0 и 1, возможно и без задержек проходит больше 2 мкс. Тогда операции PORTx в помощь.

Да, само собой. Обычно, пишу такие макросы:

#define WAIT              2             //PORTD!
#define DATA              3
#define IOR               4

#define in(x)             DDRD  &= ~(1<<(x))
#define out(x)            DDRD  |= 1<<(x)
#define on(x)             PORTD |= 1<<(x)
#define off(x)            PORTD &= ~(1<<(x))
#define pin(x)            (PIND & 1<<(x))

2 лайка

вообще-то это элементарно делается на хардварном таймере. Какова должна быть точность выдержки частоты и длины импульса?


Например, при частоте чипа 16 МГц (ардуино) для 8битного таймера берем прескалер 256 и длительность периода 204 - получаем ровно 50 Кгц
Задав регистр сравнения 20 - получим длительность импульса 1.96 uS

***** - расчет неверный

1 лайк

Нет, это delay такое разрешение.

Могу ошибаться, конечно. Но что то в голове склеротической отложилось.)
Во. Не поленился.)
“Функция delayMicroseconds
Данная функция является полным аналогом delay за исключением того, что единицы измерения у нее не миллисекунды, а микросекунды (в 1 секунде – 1000000 микросекунд). Максимальное значение будет 16383, что равно 16 миллисекундам. Разрешение равно 4, то есть число будет всегда кратно четырем.”
Хотя, “верить нельзя никому”.)

Исходному коду можно.

У неё начальная инициализация - 6 или 8 тактов процессора (6 если параметр - константа). Возврат занимает 4 такта. А сама она имеет разрешение - 4 такта процессора., т.е. для 16МГц - 1/4 микросекунды.

Вот она (я выбросил для других частот, оставил только 16МГц)

/* Delay for the given number of microseconds.  Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */
void delayMicroseconds(unsigned int us) {
	if (us <= 1) return; //  = 3 cycles, (4 when true)
	us <<= 2; // x4 us, = 4 cycles
	us -= 5; // = 2 cycles,

	__asm__ __volatile__ (
		"1: sbiw %0,1" "\n\t" // 2 cycles
		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
	);
	// return = 4 cycles
}

ОК. Отлично. Сам поленился посмотреть, а зато верю непонятно кому.(

Вы в курсе, что digitalWrite сам по себе выполняется порядка 5 мс?
Если хотите короче - только прямой работой с портами.

Вообще-то это (генерация периодического сигнала) совсем другая задача и решается она аппаратным таймером.

1 лайк