© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2021
A. SuberoProgramming Microcontrollers with Pythonhttps://doi.org/10.1007/978-1-4842-7058-5_5

5. Digital Control

Armstrong Subero1  
(1)
Basse Terre, Moruga, Trinidad and Tobago
 

At this point, we have covered enough about electronics, embedded systems architecture, and programming to begin using physical microcontroller devices. Now we will learn the basics of undoubtedly the most important operations you will handle with your microcontroller: input and output. At the heart of every microcontroller system, you will at a minimum have an output being performed, and many systems take in inputs as well.

In this chapter, you will begin to see how to control and manipulate physical sensors and actuators. There is something satisfying about manipulating physical I/O devices that just cannot be matched by pushing pixels around a screen. I hope this chapter will introduce you to the joys of working with hardware and whet your appetite for further experiments with microcontroller development.

I/O Pins

Microcontroller devices have physical pins attached to them. These pins have a valuable purpose: they allow the microcontroller device to be interfaced to the outside world. As we’ve discussed previously, a microcontroller system typically takes an input of some sort, performs some processing, and then provides an output that manipulates some external peripheral or device. This is the premise of input and output control.

Generally, you can tell a lot about a microcontroller from the number of input and output pins it controls. More pins on a microcontroller means the device will usually contain more peripherals and have a powerful CPU core. Microcontrollers typically have at least six I/O pins. Sometimes, they can have hundreds.

In the past, it was common for a microcontroller to come in a DIP package. You would need to connect it to a programmer and set up the proper connections and power configurations before you could use it. While this may be good in a professional setting, it is overly complicated for makers and people just getting started with microcontrollers. The rise of the development board has simplified the process for hobbyists. The board comes with a microcontroller in a known working state, allowing the user to concentrate right away on building circuits and attaching external devices and also focus on writing software.

Output and Input on Microcontroller Hardware

On the underlying hardware, microcontrollers typically perform output using what is known as a port. In its simplest form, a port can be thought of as a collection of pins that allow the microcontroller to be interfaced to the outside world.

Ports are usually arranged in groups of pins; typically around 8 or 16 pins make up a port, and this can be as high as 32 pins. You may be wondering why we need to group microcontroller pins in the ports in the first place. What you must know is that in the microcontroller architecture, the ports are nothing more than registers. Thus, there is some correlation between the number of pins in a port and the architecture of the microcontroller. So, an 8-bit microcontroller typically has ports that have 8 pins, and 16-bit microcontrollers have ports that have 16 pins. This is not set in stone however; you may have a 32-bit microcontroller, for example, that has ports that are 16 bits wide (have 16 pins) or may even have as low as 4 pins to a port. As a user of microcontroller devices, you can simply think of this as a manufacturer’s design decision. You should also know that since a port is a register, each pin on that port is a bit in the register. Ports are given a designation such as PORTA or PORTB, and the pins within each port are numbered. Let’s imagine we have a hypothetical microcontroller with two ports, PORTA and PORTB, as shown in Figure 5-1.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig1_HTML.jpg
Figure 5-1

A Hypothetical Microcontroller with Two Ports

The pins on PORTA are all designated with the names “AX,” where “X” is a bit associated with that port. So, for example, the A1 pin refers to the first bit on PORTA. Shortened names like “A1” make for easier identification and labeling, and they also help when you need to access a particular pin when you’re writing code for the microcontroller.

The pins on PORTB in Figure 5-1 follow a different naming convention than those on PORTA: “PBX” rather than “BX.” Different manufacturers follow different naming conventions for port pins. Some will use the names like “A1” and “D1,” while others will use names like “PA1” and “PD1.” Only the naming convention changes. The pins themselves work the same way. In practice, it is common for microcontrollers to have their pin numbers start from 0. Thus, the first pin in PORTA is typically called something like A0 or PA0.

For simplicity, it would be nice for each pin on a microcontroller to have a dedicated function. For example, we can imagine that PORTA on our hypothetical device is an output port, which means that the pins on the port can only carry data out of the microcontroller. Similarly, we can imagine that PORTB is an input-only port, being able to only accept data from the outside world and into the microcontroller.

However, what would happen if we had an application where the microcontroller must interface with a lot of output devices, like controlling 15 lights? Or we could have the microcontroller control a keypad that has 12 inputs? In both cases, the number of pins we have available for input or output would be limited if they are only used for one purpose. As such, it is common to have the pins on a microcontroller be configured as input or output based on the discretion of the circuit designer.

To allow for this, there must be some mechanism internal to the microcontroller that will allow pins on the ports to be used as either input or output. Thus, in many microcontrollers, it is common to have a register that can control the direction of data into and out of the pin. This register is programmed via software and is controlled by the microcontroller programmer.

When used in this way where the port can be configured as simply an input or an output, the port pin is said to be in a digital state. When in the digital state, the pins can be configured in several ways; usually, we say that it has three states. As an output, it can be configured as output high, where the pin is an output and is providing current to the load. The pin can also be an output low, where the pin is still configured as an output pin but is not providing current to the load. The pin can also be configured as an input.

Not only is it common to have internal circuitry that can control the direction of the pins, but many times a microcontroller has other internal peripherals and modules that depend on these same pins to perform their input and output function. These include things like serial interfaces, using internal timers or analog functions. These are known as alternate functions of the pin, and these vary depending on the manufacturer.

This is necessary as while most microcontrollers include many features and onboard peripherals, most applications only require one or two of these peripherals to be used at any point in time. Thus, in order to ensure that we don’t need pins for every peripheral present on the microcontroller, this internal circuitry will ensure that onboard functions can be shared among limited I/O pins (remember the multiplexer we talked about earlier? This is an application for that device within the microcontroller). For that reason, it is common to see a microcontroller more closely resemble the diagram in Figure 5-2.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig2_HTML.jpg
Figure 5-2

A More Realistic Microcontroller

The microcontroller in Figure 5-2 represents a more accurate depiction of what a microcontroller will look like when you consider the fact that most pins include alternate functions. As you can see, there are multiple ports: PORTA, PORTB, PORTC, and PORTD. Each of these ports has pins with various functions. The VDD pins and VSS pins on all microcontrollers are not associated with any I/O port as they provide power to the device. An experienced designer will be able to look at a similar diagram and realize which pins are used for which purpose. For example, we know that pin PA0 will most likely be used for both digital input and output. However, the label AN0 is also attached to the pin. This means the pin can also be used for an analog input functionality. The third label, INT0, means that we can use the pin for external interrupt capability as well.

As you gain more experience with design and become more familiar with different microcontroller families, you will be able to look at the ports on the circuit diagram and know which pins have what alternate functionality. Even with such experience, though, you cannot always tell what purpose a pin may serve. For example, look at pin PC3. Thanks to the alternate AN3 label, you may think that it can be used for both digital and analog functionality, but what does the CMP label mean? Such questions are best answered by the datasheet for the device you are working with. The datasheet may reveal, for example, that this pin is an input-only pin and cannot be used for any digital output functionality. Be sure to keep a copy of the device datasheet on hand to answer questions such as this.

Going Deeper into Microcontroller I/O

You may be wondering how exactly a microcontroller is able to perform the input and output using the pins. While the digital electronics behind how this works can get quite complicated, we can look at some basic circuit constructs to understand a little about what happens at the lowest level.

In the case of an output pin, look at the circuit diagram in Figure 5-3.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig3_HTML.jpg
Figure 5-3

MCU Output Circuit

In this scenario, we have a flip-flop or some other latch circuit that is under CPU control. Do you remember when we talked about the flip-flop? Well, this is one application of the flip-flop within the microcontroller. Remember we said that the flip-flop can store a single bit of data at a time. Well, when our pin is set as an output, we can output a high value (logical one) or output a low value (logic zero). The flip-flop is used to store the desired bit we want (high or low). The output of the latch circuit passes through a buffer. This buffer circuit allows for a greater drive strength and gives the microcontroller internals better protection from electrical disturbances that may be present external to the device. Also not shown here are protection diodes which work together with the buffer to protect the microcontroller. The output of the buffer circuit then connects to the physical pin on the microcontroller.

Similarly, we can gain an understanding of how input on a microcontroller works by looking at the circuit diagram in Figure 5-4.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig4_HTML.jpg
Figure 5-4

MCU Input Circuit

In this case, the pin connects to a buffer that has an enable function. When the CPU manipulates the enable pin to the buffer (which of course it will do based on instructions in the program code), the voltage level of the pin can then be read, and the CPU can then use this information for any purpose.

Of course, in real MCUs, the circuit can get more complicated than this because the pins on the microcontroller must act as both input and output. This is called bidirectional control, and it allows the microcontroller to use a single pin for input and output.

Our look at input and output circuits leads us to another consideration when working with microcontroller I/O pins: the ability of a microcontroller port to sink or to source current. Sourcing current refers to a microcontroller’s ability to supply current to the load. That is to say, current will flow from the microcontroller pin, through the load, and then to the ground. Figure 5-5 depicts what sourcing current looks like.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig5_HTML.jpg
Figure 5-5

MCU Sourcing Current

A microcontroller I/O pin can also sink current. In this case, current flows from the supply source, through the load, and into the I/O pin. Figure 5-6 shows what sinking current looks like.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig6_HTML.jpg
Figure 5-6

MCU Sinking Current

Using Output: Lighting an LED

Now that we understand a little about microcontroller ports, we can look at using output to perform a function: in this case, lighting up an LED. Much like printing “Hello, world!” is a traditional first step when learning a new coding language, operating an LED is a traditional first task when working with a new microcontroller. It allows you to verify that you have a working program and that all your connections are accurate. In this section, we will look at how to build a physical circuit to connect your microcontroller to an LED. Then we will cover how to use CircuitPython to control the microcontroller’s output and make the LED light up.

LED Control

Recall from Chapter 2 that LEDs are special diodes that emit light when a current flows through them. To drive an LED, you will need voltage to flow into the LED. Though the microcontroller can supply a regulated voltage into the LED, the current must also be regulated to avoid damaging it, as LEDs have a maximum current rating that you must not exceed. To regulate the current through the LED, you can use a resistor.

There is also a voltage drop associated with using an LED. The typical red LED, for example, will drop approximately 2 volts. Different LED colors drop different voltages, however, and the voltage drop will vary by manufacturer as well. It is best to consult the datasheet for the device you are using to get the exact specifications for your LED.

Knowing the voltage drop, you can calculate the output current that will flow through the LED. If the microcontroller gives a 5-volt output, then with a voltage drop of 2 volts given by the LED, the series resistor will have a voltage of 3 volts across it. If you want a maximum current of 10 mA to flow through the LED (you can find the actual number on your datasheet), then you can use Ohm’s law to calculate what resistor is needed.

To use Ohm’s law, divide the voltage by the current. This would be 3 V / 0.01 A. This yields 300 ohms, the minimum level of resistance needed to protect the LED. In this case, a 470-ohm resistor is a good choice. Remember, each resistor has a tolerance level that can make the actual resistance less than the expected value, so it would be risky to use the exact resistance value you calculate. If you want close to maximum brightness, then a 330-ohm resistor will suffice.

Building the Circuit

Once you have made your calculations, you are ready to design a circuit that will allow your microcontroller to control an LED. The circuit will look something like the schematic shown in Figure 5-7.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig7_HTML.jpg
Figure 5-7

MCU Circuit LED

We also use a 1k resistor to limit the amount of current that flows from the device; remember you will have no problem using a higher value resistor, and it is desirable if you want greater power efficiency as a higher resistor will draw less current.

You can follow the following steps to set up this simple circuit. Be sure that you connect your circuit before you power up your device.
  1. 1.

    Make sure that your microcontroller is properly powered by connecting the microcontroller to your power supply; if you are using a development board, then your USB connection will be sufficient to power up the device. If you wish to connect your external power supply, then connect the Vout of your power supply to the Vin input of your board (the value of the power supply output voltage is usually from 7.5 to 12; this varies depending on the board you are using, so be sure to consult the user manual of your board to see the input voltage range) and connect the ground to the ground pin of your microcontroller board.

     
  2. 2.

    Connect a jumper wire from the A1 pin on your microcontroller to a socket on the prototyping area of your breadboard.

     
  3. 3.

    Connect one lead of the resistor to another socket in the same row of the breadboard used in step 2.

     
  4. 4.

    Connect the other end of the resistor to a socket in a different row of the breadboard.

     
  5. 5.

    Connect the long lead of the LED to a different socket in the same row of the breadboard used in step 4.

     
  6. 6.

    Connect the short lead of the LED to a socket in a different row of the breadboard.

     
  7. 7.

    Connect a jumper wire to a different socket in the same row of the breadboard used in step 6.

     
  8. 8.

    Connect the other end of the jumper wire to the ground.

     
When you have finished connecting the circuit, it should look similar to Figure 5-8.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig8_HTML.jpg
Figure 5-8

MCU LED Circuit on a Breadboard

Lighting an LED with CircuitPython

Now that we’ve covered building the physical LED circuit, we can look at how to control the LED using CircuitPython. The program we will write will turn the LED on. Open the Mu editor and type the program into your “code.py” file as shown in Listing 5-1.
# import pin constants for board we are using
1 import board
# import pin control
2 import digitalio
# create object for pin we are using
3 led = digitalio.DigitalInOut(board.A1)
# set the pin to output
4 led.direction = digitalio.Direction.OUTPUT
# turn the LED on
5 while True:
    led.value = True
Listing 5-1

Controlling the LED

The first thing we do in this code is import the CircuitPython libraries needed to control the board. CircuitPython provides many libraries to perform digital I/O. At 1, we import the board module, which contains the pin constants for the board being used. With this module imported, we can refer to pins by their names – for example, A1. At 2, we import the digitalio module. It contains all the classes that provide access to the input and output function we’ll be using. Among other things, the module lets us set the pin direction to determine if we are reading data into a pin or writing data out of it.

With the necessary libraries imported, at 3 we create an instance of the pin object we are using. This instance has its own place in memory, and doing this allows us to access all the methods that are present within the “digitalio” module that we imported. This is vanilla Python syntax and shows us that our regular Python abilities can be utilized within CircuitPython programs. We then use that instance to set the direction of the LED at 4. In this case, we set the direction to output.

At this point, everything is set up, so we can now turn the LED on. At 5, we create what in the world of embedded systems is commonly called a super loop. Any instructions that fall within a while True statement will be performed over and over again, until the program is told to stop. In this case, we set the value of the led object to True, meaning the LED will light up.

We use a super loop because there is no operating system to do any control for us. The while True line ensures we keep performing our LED on action over and over. If you omit this line, then the LED will be lit once for a short period of time (too short for us to see). Almost all programs you will write for your microcontroller will contain such a super loop.

Hit the Save button in the Mu editor; this should save the changes to your “code.py” file, and you will observe that the LED connected to pin A1 has been lit. Now that you have successfully controlled digital output, feel free to experiment a little bit. Can you make the LED be controlled by pin A0? Or pin A2? To do this, you would simply rewire your circuit to the different pin and change the pin number when we are creating the pin object.

If your circuit is not working, make sure and test your connections; by that I mean make sure your wires are properly pushed into the holes designated for them. Check, check, and check again.

Blinking an LED

Turning on an LED is fun and all, but it is a bit boring. If we connected the LED directly to the power supply using a resistor, we would have the same effect. The beauty of intelligent control is that we can do things intelligently.

For example, you can program your microcontroller to not only turn on the LED but also to turn on the LED at time intervals of your choosing. This program will let you verify that your clock is set up properly, as you can look at the rate at which the LED is flashing. If the LED flashes at an incorrect rate, you will need to ensure you have the proper board selected or may need to check your USB and circuit connections. You’ve already set up the physical circuit. All you need to do is update your code with a few more lines. You can use the program given in Listing 5-2.
# import pin constants for board we are using
import board
# import pin control
import digitalio
1 # import time library
import time
# create object for pin we are using
led = digitalio.DigitalInOut(board.A1)
# set the pin to output
led.direction = digitalio.Direction.OUTPUT
# super loop
while True:
    # turn the LED on
  2 led.value = True
    # sleep for a second
  3 time.sleep(1)
    # turn the LED off
  4 led.value = False
    # sleep for a second
  5 time.sleep(1)
Listing 5-2

Blinking the LED

In this program, in addition to importing the board and digitalio modules, as we did in Listing 5-1, we also import the time library at 1. This library contains functions that will allow the microcontroller to follow time-related instructions. In particular, we’ll use the time library’s sleep method. It tells the microcontroller to wait for a certain amount of time, specified in seconds.

After initiating the led pin object as we did in Listing 5-1, we enter a super loop with a while True statement, as before. This time, the loop contains a few more instructions. At 2, we turn the LED on, just like in Listing 5-1. At 3, we tell the microcontroller to wait by passing a value of 1 second in the sleep method. At 4, we turn the LED off by setting the value of the led object to False. Then we use sleep again at 5 to delay for another second before restarting the loop.

Hit the “Save” button in the Mu editor, and you will observe that the LED connected to pin A1 flashes on and off every second. If you wanted to make the LED blink faster, you could pass a smaller value, like 0.5 seconds, into the sleep method. If you wanted the LED to run slower, you could use a longer value like 2 seconds instead.

Using Input: Adding a Pushbutton

The next time we work with our board, we will be looking at digital input. To do this, we will be adding a pushbutton to the circuit. Input is the complement to output on the microcontroller, and together they make up the two most basic microcontroller operations. If using an LED is like the “Hello World” of embedded development allowing you to print something to your screen, then reading a pushbutton will be equivalent to learning to read input from your keyboard. Our input project will be reading the state of a pushbutton on one pin, and then depending on the state read, we will toggle an LED connected to another I/O pin.

Pull-Up vs. Pull-Down Resistors

Before we start building the circuit, it’s important to note that there are different ways to connect a pushbutton to a microcontroller pin. You can do so using either a pull-up or a pull-down circuit configuration. The schematic for a pull-up configuration is shown in Figure 5-9.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig9_HTML.jpg
Figure 5-9

Pull-Up Configuration

In pull-up configuration, we use a resistor with a high value (usually between 4.7 and 10k) to pull up (which is to say, connect the I/O pin to VDD via the resistor) one side of the pushbutton to VDD. This resistor ensures that when the pushbutton is pressed, little current will flow from the circuit.

Figure 5-10 shows a schematic for a pushbutton in pull-down configuration.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig10_HTML.jpg
Figure 5-10

Pull-Down Configuration

Whereas the pull-up resistors pull the pin up to a high value, a pull-down resistor pulls the pin down to a logical low value, which is to say we connect the I/O pin to the ground through the resistor. To connect a switch in pull-down configuration, the switch must be placed between the supply voltage and the microcontroller pin.

When you use a pull-up configuration, the circuit will be active low, while with a pull-down configuration, the circuit will be active high. Generally, you will use your pushbuttons with pull-up resistors, and most microcontrollers provide pull-up resistors on their pins. Either configuration will work, however. Depending on your circuit application, one or the other approach might be preferable.

Later in this section, we will look at how to use the microcontroller with both a pull-up and pull-down circuit configuration. For other circuits in this book, though, I will only use the pull-up configuration. If you wish, you can modify any circuit in this book to use the pull-down configuration without having any adverse effect on circuit operation by following the pull-down model demonstrated as follows.

Switch Debouncing

Another facet to consider when working with microcontroller inputs once we are using a type of switch is switch debouncing. No device is perfect, and the more moving parts a device has, the more problems there will be associated with it. This is also true of mechanical pushbutton switches when they must be interfaced to microcontroller circuits.

Due to their construction, when you press a pushbutton switch, the microcontroller may register multiple presses of the switch. This effect is similar to what happens when you drop a ball. The ball does not immediately come to rest, but instead bounces for a few intervals of time. Likewise, when you push a switch, it does not have one solid close. There are a series of openings and closings that take place when the switch is closed.

Because of this bouncing effect, there’s a risk that the microcontroller will register the switch as open when it’s meant to be closed. To counteract this problem, you can implement a technique called switch debouncing. This can be done using either hardware or software.

For hardware debouncing, we can use a flip-flop (latch), as is shown in Figure 5-11. The flip-flop works as a switch debouncing as once Q is set to a high state by the input, there are no further changes that will occur at the output of Q. The flip-flop will latch the value of the input whenever there is a change in state. There are other methods of hardware debouncing such as using a Schmitt trigger; however, the flip-flop method is simple and effective.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig11_HTML.jpg
Figure 5-11

Flip-Flop Debounce

Instead of adding a piece of hardware, you can also build a debouncing effect into your code. There are several software debouncing methods, including using counters and software shift registers. Later in this section, we will use a simple software delay to debounce the pushbutton switch.

Input with MCU Schematic (Pull-Up)

We can build a simple pushbutton circuit by building the program that is shown in Figure 5-12. In this circuit, we use the switch in pull-up configuration.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig12_HTML.jpg
Figure 5-12

MCU with Pull-Up Switch

Pushbutton Pull-Up Circuit Connection Tips

This circuit is simple and hard to mess up. If your circuit is not working, make sure and test your connections. Check, check, and check again. Ensure that you connect your circuit before you power up your device.

These are the recommended steps to connect the circuit:
  1. 1.

    Connect the LED as we did in the previous section as per schematic diagram. To make it easier, you may want to run one jumper wire from the 3.3v voltage output socket on your development board to the positive rail and the other jumper wire from the ground connection to the ground rail. To make layout easier, and better utilize the board, you can connect both positive rails together and both negative rails as well.

     
  2. 2.

    Place the switch across the ravine in the center of the board, ensuring both pins on either side of the switch are placed into sockets of the prototyping area of your breadboard.

     
  3. 3.

    Connect one end of the switch to one end of the resistor in the same socket and the other end of the resistor to the positive rail. There is no need to use a jumper wire as the resistor can directly be connected to the LED.

     
  4. 4.

    Connect the other end of the switch to the ground using a jumper wire.

     
  5. 5.

    Run a jumper wire from the intersection point between the switch and resistor that leads to PIN A5 on your MCU. To accomplish this, ensure that the lead of the switch, the lead of the resistor, and the jumper wire are all in the same sockets.

     
When you have finished connecting the circuit, it should look like Figure 5-13.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig13_HTML.png
Figure 5-13

MCU Pull-Up Circuit on a Breadboard

Pushbutton Pull-Up with CircuitPython Program

Once we have our circuit connected, we can write a program that will allow the MCU to use the pushbutton in a pull-up circuit configuration. Edit the code.py file so that it resembles Listing 5-3.
# import pin constants for board we are using
import board
# import pin control
import digitalio
# import time library
import time
# create object for LED we are using
1 led = digitalio.DigitalInOut(board.A1)
# create object for the switch we are using
            switch = digitalio.DigitalInOut(board.A5)
# set the LED to output
led.direction = digitalio.Direction.OUTPUT
# set the switch to input
            switch.direction = digitalio.Direction.INPUT
# super loop
2 while True:
       # if our pin goes low
         if switch.value == False:
       # wait 100 ms to see if switch is still on
               3 time.sleep(0.1)
        # if the switch is still on
          4 if switch.value == False:
            # turn the LED on 5
             led.value = True
    else:
        # turn the LED off 6
        led.value = False
Listing 5-3

Reading a Pushbutton with MCU Pull-Up

Save the file and observe what happens. When you press the pushbutton, the LED will light up, and when you release it, the LED will stop being lit.

Do you understand what is happening here? Let us go through the program. We do our usual imports and set up objects for the LED and switch we are using at 1. Once we have these set, we set the direction of the LED to output and the direction of the switch to be an input after 1. Our super loop is where it all happens.

Within our super loop at 2, we use a conditional if/else statement to test our program to see if the pushbutton is pressed. If the pushbutton is pressed, then we wait 100 milliseconds at 3. If after the 100 milliseconds has passed, the pushbutton is still pressed at 4, then we turn the LED on at 5. To accomplish this task, we use a nested if statement. This checking the pushbutton, waiting, then checking the pushbutton again is the switch debouncing we were talking about. At 6, we turn the LED off which is the default state of the program.

When we look at the conditional, we see that if the pushbutton is low, then we turn the LED on. If this is confusing to you, remember that the pull-up resistor will set the pin to a default high state, so our MCU will be reading a high state on the pin constantly. Essentially, since we have a pull-up resistor connected to the pin, then the pin will be held high up to VCC which is 3.3 volts. When we press the pushbutton, the pin will be pulled low to the ground. We can also use the pushbutton in a pull-down state as we will learn in the next section.

Input with MCU Schematic (Pull-Down)

We can build a simple pushbutton circuit by building the program that is shown in Figure 5-14. In this circuit, we use the switch in pull-down configuration.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig14_HTML.jpg
Figure 5-14

MCU with Pull-Down Switch

Pushbutton Pull-Down Circuit Connection Tips

If your circuit is not working, make sure and test your connections. Check, check, and check again. Ensure that you connect your circuit before you power up your device.

These are the recommended steps to connect the circuit:
  1. 1.

    Connect the LED as we did in the previous section. To make it easier, you may want to run one jumper wire from the 3.3v voltage output socket on your development board to the positive rail and the other jumper wire from the ground connection to the ground rail. To make layout easier, and better utilize the board, you can connect both positive rails together and both negative rails as well.

     
  2. 2.

    Place the switch across the ravine in the center of the board, ensuring both pins on either side of the switch are placed into sockets of the prototyping area of your breadboard.

     
  3. 3.

    Connect one end of the switch to one end of the resistor, ensuring that they are in the same socket on the breadboard, and the other end of the resistor to the ground rail; there is no need to use a jumper wire here as the resistor is long enough to reach.

     
  4. 4.

    Connect the other end of the switch to the positive supply rail using a jumper wire.

     
  5. 5.

    Run a jumper wire from the intersection point between the switch and resistor that leads to PIN A5 on your MCU.

     
When you have finished connecting the circuit, it should look like Figure 5-15.
../images/511128_1_En_5_Chapter/511128_1_En_5_Fig15_HTML.jpg
Figure 5-15

MCU Pull-Down Circuit on a Breadboard

Pushbutton Pull-Down with CircuitPython Program

Once we have our circuit connected, we can write a program that will allow the MCU to use the pushbutton in a pull-up circuit configuration. Once you have built your circuit you can connect your board and edit the code.py file so that it resembles Listing 5-4.
# import pin constants for board we are using
import board
# import pin control
import digitalio
# import time library
import time
# create object for LED we are using
led = digitalio.DigitalInOut(board.A1)
# create object for the switch we are using
switch = digitalio.DigitalInOut(board.A5)
# set the LED to output
led.direction = digitalio.Direction.OUTPUT
# set the switch to input
switch.direction = digitalio.Direction.INPUT
# super loop
while True:
    # if our pin goes high
   1 if switch.value == True:
        # wait 100 ms to see if switch is still on
   2    time.sleep(0.1)
        # if the switch is still on
   3if switch.value == True:
            # turn the LED on
            4led.value = True
    else:
        # turn the LED off
        led.value = False
Listing 5-4

Reading a Pushbutton with MCU Pull-Down

Save the file and observe what happens. You will get the same effect as when you used the MCU with the pushbutton connected as a pull-up. When you press the pushbutton, the LED will light up, and when you release it, the LED will stop being lit.

The only change you will see is to the conditional statement that checks the pushbutton. When we look at the conditional at 1, we see that if the pushbutton is high, we wait for 100 ms at 2, then at 3 once the switch is still pressed, and then at 4 we turn the LED on. We must remember that since we have a pull-down resistor connected to the pin, then the pin will be held low to the ground. When we press the pushbutton, the pin will get current from the power supply.

You can try using a different pin to connect the pushbutton with. Don’t be afraid to experiment and keep trying new things. Remember that is the only way you will learn; try swapping pins, try changing your “True” condition to false, and observe the effect it will have (the LED will be on until you press the button, then it will turn off). That is all you need to do to learn how to use your microcontroller.

Conclusion

In this chapter, we covered a lot of information related to input and output on a microcontroller. We learned about microcontroller ports and how we can use them as input and output. We looked at how we can use output to control LEDs and how we can use input to control pushbuttons, in both pull-up and pull-down states. In the next chapter, we’ll expand beyond digital signals and look at how we can perform analog input and output and use this to interface to analog devices as well.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
174.129.140.206