Включить пьезоэмиттер на короткое время

Мне нужен короткий звуковой сигнал для каждой минуты перемены. Я написал отдельную функцию. Длительность сигнала должна составлять 50 мс, в остальное время эмиттер, подключенный к контакту А1, должен молчать.

Действительно рабочий скетч показан ниже:

uint32_t mysound; // Переменная для хранения времени (длительности звукового сигнала)
uint32_t myTimer1;
uint32_t t; //Время, которое всегда увеличивается
byte seconds; // Секунды
byte minutes; // Минуты
int k = 1;
void setup()
{
  DDRC = B00000010; // Установить вывод A1 в качестве выхода
  //      76543210
  Serial.begin(9600);
  myTimer1 = millis();
}

void loop()
{
  t = (millis() - myTimer1) / 1000; // Время в секундах
  seconds = t % 60; // при достижении 60 секунд он сбрасывается в ноль
  minutes = t / 60 % 60; // Отсчитывает минуты и падает до нуля при достижении 60 минут
  Serial.println(seconds);
  if (seconds == 0 && k)
  {
    sound();
  }
  if (seconds > 0) k = 1;
}

void sound()
{
  mysound = millis();
  while (millis() - mysound < 50)
  {
    PORTC = B00000010; // Устанавливаем высокое напряжение на вывод A1 на время 50 мс
  }
  k = 0;
  PORTC = B00000000;
}

, 👍1

Обсуждение

`не работает " - это бессмысленное описание того, что вы наблюдали ... пожалуйста, опишите, что происходит ... кроме того, опишите, какие тесты вы провели, чтобы убедиться, что пьезоэмиттер работает, @jsotola

издает ли пьезо звук с высоким штифтом?, @Juraj

Да, если просто поднять штифт на высокий уровень, то пьезоэмиттер подаст звуковой сигнал, @Антон

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

Я предполагаю, что вы используете atmega328 или atmega2560 при использовании register PORTC вместо digitalWrite() для общей платы arduino. Вы пытаетесь избежать использования TIM1 или TIM2? И поэтому, возможно, есть причина избегать использования delay (). Так что попробуйте этот однострочный код >>>> if ((millis() % 60000) < 50) PORTC |= 0x02; else PORTC &= ~0x02;, @SimonVu14


2 ответа


4

Ваш myTimer1 в t = (millis() - myTimer1) / 1000; не установлен

,

3

В дополнение к ответу Qareke у вас также есть проблема с переменной mysound. Вы устанавливаете эту метку времени только в millis() внутри вашего оператора millis() if. mysound является глобальным и поэтому будет неявно инициализирован нулем. Таким образом, к тому времени, когда код достигает оператора if, разница между millis() и mysound, скорее всего, уже слишком велика, поэтому метка времени никогда не устанавливается.

Решение: Вам нужно переместить 2 строки в вашем коде:

  • Переместите оператор mysound = millis(); вверх в оператор if (seconds == 0).
  • Переместите оператор sound(); за пределы оператора if непосредственно в функцию void loop () (например, непосредственно после оператора if (seconds == 0)).

Теперь функция sound() будет выполняться всегда, но она будет издавать звук только в том случае, если ранее метка времени была установлена на millis (), а затем только на 50 мс. Теперь нам нужно только убедиться, что переменная метки времени mysound будет установлена только один раз, когда секунды станут равными нулю. Вы можете либо ввести новую переменную флага для этого, либо просто использовать саму метку времени и проверить, не прошло ли более 1 секунды с момента последней установки метки времени. Так что вам нужно измениться

if (seconds == 0)

Для

if (seconds == 0 && millis() - mysound > 1100)

Я использовал 1100 (1.1 s) здесь, чтобы убедиться, что нет плохого краевого случая. Поскольку секунды будут равняться нулю каждую минуту, это не должно быть проблемой.

,

Извините, но я не понял, как можно вывести вызов функции из состояния. Тогда что же остается внутри этого условия? Я исправил программу сверху, в таком виде писк начинается, но никогда не прекращается, @Антон

Если вы внимательно прочитаете мой ответ, то увидите, что я велел вам переместить оператор mysound = millis(); внутрь этого оператора if. Но вы все равно поместили его внутрь функции sound (). Кроме того, вы решили использовать переменную флага (вместо предлагаемого решения millis ()). Значит, вы не воспользовались моим решением этой проблемы. Тем не менее, ваш текущий код отлично работает для меня. У меня нет пьезо под рукой, но мой логический анализатор показывает положительный импульс длиной 50 мс каждую минуту. Если это не работает для вас, вероятно, что-то не так с вашей проводкой, @chrisl