Online Activities

Cymraeg

THIS PAGE IS UNDERGOING CHANGES - PLEASE RETURN SHORTLY

Introduction to Programming in Arduino C

We have adapted the material created for our Robotics Club for anyone to work through at home or in school.

Each of the below sessions include a video lesson from one of our staff and a set of exercises to assess your understanding. As this page is for independent learners, answers are included.

We recommend that learners first visit our Online Micro:Bit Series for an introduction to programming, and our Online Electronics Series to better understand both hardware and software used.

Please select a session heading to get started.

Exercises

You will need to copy our 'Valiant' Robot Tinkercad circuit into your Tinkercad account for these exercises.

As a reminder for how to log-in and use Tinkercad, please see Session One of our Online Electronics Series

These challenges involve getting started with our 'Valiant' robot programming.

All learners should start with the bronze level and work their way up as far as they can.

Click on each challenge heading to expand.



Important: Make sure you have the code panel on Tinkercad set to Text, as shown here:

A screenshot of the Tinkercad code panel with the top left drop down box selected to 'Text'.

The program provided is Tinkercad's default Arduino program which turns the built-in LED on the Arduino on and off.

Delete the contents of the void setup() and void loop() so your start code looks like this:

              
    //C++ code
    //
    void setup ()
    {
      
    }

    void loop ()
    {

    }
              
            
  1. Define pin 13 (where the LED is connected) as an output pin in the void setup() (on start).


    • When using block-based programming, a lot of the setup was automatically included for us. Now, we need to write this ourselves.

    • We use pinMode() to identify a pin in use and whether it is an INPUT or OUTPUT.

    • Inside the pinMode() brackets we need to add the pin's number and that it's an OUTPUT.

    • Do not forget the semi-colon (;) at the end of the instruction.

    If you are still stuck, please use the answer button below.


                        
        //C++ code
        //
        void setup ()
        {
          pinMode(13, OUTPUT);
        }
    
        void loop ()
        {
    
        }
                        
                      

  2. Inside the void loop() (forever loop) write the code to turn this LED on and off.

    Tip: You will need to add a 100ms delay (wait) between light changes to observe them in the simulator.


    • We are using the LED as a digital output (on or off) for this exercise.

    • Use digitalWrite() instructions to tell a digital component to turn on or off.

    • Inside the brackets of the digitalWrite() command we need to include the pin we're changing followed by HIGH or LOW.

    • Remember, in coding, we use HIGH for on and LOW for off.

    • The delay() instruction makes the program wait for the length of time stated inside the brackets - measured in milliseconds.

    • Remember, the void loop() acts the same as a forever loop.

    • Every instruction/command line needs to end with a semi-colon (;) or the program will not work.

    • You can use the simulator to check your code works - the blue LED in the circuit should flash on and off rapidly.

    If you are still stuck, please use the answer button below.


                        
        //C++ code
        //
        void setup ()
        {
          pinMode(13, OUTPUT);
        }
    
        void loop ()
        {
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
          delay(100);
        }
                        
                      




  1. Write the setup instruction needed to tell our program we have an LDR/Photoresistor connected to pin A0.

    Tip: The LDR/Photoresistor is an analog input device.


    • This needs to go inside the void setup().

    • It uses the pinMode() command as explained in the Bronze Level exercises.

    • In this case the key information needed is that the component uses pin A0 and is an INPUT.

    • The setup does not need to know if a component is digital or analog - this information will be useful once we start programming the LDR/Photoresistor.

    If you are still stuck, please use the answer button below.


                        
        //C++ code
        //
        void setup ()
        {
          pinMode(13, OUTPUT);
          pinMode(A0, INPUT);
        }
    
        void loop ()
        {
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
          delay(100);
        }
                        
                      

  2. Like our pins, to use the serial monitor in our program, we need to include it in the setup.

    Tip: Setting up the serial monitor was demonstrated in the video lesson.


    • You will need to use the Serial.begin() instruction inside the void setup().

    • The value inside the brackets for the serial command is the communication speed - we recommend that you use 9600 as a default value.

    • Be aware, this instruction is slightly different as it starts with a capital letter.

    • This does not automatically open the serial monitor for you, but tells the program we will be using it.

    If you are still stuck, please use the answer button below.


                        
        //C++ code
        //
        void setup ()
        {
          pinMode(13, OUTPUT);
          pinMode(A0, INPUT);
          Serial.begin(9600);
        }
    
        void loop ()
        {
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
          delay(100);
        }                  
                        
                      

  3. Create a variable called 'ldrValue' to store the value of the LDR reading and set it to 0 on start.

    Tip: These values are integers (whole numbers). This means we need to tell the program this is a variable with type int.


    Important: Where we create a variable in the program decides where we can use it.

    For this topic, we shall be using mainly Global Variables. These are variables we define at the very start of a program, even before the void setup(). This means we can then use them in any and all sections of the program.

    If you were to create a variable inside a loop/function it would only be accessible inside that same loop/function and no-where else in the program. This would be called a Local Variable. Remember, this means the variable will be re-created every time the loop/function it is in runs.


    • Some programming languages, like Arduino C, need us to tell it what type a variable is. You only need to include the variable type when creating the variable, not when using it.

    • This is a global variable and therefore needs to be created at the very start of the program.

    • We introduced the good practice of setting variables to 0 throughout our Micro:Bit and Electronics topics to help you remember to do it in text-based languages.

    If you are still stuck, please use the answer button below.


                        
        //C++ code
        //
        int ldrValue = 0;
    
        void setup ()
        {
          pinMode(13, OUTPUT);
          pinMode(A0, INPUT);
          Serial.begin(9600);
        }
    
        void loop ()
        {
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
          delay(100);
        }
                        
                      

  4. Inside the void loop(), have your new LDR variable equal to the LDR sensor reading. Then have the program print the value of this variable to the serial monitor.

    Tip: The LDR is an analog input and is connected to pin A0.


    • Arduino programs 'read' inputs and 'write' outputs.

    • Use the analogRead() instruction with the pin identified inside its brackets.

    • The Serial.println() command tells the program to print whatever is in its brackets on a new line of the serial monitor.

    If you are still stuck, please use the answer button below.


                        
        //C++ code
        //
        int ldrValue = 0;
    
        void setup ()
        {
          pinMode(13, OUTPUT);
          pinMode(A0, INPUT);
          Serial.begin(9600);
        }
    
        void loop ()
        {
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
          delay(100);
          ldrValue = analogRead(A0);
          Serial.println(ldrValue);
        }
                        
                      



The Tinkercad code editor has a built-in debugger. This lets us know when there is an error in the code and the type. It runs every time we start the simulation. In this exercise we will be introducing errors into our program to help us match them to the error messages.

Change your void setup() to match each of the below examples to see the error message produced.

Tip: the numbers at the beginning of the error messages may differ as they are referring to line numbers in the code which are dependent on your spacing.

1. Missing '}':

                
    void setup ()
    {
      pinMode(13, OUTPUT);
      pinMode(A0, INPUT);
      Serial.begin(9600);
    
    
    void loop ()

2. Missing '{':

                
    void setup ()
    
      pinMode(13, OUTPUT);
      pinMode(A0, INPUT);
      Serial.begin(9600);
    }
               
              

3. Missing ';':

                
    void setup ()
    {
      pinMode(13, OUTPUT);
      pinMode(A0, INPUT)
      Serial.begin(9600);
    }
               
              

4. Missing '()':

                
    void setup 
    {
      pinMode(13, OUTPUT);
      pinMode(A0, INPUT);
      Serial.begin(9600);
    }
               
              

5. Spelling Mistake:

                
    void setup ()
    {
      pinMoed(13, OUTPUT);
      pinMode(A0, INPUT);
      Serial.begin(9600);
    }
               
              

6. Missing ',':

                
    void setup ()
    {
      pinMode(13 OUTPUT);
      pinMode(A0, INPUT);
      Serial.begin(9600);
    }
               
              


  1. 
        In function 'void setup()':
        13:1: error: a function-definition is not allowed here before '{' token   
        20:1: error: expected '}' at end of input
                        

  2. 
        7:3: error: expected initializer before 'pinMode'
        8:10: error: expected constructor, destructor, or type conversion before '(' token    
        9:3: error: 'Serial' does not name a type
        10:1: error: expected declaration before '}' token
                        

  3. 
          In function 'void setup()':
        9:3: error: expected ';' before 'Serial'    
                        

  4. 
        5:6: error: variable or field 'setup' declared void
        7:22: error: expected '}' before ';' token
        8:10: error: expected constructor, destructor, or type conversion before '(' token    
        9:3: error: 'Serial' does not name a type
        10:1: error: expected declaration before '}' token
                        

  5. 
          In function 'void setup()':
        7:3: error: 'pinMoed' was not declared in this scope    
        7:3: note: suggested alternative: 'pinMode'
                        

  6. 
        1:0:
          In function 'void setup()':
        44:16: error: expected ')' before numeric constant
    
    
        7:14: note: in expansion of macro 'OUTPUT'
        7:20: error: too few arguments to function 'void pinMode(uint8_t, uint8_t)'    
        1:0:
        134:6: note: declared here
                        




Exercises

These exercises continue using the program developed in Session One.

All learners should start with the bronze level and work their way up as far as they can.

Click on each challenge heading to expand.



  1. For this exercise, we are going to change what the LED does so we need to remove the instructions that make the LED flash on and off.

    Tip: As we are still using the LED, so do not remove the pinMode setup.


    • Only delete the lines created in step 2 of Bronze Level in Session One.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(13, OUTPUT);
        pinMode(A0, INPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrValue = analogRead(A0);
        Serial.println(ldrValue);
      }
                        
                      

  2. Create a new integer type variable called blueLED and set it to 13 (the number of the pin it is connected to).

    Tip: If you successfully completed the first extension exercise in Session One, skip this step.


    • This is a global variable so needs to be set at the very beginning of the program before the void setup().

    • Have this new variable equal to 13.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(13, OUTPUT);
        pinMode(A0, INPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrValue = analogRead(A0);
        Serial.println(ldrValue);
      }
                        
                      

  3. Create a new integer type variable called ldr and set this to A0.

    Tip: Although A0 appears to be a mix of characters and letters, it is a pin's number and therefore recognised as an integer.


    • This is a global variable so needs to be set at the very beginning of the program before the void setup().

    • Have this new variable equal to A0.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(13, OUTPUT);
        pinMode(A0, INPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrValue = analogRead(A0);
        Serial.println(ldrValue);
      }
                        
                      

  4. Now, replace every time we call the pins by their numbers (13 and A0) in the program with the correct variable instead. This means that if we change which pin a component is connected to, we only need to adapt the code in one place - where the variable is created.


    • You will need to call the blueLED variable once in the void setup().

    • The ldr variable needs to be called once in void setup() and once in void loop().

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
      }
                        
                      

  5. Add an if-statement to your void loop() that turns the LED on when the LDR reading is less than 160.

    Tip: If you completed the extension exercises in Session One, you only need to change the condition for the if-statement.


    • Remember to use our new variables when calling the pins.

    • You will need an else-statement to turn the LED off when the condition is false.

    • Make sure your instructions are inside the curly brackets {} of the statement.

    • We are using the LED as a digital output. This means we will need to use digitalWrite commands with HIGH and LOW values.

    • Don't forget to run the simulation to test your program.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
      } 
                        
                      




  1. We are now going to start programming our servo. To do this, we need to tell the program to access the servo library - this is like when we added the servo extension to the Micro:Bit block menu.

    Tip: The library/extension is called Servo.h


    • We use the #include command to add a library/extension.

    • The name of the library/extension goes inside angled brackets < >.

    • To access the library/extension throughout our program (globally), we need to do this before our void setup().

    • An #include instruction does not have a semi-colon (;) at the end.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      #include <Servo.h>
    
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
      } 
                        
                      

  2. Add a servo to your program called myServo using the new library commands.

    Tip: Additional libraries can have different ways to produce variables. In this case, we use the command Servo variableName; to add a servo.


    • This is a global variable that needs setting at the start of the program.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
      } 
                        
                      

  3. Create a new global integer type variable called servoPin and set it to 12. Use this new variable in the void setup() to tell the program which pin myServo is connected to.

    Tip: The Servo library command for identifying pins is different again. You will need to use the command structure of servoName.attach(pin);


    • Set up the new servoPin variable the same way as we did for the ldr and blueLED variables.

    • Using the command structure of servoName.attach(pin); replace the servoName with myServo and the pin with servoPin.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
      }
                        
                      

  4. Inside the void loop(), write a program using myServo.write(angle); instructions to make the servo move between the angles of 0°, 90°, 180°, and back to 90°. Include one second delays after each movement.

    Tip: the delay(); instruction uses milliseconds for the value inside the brackets. 1000 milliseconds = 1 second.


    • The 1000ms delays are necessary to allow the servo time to complete a movement before starting the next.

    • The angle value in the command does not need a ° symbol.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
        myServo.write(0);
        delay(1000);
        myServo.write(90);
        delay(1000);
        myServo.write(180);
        delay(1000);
        myServo.write(90);
        delay(1000);
      }
                          
                        
                      




  1. Create a new global variable called piezo or piezoPin to store the pin value for the piezo buzzer.

    Tip: You will need to look at the circuit to identify which pin this is.


    • Remember, all programmable pins, including those with the letter A in their names, are considered to be numbers/integers.

    • The programmable pin for the piezo buzzer is the one connected to its positive terminal.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
        myServo.write(0);
        delay(1000);
        myServo.write(90);
        delay(1000);
        myServo.write(180);
        delay(1000);
        myServo.write(90);
        delay(1000);
      }
                        
                      

  2. Using our new piezo variable, set up the pinMode() for the buzzer inside the void setup().

    Tip: You will need to consider if the buzzer is an input or output.


    • The piezo buzzer is an analog output device.

    • Pay attention to which descriptions need to be written in capital letters.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
        pinMode(piezo, OUTPUT);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
        myServo.write(0);
        delay(1000);
        myServo.write(90);
        delay(1000);
        myServo.write(180);
        delay(1000);
        myServo.write(90);
        delay(1000);
      }
                        
                      

  3. Program your buzzer to play a tone for 0.5 seconds according to the LDR reading. The conditions are:

    • If the light level is less than 60, play the tone frequency of 65.
    • Else, if the light level is less than 100, play the tone frequency of 82.
    • Else, if the light level is less than 160, play the tone frequency of 98.
    • Else, if the light level is less than 220, play the tone frequency of 131.
    • Else, if the light level is less than 280, play the tone frequency of 165.
    • Else, if the light level is less than 340, play the tone frequency of 196.
    • Else, if the light level is less than 400, play the tone frequency of 262.
    • Else, if the light level is less than 460, play the tone frequency of 330.
    • Else, if the light level is less than 520, play the tone frequency of 392.
    • Else, play the tone frequency of 523.

    Tip: Pay attention to the start of each condition for a clue as to the statements needed for each.


    • You will need to create an if-statement, 8 else-if statements and an else statement. These should be in the void loop() section of your program.

    • Programs will go down all the options until one is true. It will then perform the coded actions and stop going down the list. This means we only need to write the maximum light level in each statement.

    • The instruction is written tone(pin, frequency, duration);

    • We have a variable to use for the pin, the frequencies are provided, and the duration is measured in milliseconds (so 0.5 seconds = 500 milliseconds).

    • When you test the program, there will be a pause between each tone played as the other instructions are completed in the void loop().

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
      {
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
        pinMode(piezo, OUTPUT);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
        myServo.write(0);
        delay(1000);
        myServo.write(90);
        delay(1000);
        myServo.write(180);
        delay(1000);
        myServo.write(90);
        delay(1000);
        if (ldrValue < 60)
        {
          tone(piezo, 65, 500);
        }
        else if (ldrValue < 100)
        {
          tone(piezo, 82, 500);
        }
        else if (ldrValue < 160)
        {
          tone(piezo, 98, 500);
        }
        else if (ldrValue < 220)
        {
          tone(piezo, 131, 500);
        }
        else if (ldrValue < 280)
        {
          tone(piezo, 165, 500);
        }
        else if (ldrValue < 340)
        {
          tone(piezo, 196, 500);
        }
        else if (ldrValue < 400)
        {
          tone(piezo, 262, 500);
        }
        else if (ldrValue < 460)
        {
          tone(piezo, 330, 500);
        }
        else if (ldrValue < 520)
        {
          tone(piezo, 392, 500);
        }
        else 
        {
          tone(piezo, 523, 500);
        }
      }
                        
                      


For these exercises we would advise that use a copy of your program in case things go wrong.

Mapping: As with the previous block coding in Makecode and Tinkercad, it is possible to map ranges of values from inputs to outputs instead of having such long if-statements.

For this we need to create a value to hold the mapping:

int mappedVariable = map(inputValue, inputMin, inputMax, outputMin, outputMax);

For example, if we wanted to map the range of a potentiometer (analog input) to an LED (analog output), making the LED brighter as the potentiometer value increases, we need the following information:

  • inputValue: This is the current value of the potentiometer.
  • inputMin: The minimum possible value of the potentiometer (0).
  • inputMax: The maximum possible value of the potentiometer (1023).
  • outputMin: The minimum possible value of the LED (0).
  • outputMax: The maximum possible value of the LED (255).

The program would look something like this:

            
  int potPin = A4;
  int ledPin = 9;
  int potValue = 0;
  int potMapLED = 0;

  void setup()
  {
    pinMode(potPin, INPUT);
    pinMode(ledPin, OUTPUT);
  }

  void loop()
  {
    potValue = analogRead(potPin);
    potMapLED = map(potValue, 0, 1023, 0, 255);
    analogWrite(ledPin, potMapLED);
  }
            
          
  1. In your program, map the LDR input range to the Servo angle.

    Tip: The LDR range in the Tinkercad simulator is 6 to 679. The servo angle can be anything between 0 and 180.


  2. Now try mapping the LDR to the piezo buzzer instead.

    The frequency range of the buzzer is 31 to 4978.


Exercises

We shall be continuing on from the program produced in Session Two.

All learners should start with the bronze level and work their way up as far as they can.

Click on each challenge heading to expand.


These exercises will take you through how to set up motor functions for this robot.

  1. Add four new integer type variables to the start of your program for the following:

    A variable called leftForwardPin which is set to 10,
    A variable called leftReversePin which is set to 11,
    A variable called rightForwardPin which is set to 9,
    A variable called rightReversePin which is set to 6.


    • These need to go before the void setup() so we can use them globally.

    • If unsure, look at the previous integer type variables already written in your program.

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of each level.

                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int leftForwardPin = 10;
      int leftReversePin = 11;
      int rightForwardPin = 9;
      int rightReversePin = 6;
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void setup ()
                        
                      

  2. We now need to set-up the pin mode for each of these, using our new variables.


    • Motors are output devices.

    • For example: pinMode(leftForwardPin, OUTPUT);

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of each level.

                        
      void setup ()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
        pinMode(piezo, OUTPUT);
      }
                        
                      

  3. We now need to create our own functions for the different robot directions (forward, backward, left, right, and stop).

    Tip: The motors used in this circuit are digital devices.


    • We would suggest putting these new functions after your global variables but before the void setup(). This will reduce the risk of accidentally mixing these new functions inside the existing program.

    • A new function starts with void functionName() { } with the instructions inside the curly brackets.

    • Function names are written in camel text (start with a lowercase letter, no spaces, and with each new word starting with a capital letter).

    • Inside each function you will need to include the digitalWrite(); commands for each motor variable.

    • As these are digital devices, we will need to set them to HIGH or LOW.

    • Inside the digitalWrite(); brackets, you will need to include the variable and whether it is HIGH or LOW.

    • For the robot to turn left, it needs the right wheel to go forward and the left wheel backwards. It is the opposite for the robot to turn right.

    • For example, your forward function will look like this:
                            
        void forward()
        {
          digitalWrite(leftForwardPin, HIGH);
          digitalWrite(leftReversePin, LOW);
          digitalWrite(rightForwardPin, HIGH);
          digitalWrite(rightReversePin, LOW);
        }
                            
                          

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of each level.

                        
      int ldrValue = 0;
    
      void robotForward()
      {
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
      }
    
      void robotReverse()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
      }
    
      void robotLeft()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
      }
    
      void robotRight()
      {
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
      }
    
      void robotStop()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
      }
    
      void setup ()
                          
                      

  4. Start the simulation to check for any errors in your code. The motors will not do anything yet, as we have not called any of our new functions.


                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int leftForwardPin = 10;
      int leftReversePin = 11;
      int rightForwardPin = 9;
      int rightReversePin = 6;
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void robotForward()
      {
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
      }
    
      void robotReverse()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
      }
    
      void robotLeft()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
      }
    
      void robotRight()
      {
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
      }
    
      void robotStop()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
      }
    
      void setup ()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
        pinMode(piezo, OUTPUT);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
        myServo.write(0);
        delay(1000);
        myServo.write(90);
        delay(1000);
        myServo.write(180);
        delay(1000);
        myServo.write(90);
        delay(1000);
        if (ldrValue < 60)
        {
          tone(piezo, 65, 500);
        }
        else if (ldrValue < 100)
        {
          tone(piezo, 82, 500);
        }
        else if (ldrValue < 160)
        {
          tone(piezo, 98, 500);
        }
        else if (ldrValue < 220)
        {
          tone(piezo, 131, 500);
        }
        else if (ldrValue < 280)
        {
          tone(piezo, 165, 500);
        }
        else if (ldrValue < 340)
        {
          tone(piezo, 196, 500);
        }
        else if (ldrValue < 400)
        {
          tone(piezo, 262, 500);
        }
        else if (ldrValue < 460)
        {
          tone(piezo, 330, 500);
        }
        else if (ldrValue < 520)
        {
          tone(piezo, 392, 500);
        }
        else 
        {
          tone(piezo, 523, 500);
        }
      }
    
                        
                      




  1. Now we are going to add a program to the void loop() that calls our new functions when needed. We want our robot to do the following before moving its servo:
    1. Drive forward for one second.
    2. Stop for half a second.
    3. Turn left for half a second.
    4. Turn right for a second.
    5. Turn left for half a second.
    6. Stop for half a second.
    7. Drive backwards for one second.
    8. Stop for one second.

    Tip: Use the delay(); instruction for the timings.


    • To call a function use functionName(); instruction, replacing the function name to match the one you're calling.

    • Delays are measured in milliseconds - there are 1000 of these in a second.

    • In our answer program, we used the function names robotForward(), robotReverse(), robotLeft(), robotRight(), and robotStop(). So, using these function names, if we wanted the robot to move forward for 5 seconds and then stop for 2 seconds before moving backwards for 5 seconds, we'd write:
                          
        robotForward();
        delay(5000);
        robotStop();
        delay(2000);
        robotReverse();
        delay(5000);
        robotStop();
                          
                        

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of each level.

                        
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
    
        robotForward();
        delay(1000);
        robotStop();
        delay(500);
        robotLeft();
        delay(500);
        robotRight();
        delay(1000);
        robotLeft();
        delay(500);
        robotStop();
        delay(500);
        robotReverse();
        delay(1000);
        robotStop();
        delay(1000);
    
        myServo.write(0);
        delay(1000);
        myServo.write(90);
        delay(1000);
        myServo.write(180);
        delay(1000);
        myServo.write(90);
        delay(1000);
                        
                      

  2. Start the simulation to check for bugs and to make sure the motors are working.


                      
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int leftForwardPin = 10;
      int leftReversePin = 11;
      int rightForwardPin = 9;
      int rightReversePin = 6;
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void robotForward()
      {
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
      }
    
      void robotReverse()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
      }
    
      void robotLeft()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
      }
    
      void robotRight()
      {
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
      }
    
      void robotStop()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
      }
    
      void setup ()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
        pinMode(piezo, OUTPUT);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
    
        robotForward();
        delay(1000);
        robotStop();
        delay(500);
        robotLeft();
        delay(500);
        robotRight();
        delay(1000);
        robotLeft();
        delay(500);
        robotStop();
        delay(500);
        robotReverse();
        delay(1000);
        robotStop();
        delay(1000);
    
        myServo.write(0);
        delay(1000);
        myServo.write(90);
        delay(1000);
        myServo.write(180);
        delay(1000);
        myServo.write(90);
        delay(1000);
        if (ldrValue < 60)
        {
          tone(piezo, 65, 500);
        }
        else if (ldrValue < 100)
        {
          tone(piezo, 82, 500);
        }
        else if (ldrValue < 160)
        {
          tone(piezo, 98, 500);
        }
        else if (ldrValue < 220)
        {
          tone(piezo, 131, 500);
        }
        else if (ldrValue < 280)
        {
          tone(piezo, 165, 500);
        }
        else if (ldrValue < 340)
        {
          tone(piezo, 196, 500);
        }
        else if (ldrValue < 400)
        {
          tone(piezo, 262, 500);
        }
        else if (ldrValue < 460)
        {
          tone(piezo, 330, 500);
        }
        else if (ldrValue < 520)
        {
          tone(piezo, 392, 500);
        }
        else 
        {
          tone(piezo, 523, 500);
        }
      }
                      
                    



We are now going to setup and program the ultrasonic sensor.

  1. Create integer type variables and set the pin modes for the below:

    • A variable called ultrasonicTrigger - connected to pin 7 - an output.

    • A variable called ultrasonicEcho - connected to pin 8 - an input.


    • Set the new integer variables to the value of the pin.

    • Use the variable in the pin modes, instead of the pin's number.

    If you are still stuck, please use the answer button below.

    The sections of the program altered are shown below. The full program will be added at the end of each level.

                        
      int ultrasonicTrigger = 7;
      int ultrasonicEcho = 8;
      int leftForwardPin = 10;
      int leftReversePin = 11;
      int rightForwardPin = 9;
      int rightReversePin = 6;
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
                        
                      
                        
      void setup ()
      {
        pinMode(ultrasonicTrigger, OUTPUT);
        pinMode(ultrasonicEcho, INPUT);
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
        pinMode(piezo, OUTPUT);
      }
                        
                      

  2. Important: The ultrasonic sensor has a complicated setup which you do not need to worry about learning at this stage. Instead, we ask that you carefully copy the below calculation function into your program just after your motor functions but before the void setup();.

                    
      int readUltrasonic() 
      {
        digitalWrite(ultrasonicTrigger,LOW); // Clear the signal
        delayMicroseconds(2);
        digitalWrite(ultrasonicTrigger, HIGH); // Send out new signal
        delayMicroseconds(10);
        digitalWrite(ultrasonicTrigger,LOW); // Stop sending signal
    
        unsigned long duration = pulseIn(ultrasonicEcho, HIGH);
        int distance = duration /2 /29;
        Serial.print(distance);
        Serial.print("cm");
        return distance;
      }
                    
                  

    This function gives us the distance to a detected object in centimetres. We can now call it in our program to help with the rest of this exercise.

    Please note: If you used different variable names to those provided in step 1, this will not work.


  3. Create new global integer variables called 'left', 'front', and 'right'. Set them all to 0.

    The section of the program altered is shown below. The full program will be added at the end of each level.

                      
      int left = 0;
      int front = 0;
      int right = 0;
      int ultrasonicTrigger = 7;
      int ultrasonicEcho = 8;
      int leftForwardPin = 10;
      int leftReversePin = 11;
      int rightForwardPin = 9;
      int rightReversePin = 6;
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
                      
                    

  4. Our program already includes servo movements as shown below.
                    
      myServo.write(0);
      delay(1000);
      myServo.write(90);
      delay(1000);
      myServo.write(180);
      delay(1000);
      myServo.write(90);
      delay(1000);
                    
                  
    We now want to take ultrasonic readings from each direction. So, after moving to 0°, insert a line that sets our new 'left' variable to call our readUltrasonic() function. Then, after it's moved to 90°, set the 'front' variable to call the same function. Repeat again for 180° with the 'right' variable. The fourth movement does not need a reading as we've already taken that one.

    Tip: Remember, the delays are to allow the servos to finish their movements so the readings should be taken after the delay but before the next move.


    • Here is how to add the left reading as an example:
                            
        myServo.write(0);
        delay(1000);
        left = readUltrasonic();
        myServo.write(90);
        delay(1000);
        myServo.write(180);
        delay(1000);
        myServo.write(90);
        delay(1000);
                            
                          

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of each level.

                        
      myServo.write(0);
      delay(1000);
      left = readUltrasonic();
      myServo.write(90);
      delay(1000);
      front = readUltrasonic();
      myServo.write(180);
      delay(1000);
      right = readUltrasonic();
      myServo.write(90);
      delay(1000);
                        
                      

  5. We have already programmed a movement path for the robot. Now, we want to make sure this is safe for the robot to do without crashing. As the current path is just backwards and forwards with some spins, we only need to check there is nothing in front. Change your program to stop if the front sensor reading is less than a metre.

    Tip: The readUltrasonic() function gives a distance in centimetres.


    • This requires an if-statement for when front < 100.

    • We will need to put our previous motor instructions into an else statement.

    • Remember, to stop moving we have a stop function we made earlier.

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of each level.

                        
      if (front < 100)
      {
        robotStop();
      }
      else
      {
        robotForward();
        delay(1000);
        robotStop();
        delay(500);
        robotLeft();
        delay(500);
        robotRight();
        delay(1000);
        robotLeft();
        delay(500);
        robotStop();
        delay(500);
        robotReverse();
        delay(1000);
        robotStop();
        delay(1000);
      }                  
                        
                      

  6. In your void loop(), create a set of instructions that will print into the serial monitor whether right or left is safer to travel in.

    Tip: This will require an if-statement, an else if statement, and an else-statement. The else statement is used to capture when both measurements are the same.


    • If right > left, we want the serial monitor to show the word right, as this is the safer direction.

    • Else if left > right, we want the serial monitor to show the word left.

    • Else, we want the serial monitor to show the phrase 'no problem'.

    • Remember, when printing words to the serial monitor, we use double quotation marks: Serial.println("word");

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of each level.

                        
      myServo.write(0);
      delay(1000);
      left = readUltrasonic();
      myServo.write(90);
      delay(1000);
      front = readUltrasonic();
      myServo.write(180);
      delay(1000);
      right = readUltrasonic();
      myServo.write(90);
      delay(1000);
    
      if (right > left)
      {
        Serial.println("right");
      }
      else if (left > right)
      {
        Serial.println("left");
      }
      else
      {
        Serial.println("no problem");
      }
                        
                      

  7. Hopefully, you've been running checks of your code after each step. If not, start the simulation to check for bugs and to test your program.


                      
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;
    
      int left = 0;
      int front = 0;
      int right = 0;
      int ultrasonicTrigger = 7;
      int ultrasonicEcho = 8;
      int leftForwardPin = 10;
      int leftReversePin = 11;
      int rightForwardPin = 9;
      int rightReversePin = 6;
      int piezo = A3;
      int servoPin = 12;
      int ldr = A0;
      int blueLED = 13;
      int ldrValue = 0;
    
      void robotForward()
      {
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
      }
    
      void robotReverse()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
      }
    
      void robotLeft()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
      }
    
      void robotRight()
      {
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
      }
    
      void robotStop()
      {
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
      }
    
      int readUltrasonic() 
      {
        digitalWrite(ultrasonicTrigger,LOW); // Clear the signal
        delayMicroseconds(2);
        digitalWrite(ultrasonicTrigger, HIGH); // Send out new signal
        delayMicroseconds(10);
        digitalWrite(ultrasonicTrigger,LOW); // Stop sending signal
    
        unsigned long duration = pulseIn(ultrasonicEcho, HIGH);
        int distance = duration /2 /29;
        Serial.print(distance);
        Serial.print("cm");
        return distance;
      }
    
      void setup ()
      {
        pinMode(ultrasonicTrigger, OUTPUT);
        pinMode(ultrasonicEcho, INPUT);
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(blueLED, OUTPUT);
        pinMode(ldr, INPUT);
        Serial.begin(9600);
        myServo.attach(servoPin);
        pinMode(piezo, OUTPUT);
      }
    
      void loop ()
      {
        ldrValue = analogRead(ldr);
        Serial.println(ldrValue);
        if (ldrValue < 160)
        {
          digitalWrite(blueLED, HIGH);
        }
        else
        {
          digitalWrite(blueLED, LOW);
        }
    
        if (front < 100)
        {
          robotStop();
        }
        else
        {
          robotForward();
          delay(1000);
          robotStop();
          delay(500);
          robotLeft();
          delay(500);
          robotRight();
          delay(1000);
          robotLeft();
          delay(500);
          robotStop();
          delay(500);
          robotReverse();
          delay(1000);
          robotStop();
          delay(1000);
        }   
    
        myServo.write(0);
        delay(1000);
        left = readUltrasonic();
        myServo.write(90);
        delay(1000);
        front = readUltrasonic();
        myServo.write(180);
        delay(1000);
        right = readUltrasonic();
        myServo.write(90);
        delay(1000);
    
        if (right > left)
        {
          Serial.println("right");
        }
        else if (left > right)
        {
          Serial.println("left");
        }
        else
        {
          Serial.println("no problem");
        }
    
        if (ldrValue < 60)
        {
          tone(piezo, 65, 500);
        }
        else if (ldrValue < 100)
        {
          tone(piezo, 82, 500);
        }
        else if (ldrValue < 160)
        {
          tone(piezo, 98, 500);
        }
        else if (ldrValue < 220)
        {
          tone(piezo, 131, 500);
        }
        else if (ldrValue < 280)
        {
          tone(piezo, 165, 500);
        }
        else if (ldrValue < 340)
        {
          tone(piezo, 196, 500);
        }
        else if (ldrValue < 400)
        {
          tone(piezo, 262, 500);
        }
        else if (ldrValue < 460)
        {
          tone(piezo, 330, 500);
        }
        else if (ldrValue < 520)
        {
          tone(piezo, 392, 500);
        }
        else 
        {
          tone(piezo, 523, 500);
        }
      }                  
                      
                    


For an extra challenge attempt the below in a copy of your program.

Delete the current movements from you void loop() and write a new program which instead has the robot use its servos and ultrasonic readings before deciding which way to move. Remember, our left and right movements involve spinning on the spot, you then have to drive forward to go that way.


Video Lesson

Exercises

This session we shall be using a different Tinkercad circuit to revise everything covered in this topic.

You will need to copy our Sensor Board circuit to use for these exercises.

This sensor board has a number of sensors and LEDS fitted and will allow us to replicate a series of different home devices.

These challenges involve getting started with our 'Valiant' robot programming.

All learners should start with the bronze level and work their way up as far as they can.

Click on each challenge heading to expand.


In this section, we shall be creating a program using the LDR/Photoresistor to control the brightness of the red LED.

  1. Create integer type variables for the LDR and red LED pins.


    • You can use the circuit to determine which programmable pins the components are connected to.

    • Remember, all pin names are classed as whole numbers (integers), even those that include the letter A.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      int ldrPin = A5;
      int redLEDPin = 3;
    
      void setup ()
      {
        
      }
    
      void loop ()
      {
    
      }
                        
                      

  2. Set the pinMode(); for these two components.


    • The pinMode(); instruction requires you to tell it (inside the brackets) the pin's value and whether it is an input or output.

    • Remember, input and output are written in block capitals for this.

    • Instead of writing the pin's number, use the variable created in the previous step.

    • Sensors that collect information are input devices.

    • Components that we control, using the program, are outputs.

    If you are still stuck, please use the answer button below.


                         
      //C++ code
      //
    
      int ldrPin = A5;
      int redLEDPin = 3;
    
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
      }
    
      void loop ()
      {
    
      }
                         
                       

  3. In the void loop() write a program to store the LDR's value in a variable.

    Tip: You will need to create a new integer type variable for this.


    • This is where choosing names for variables is important. You need to be able to tell which variable is the pin value and which is the reading. Especially, as your program for this requires both.

    • Make this new variable globally available and intially set to zero.

    • Remember, the LDR is an analog input device.

    • We 'read' inputs and 'write' outputs.

    If you are still stuck, please use the answer button below.


                         
      //C++ code
      //
    
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
    
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
      }
    
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
      }                       
                         
                       

  4. Print this value in the serial monitor.

    Tip: Don't forget to include the necessary set-up instruction to use the serial monitor.


    • In the void setup() function you will need to add the Serial.begin(9600); instruction so the program knows to use the serial monitor.

    • Inside the void loop() you will need to write the variable value to the serial monitor.

    If you are still stuck, please use the answer button below.


                         
      //C++ code
      //
    
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
    
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
      }                       
                         
                        

  5. Use the simulator to find the minimum and maximum values of the LDR.


    • If the code doesn't work, check it against the answer for the above section. The most common error involves too many or too few semi-colons.

    • Remember, you can chang the values of the LDR in the simulator by selecting it and then adjuster the slider that appears.

    • You will need the serial monitor open at the bottom of your code window to see the values.

    If you are still stuck, please use the answer button below.

    The range of the LDR in the Tinkercad simulator is 6 - 679.


  6. Map the LDR reading to the range of the red LED (0 - 255) and store the value in a new integer type variable.

    Mapping: As with the previous block coding in Makecode and Tinkercad, it is possible to map ranges of values from inputs to outputs instead of having such long if-statements.

    For this we need to create a value to hold the mapping:

    int mappedVariable = map(inputValue, inputMin, inputMax, outputMin, outputMax);

    For example, if we wanted to map the range of a potentiometer (analog input) to an LED (analog output), making the LED brighter as the potentiometer value increases, we need the following information:

    • inputValue: This is the current value of the potentiometer.
    • inputMin: The minimum possible value of the potentiometer (0).
    • inputMax: The maximum possible value of the potentiometer (1023).
    • outputMin: The minimum possible value of the LED (0).
    • outputMax: The maximum possible value of the LED (255).

    The program would look something like this:

                      
      int potPin = A4;
      int ledPin = 9;
      int potValue = 0;
      int potMapLED = 0;
    
      void setup()
      {
        pinMode(potPin, INPUT);
        pinMode(ledPin, OUTPUT);
      }
    
      void loop()
      {
        potValue = analogRead(potPin);
        potMapLED = map(potValue, 0, 1023, 0, 255);
        analogWrite(ledPin, potMapLED);
      }
                      
                    


    • Create an integer type global variable and set it to zero. This is where we will then store the mapped LDR value inside our program.

    • Looking at the structure of map(inputValue, inputMin, inputMax, outputMin, outputMax); we know the inputValue is our reading from step 4, the inputMin is 6 as we discovered in step 5, and from the same step we also know that inputMax is 679. The output is an LED, which always has a range of 0 - 255.

    • Set your new variable for the mapped value to equal the mapping function inside the void loop().

    If you are still stuck, please use the answer button below.


                        
     //C++ code
     //
    
     int ldrPin = A5;
     int redLEDPin = 3;
     int ldrReading = 0;
     int ldrMapValue = 0;
    
     void setup ()
     {
       pinMode(ldrPin, INPUT);
       pinMode(redLEDPin, OUTPUT);
       Serial.begin(9600);
     }
    
     void loop ()
     {
       ldrReading = analogRead(ldrPin);
       Serial.println(ldrReading);
       ldrMapValue = map(ldrReading, 6, 679, 0, 255);
     }                       
                        
                       

  7. Use this mapped value to set the brightness of the red LED.


    • As we are adjusting the brightness of the LED, we are using it as an analog output device.

    • Remember, we 'read' inputs and 'write' outputs.

    If you are still stuck, please use the answer button below.


                        
      //C++ code
      //
    
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
      int ldrMapValue = 0;
    
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 0, 255);
        analogWrite(redLEDPin, ldrMapValue);
      }                       
                        
                       

  8. If this was part of a home circuit to turn the lights on and off, we have a problem. At the moment the LED is at it's brightest when the light level is at it's highest. We would want it to be the other way round. Can you work out how to set it so the LED gets brighter as the light level drops?


    • We do not need to add any new lines of code, just to alter what we currently have.

    • By changing the range of the redLED in the mapping function from 0 - 255 to 255 - 0, we can reverse the program.

    If you are still stuck, please use the answer button below.


                         
      //C++ code
      //
    
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
      int ldrMapValue = 0;
    
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
        Serial.begin(9600);
      }
    
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
      }   
                         
                       



Continue using the program developed in the Bronze Level.

In this set of exercises we shall be creating a simulation of a home heating system. For this, we will need to use the temperature sensor to collect readings, the potentiometer to set our preferred heating level, and the blue and green LEDs to indicate when it is too cold, at the correct temperature, and too hot.

  1. As we are adding new components to our program, we need to create variables to store their pin values.

    Tip: There are four new components being added; the temperature sensor, the potentiometer, the blue LED, and the green LED.


    • Choose suitable variable names.

    • These are all integer type variables.

    • Look at the wiring of the components in the provided circuit to determine which programmable pin they each use.

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of the level.

                         
      //C++ code
      //
    
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
      int ldrMapValue = 0;
      int tempPin = A4;
      int potPin = A3;
      int greenLEDPin = 5;
      int blueLEDPin = 6;
    
                         
                       

  2. Now complete the necessary void setup() instructions for these components.


    • This means creating the pinMode() for each component.

    • Two of these components are inputs.

    • Use your pin value variables in place of the pin numbers.

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of the level.

                         
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
        Serial.begin(9600);
        pinMode(tempPin, INPUT);
        pinMode(potPin, INPUT);
        pinMode(greenLEDPin, OUTPUT);
        pinMode(blueLEDPin, OUTPUT);
      }
                         
                       

  3. Print the temperature sensor reading to the serial monitor and find its range of values.

    Tip: You will need a new variable to store this value.


    • We have already set-up the serial monitor for usage in the Bronze Level exercises.

    • The new variable is a global integer type variable which will store the temperature sensor's reading.

    • The temperature sensor is an analog input device.

    • Use the Serial.println() command in your void loop() to print the value of your new variable.

    • Remember, you are already printing the LDR value, so will get 2 values in the serial monitor each time the void loop() runs.

    If you are still stuck, please use the answer button below.

    The sections of the program altered is shown below. The full program will be added at the end of the level.

                        
     //C++ code
     //
    
     int ldrPin = A5;
     int redLEDPin = 3;
     int ldrReading = 0;
     int ldrMapValue = 0;
     int tempPin = A4;
     int potPin = A3;
     int greenLEDPin = 5;
     int blueLEDPin = 6;
     int tempReading = 0;
    
                        
                      

                         
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
        tempReading = analogRead(tempPin);
        Serial.println(tempReading);
      } 
                         
                       

    The range of the temperature sensor in this simulator is 20 - 358.


  4. The values we are currently collecting from the tempature sensor do not have much meaning in their current form. Map the temperature value onto a range of -40°C to 125°C, the program will the do the mathematical conversion to a known measurement for us.

    Tip: You will need a new variable to hold your converted temperature value.


    • Create a global integer type variable to store this value in and initially set it to zero.

    • When mapping values, we can map them to a new set of values rather than to an output's range.

    • Replace the outputMin value in the mapping function with -40, and the outputMax value to 125.

    • Use the range values from step 3 for the inputMin and inputMax values.

    If you are still stuck, please use the answer button below.

    The sections of the program altered is shown below. The full program will be added at the end of the level.

                        
     //C++ code
     //
    
     int ldrPin = A5;
     int redLEDPin = 3;
     int ldrReading = 0;
     int ldrMapValue = 0;
     int tempPin = A4;
     int potPin = A3;
     int greenLEDPin = 5;
     int blueLEDPin = 6;
     int tempReading = 0;
     int tempDegreesC = 0;
    
                        
                      

                         
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
        tempReading = analogRead(tempPin);
        Serial.println(tempReading);
        tempDegreesC = map(tempReading, 20, 358, -40, 125);
      } 
                         
                       

  5. If the temperature is more than 20°C, we want the green LED to turn on. However, if the temperature gets too high (over 50°C), we want the green LED to flash on and off every 250ms as a warning.

    Tip: Don't forget to turn the LED off when the temperature drops back down.


    • As we are simply turning the green LED on and off, we can use the digitalWrite() command, with the HIGH and LOW instructions.

    • You will need to think about the order of your if and else-if statements. The program will run the first one that is true. So if you first check to see if the temperature is over 20&drg;C, this will be true when it's over 50°C too and the warning light program will not work.

    • Remember, the instructions included in these statements need to be inside the curly brackets, { }. The statements themselves do not require semi-colons, but the instructions inside do.

    • We are using the newly mapped values of temperature in °C for these statement conditions.

    • For the flashing light, you will need to include delay() intructions.

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of the level.

                         
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
        tempReading = analogRead(tempPin);
        Serial.println(tempReading);
        tempDegreesC = map(tempReading, 20, 358, -40, 125);
        if (tempDegreesC > 50)
        {
          digitalWrite(greenLEDPin, HIGH);
          delay(250);
          digitalWrite(greenLEDPin, LOW);
          delay(250);
        }
        else if (tempDegreesC > 20)
        {
          digitalWrite(greenLEDPin, HIGH);
        }
        else
        {
          digitalWrite(greenLEDPin, LOW);
        }
      } 
                         
                       

  6. We need to add the potentiometer to our program as a temperature control dial. This means it needs to be mapped onto a more suitable range of values, in this case 5°C to 35°C.

    Tip: This is using the same method as converting the temperature readings.


    • Create global integer type variables for your potentiometer reading and the mapped potentiometer value and set them to zero.

    • If you do not know the range of the potentiometer, you will need to use the serial monitor to help you find it.

    • To test your mapping use the serial monitor. You may need to start printing additional information to separate the different values currently being produced. For this you can use Serial.print("") which will print whatever is typed between the quotation marks inside the brackets.

    • Add a one second delay at the end of your void loop() to give you chance to read the serial monitor before the program repeats.

    If you are still stuck, please use the answer button below.

    The sections of the program altered is shown below. The full program will be added at the end of the level.

                         
      //C++ code
      //
      
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
      int ldrMapValue = 0;
      int tempPin = A4;
      int potPin = A3;
      int greenLEDPin = 5;
      int blueLEDPin = 6;
      int tempReading = 0;
      int tempDegreesC = 0;
      int potReading = 0;
      int potDegreesC = 0;
                         
                       

                        
     void loop ()
     {
       ldrReading = analogRead(ldrPin);
       Serial.println(ldrReading);
       ldrMapValue = map(ldrReading, 6, 679, 255, 0);
       analogWrite(redLEDPin, ldrMapValue);
       tempReading = analogRead(tempPin);
       Serial.println(tempReading);
       tempDegreesC = map(tempReading, 20, 358, -40, 125);
       if (tempDegreesC > 50)
       {
         digitalWrite(greenLEDPin, HIGH);
         delay(250);
         digitalWrite(greenLEDPin, LOW);
         delay(250);
       }
       else if (tempDegreesC > 20)
       {
         digitalWrite(greenLEDPin, HIGH);
       }
       else
       {
         digitalWrite(greenLEDPin, LOW);
       }
       potReading = analogRead(potPin);
       Serial.println("Potentiometer reading: ");
       Serial.println(potReading);
       potDegreesC = map(potReading, 0, 1023, 5, 35);
       Serial.println("Potentiometer in degrees: ");
       Serial.println(potDegreesC);
       delay(1000);
     } 
                        
                      

  7. Now turn on the blue LED when the temperature is lower that that set on the potentiometer.

    Tip: Imagine that this is turning on the heating at the same time.


    • You will need to compare the mapped values for both the temperature sensor and the potentiometer inside an if-statement for this.

    • Remember to include an else statement to turn the Led off again when the temperature is reached.

    • You can remove any delay you may have added to help read the serial monitor in the previous step.

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of the level.

                         
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
        tempReading = analogRead(tempPin);
        Serial.println(tempReading);
        tempDegreesC = map(tempReading, 20, 358, -40, 125);
        if (tempDegreesC > 50)
        {
          digitalWrite(greenLEDPin, HIGH);
          delay(250);
          digitalWrite(greenLEDPin, LOW);
          delay(250);
        }
        else if (tempDegreesC > 20)
        {
          digitalWrite(greenLEDPin, HIGH);
        }
        else
        {
          digitalWrite(greenLEDPin, LOW);
        }
        potReading = analogRead(potPin);
        Serial.println("Potentiometer reading: ");
        Serial.println(potReading);
        potDegreesC = map(potReading, 0, 1023, 5, 35);
        Serial.println("Potentiometer in degrees: ");
        Serial.println(potDegreesC);
        if (tempDegreesC < potDegreesC)
        {
          digitalWrite(blueLEDPin, HIGH);
        }
        else
        {
          digitalWrite(blueLEDPin, LOW);
        }
      } 
                         
                       

  8. Run the simulation to check for bugs and to test your heating system works as expected.


                      
      //C++ code
      //
      
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
      int ldrMapValue = 0;
      int tempPin = A4;
      int potPin = A3;
      int greenLEDPin = 5;
      int blueLEDPin = 6;
      int tempReading = 0;
      int tempDegreesC = 0;
      int potReading = 0;
      int potDegreesC = 0;
    
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
        Serial.begin(9600);
        pinMode(tempPin, INPUT);
        pinMode(potPin, INPUT);
        pinMode(greenLEDPin, OUTPUT);
        pinMode(blueLEDPin, OUTPUT);
      }
    
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
        tempReading = analogRead(tempPin);
        Serial.println(tempReading);
        tempDegreesC = map(tempReading, 20, 358, -40, 125);
        if (tempDegreesC > 50)
        {
          digitalWrite(greenLEDPin, HIGH);
          delay(250);
          digitalWrite(greenLEDPin, LOW);
          delay(250);
        }
        else if (tempDegreesC > 20)
        {
          digitalWrite(greenLEDPin, HIGH);
        }
        else
        {
          digitalWrite(greenLEDPin, LOW);
        }
        potReading = analogRead(potPin);
        Serial.println("Potentiometer reading: ");
        Serial.println(potReading);
        potDegreesC = map(potReading, 0, 1023, 5, 35);
        Serial.println("Potentiometer in degrees: ");
        Serial.println(potDegreesC);
        if (tempDegreesC < potDegreesC)
        {
          digitalWrite(blueLEDPin, HIGH);
        }
        else
        {
          digitalWrite(blueLEDPin, LOW);
        }
      } 
                      
                    



Continuing on with our program we shall now program a home security system with some of the other components.

  1. Create global integer variables to store the PIR (motion sensor) and filament lightbulb pin values. Then use these to set-up the pin modes for both components.


    • The PIR is a digital input device that detects motion/movement.

    • For this exercise, the filament lightbulb is a digital output.

    If you are still stuck, please use the answer button below.

    The sections of the program altered is shown below. The full program will be added at the end of the level.

                         
      //C++ code
      //
      
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
      int ldrMapValue = 0;
      int tempPin = A4;
      int potPin = A3;
      int greenLEDPin = 5;
      int blueLEDPin = 6;
      int tempReading = 0;
      int tempDegreesC = 0;
      int potReading = 0;
      int potDegreesC = 0;
      int pirPin = 4;
      int bulbPin = 12;
                         
                       

                        
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
        Serial.begin(9600);
        pinMode(tempPin, INPUT);
        pinMode(potPin, INPUT);
        pinMode(greenLEDPin, OUTPUT);
        pinMode(blueLEDPin, OUTPUT);
        pinMode(pirPin, INPUT);
        pinMode(bulbPin, OUTPUT);
      }
                        
                      

  2. New Variable Type: The PIR sensor is a digital input device which reads TRUE when it detects motion, and FALSE when it does not. When a variable is true or false, it is called a Boolean type variable.

    So, when creating a variable to store a digital input value, we use bool instead of int.


  3. Create a global Boolean type variable and set it to 0. Then, in the void loop() set this new variable to read the PIR's digital input.


    • Use this new type of variable in the same way you would any other.

    • You will need to use the digitalRead() instruction.

    If you are still stuck, please use the answer button below.

    The sections of the program altered is shown below. The full program will be added at the end of the level.

                        
     //C++ code
     //
     
     int ldrPin = A5;
     int redLEDPin = 3;
     int ldrReading = 0;
     int ldrMapValue = 0;
     int tempPin = A4;
     int potPin = A3;
     int greenLEDPin = 5;
     int blueLEDPin = 6;
     int tempReading = 0;
     int tempDegreesC = 0;
     int potReading = 0;
     int potDegreesC = 0;
     int pirPin = 4;
     int bulbPin = 12;
     bool pirReading = 0;
                        
                      

                         
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
        tempReading = analogRead(tempPin);
        Serial.println(tempReading);
        tempDegreesC = map(tempReading, 20, 358, -40, 125);
        if (tempDegreesC > 50)
        {
          digitalWrite(greenLEDPin, HIGH);
          delay(250);
          digitalWrite(greenLEDPin, LOW);
          delay(250);
        }
        else if (tempDegreesC > 20)
        {
          digitalWrite(greenLEDPin, HIGH);
        }
        else
        {
          digitalWrite(greenLEDPin, LOW);
        }
        potReading = analogRead(potPin);
        Serial.println("Potentiometer reading: ");
        Serial.println(potReading);
        potDegreesC = map(potReading, 0, 1023, 5, 35);
        Serial.println("Potentiometer in degrees: ");
        Serial.println(potDegreesC);
        if (tempDegreesC < potDegreesC)
        {
          digitalWrite(blueLEDPin, HIGH);
        }
        else
        {
          digitalWrite(blueLEDPin, LOW);
        }
        pirReading = digitalRead(pirPin);
      } 
                         
                       

  4. We now want the filament lightbulb to turn on for 5 seconds when the PIR detects movement.

    Boolean conditions: The conditions of an if statement (or else if statement), are Boolean - they are either true or false. If it is true, then the program runs its contents. If it is not true (false) then it skips to the next section.

    This means that when we create an if statement checking to see if a Boolean variable is true we can simply use if (booleanVariable) because the condition is already checking to see if it is true.

    For example: Let's say we have a boolean variable called 'active' that tells the program to program to turn on an LED connected to pin 3 when 'active' is true. Here is the resulting program:

                      
      bool active = 0;
    
      void setup() 
      {
        pinMode(3, OUTPUT);
      }
    
      void loop()
      {
        active = FALSE;
        if (active)
        {
          digitalWrite(3, HIGH);
        }
        else
        {
          digitalWrite(3, LOW);
        }
      }
                      
                    

    At the moment, this program is checking to see if the Boolean value of active is true, which it is not, so the light will not turn on.

    If you wanted to change the program to do the opposite, turning the LED on when 'active' is false, you have two options. You could simply switch the instructions around in the previous program, like this:

                      
      if (active)
      {
        digitalWrite(3, LOW);
      }
      else
      {
        digitalWrite(3, HIGH);
      }  
                      
                    

    Alternatively you could have changed the condition to false using an exclaimation mark (!) before the variable name, like this:

                      
      if (!active)
      {
        digitalWrite(3, HIGH);
      }
      else
      {
        digitalWrite(3, LOW);
      }
                      
                    

    If you do write if(boolVariable = TRUE) or if(boolVariable = FALSE), it will still work. However, it demonstrates that the programmer does not fully understand how if-statements work.



    • You will need to turn the light off again after the 5 seconds.

    • Using a delay and a turn off command in the if-statement means we do not need an else statement.

    If you are still stuck, please use the answer button below.

    The section of the program altered is shown below. The full program will be added at the end of the level.

                         
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
        tempReading = analogRead(tempPin);
        Serial.println(tempReading);
        tempDegreesC = map(tempReading, 20, 358, -40, 125);
        if (tempDegreesC > 50)
        {
          digitalWrite(greenLEDPin, HIGH);
          delay(250);
          digitalWrite(greenLEDPin, LOW);
          delay(250);
        }
        else if (tempDegreesC > 20)
        {
          digitalWrite(greenLEDPin, HIGH);
        }
        else
        {
          digitalWrite(greenLEDPin, LOW);
        }
        potReading = analogRead(potPin);
        Serial.println("Potentiometer reading: ");
        Serial.println(potReading);
        potDegreesC = map(potReading, 0, 1023, 5, 35);
        Serial.println("Potentiometer in degrees: ");
        Serial.println(potDegreesC);
        if (tempDegreesC < potDegreesC)
        {
          digitalWrite(blueLEDPin, HIGH);
        }
        else
        {
          digitalWrite(blueLEDPin, LOW);
        }
        pirReading = digitalRead(pirPin);
        if (pirReading)
        {
          digitalWrite(bulbPin, HIGH);
          delay(5000);
          digitalWrite(bulbPin, LOW);
        }
      } 
                         
                       
  5. You now have a working security light which activates whenever something moves nearby.

  6. Create more variables to store the pin values for the force sensor, RGB LED, ultrasonic sensor and tilt sensor.

    Tip: Some of these components need more than one variable.


    • The RGB LED will require three different variables for the red, green and blue pins.

    • The ultrasonic sensor needs two variables. One for the trigger pin, the other for the echo pin.

    If you are still stuck, please use the answer button below.

    Here is an example of the new code that needs adding. Remember, your variable names may vary. The complete program is available at the end of this level.

                        
      int forcePin = A1;
      int rgbRedLEDPin = 9;
      int rgbGreenLEDPin = 10;
      int rgbBlueLEDPin = 11;
      int tiltPin = 2;
      int ultraTrigPin = 7;
      int ultraEchoPin = 8;
                        
                      

  7. Now create the pin modes in the void setup() for these new components.


    • The force sesor is an analog input device.

    • The RGB LED is an output.

    • The tilt sensor is a digital input.

    • The trigger pin on the ultrasonic is an output, whilst the echo pin is an input.

    If you are still stuck, please use the answer button below.

    Here is an example of the new code that needs adding. Remember, your variable names may vary. The complete program is available at the end of this level.

                        
      pinMode(forcePin, INPUT);
      pinMode(rgbRedLEDPin, OUTPUT);
      pinMode(rgbGreenLEDPin, OUTPUT);
      pinMode(rgbBlueLEDPin, OUTPUT);
      pinMode(tiltPin, INPUT);
      pinMode(ultraTrigPin, OUTPUT);
      pinMode(ultraEchoPin, INPUT);
                        
                      

  8. As we are using the ultrasonic, we need to add the below function to the program, like we did for Session Three's Gold Level exercises. This function produces an integer value of the distance (in cm) an object is from the ultrasonic sensor.

                    
      int readUltrasonic() 
      {
        digitalWrite(ultrasonicTrigger,LOW); // Clear the signal
        delayMicroseconds(2);
        digitalWrite(ultrasonicTrigger, HIGH); // Send out new signal
        delayMicroseconds(10);
        digitalWrite(ultrasonicTrigger,LOW); // Stop sending signal
    
        unsigned long duration = pulseIn(ultrasonicEcho, HIGH);
        int distance = duration /2 /29;
        Serial.print(distance);
        Serial.print("cm");
        return distance;
      }
                    
                  

    You will need to change the variables of ultrasonicTrigger and ultrasonicEcho in this code to match the variable names you created for the ultrasonic's trigger and echo pins.

    Tip: As this is a function, have it in your code after the variables, but before the void setup() section

    .

    We've re-written the code provided to match the variable names in our answer program.

                      
      int readUltrasonic() 
      {
        digitalWrite(ultraTrigPin,LOW); // Clear the signal
        delayMicroseconds(2);
        digitalWrite(ultraTrigPin, HIGH); // Send out new signal
        delayMicroseconds(10);
        digitalWrite(ultraTrigPin,LOW); // Stop sending signal
    
        unsigned long duration = pulseIn(ultraEchoPin, HIGH);
        int distance = duration /2 /29;
        Serial.print(distance);
        Serial.print("cm");
        return distance;
      }
                      
                    

  9. Create a new function which we will be using to contain an alarm system program.

    Here is an example of the new code that needs adding. Remember, your function name may be different. The complete program is available at the end of this level.

                      
      void alarmSystem()
      {
    
      }
                      
                    

  10. Inside our alarm system function we want to write a program that increases the brightness of the red pin on the RGB LED as the force sensor reading increases.


    • You will need to create a variable to store your force sensor reading and another for the mapped value.

    • In you void loop(), use the serial monitor to work out the range for the force sensor. Remember, you already have lots of values being printed, so include some text. You may also need to add a delay to slow the serial monitor print-outs.

    • Once you have the range of the force sensor, you can map them onto the red pin of the RGB LED.

    • To test your program, you will need to call the alarm system function inside the void loop().

    If you are still stuck, please use the answer button below.

    Here is an example of setting the necessary variables for this:

                        
      int forceReading = 0;
      int forceMapRed = 0;
                        
                      

    Here is the code needed to find the range of the force sensor. This needs to be removed after use.

                        
      forceReading = analogRead(forcePin);
      Serial.println("Force Reading: ");
      Serial.println(forceReading);
      delay(1000);
      alarmSystem(); //to test our new function's program.
                        
                      

    Here is the code for our alarm system function:

                        
      forceReading = analogRead(forcePin);
      forceMapRed = map (forceReading, 0, 466, 0, 255);
      analogWrite(rgbRedLEDPin, forceMapRed);
                        
                      

  11. Continuing with the program inside the alarm system function, add instructions for the blue light in the RGB LED to increase as an object moves closer to the ultrasonic sensor.


    • You do not need to create a variable for the ultrasonic reading as we already have a function for that.

    • Follow the same steps as we did for the force sensor mapping.

    • Remember, by setting the range of an LED the other way around (255 - 0) in a mapping, we get a brighter light for lower values.

    If you are still stuck, please use the answer button below.


    Here is an example of setting the necessary variables for this:

                          
      int ultraMapBlue = 0;
                          
                        

    Here is the code needed to find the range of the force sensor. This needs to be removed after use.

                          
      Serial.println("Ultrasonic Distance:");
      Serial.println(readUltrasonic());
      delay(1000);
      alarmSystem(); //to test our new function's program.
                          
                        

    Here is the code for our alarm system function:

                          
      ultraMapBlue = map (readUltrasonic(), 2, 331, 255, 0);
      analogWrite(rgbBlueLEDPin, ultraMapBlue);
                          
                        

  12. In our alarm system function we now need to add instructions that if the tilt sensor gets a positive reading (is tilted), the green light in the RGB LED turns on.


    • We are using the tilt sensor as a digital input like the PIR. This means you will need a Boolean variable to store the reading.

    • This does not require mapping as we are using digital read and write for this.

    • Make sure the light turns off when the condition is not being met.

    If you are still stuck, please use the answer button below.

    You will need to add a new variable for the tilt sensor reading.

                          
      bool tiltReading = 0;
                          
                        

    The program you'll need to add to you alarm system function. Variable names may differ to your own.

                          
      tiltReading = digitalRead(tiltPin);
      if (tiltReading)
      {
        digitalWrite(rgbGreenLEDPin, HIGH);
      }
      else
      {
        digitalWrite(rgbGreenLEDPin, LOW);
      }
                          
                        

  13. At the moment, if more than one sensor of our alarm system triggers, we get a mixed colour from the RGB LED. Instead, we want the program to flash each colour one after the other. That way, the user can clearly see which sensors are triggered.


    • We need to add delays between each different sensor - 250ms should be enough.

    • Also, we need to set the pins back to zero before the next sensor.

    If you are still stuck, please use the answer button below.

    The alarm system function should now look like this:

                          
      void alarmSystem()
      {
        forceReading = analogRead(forcePin);
        forceMapRed = map (forceReading, 0, 466, 0, 255);
        analogWrite(rgbRedLEDPin, forceMapRed);
        delay(250);
        analogWrite(rgbRedLEDPin, 0);
        ultraMapBlue = map (readUltrasonic(), 2, 331, 255, 0);
        analogWrite(rgbBlueLEDPin, ultraMapBlue);
        delay(250);
        analogWrite(rgbBlueLEDPin, 0);
        tiltReading = digitalRead(tiltPin);
        if (tiltReading)
        {
          digitalWrite(rgbGreenLEDPin, HIGH);
        }
        else
        {
          digitalWrite(rgbGreenLEDPin, LOW);
        }
        delay(250);
        digitalWrite(rgbGreenLEDPin, LOW);
      }
                          
                        

  14. Although we have included been calling the alarm system function inside our void loop() during testing, we have yet to decide when it should be called. Create a new boolean type variable called 'activate'. We shall use this to tell the program that the alarm system needs to run if activate is set to TRUE.


    • We don't have a physical input device to read for this variable. Instead, we will need to set the variable to 1 (TRUE) or 0 (FALSE) inside the void loop() to test.

    • Remember, this is a Boolean condition for the if-statement.

    If you are still stuck, please use the answer button below.

    Here are the sections of code that need adding to your program. Remember, the variable and function names be be different to your own.

                          
      bool activate = 0;
                          
                        

                          
      activate = 1;                      
      if (activate)
      {
        alarmSystem();
      }
                          
                        

  15. Hopefully, you've been constantly testing your program throughout these exercises. If not, it could be difficult to debug at such a late stage.


                        
      //C++ code
      //
      
      int ldrPin = A5;
      int redLEDPin = 3;
      int ldrReading = 0;
      int ldrMapValue = 0;
      int tempPin = A4;
      int potPin = A3;
      int greenLEDPin = 5;
      int blueLEDPin = 6;
      int tempReading = 0;
      int tempDegreesC = 0;
      int potReading = 0;
      int potDegreesC = 0;
      int pirPin = 4;
      int bulbPin = 12;  
      bool pirReading = 0;
      int forcePin = A1;
      int rgbRedLEDPin = 9;
      int rgbGreenLEDPin = 10;
      int rgbBlueLEDPin = 11;
      int tiltPin = 2;
      int ultraTrigPin = 7;
      int ultraEchoPin = 8;
      int forceReading = 0;
      int forceMapRed = 0;
      int ultraMapBlue = 0;
      bool tiltReading = 0;
      bool activate = 0;
    
      int readUltrasonic() 
      {
        digitalWrite(ultraTrigPin,LOW); // Clear the signal
        delayMicroseconds(2);
        digitalWrite(ultraTrigPin, HIGH); // Send out new signal
        delayMicroseconds(10);
        digitalWrite(ultraTrigPin,LOW); // Stop sending signal
    
        unsigned long duration = pulseIn(ultraEchoPin, HIGH);
        int distance = duration /2 /29;
        Serial.print(distance);
        Serial.print("cm");
        return distance;
      }
    
      void alarmSystem()
      {
        forceReading = analogRead(forcePin);
        forceMapRed = map (forceReading, 0, 466, 0, 255);
        analogWrite(rgbRedLEDPin, forceMapRed);
        delay(250);
        analogWrite(rgbRedLEDPin, 0);
        ultraMapBlue = map (readUltrasonic(), 2, 331, 255, 0);
        analogWrite(rgbBlueLEDPin, ultraMapBlue);
        delay(250);
        analogWrite(rgbBlueLEDPin, 0);
        tiltReading = digitalRead(tiltPin);
        if (tiltReading)
        {
          digitalWrite(rgbGreenLEDPin, HIGH);
        }
        else
        {
          digitalWrite(rgbGreenLEDPin, LOW);
        }
        delay(250);
        digitalWrite(rgbGreenLEDPin, LOW);
      }
    
      void setup ()
      {
        pinMode(ldrPin, INPUT);
        pinMode(redLEDPin, OUTPUT);
        Serial.begin(9600);
        pinMode(tempPin, INPUT);
        pinMode(potPin, INPUT);
        pinMode(greenLEDPin, OUTPUT);
        pinMode(blueLEDPin, OUTPUT);
        pinMode(pirPin, INPUT);
        pinMode(bulbPin, OUTPUT);
        pinMode(forcePin, INPUT);
        pinMode(rgbRedLEDPin, OUTPUT);
        pinMode(rgbGreenLEDPin, OUTPUT);
        pinMode(rgbBlueLEDPin, OUTPUT);
        pinMode(tiltPin, INPUT);
        pinMode(ultraTrigPin, OUTPUT);
        pinMode(ultraEchoPin, INPUT);
      }
    
      void loop ()
      {
        ldrReading = analogRead(ldrPin);
        Serial.println(ldrReading);
        ldrMapValue = map(ldrReading, 6, 679, 255, 0);
        analogWrite(redLEDPin, ldrMapValue);
        tempReading = analogRead(tempPin);
        Serial.println(tempReading);
        tempDegreesC = map(tempReading, 20, 358, -40, 125);
        if (tempDegreesC > 50)
        {
          digitalWrite(greenLEDPin, HIGH);
          delay(250);
          digitalWrite(greenLEDPin, LOW);
          delay(250);
        }
        else if (tempDegreesC > 20)
        {
          digitalWrite(greenLEDPin, HIGH);
        }
        else
        {
          digitalWrite(greenLEDPin, LOW);
        }
        potReading = analogRead(potPin);
        Serial.println("Potentiometer reading: ");
        Serial.println(potReading);
        potDegreesC = map(potReading, 0, 1023, 5, 35);
        Serial.println("Potentiometer in degrees: ");
        Serial.println(potDegreesC);
        if (tempDegreesC < potDegreesC)
        {
          digitalWrite(blueLEDPin, HIGH);
        }
        else
        {
          digitalWrite(blueLEDPin, LOW);
        }
        pirReading = digitalRead(pirPin);
        if (pirReading)
        {
          digitalWrite(bulbPin, HIGH);
          delay(5000);
          digitalWrite(bulbPin, LOW);
        }
        activate = 1;                      
        if (activate)
        {
          alarmSystem();
        }
      } 
                        
                      


Should you wish to continue working with this circuit and program, here are some additional ideas for you.