Internet of Things with Python
上QQ阅读APP看书,第一时间看更新

Taking advantage of object-oriented code to control digital outputs

The previous example just turns on the LEDs. Thus, in case we want to count in a reverse order, that is, from 9 to 1, the results are not going to be as expected. After the code turns on 9 LEDs, the code will turn on 8 LEDs but there are still going to be 9 LEDs turned. The problem is that we never turn off the LEDs that we don't need to be turned on, and therefore the 9 LEDs will stay on until the edited loop finishes its execution.

We are always talking about LEDs turning on and turning off LEDs. However, we have been using just instanced of the mraa.Gpio class and called the write method. Python is an object-oriented programming language, and therefore, we can definitely take advantage of its object-oriented features to write reusable, easier to understand and simpler to maintain code. For example, in this case, it makes a lot of sense to create an Led class to represent an LED connected to our board.

The following lines show the code for the new Led class. The code file for the sample is iot_python_chapter_03_03.py.

import mraa
import time


class Led:
    def __init__(self, pin):
        self.gpio = mraa.Gpio(pin)
        self.gpio.dir(mraa.DIR_OUT)

    def turn_on(self):
        self.gpio.write(1)
        print("I've turned on the LED connected to GPIO Pin #{0}.".format(self.gpio.getPin()))

    def turn_off(self):
        self.gpio.write(0)
        print("I've turned off the LED connected to GPIO Pin #{0}.".format(self.gpio.getPin()))

We have to specify the pin number to which the LED is connected when we create an instance of the Led class in the pin required argument. The constructor, that is, the __init__ method, creates a new mraa.Gpio instance with the received pin as its pin argument, saves its reference in the gpio attribute and calls its dir method to configure the pin to be an output pin.

The class defines the following two methods:

  • turn_on: Calls the write method for the related mraa.Gpio instance to send a high value (1) to the pin and turn on the LED connected to this pin. Then, it prints a message with details about the performed action.
  • turn_off: Calls the write method for the related mraa.Gpio instance to send a low value (0) to the pin and turn off the LED connected to this pin. Then, it prints a message with details about the performed action.

Now, we can write code that uses the new Led class to create the necessary instances based on the number of LEDs we want to control and the pins to which they are connected. The following lines show an improved version of the code that uses the new Led class to count from 1 to 9 with the LEDs. The code file for the sample is iot_python_chapter_03_03.py.

if __name__ == "__main__":
    print ("Mraa library version: {0}".format(mraa.getVersion()))
    print ("Mraa detected platform name: {0}".format(mraa.getPlatformName()))

    # Configure GPIO pins #1 to 9 to be output pins
    leds = []
    for i in range(1, 10):
        led = Led(i)
        leds.append(led)

    # Count from 1 to 9
    for i in range(1, 10):
        print("==== Turning on {0} LEDs ====".format(i))
        for j in range(0, i):
            leds[j].turn_on()
        for k in range(i, 9):
            leds[k].turn_off()
        time.sleep(3)

First, the code declares an empty list named leds. Then, a for loop creates nine instances of the Led class and each of them represent an LED connected to a GPIO pin on the board. We pass i as an argument for the pin parameter. Then, we call the append method for the leds list to add the Led instance (led) to the leds list. Our for loop will start with i equal to 1 and its last iteration will be with i equal to 9.

Another for loop determines the number of LEDs to be turned on. We use range(1, 10) to generate the same list than in the previous loop. The first line within the for loop calls a print method to display the number of LEDs that we are going to be turned on in the iteration.

An inner loop within the loop uses range(0, i) to generate the list of indexes of the elements in the leds list that we have to turn on for the iteration of the main for loop (i). The inner loop uses j as its variable and the code within this inner loop just calls the turn_on method for each Led instance.

Another inner loop wihin the loop uses range(i, 9) to generate the list of indexes of the elements in the leds list that we have to turn off for the iteration of the main for loop (i). The inner loop uses k as its variable and the code within this inner loop just calls the turn_off method for each Led instance.

Tip

The code is easier to understand than the previous version and the Led class handles everything related to an LED. We can easily understand that the line that calls the turn_on method for leds[j] is turning on an LED. We definitely know that an LED is being turned off in the line that calls the turn_off method for leds[k].

As the new code turns off the LEDs that don't have be turned on, we can easily create a new version that counts from 9 to 1 by changing one line. The following lines show the new version of the code that works with the Led class to count from 9 to 1 with the LEDs. The only line that had to be edited is the highlighted one. The code file for the sample is iot_python_chapter_03_04.py.

if __name__ == "__main__":
    print ("Mraa library version: {0}".format(mraa.getVersion()))
    print ("Mraa detected platform name: {0}".format(mraa.getPlatformName()))

    # Configure GPIO pins #1 to 9 to be output pins
    leds = []
    for i in range(1, 10):
        led = Led(i)
        leds.append(led)

    # Count from 9 to 1
 for i in range(9, 0, -1):
        print("==== Turning on {0} LEDs ====".format(i))
        for j in range(0, i):
            leds[j].turn_on()
        for k in range(i, 9):
            leds[k].turn_off()
        time.sleep(3)