Как запустить светодиод и зуммер одновременно?

Я делаю полицейский свет и сирену, но с задержкой на свет (); влияет на тон задержки зуммера

Это код:

//PIN 9 — Зуммеры
int f,d;
int t =0;

void setup()
{
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
}

void loop()
{      
    buzzer ();                                     

}

void buzzer () {

  for(f=635;f<=912;f++)
    {
        tone(9, f);
        delay(d);
        d=10;

        light ();
    }



    for(f=911;f>=634;f--)
    {

        light ();
        tone(9, f);
        delay(d);
            d=9;

    }

}


void light() {
 digitalWrite(5,HIGH);
  delay(t);
  digitalWrite(5,LOW);
  delay(t);

  digitalWrite(5,HIGH);
  delay(t);
  digitalWrite(5,LOW);
  delay(t);

  digitalWrite(5,HIGH);
  delay(t);
  digitalWrite(5,LOW);
  delay(t);

  digitalWrite(7,HIGH);
  delay(t);
  digitalWrite(7,LOW);
  delay(t);

  digitalWrite(7,HIGH);
  delay(t);
  digitalWrite(7,LOW);
  delay(t);

  digitalWrite(7,HIGH);
  delay(t);
  digitalWrite(7,LOW);
  delay(t);

  digitalWrite(5,HIGH);
  digitalWrite(6,HIGH);
  digitalWrite(7,HIGH);

  delay(t);

  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);

  delay(t);

  digitalWrite(5,HIGH);
  digitalWrite(6,HIGH);
  digitalWrite(7,HIGH);

  delay(t);

  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);

  delay(t);

  digitalWrite(5,HIGH);
  digitalWrite(6,HIGH);
  digitalWrite(7,HIGH);

  delay(t);

  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);

  delay(t);

  digitalWrite(5,HIGH);
  delay(t);
  digitalWrite(5,LOW);
  digitalWrite(7,HIGH);
  delay(t);
  digitalWrite(7,LOW);
  delay(t);

  digitalWrite(5,HIGH);
  delay(t);
  digitalWrite(5,LOW);
  digitalWrite(7,HIGH);
  delay(t);
  digitalWrite(7,LOW);
  delay(t);

  digitalWrite(5,HIGH);
  delay(t);
  digitalWrite(5,LOW);
  digitalWrite(7,HIGH);
  delay(t);
  digitalWrite(7,LOW);
  delay(t);

  digitalWrite(5,HIGH);
  delay(t);
  digitalWrite(5,LOW);
  digitalWrite(7,HIGH);
  delay(t);
  digitalWrite(7,LOW);
  delay(t);


}

, 👍1

Обсуждение

Есть 2 способа. 1) Государственная машина. 2) Используйте оборудование PWM для создания звука зуммера. Я бы использовал оба. Комментарий, вам нужен более полный ответ., @st2000

Так как t=0, вы можете безопасно удалить строки delay(t) ;-) И почему вы установили d=10 после того, как использовали его. Не лучше ли было бы установить его перед циклом for? Вам нужно около 300 шагов, чтобы подметать вверх и ~ 300 шагов, чтобы подметать вниз, и для каждого шага вы позволяете светодиодам мерцать с узором, который ваши глаза недостаточно быстры, чтобы увидеть. Это действительно ваше намерение? Я ожидаю, что вам понравится видеть, как звуковые волны и светодиод мигают параллельно. Лучший способ добиться этого — удалить циклы for и делать все параллельно. Смотрите мой ответ., @Peter Paul Kiefer

@st2000, как ты хочешь сделать сирену с аппаратным ШИМ?, @Juraj

Мой плохой @Juraj, функция tone() уже используется. Таким образом, все, что нужно для этого вопроса, — это государственная проверка. Использование функции mills() — это шаг в правильном направлении, если уже не простой конечный автомат. Более общее решение конечного автомата может принести пользу OP, поскольку оно дает им основу для более сложных программных задач., @st2000


2 ответа


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

6

Следующий код не тестировался. Вы можете взять его в качестве примера. Если найдёте ошибки, было бы неплохо о них сообщить, чтобы я мог поправить свою прогу.

// здесь я просто предполагаю (10 мс), я думаю, вам не нужна задержка
// из 0, как в вашем коде.
int   blinkDelay        = 10;
long  lastBlinkTime     =  0;
int   patternSequence[] = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 2, 1, 2, 1, 2, 1, 2 };

int   patternSize     = 17;
int   actPattern      =  0;
int   delActive       = -1;

int  frequency     = 635;
int deltaFreq      =   1;
int  toneDelay     =  10;
long lastBuzzTime  =   0;


void setup()
{
  pinMode( 5, OUTPUT ) ;
  pinMode( 6, OUTPUT ) ;
  pinMode( 7, OUTPUT ) ;

  ledsOff();
  buzzer( frequency );
}

void loop()
{      
  int actTime = millis();

  if ( ( actTime - lastBlinkTime ) > blinkDelay )
  {
    if ( delActive > 0 )
    {
      ledsOff();
    }
    else
    {
      actPattern++;
      if( actPattern > ( patternSize - 1) ) actPattern = 0;   
      pattern( patternSequence[ actPattern ] );
    }
    delActive *= -1;

    lastBlinkTime = actTime;
  }

  if ( ( actTime - lastBuzzTime ) > toneDelay )
  {
    frequency += deltaFreq;

    if ( frequency > 911 ) deltaFreq = -1;
    if ( frequency < 636 ) deltaFreq = 1;

    buzzer( frequency );
    lastBuzzTime = actTime;
  }

}

void buzzer( int freq ) 
{
  //PIN 9 - Зуммер
  tone(9, freq);
}

void ledsOff()
{
  digitalWrite( 5, LOW );
  digitalWrite( 6, LOW );
  digitalWrite( 7, LOW );
}

void pattern( int num ) 
{
   switch ( num )
   {
      case 0:
        ledsOff();
        break;       

      case 1:
        digitalWrite( 5, HIGH );
        break;       

      case 2:
        digitalWrite( 7, HIGH );
        break;       

      case 3:
        digitalWrite( 5, HIGH );
        digitalWrite( 6, HIGH );
        digitalWrite( 7, HIGH );
        break;       
   }
}

Обновить

Я протестировал код дома на своем esplora. Работало, но не долго. Мне пришлось изменить логику синхронизации, используя метод millis() напрямую. Теперь это работает. Ниже приведен новый код; тестил на этот раз. Я также ввел некоторые константы сверху, потому что их имена действуют как документация ;-). И я экспериментировал со значениями. Фактические значения - это мои предпочтения, но я далеко не Бетховен и не могу сказать, действительно ли это звучит как полицейская сирена. По крайней мере, это звучит не как немецкая полицейская сирена, которую я знаю лучше. (Нет, я не полицейский и не его клиент ;-))

Поскольку я тестировал код на своей Esplora, мне пришлось изменить назначение пинов (теперь они не закомментированы). В этой копии я вернулся к исходным.

int   blinkDelay        = 100;
long  lastBlinkTime     =  0;
int   patternSequence[] = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 2, 1, 2, 1, 2, 1, 2 };

int   patternSize     = 17;
int   actPattern      =  0;
int   clearActive       = -1;

int  lowerFreq       = 680;
int  higherFreq      = 840;
int  deltaFreq       =   2;
int  toneDelay       =  20;
int  toneDelayOffset =  -1;
long lastBuzzTime    =   0;

int  actFreqStep   = deltaFreq;
int  actFreq       = lowerFreq;

// исходные контакты
int col1Pin   =  5;
int col2Pin   =  6;
int col3Pin   =  7;
int buzzerPin =  9;

// выводы исследования
// int col1Pin = 5;
// int col2Pin = 10;
// int col3Pin = 9;
// int buzzerPin = 6;

void setup()
{
  pinMode( col1Pin, OUTPUT ) ;
  pinMode( col2Pin, OUTPUT ) ;
  pinMode( col3Pin, OUTPUT ) ;

  // инициализируем выключение светодиодов
  ledsOff( );

  // и зуммер на частоту действия
  buzzer( actFreq );
}

void loop()
{      
  if ( ( millis() - lastBlinkTime ) > blinkDelay )
  {
    if ( clearActive > 0 ) 
    { 
      ledsOff(); 
    }
    else
    {
      actPattern++;
      if( actPattern > ( patternSize - 1) ) actPattern = 0;   
      pattern( patternSequence[ actPattern ] );
    }

    clearActive     *= -1;
    lastBlinkTime  = millis();
  }

  if ( ( millis() - lastBuzzTime ) > ( toneDelay + toneDelayOffset ) )
  {
    actFreq += actFreqStep;

    if ( actFreq >= higherFreq )
    {
      actFreqStep   = -1 * deltaFreq;

      // развертка вниз медленнее
      toneDelayOffset = -1;
    }

    if ( actFreq <= lowerFreq )
    {
      actFreqStep   =  deltaFreq;
      toneDelayOffset =  0;
    }

    buzzer( actFreq );
    lastBuzzTime = millis();
  }

}

void buzzer( int freq ) 
{
  tone( buzzerPin, freq );
}

void ledsOff()
{
  digitalWrite( col1Pin, LOW );
  digitalWrite( col2Pin, LOW );
  digitalWrite( col3Pin, LOW );
}

void pattern( int num ) 
{
   switch ( num )
   {
      case 0:
        ledsOff();
        break;       

      case 1:
        // красный
        digitalWrite( col1Pin, HIGH );
        break;       

      case 2:
        // синий
        digitalWrite( col3Pin, HIGH );
        break;       

      case 3:
        // белый
        digitalWrite( col1Pin, HIGH );
        digitalWrite( col2Pin, HIGH );
        digitalWrite( col3Pin, HIGH );
        break;       
   }
}
,

Это работает именно так, как я хочу, чтобы это произошло. Спасибо, @Nydigorith

Пожалуйста. Пожалуйста, не копируйте и не вставляйте прогу. Попытайтесь понять, почему и как это работает. Мир нуждается в более квалифицированных людях, и вы, кажется, интересуетесь этой темой. Я использовал некоторые вещи, которым научился за 25 лет работы разработчиком, и они могут быть сложными для новичка. Если какая-то часть кода неясна, пожалуйста, не стесняйтесь спрашивать меня здесь. Я был бы рад помочь вам понять и, возможно, вы найдете скрытую ошибку, которую я наблюдал., @Peter Paul Kiefer


3

Не используйте delay(). Вам нужно будет переписать свой скетч, чтобы использовать функцию millis(), чтобы определить, когда прошло желаемое количество времени. Найдите информацию в разделе «Arduino Blink Without Delay».

,