Noodsituatievoertuig - Laat twee LED's knipperen met knoppen en een passief zoemerveranderend geluid

Mijn vader en ik leren gewoon hoe ik mijn nieuwe UNO moet gebruiken.

We hebben geleerd hoe leds met één druk op de knop kunnen knipperen. We hebben ook geleerd hoe je met één druk op de knop een passief zoemergeluid maakt en van toon verandert om als een politiewagen te klinken.

We hebben zojuist geleerd dat we niet meer dan één lus kunnen uitvoeren, dus we hebben de zoemercode en de LED-code twee keer gecombineerd (voor blauwe en rode LED's) en het werkt ... maar de vertraging op de LED's verpest het zoemergeluid. Kunnen we iets doen?

De code staat hieronder.

Dank je!

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
Wauw dankjewel. We zijn nu heel trots.
toegevoegd de auteur Steve S, de bron
+1 voor mooi geformatteerde code ... zou je een ander geven, als ik dat zou kunnen, om opmerkingen en code gescheiden te houden ... code is leuk om naar te kijken
toegevoegd de auteur jsotola, de bron

5 antwoord

Uw probleem is de vertraging() in uw BlueLED-() en RedLED() -aanroepen. Om meer "gelijktijdige" activiteiten te krijgen, moet u timeronderbrekingen gebruiken om die vertragingen te implementeren. Het is conceptueel veel complexer, maar de juiste manier om het te doen.

2
toegevoegd
Dat was snel werk! Ik ben blij dat je het hebt gedaan.
toegevoegd de auteur George Bailey, de bron
Heel erg bedankt Harper; dat was erg behulpzaam. We hebben je advies opgevolgd en hebben het zojuist opgelost !!! Bedankt!
toegevoegd de auteur Steve S, de bron

We hebben het gedaan. Bedankt voor de hulp Harper Shelby.

We combineerden het Blink Without Delay-voorbeeld met onze originele code:

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
toegevoegd

Ten eerste gefeliciteerd! je hebt je eerste stap gezet in de zeer lonende wereld van microcontrollers. Ik geef les in robotica aan een plaatselijke universiteit, dus het is altijd leuk om te zien wanneer de gloeilamp gaat branden en mensen beginnen te begrijpen.

Zoals hierboven vermeld, is het knipperen zonder vertragingscode een goed begin. Goede code moet ook uitvouwbaar zijn in het geval u later nog een lampje wilt toevoegen of 10, en dit is waar codering elke regel erg groot kan worden. Er zijn veel andere methoden om dit soort taken uit te voeren, maar wellicht wilt u deze reeks zelfstudies bekijken. Multitasking met de Arduino.

Het voordeel van de state-machinebenadering die in dat voorbeeld wordt gebruikt, is dat het later zeer eenvoudig wordt om uw code te wijzigen; als je wilt dat meer lichten achter elkaar knipperen (zoals de ridderrijders oplichten) of meer sirenes, wordt het gemakkelijker om op te nemen. In uw tweede code bevatten de ongeldige rodeLED() en ongeldige blueLED() -codes meestal dezelfde regels; je zou een object met de naam 'LED' kunnen maken en dan zo veel exemplaren hiervan maken als je nodig hebt, allemaal werkend met verschillende snelheden en verschillende pinnen (het voorbeeld op de website zou zoveel moeten bieden.) De zoemer kan waarschijnlijk het servo-sweepgedeelte opnieuw gebruiken van de code). U kunt bijvoorbeeld ook 4 verschillende soorten sirenes programmeren als een schakelaar: case en na de verstreken tijd schakelen tussen deze.

Een andere geavanceerdere methode zou zijn om een ​​real-time besturingssysteem op te nemen. Met een RTOS is het heel eenvoudig om meerdere onafhankelijke taken uit te voeren. Elk licht zou op zijn eigen taak kunnen zijn en de sirene op een derde, en het systeem zou elke functie effectief gelijktijdig houden. Deze benadering heeft dan voordelen als je de timing van één licht wilt wijzigen; het wordt op één plek veranderd zonder de angst de hele code te hoeven veranderen. Informatie over FreeRTOS op de Arduino is te vinden hier . Er is een voorbeeld onderaan de pagina dat zowel Blink- als analoge leesvoorbeelden bevat.

Dit zijn vrij geavanceerde onderwerpen, maar ik denk dat jij en je vader er zullen komen. Nogmaals gefeliciteerd.

1
toegevoegd
Heel erg bedankt Nathan! We zullen het volgende bekijken, en de link op de website die u ons gaf ziet er geweldig uit.
toegevoegd de auteur Steve S, de bron

Dit is waarschijnlijk een beetje geavanceerd maar ...

U kunt een basisklasse en verwijzingen naar de afgeleide LED- en Buzzer-klassen gebruiken om uw lusfunctie tot een lus te reduceren. Op dit niveau krijg je niet veel te winnen, maar als je meer voorwerpen toevoegt, zoals de knipperende koplampen en spiegellampen, misschien zelfs een aan de achterkant geplaatst prikbord, zul je het je leven gemakkelijker maken.

/*
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
toegevoegd

We hebben het beter gemaakt met de aanwijzer van Nathan.

We hebben geleerd hoe we een klasse moesten maken, maar de LED's flitsten samen, dus we leerden hoe we een andere les konden maken (met Public and Void Update in de klas - betrapte ons er eerst op dat beetje). Eén klasse begint met de status HOOG en de andere met de status LAAG, zodat de LED's afwisselen. Als we op alle drie de knoppen drukken, krijgen we de tweekleurige zoemer en de wisselende leds.

Met behulp van deze methode kunnen we zoveel nieuwe LED's toevoegen als we willen.

Dit is de code die we hebben geschreven:

/*
  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
toegevoegd
Is het enige verschil tussen FlashingLED_A en FlashingLED_B het feit dat A LAGE begint en B HOOG begint? Als dat het geval is, zou ik een extra parameter toevoegen aan de klasseconstructor en gewoon een van de klassen gebruiken.
toegevoegd de auteur Thomas Myron, de bron