2

My Dad and I are just learning how to use my new UNO.

We have learned how to make leds flash at the touch of a button. We have also learned how to make a passive buzzer sound at the touch of a button and change tone to sound like a police car.

We have just learned that we cant run more than one loop so we have combined the buzzer code and the LED code twice (for blue and red LEDs) and it works... but the delay on the LEDs is ruining the buzzer sound. Is there anything we can do?

The code is below.

Thank you!

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
}
  • 1
    +1 for nicely formatted code ... would give you another, if i could, for keeping comments and code separate ... code that is joy to look at – jsotola Jan 15 '18 at 22:30
  • Wow, thanks. We are feeling very proud right now. – Jacob Dickson Jan 15 '18 at 22:35
2

Your problem is the delay() in your BlueLED() and RedLED() calls. To get more "simultaneous" activities, you'd need to use timer interrupts to implement those delays. It's a lot more complex conceptually, but the right way to do it.

  • 1
    Thanks very much Harper; that was very helpful. We followed your advice and have just solved it!!! Thanks! – Jacob Dickson Jan 15 '18 at 22:11
  • That was quick work! Glad you got it going. – Harper Shelby Jan 15 '18 at 22:22
2

We have done it. Thanks for the help Harper Shelby.

We combined the Blink Without Delay example with our original 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);
  }

}
1

Firstly, congratulations! you've taken your first step into the very rewarding world of micro-controllers. I teach robotics at a local university, so it's always nice to see when the light-bulb goes on and people start understanding.

As mentioned above, the blink without delay code is a good start. Good code should also be expandable in case later you want to add another light or 10, and this is where coding every line can get very large. There are many other methods for doing this sort of task, however you might want to have a look at this series of tutorials. Multitasking with the Arduino.

The benefit to the state machine approach used in that example is it becomes very easy later on to change your code; if you want to have more lights flashing in sequence (like the knight-rider lights) or more sirens, it becomes easier to include. In your second code, the void redLED() and void blueLED() codes contain mostly the same lines; you could make an object called 'LED' and then just make as many instances of this as you need, all working at different speeds and different pins (the example on the website should provide this much. The buzzer can probably reuse the servo sweep part of the code). You could also for example, program 4 different types of siren as a switch:case, and after the elapsed time, switch between them.

Another more advanced method would be to include a real-time operating system. An RTOS makes it very easy to have multiple independent tasks running. Each light could be on its own task and the siren on a third, and the system would keep each working, effectively simultaneously. This approach then has advantages if you want to change the timing of one light; it gets changed in one place without fear of needing to change the whole code. Information on FreeRTOS on the arduino can be found here. There is an example at the bottom of the page which includes both Blink and analog read examples.

These are fairly advanced topics, but I think you and your dad will get there. Once again, congratulations.

  • Thank you very much Nathan! We will look in to this next, and the website link you gave us looks great. – Jacob Dickson Jan 16 '18 at 21:09
0

We made it better with Nathan's pointer.

We learned how to make a class but the LEDs flashed together so we learned how to make another class (with Public and Void Update in the class - caught us out at first that bit). One class starts with state HIGH and the other with state LOW so the LEDs alternate. When we press all three buttons we get the two tone buzzer, and the alternating LEDs.

Using this method we can add as many new LEDs as we like.

Here is the code we wrote:

/*
  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);
  }
 }
  • Is the only difference between FlashingLED_A and FlashingLED_B the fact that A starts LOW and B starts HIGH? If so then I would add an extra parameter to the class constructor and just use one of the classes. – Code Gorilla Jan 23 '18 at 8:48
0

This is probably a bit advanced but...

You could use a base class and pointers to the derived LED and Buzzer classes to reduce you loop function to a loop. You won't gain much at this level, but as you add more objects, such as the flashing headlights and mirror lights, maybe even a rear facing message board you will make life easier for your self.

/*
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();
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.