Arduino Programming Guide

  • Variables

    Code: Select all

    int led - 13;
    // the start procedure is executed once 
    // after you press the reset button:
    void setup(){
    // initialize the digital pin as an output.
    pinMode(led, OUTPUT);
    // the cyclic procedure repeats over and over again,
    // and so on ad infinitum:
    void loop(){
    
    digitalWrite(led, HIGH); // turn on the LED
                                        // (HIGH is the voltage level)
    delay(1000); // wait 1 second
    digitalWrite(led, LOW); // turn off the LED,
                                       // by switching the voltage to the LOW level
    delay(1000); // wait 1 second
    Variables act as labels for values in your code. In the Blink sketch, the opening line (excluding comments) is:

    int led = 13;

    This line creates the variable called "led," initializing it with a value of 13.

    The selection of 13 corresponds to the Arduino pin marked as "13," where the LED "L" is attached. The data type of this variable is "int," which is an abbreviation for "integer," representing a whole number without decimals.

    Although it is not compulsory to assign a distinct variable name for every contact or component used in your work, it is recommended. This approach improves code clarity by allowing for a better understanding of each variable's purpose in your programme. Furthermore, if you need to modify a variable name, you'll only need to do it in one location where it was initially defined, should you choose to switch to a different contact or component.

    In the examples featured in this book, when defining variables in this way (where you specify the pin you intend to work with), the term "const" appears before the line, as shown:

    const int led=13;

    The "const" keyword
    tells the Arduino IDE that this isn't really a variable but a constant.

    In other words, its value remains fixed at 13 and never changes. This technique aids in creating more succinct and effective sketches. It is strongly recommended to develop the habit of using this keyword when it is appropriate.
    Last edited by Oleg on 03 Oct 2023, 05:57, edited 1 time in total.
  • Digital outputs

    The Blink programme serves as a useful demonstration of digital output. Firstly, we assigned the value 13 to the variable "led." Next, we used the following line within the setup() function to configure pin 13 for output:

    pinMode(led, OUTPUT);

    This configuration takes
    place within the setup() function as it's a one-time operation.

    If a pin is set up for output, it will keep this configuration until you issue a different command.

    To make the LED blink, it must be turned on and off alternately in a continuous cycle. Here is the corresponding code for this action.

    Code: Select all

    digitalWrite(led, HIGH); // turn LED on
                                        // (HIGH is the voltage level)
    delay(1000); // wait 1 second
    digitalWrite(led, LOW);// turn off the LED,
                                       // by switching the voltage to the LOW level
    delay(1000); // wait 1 second
    The digitalWrite() function requires two parameters enclosed within parentheses and separated by a comma. The first parameter designates the Arduino pin to be operated, while the second parameter specifies the value to be written to that pin. A value of HIGH illuminates the LED, resulting in 5V output. Conversely, a value of LOW corresponds to 0V, switching off the LED.

    Additionally, the delay() function creates a pause in program execution for a specified period designated in milliseconds. It's noteworthy that 1000 milliseconds comprise one second. Hence, using the delay(1000) function will pause program execution for precisely one second.
    Last edited by Oleg on 03 Oct 2023, 05:57, edited 1 time in total.
  • Digital inputs

    It's essential to understand digital inputs as they enable you to connect switches and sensors to the Arduino. To designate an Arduino pin as a digital input, utilize the pinMode() function as follows:


    pinMode(7, INPUT);

    In this particular instance, we are configuring pin 7 as an input.

    Instead of specifying the pin number directly, you can use a variable name.
    Similar to the output pins' configuration, set up an input pin within the setup() function. It's usually unnecessary to change the pin's mode during the sketch's execution phase. After setting up a pin for input, you can retrieve information by checking the voltage at the pin to determine whether it's closer to 5V (HIGH) or 0V (LOW). In the following example, the LED will turn on if the input is LOW during the evaluation (keep in mind that the LED will stay on because there's no code command to turn it off).

    Code: Select all

    void loop()
    {
    if (digitalRead(7) == HIGH)
    {
    digitalWrite(led, LOW)
    }
    }
    Our program is getting more complex, so let's break it down step by step.

    On the second line, there is a curly brace '{' that may be placed on the same line as 'loop()' or on the following line - both are acceptable. The curly brace begins the code block and is matched with a closing curly brace '}' to signal its end. This approach groups all code lines related to the 'loop()' function.

    The beginning of these lines has an 'if' statement with a condition following immediately. For us, the condition is '(digitalRead(7) == HIGH)'. Using '==' signifies a comparison between values on either side. In our case, if pin 7 has a HIGH value, the code within '{' and '}' executes; otherwise, it won't. Vertically aligning the opening and closing curly braces '{' and '}' helps clarify which '}' corresponds to which '{'.

    We've explained already how the code functions when the condition is met; the 'digitalWrite()' function activates the LED.

    In this example, we assumed that a digital input can only have one of two values: HIGH or LOW. If you use a switch connected to the digital input, it usually only allows you to close the circuit. In most cases, connecting the digital input to ground (0V) is necessary. If the switch's connection is open, it's called the digital input being "unconnected" or "floating." In simpler terms, it lacks an electrical connection, making it susceptible to electrical interference and frequent transitioning between high and low states spontaneously. To avoid this undesired behavior, a "pull-up resistor" is frequently used, as depicted in the diagram.


    When the switch is open (as shown in the diagram), the resistor pulls up the input pin to a 5V voltage. However, when we press the button and close the switch, the connection to ground from the switch supersedes the weak input pull-up.

    You can opt to use separate external pull-up resistors, but Arduino inputs have built-in pull-up resistors with an approximate value of 40k ohms. Activate the built-in pull-up resistors by setting the pin's operational mode to INPUT_PULLUP, instead of INPUT alone. The code below illustrates how to configure a digital input pin to operate with a switch, eliminating the necessity for an external pull-up resistor as illustrated in the

    diagram:


    pinMode(switchPin, INPUT_PULLUP);
    Attachments
    image.png
    image.png (52.5 KiB)
    Viewed 5644 times
    Last edited by Oleg on 03 Oct 2023, 05:56, edited 2 times in total.
  • Analog inputs

    Analog inputs enable you to measure voltages ranging from 0 to 5V on any of the Arduino's specialized analog pins, identified as A0 to A5. Unlike digital pins and inputs, analog inputs do not require the use of the pinMode() function during the setup stage.

    To obtain the value of an analog input, utilize the analogRead() function, where one of the parameters is the designated pin for reading. Unlike the digitalRead() function, the analogRead() function provides a numerical value instead of a boolean. The value returned by analogRead() ranges from 0 to 1023, where 0 corresponds to 0 volts and 1023 corresponds to 5 volts. To convert the analogRead() value to an actual voltage reading, multiply the value by 5 and divide it by 1023, or divide it directly by 204.6. Here is an example of how to perform this calculation in C for the Arduino platform:

    int raw = analogRead(A0);
    float volts = raw / 204.6;


    To convert the analog input reading into a decimal number, the raw variable should be of type float (floating point number), even though we always receive an integer value from the analog input.

    Various sensors can be connected to the analog inputs. For instance, one can use the analog input with a photoresistor sensor and connect a variable resistor.
    Last edited by Oleg on 03 Oct 2023, 05:58, edited 1 time in total.
  • Analog Outputs

    On an Arduino Uno, the digital pins are capable of only toggling electronic components, like LEDs, on and off.

    However, if you need to finely adjust the voltage being delivered to a device, you'll require an analog output. This type of output is particularly handy for controlling the brightness of an LED or the speed of a motor.

    It's important to note that not all pins on the Arduino Uno support analog output functionality. Only pins D3, D5, D6, D9, D10, and D11 can serve this purpose. These pins on the Arduino board are identified with a tilde symbol (~).

    To regulate the analog output, you can utilize the analogWrite() function, which accepts parameters ranging from 0 to 255. A value of 0 signifies 0 V (completely inactive), while 255 represents full power.

    One might assume that the analog pin accepts a voltage within the 0 V to 5 V range. If you were to connect a voltmeter between the analog pin and ground, and then adjust the analogWrite() parameters from 0 to 255, it might seem like the voltage is smoothly changing between 0 and 5 V. However, the reality is more intricate. This phenomenon is known as Pulse Width Modulation (PWM), as illustrated in the figure.

    Each pin operating in analog output mode generates 490 pulses per second, with the exception of pins D5 and D6, which produce 980 pulses per second. You can alter the duration of these pulses by adjusting the parameters of the analogWrite() function. Essentially, the longer the pulse remains high, the more power is delivered to the output. Consequently, the LED will shine brighter or the motor will spin faster.
    image.png
    image.png (46.44 KiB)
    Viewed 5644 times
    The voltmeter records this process as a change in voltage because it is not capable of reacting swiftly enough. As a result, it effectively averages the received voltage, creating the impression of a gradual change to us.
  • If...Else operator
    If you recall, in Section "Digital Inputs," we utilized the if operator to execute a specific action when a particular condition is satisfied. To improve code execution control, utilize the if...else operator. This operator executes one code if a condition is met, and another code if it is not met.

    The LED in the code below will turn on or off depending on whether the analog value is greater than 500 or less than or equal to 500:

    Code: Select all

    if (analogRead(A0) > 500) {
        digitalWrite(led, HIGH);
    } else {
        digitalWrite(led, LOW);
    }
    
    So far, we have learned about two comparison operators: == for equal and > for greater than. However, there are other comparison operators that you can use, including <=
    for less than or equal
    to, >= for greater than or
    equal to, and != for not equal.

    You can make more complex comparisons using the "&&&" (AND) and "||" (OR) operators in addition to comparing pairs of values. For instance, to activate the LED only when the value is within the range of 300 to 400, write the subsequent code:

    Code: Select all

     int reading = analogRead(A0);
    if ((reading >= 300) && (reading <= 400)) {
        digitalWrite(led, HIGH);
    } else {
        digitalWrite(led, LOW);
    }
    
    Last edited by Oleg on 03 Oct 2023, 05:58, edited 1 time in total.
  • Cycles

    Loops allow you to repeat code a specific number of times or continuously until a certain condition changes. For this purpose, you can use for or while loops: for loops are convenient for performing a specific action a fixed number of times, while while loops are suitable for executing an operation as long as a specific condition remains true.

    In the following example, a for loop will make the LED blink 10 times (note that the for loop is located within the setup() function, not in loop()). This is important because if the for loop were placed in loop(), the LED would blink another 10 times after the initial 10, which may not produce the desired effect:

    Code: Select all

    for (int i = 0; i < 10; i++) {
      digitalWrite(led, HIGH); 
      delay(1000);
      digitalWrite(led, LOW);
      delay(1000);
    }
    
    If you wanted all LEDs to blink as long as a button connected to a digital input remained pressed, you would use a while loop:

    Code: Select all

    while (digitalRead(9)) {
      digitalWrite(led, HIGH);
      delay(1000);
      digitalWrite(led, LOW);
      delay(1000);
    }

    This code assumes that digital pin D9 is connected to a button.
  • Functions

    Functions can be quite daunting for a novice programmer. Perhaps the easiest way to think of a function is as a means to group several lines of code together and give them a common name, making it easy to reuse that code fragment again and again.

    If you were to delve into the inner workings of Arduino, you would notice that built-in functions like digitalWrite() can be, to put it mildly, complex. Below is the code for the digitalWrite() function (don't attempt to decipher what it does; just be grateful that you don't have to type all of this code every time you want to change a pin from a high state to a low state):

    Code: Select all

    void digitalWrite(uint8_t pin, uint8_t val) {
      uint8_t timer = digitalPinToTimer(pin);
      uint8_t bit = digitalPinToBitMask(pin); 
      uint8_t port = digitalPinToPort(pin);
      volatile uint8_t *out;
      
      if (port == NOT_A_PIN) return;
    
      // If the pin supports PWM output, it must be turned off before performing digital write
      if (timer == NOT_ON_TIMER) turnOffPWM(timer);
      
      out = portOutputRegister(port);
    
      uint8_t oldSREG = SREG;
      cli();
    
      if (val == LOW) {
        *out &= ~bit;
      } else {
        *out |= bit;
      }
      SREG = oldSREG;
    }

    By assigning a name to such a large code fragment, we only need to refer to it by name and use it.

    In addition to built-in functions (such as digitalWrite), you can create your own functions to encapsulate operations you frequently use. For example, you can write a function that makes an LED blink a specified number of times, with the target pin also specified as a parameter. This is demonstrated in the following sketch: we define a blink function and call it in the setup() stage, causing the LED on the Arduino board to blink 5 times after a reset:

    Code: Select all

    const int ledPin = 13;
    
    void setup()
    {
      pinMode(ledPin, OUTPUT);
      blink(ledPin, 5);
    }
    
    void loop() {}
    
    void blink(int pin, int n)
    {
      for (int i = 0; i < n; i++)
      {
        digitalWrite(pin, HIGH);
        delay(500);
        digitalWrite(pin, LOW);
        delay(500);
      }
    }

    In this code, the setup() function sets ledPin as an output and then calls the blink function, providing it with the name of the pin to blink and the number of times it should blink. The loop() function is empty and does nothing, but the Arduino IDE expects it to be present.

    The blink function itself begins with the word void, indicating that the function doesn't return anything. In other words, you cannot assign the result of calling this function to a variable, which might be something you'd want to do if the function performed some calculations. Next, we see the name of the function (blink) and its parameters enclosed in parentheses and separated by commas. When defining a function, you need to specify the type of each parameter (e.g., int, float, etc.). In our case, both the pin to blink (pin) and the number of blinks (n) are integers (int).

    In the C language, as well as in most other programming languages, there is a distinction between local and global variables. Global variables (like ledPin in the previous example) can be used anywhere in the program. On the other hand, local variables, such as function parameters (in our case, pin and n), and even the variable i in the for loop, are only accessible within the function where they are defined.

    So, in the setup() function, the line blink(ledPin, 5) passes the global variable ledPin to the blink function, where it is assigned to the local variable pin. It may seem redundant, but by passing pin to blink, we make the blink function versatile, allowing us to blink any specified pin, not just ledPin.

    Inside the blink function's body, there is a for loop that will repeatedly call the digitalWrite() and delay() functions 5 times. However, if you set it to 3, the LED will blink 3 times.