Notfallfahrzeug - Lassen Sie zwei LEDs mit Tasten blinken und ein passiver Summer ertönt

Mein Vater und ich lernen gerade, wie man meine neue UNO benutzt.

Wir haben gelernt, wie LEDs auf Knopfdruck blinken. Wir haben auch gelernt, auf Knopfdruck einen passiven Summer zu erzeugen und den Ton so zu verändern, dass er wie ein Polizeiauto klingt.

Wir haben gerade gelernt, dass wir nicht mehr als eine Schleife laufen können, also haben wir den Summercode und den LED-Code zweimal kombiniert (für blaue und rote LEDs) und es funktioniert ... aber die Verzögerung an den LEDs ruiniert den Summerton. Können wir irgendetwas tun?

Der Code ist unten.

Vielen Dank!

Code:

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
Wow, danke. Wir fühlen uns gerade sehr stolz.
hinzugefügt der Autor Steve S, Quelle
+1 für schön formatierten Code ... würde Ihnen einen anderen geben, wenn ich könnte, um Kommentare und Code getrennt zu halten ... Code, der Freude zu betrachten ist
hinzugefügt der Autor jsotola, Quelle

5 Antworten

Ihr Problem ist die Verzögerung() in Ihren BlueLED() - und RedLED() - Aufrufen. Um mehr "gleichzeitige" Aktivitäten zu erhalten, müssen Sie Timer-Interrupts verwenden, um diese Verzögerungen zu implementieren. Es ist konzeptionell viel komplexer, aber der richtige Weg dazu.

2
hinzugefügt
Das war schnelle Arbeit! Ich bin froh, dass du es geschafft hast.
hinzugefügt der Autor George Bailey, Quelle
Vielen Dank Harper; Das war sehr hilfreich. Wir sind Ihrem Rat gefolgt und haben ihn gerade gelöst !!! Vielen Dank!
hinzugefügt der Autor Steve S, Quelle

Wir haben es getan. Danke für die Hilfe Harper Shelby.

Wir haben das Blink Without Delay-Beispiel mit unserem ursprünglichen Code kombiniert:

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
hinzugefügt

Erstens, herzlichen Glückwunsch! Sie haben Ihren ersten Schritt in die sehr lohnende Welt der Mikrocontroller gemacht. Ich lehre Robotik an einer lokalen Universität, es ist also immer schön zu sehen, wann die Glühbirne weitergeht und die Leute anfangen zu verstehen.

Wie oben erwähnt, ist das Blinken ohne Verzögerungscode ein guter Anfang. Guter Code sollte auch erweiterbar sein, falls Sie später ein anderes Licht oder 10 hinzufügen möchten, und hier kann jede Zeile sehr groß werden. Es gibt viele andere Methoden, um diese Art von Aufgabe zu erledigen, aber Sie sollten sich diese Tutorials ansehen. Multitasking mit dem Arduino.

Der Vorteil des in diesem Beispiel verwendeten Zustandsautomaten ist, dass es später sehr einfach wird, Ihren Code zu ändern; Wenn Sie mehr Lichter in der Reihe blinken lassen möchten (wie die Ritter-Fahrer-Lichter) oder mehr Sirenen, wird es leichter, sie einzuschließen. In Ihrem zweiten Code enthalten die void-Codes redLED() und void blueLED() meistens dieselben Zeilen. Sie könnten ein Objekt mit der Bezeichnung "LED" erstellen und dann so viele Instanzen wie benötigt erzeugen, alle arbeiten mit unterschiedlichen Geschwindigkeiten und unterschiedlichen Pins (das Beispiel auf der Website sollte so viel bieten. Der Summer kann wahrscheinlich den Servo-Sweep-Teil wiederverwenden des Codes). Sie könnten beispielsweise auch 4 verschiedene Arten von Sirenen als Schalter programmieren: case und nach Ablauf der Zeit zwischen ihnen wechseln.

Eine weitere fortgeschrittene Methode wäre ein Echtzeit-Betriebssystem. Ein RTOS macht es sehr einfach, mehrere unabhängige Aufgaben auszuführen. Jedes Licht könnte auf seine eigene Aufgabe und die Sirene auf ein drittes gerichtet sein, und das System würde jeden gleichzeitig wirksam in Gang halten. Dieser Ansatz hat dann Vorteile, wenn Sie das Timing eines Lichts ändern möchten. Es ändert sich an einem Ort ohne Angst, den ganzen Code ändern zu müssen. Informationen zu FreeRTOS auf dem Arduino finden Sie hier . Unten auf der Seite finden Sie ein Beispiel, das sowohl Blink- als auch analoge Lesebeispiele enthält.

Das sind ziemlich fortgeschrittene Themen, aber ich denke, du und dein Vater werden dort ankommen. Noch einmal, herzlichen Glückwunsch.

1
hinzugefügt
Vielen Dank Nathan! Wir schauen uns das als nächstes an und der Link zur Website, den Sie uns gegeben haben, sieht gut aus.
hinzugefügt der Autor Steve S, Quelle

Dies ist wahrscheinlich ein bisschen fortgeschritten, aber ...

Sie könnten eine Basisklasse und Zeiger auf die abgeleiteten LED- und Buzzer-Klassen verwenden, um Ihre Schleifenfunktion auf eine Schleife zu reduzieren. Sie werden auf dieser Ebene nicht viel gewinnen, aber wenn Sie weitere Objekte hinzufügen, wie zum Beispiel die blinkenden Scheinwerfer und Spiegelleuchten, vielleicht sogar ein nach hinten gerichtetes Nachrichtenbrett, werden Sie das Leben für sich selbst leichter machen.

/*
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
hinzugefügt

Wir haben es mit Nathans Zeiger besser gemacht.

Wir haben gelernt, wie man eine Klasse baut, aber die LEDs blinken zusammen, so dass wir gelernt haben, wie man eine andere Klasse macht (mit Public und Void Update in der Klasse - hat uns zuerst diesen Teil entdeckt). Eine Klasse beginnt mit dem Status HIGH und die andere mit dem Status LOW, so dass sich die LEDs abwechseln. Wenn wir alle drei Tasten drücken, erhalten wir den Zwei-Ton-Summer und die alternierenden LEDs.

Mit dieser Methode können wir beliebig viele neue LEDs hinzufügen.

Hier ist der Code, den wir geschrieben haben:

/*
  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
hinzugefügt
Ist der einzige Unterschied zwischen FlashingLED_A und FlashingLED_B die Tatsache, dass A LOW startet und B HIGH startet? Wenn ja, würde ich einen zusätzlichen Parameter zum Klassenkonstruktor hinzufügen und einfach eine der Klassen verwenden.
hinzugefügt der Autor Thomas Myron, Quelle