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 thewrite
method for the relatedmraa.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 thewrite
method for the relatedmraa.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)