Аварийное транспортное средство - сделайте два светодиода мигающими кнопками и звук пассивного звукового сигнала

Мой отец и я просто учимся использовать мой новый UNO.

Мы узнали, как заставить светодиоды мигать одним нажатием кнопки. Мы также узнали, как сделать пассивный звук зуммера одним нажатием кнопки и изменить тон, чтобы звучать как полицейская машина.

Мы только что узнали, что мы не можем запускать более одного цикла, поэтому мы дважды комбинировали код зуммера и код светодиода (для синих и красных светодиодов), и он работает ... но задержка на светодиодах разрушает звук зуммера. Мы можем что-то сделать?

Код ниже.

Спасибо!

Код:

int buzzerPin = 9;   //the number of the buzzer pin
int BlueLEDpin = 5;  //the number of the blue LED pin
int RedLEDpin = 7;   //the number of the Red LED pin  
float sinVal;        //Define a variable to save sine value for buzzer
int toneVal;         //Define a variable to save sound frequency for buzzer

void setup() {
  pinMode(buzzerPin, OUTPUT);//Set Buzzer pin to output mode
  pinMode(BlueLEDpin, OUTPUT);//Set Blue LED pin to output mode
  pinMode(RedLEDpin, OUTPUT);//Set Red LED pin to output mode
}

void loop() { 
    Buzzer(); 
    BlueLED();
    RedLED();

}

void Buzzer() {
  for (int x = 0; x < 360; x++) {      //X from 0 degree->360 degree
    sinVal = sin(x * (PI/180));      //Calculate the sine of x
    toneVal = 2000 + sinVal * 500;     //Calculate sound frequency according to the sine of x
    tone(buzzerPin, toneVal);          //Output sound frequency to buzzerPin
    delay(1);
  }

 }

  void BlueLED() {
  digitalWrite(5, HIGH);  //turn the LED on (HIGH is the voltage level)
  delay(1);             //wait for a second
  digitalWrite(5, LOW);   //turn the LED off by making the voltage LOW
  delay(1);             //wait for a second
}

void RedLED() {
  digitalWrite(7, HIGH);  //turn the LED on (HIGH is the voltage level)
  delay(1);             //wait for a second
  digitalWrite(7, LOW);   //turn the LED off by making the voltage LOW
  delay(1);             //wait for a second
}
3
Вау, спасибо. Сейчас мы очень гордимся.
добавлено автор Steve S, источник
+1 для красиво отформатированного кода ... дал бы вам другой, если бы мог, для хранения комментариев и кода отдельно ... код, который является радостью смотреть на
добавлено автор jsotola, источник

5 ответы

Ваша проблема заключается в задержке() в ваших вызовах BlueLED() и RedLED (). Чтобы получить больше «одновременных» действий, вам необходимо использовать таймерные прерывания для реализации этих задержек. Это намного сложнее концептуально, но правильный способ сделать это.

2
добавлено
Это была быстрая работа! Рад, что у тебя все получилось.
добавлено автор George Bailey, источник
Большое спасибо Харпер; это было очень полезно. Мы следовали вашим советам и только что решили! Благодаря!
добавлено автор Steve S, источник

Мы сделали это. Спасибо за помощь Харпер Шелби.

Мы объединили пример Blink Without Delay с нашим исходным кодом:

int buzzerPin = 9;   //the number of the buzzer pin
const int BlueLEDpin = 5;
const int RedLEDpin = 7;    
float sinVal;        //Define a variable to save sine value
int toneVal;         //Define a variable to save sound frequency
int BlueLEDState = LOW; 
int RedLEDState = HIGH; 
unsigned long previousMillisBlue= 0;
unsigned long previousMillisRed= 0;
const long interval = 200; 

void setup() {
  pinMode(buzzerPin, OUTPUT);//Set Buzzer pin to output mode
  pinMode(BlueLEDpin, OUTPUT);
  pinMode(RedLEDpin, OUTPUT);
}

void loop() {
    Buzzer(); 
    BlueLED();
    RedLED();

}

void Buzzer() {
  for (int x = 0; x < 360; x++) {      //X from 0 degree->360 degree
    sinVal = sin(x * (PI/180));      //Calculate the sine of x
    toneVal = 2000 + sinVal * 500;     //Calculate sound frequency according to the sine of x
    tone(buzzerPin, toneVal);          //Output sound frequency to buzzerPin
    delay(1);
  }

 }

  void BlueLED() {
  unsigned long currentMillisBlue = millis();

  if (currentMillisBlue - previousMillisBlue >= interval) {
    previousMillisBlue = currentMillisBlue;
    if (BlueLEDState == LOW) {
      BlueLEDState = HIGH;
    } else {
      BlueLEDState = LOW;
    }

    digitalWrite(BlueLEDpin, BlueLEDState);
  }

}

void RedLED() {
  unsigned long currentMillisRed = millis();

  if (currentMillisRed - previousMillisRed >= interval) {
    previousMillisRed = currentMillisRed;
    if (RedLEDState == LOW) {
      RedLEDState = HIGH;
    } else {
      RedLEDState = LOW;
    }

    digitalWrite(RedLEDpin, RedLEDState);
  }

}
2
добавлено

Во-первых, поздравляю! вы сделали свой первый шаг в очень полезный мир микроконтроллеров. Я преподаю робототехнику в местном университете, поэтому всегда приятно видеть, когда лампочка загорается, и люди начинают понимать.

Как упоминалось выше, мигание без кода задержки является хорошим началом. Хороший код также следует расширять, если позже вы захотите добавить еще один свет или 10, и именно здесь кодирование каждой строки может стать очень большим. Есть много других методов для выполнения такого рода задач, однако вы можете захотеть взглянуть на эту серию учебных пособий. Многозадачность с Arduino.

Преимущество подхода машинного подхода, используемого в этом примере, становится очень легким после изменения кода; если вы хотите, чтобы во время мигания больше мигающих индикаторов (например, огни рыцаря-рыцаря) или более сирены, его легче включить. Во втором коде коды void redLED() и void blueLED() содержат в основном одни и те же строки; вы можете сделать объект под названием «LED», а затем просто сделать столько случаев, сколько вам нужно, все работают на разных скоростях и разных контактах (пример на веб-сайте должен обеспечить это много). Зуммер может, вероятно, повторно использовать часть развертки сервопривода кода). Например, вы можете также использовать программу 4 разных типа сирены в качестве переключателя: case и по истечении прошедшего времени переключаться между ними.

Еще одним дополнительным методом будет включение оперативной системы реального времени. RTOS упрощает выполнение нескольких независимых задач. Каждый свет может быть по собственной задаче, а сирена - на третьей, и система будет поддерживать каждую работу эффективно одновременно. Этот подход тогда имеет преимущества, если вы хотите изменить время одного света; он меняется в одном месте, не опасаясь изменить весь код. Информацию о FreeRTOS на ардуине можно найти здесь . В нижней части страницы есть пример, включающий как Blink, так и аналоговые примеры чтения.

Это довольно сложные темы, но я думаю, что вы и ваш папа доберетесь туда. Еще раз поздравляю.

1
добавлено
Большое спасибо Натан! Мы рассмотрим это дальше, и ссылка на сайт, которую вы нам дали, выглядит великолепно.
добавлено автор Steve S, источник

Это, вероятно, немного продвинуто, но ...

Вы можете использовать базовый класс и указатели на производные классы LED и Buzzer, чтобы сократить вашу функцию цикла до цикла. Вы не наберете много на этом уровне, но по мере того, как вы добавляете больше объектов, таких как проблесковые фары и зеркальные фонари, возможно, даже доска для обратной стороны, вы сделаете жизнь проще для себя.

/*
Jacob & Dad’s Police Car light and sounds
*/

class BaseOutputObject
{
protected:
    int Pin;
public:
    BaseOutputObject(const int& pin)
        : Pin(pin)
    {
        pinMode(Pin, OUTPUT);
    }
    virtual void Update()
    {
    }
};

class FlashingLED : public BaseOutputObject
{
    long OnTime;
    long OffTime;
    int ledState;
    unsigned long previousMillis;
public:
    FlashingLED(const int& pin, const long& on, const long& off, const bool& startLow = true)
        : BaseOutputObject(pin)                    //Call base class constructor                      
        , OnTime(on)                           //Use initialisers rather than assignments 
        , OffTime(off)
        , ledState(startLow ? LOW : HIGH)
        , previousMillis(0)
    {
    }

    void Update()
    {
       //check to see if it's time to change the state of the LED
        const unsigned long currentMillis = millis();          //Make it const because it won't change within this call of the function.

        if (currentMillis - previousMillis >= OnTime)
        {
            ledState = (ledState == LOW ? HIGH : LOW); //Toggle the state.
            previousMillis = currentMillis; //Remember the time
            digitalWrite(Pin, ledState); //Update the actual LED
        }
    }
};

class Buzzer : public BaseOutputObject
{
    float SinValue;
    int ToneValue;
public:
    Buzzer(const int& pin)
        : BaseOutputObject(pin)
        , SinValue(0.0f)       //Always initialise variables, in case you change the code later.
        , ToneValue(0)
    {
    }

    void Update()
    {
        for (int x = 0; x < 360; x++)
        {
            SinValue = sin(x * (PI/180));
            ToneValue = 2000 + SinValue * 500;
            tone(Pin, ToneValue);
            delay(1);
        }
    }

};

// The objects could be declared dynamically, but thats not a great idea on embedded systems.
FlashingLED ledOne(5, 100, 400);
FlashingLED ledTwo(7, 100, 400);
Buzzer buzzer(9);
enum { LED_ONE, LED_TWO, BUZZER, MaxObjects };
// Have to have pointers to the objects to allow you to cast them down to the base objects.
BaseOutputObject* objects[MaxObjects] = {  &ledOne, &ledTwo, &buzzer};

void setup()
{
}

void loop()
{
    for (int index = 0; index < MaxObjects; ++index)
    {
        objects[index]->Update();
    }
}
0
добавлено

Мы сделали это лучше с указателем Натана.

Мы узнали, как сделать класс, но светодиоды вспыхнули вместе, и мы узнали, как сделать еще один класс (с Public и Void Update в классе - сначала поймали нас). Один класс начинается с состояния HIGH, а другой с состоянием LOW, поэтому светодиоды чередуются. Когда мы нажимаем все три кнопки, мы получаем двухтональный зуммер и чередующиеся светодиоды.

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

Вот код, который мы написали:

/*
  Jacob & Dad’s Police Car light and sounds
*/

int buzzerPin = 9;    
float sinVal;         
int toneVal;         

class FlashingLED_A
{
    int ledPin;     
    long OnTime;     
    long OffTime;    
    int ledState;                   
    unsigned long previousMillis;   
  public:
  FlashingLED_A(int pin, long on, long off)
  {
    ledPin = pin;
    pinMode(ledPin, OUTPUT);     
    OnTime = on;
    OffTime = off;
    ledState = LOW; 
    previousMillis = 0;
  }

 void Update()
  {
   //check to see if it's time to change the state of the LED
    unsigned long currentMillis = millis();

    if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
    {
        ledState = LOW; //Turn it off
      previousMillis = currentMillis; //Remember the time
      digitalWrite(ledPin, ledState); //Update the actual LED
    }
    else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
    {
      ledState = HIGH; //turn it on
      previousMillis = currentMillis;   
      digitalWrite(ledPin, ledState);     
    }
  }

};

class FlashingLED_B
{
    int ledPin;  
    long OnTime;    
    long OffTime;   
    int ledState;                   
    unsigned long previousMillis;   
  public:
  FlashingLED_B(int pin, long on, long off)
  {
    ledPin = pin;
    pinMode(ledPin, OUTPUT);     
    OnTime = on;
    OffTime = off;
    ledState = HIGH; 
    previousMillis = 0;
  }

 void Update()
  {
   //check to see if it's time to change the state of the LED
    unsigned long currentMillis = millis();

    if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
    {
        ledState = LOW; //Turn it off
      previousMillis = currentMillis; //Remember the time
      digitalWrite(ledPin, ledState); //Update the actual LED
    }
    else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
    {
      ledState = HIGH; //turn it on
      previousMillis = currentMillis;   
      digitalWrite(ledPin, ledState);    
    }
  }

};

FlashingLED_A led1(5, 100, 400);
FlashingLED_B led2(7, 100, 400);

void setup() {
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  Buzzer(); 
    led1.Update();
    led2.Update();
}

void Buzzer() {
  for (int x = 0; x < 360; x++) {      
    sinVal = sin(x * (PI/180));       
    toneVal = 2000 + sinVal * 500;    
    tone(buzzerPin, toneVal);          
    delay(1);
  }
 }
0
добавлено
Единственная разница между FlashingLED_A и FlashingLED_B фактом, что A начинает LOW и B запускает HIGH? Если это так, я бы добавил дополнительный параметр к конструктору класса и просто использовал один из классов.
добавлено автор Thomas Myron, источник