Thursday, December 31, 2015

Raspberry Pi Prompting User for Lighting an LED

Project 1 - Prompting a user to light up an LED

Welcome back kinder!  Today I spend a few hours playing with the GPIO pins on the Raspberry Pi 2.  I really didn't know what to expect, so I bought a kit from Sunfounder.  The instructions as everyone else mentioned stink so I just tossed them aside and googled everything.  The kit itself is good with the exception of their labeling...there is none.  I had to use my multimeter to figure out which resistors where of which ohmage... ohmeratude... ohmwhatever.  Yes the resistors do have the little color coded bands on them, but when I went to check them, it didn't match various web sites and color keys.  I suspect either the colors on the bands are off, or I just can't tell the difference between their black and brown.  Other than that so far so good!

Step 1, figure out the resistors to use

Why is using a resistor important you ask?  I didn't know the answer either, so I googled it and apparently if you don't add resistors in front of LEDs then the LED will try to draw as much current from the Pi as possible, therefor potentially burning it out. For my first test I went with the 1k ohm resistors.  Why that amount, I have no idea, but the very project page in the manual I tossed was using that so I thought it was safe.  Apparently If you use a higher ohm resistor it will RESIST more voltage than a lower ohm resistor.  So it makes it safer it seems... [note to self, look into this later, hopefully without burning out the Pi first]

Step 2, first test with a breadboard and GPIO

What's a breadboard you say? Basically it is a circuit board that doesn't require soldering and is great for tinkerers like us.  I initially went the quick and dirty route and wired up the led to the breadboard and the LED longer leg (the anode aka the positive lead) directly to the 3.3v pin on the GPIO (pin 1) and the LED shorter leg connects to the 1k ohm resistor which connects to GPIO GND (ground pin 6).  As UNexpected, it worked on the first shot (go me!).

PS - sorry for no pictures, I didn't take any on the first round.

Step 3, turning an LED on and off

This part was a little tricky at first. The important take away was that in Step 2 you change the POSITIVE lead from pin 1 (3.3v) to pin 11 (aka GPIO17).  OK small aside here.  When programming with the Pi and interacting with the GPIO board you have 2 ways of referencing the pins on the Pi.  
  1. Using the actual pin number (1,2,3,4,5...).  In python you reference this by using:
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(11, GPIO.OUT)
  2. Using the pin BCM name (Broadcom SOC channel)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17, GPIO.OUT)
More information from stackoverflow.

Now comes the fun part, using python to turn the LED on and off.  Through some googleing and self learning, but first a little rant: 

[rant] I came to the realization that I don't much care for Python as a language. I knew nothing about Python coming in and I guess this is to be expected since I'm coming from Java mostly.  I hate the tabbing structure of everything from functions, to if blocks to try blocks.  I miss curly brackets so.  Next up is the typeless language structure.  I found that when I was prompting someone for input and I wanted to make sure it was a number, I had to either check the type or try/catch the input and the force a casting like this: int(somevar).  I would prefer to declare my variable types ahead of time so that the runtime would throw errors properly.  Next up is "elif"...really?  Could type out "else if".  What is this perl?  Finally back to tabbing.  Seriously, it makes it quite the chore to know if you are still within a nested if block or the outer while loop etc.  Anyway noob statements I know, I'll get used to it or try out the Java implementation.[/rant]

I'm attaching my first program here.
To run the program use the following command in the same directory that you uploaded the file:
sudo python3 p0-led.py
If you run into an issue where it won't run at all you most likely need to set it as executable:
sudo chmod a+x p0-led.py

Step 4, multiple LEDs!

This was a little trickier.  First off I did some reading and apparently you can share the ground between multiple LEDs.  Not sure how true this is, but it seems to work, but I still put a 1k ohm resistor in front of each LED just to be safe.  I lined the 3 LEDs in a row on the breadboard and ran all 3 resistors on the negative lead (short leg) of each LED to the global ground wire on the board.  Then I ran each positive lead on the LEDs to the following GPIO pins that accept input from the Pi (11, 12, 13) aka (GPIO17, GPIO18, GPIO27 - no idea why they skipped names).  Here is a picture of the breadboard and a bad picture of the Pi pins (sorry) with Pin 1 being the top right and Pin 2 being bottom right.  Click each image for a larger version.


Now comes the fun part again Python!  I really do mean it, it is fun!  So first off I learned something.  Those warning message you get about "RintimeWarning: This channel is already in use" were nagging me so I looked it up.  They are actually important.  The trick is properly closing out your code with:
GPIO.cleanup()
That releases the resources associated with those pins and resets them back to INPUT. Now that opened a can of worms and I must be a good programmer and catch  my errors and release connections etc.  It is overkill for this kind of project, but it was fun to learn.  The first thing I realized is that I need to learn how methods are defined in python.  Simply they work like this:
def YOUR FUNCTION(yourInputs)

Everything in the method is tabbed in and you can do standard return statements too.  Next up is learning how to prompt someone for input with the "input()" method!  Here is what my method looks like to prompt a user:

def promptLED():
print ("\n\nChoose LED to light up")
print ("1 = Green")
print ("2 = Red")
print ("3 = Yellow")
print ("4 = All")
print ("0 = exit")
return input("> ")

Now when you call the promptLED() method, it will prompt the user for an input and then returns the value of the input back to the main program.  From there I pass it to another method that inspects the input and then lights up the proper LED:

def exeChoice(userchoice):
choice = 0
try:
choice = int(userchoice)

if (choice == 1):
print ("[info] Lighting green LED")
GPIO.output(ledGreen, True)
time.sleep(1)
GPIO.output(ledGreen, False)

Ignore the try up there, it is caught later below.  For now the important part is the line that says:
choice = int(userchoice)
This line forces the choosing of a NUMBER and it throws an error if it gets anything but that - hence the try.  There is also an else in there to handle cases where it is not 1,2,3,4 or 0.

The next line of importance is:
time.sleep(1)
This simply pauses execution of everything for 1 second.  It can take decimals for shorter time.  NOTE: you have to import "time" at the top of your program:
import time

In exeChoice, I return a number ranging from -1 to 4.  -1 is an error and 0 is exit.  The main program is within a while loop to constantly prompt the user.  If it sees a -1 it shows an error and reprompts the user.

# holds response code from last LED method call
lastResponse = -1

# Exit if we have a 0 response, otherwise keep prompting
while (int(lastResponse) != 0):
promptChoice = promptLED()
lastResponse = int(exeChoice(promptChoice))

There is more to the program, but half the fun is looking at code, so here you go:

Link to the full program here
To run it make sure it has execute rights and run:
sudo python3 p1-multi-led-prompts.py

WOOO HOOO and happy coding!

No comments: