Генерация и чтение ШИМ-сигнала одновременно на Arduino Uno R3?

Приведенный ниже код должен генерировать сигнал ШИМ на цифровом выводе 3. Но знайте, я хочу проверить, работает ли он вообще. Я думал о методе запуска событий, таком как ISR. Но как-то не работает. Я предполагаю, что ISR должен иметь входной контакт, например, он будет работать, когда откуда-то будет поступать ШИМ-сигнал.

Возможно ли вообще сгенерировать ШИМ-сигнал и прочитать его, чтобы увидеть результаты на последовательном мониторе?

отредактированный код:

byte const PWM_PIN = 3;

volatile unsigned long pwm_value = 0;
volatile unsigned long prev_time = 0;

void setup() {
  pinMode(PWM_PIN, OUTPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(PWM_PIN), rising, RISING);
}

void loop() {
  digitalWrite(PWM_PIN, HIGH);
  delay(400);
  digitalWrite(PWM_PIN, LOW);
  delay(1600);
}

void rising() {
  attachInterrupt(digitalPinToInterrupt(PWM_PIN), falling, FALLING);
  prev_time = millis();
}

void falling() {
  attachInterrupt(digitalPinToInterrupt(PWM_PIN), rising, RISING);
  pwm_value = millis()-prev_time;
  Serial.println(pwm_value);
}

, 👍0

Обсуждение

подключите контакт к другому контакту и прочитайте другой контакт. то, что вы генерируете, не является PWM. вы не прикрепляете прерывание в настройке. использовать прерывание CHANGE, @Juraj

Если digitalWrite не работает для выходного контакта, вам больше не следует использовать эту плату Arduino. Вы создаете дополнительный код, который может содержать ошибки, чтобы протестировать что-то очень простое, поэтому более вероятно, что дополнительный код неверен. Разрешено выполнять цифровое чтение для выходного вывода, поэтому вы можете сделать вывод высоким и прочитать, если он действительно высокий. Но, пожалуйста, не делай этого. Если это не удается, то что-то еще очень неправильно. Когда вы присваиваете значение переменной (например, int i = 3 ;), как вы узнаете, что это работает? Вы хотите добавить дополнительные тесты, чтобы проверить, работают ли переменные?, @Jot

С вашим текущим кодом задержки настолько велики, что вы можете увидеть, как работает код, подключив светодиод к выходному контакту. Время включения 400 мс хорошо заметно на глаз. Хотя я бы не назвал этот медленный сигнал ШИМ., @chrisl

@Juraj Да, верно. Я пытался сделать это без Serial.println(); в loop(), а также добавил attachInterrupt в setup(). Я установил обе задержки на 1000 (должно быть в мс). Но значение pwm_value составляет всего 16984 микросекунды. ---> 16,9 мс, @Gamdschiee

Но это не имеет смысла, правильное pwm_value должно быть 1000000 мкс, верно?, @Gamdschiee

И подключение вывода pwm к другому выводу, который используется как прерванный, не имеет никакого значения., @Gamdschiee

Вы можете использовать подход из этого видео: https://www.youtube.com/watch?v=p-kCPR42EtU, @uhren


2 ответа


Лучший ответ:

1

Вы объявляете переменные prev_time и pwm_value как int, который имеет (на стандартном Arduino) 16 бит. Поскольку вы используете вариант со знаком, вы получаете диапазон значений от -32768 до 32767. Но micros() возвращает unsigned long, который имеет 4 байта (32 бита). ) и не подписан. С int есть только 32,767 мс (так как здесь это представляет микросекунды), не допуская переполнения переменной. Даже полный диапазон даст вам всего около 65 мс. Он просто не может содержать такое значение, как 1000000. Если вы присвоите это значение int, оно будет напрямую переполнено (что, я думаю, даст вам значение по модулю 2^16), эффективно теряя большие части информации. Вы не можете получить значимые результаты с этим в таком большом временном масштабе.

При измерении времени (с помощью millis() или micros()) вы всегда должны использовать unsigned long в качестве типа, чтобы предотвратить эти проблемы.


Помимо типа переменной, почему вы используете здесь micros()? Вы измеряете время сотнями миллисекунд, так почему бы не использовать millis()? Это позволит снизить значения.

,

Да! Теперь это работает. Я отредактировал код выше. Таким образом, вы можете прикрепить прерывание как к вводу, так и к выводу. Через @leoc7 я, вероятно, даже нашел более простой способ создания ШИМ-сигнала с помощью: https://playground.arduino.cc/code/timer1., @Gamdschiee

Если это работает сейчас, рассмотрите возможность принять ответ как правильный., @chrisl


0
  1. Вы генерируете неправильный ШИМ, так как Serial.println вносит задержку. Правильный способ генерации ШИМ — использовать функцию analogWrite.

  2. Вы не можете использовать функцию attachInterrupt для обнаружения нарастающего и спадающего фронта выходного контакта.

  3. Для обнаружения нарастающего и спадающего фронта сигнала ШИМ необходимо использовать прерывание по таймеру модуля ШИМ. Для этого вам нужно напрямую писать/читать регистры ATmega без использования библиотек Arduino. Какую версию Arduino вы используете?

,

1. есть delay(1200) и вы придираетесь к Serial println()? 3. что?, @Juraj

3. Я имею в виду прерывание по переполнению таймера, @leoc7

2. неверно. Ты можешь., @Edgar Bonet

@leoc7 Ардуино 1.8.8, @Gamdschiee

@Gamdschiee Извините, я имел в виду **модель** Arduino., @leoc7

@leoc7 Элегоо Уно R3, @Gamdschiee

@Gamdschiee Взгляните на это руководство по обнаружению нарастающего фронта с помощью прерывания переполнения таймера 1 https://playground.arduino.cc/code/timer1, @leoc7