Showing posts with label education. Show all posts
Showing posts with label education. Show all posts

Sunday, August 9, 2015

Computing at 80,000ft, future tech and the future of tech






Another exciting Winston-Salem Section meeting at CDI !  Wednesday, August 12, 2015 at 11:30am.

Presenter: Francois Dion

Originally from Montreal, Canada, Francois Dion is a Coder, Data Scientist, Entrepreneur, Hacker, Mentor, Musician, Polyglot, Photographer, Polymath and Sound Engineer.  He is the founder of Dion Research LLC, an R&D firm specializing in Fully Integrated Software and Hardware (www.dionresearch.com) and works as a Data Scientist at Inmar, Inc. (www.inmar.com).

He is also the founder of the local Python user group (PYPTUG), a group he founded to “promote and advance computing, electronics and science in general in North Carolina using the Python programming language.”

Detail:

Behind the scene and various aspects of electronics and computing cluster and data science in near space. A glimpse at future technology. and at the future of technology.

When
Date: 12-August-2015
Time: 11:30AM to 01:30PM (2.00 hours)
All times are: America/New_York
Where

Building: CDI
Center For Design Innovation
450 Design Ave.
Winston Salem, North Carolina
United States 27102
Staticmap?size=800x400&sensor=false&zoom=16&markers=36.0906389%2c-80
More

No Admission Charge.


Wednesday, May 13, 2015

SELF 2015 Keynote


South East Linux Fest 2015


For the past several years, South East Linux Fest has been one of the conference in the southeast US that I've looked forward to. Not just for your day to day Linux admin stuff, but for a wide gamut of talks on databases, operating system design, security, programming, history, so on and so forth.

In 2013, we started to see some Raspberry Pi related talks (see Alcyone And On And On - hope you get the musical reference), and in 2014 I was able to present about Python 3 in the browser (thanks to Brython).

And here comes SELF 2015. I was pleasantly surprised to find out that my proposal for 2015 was not only accepted, but selected as the Saturday keynote, at 9am.

SELF Keynote

Title: "Team Near Space Circus: Computing at 80,000 ft"

By Francois Dion

Description:
On April 21st 2015, Team Near Space Circus made history, sending a high altitude balloon (NSC-01) into near space. Aboard the vehicle, a computing cluster (a first for HAB flights) of 7 networked Raspberry Pi, 8 cameras and multiple sensors recorded 250GB of data, images and video. 


This is the behind the scene story of this ground breaking flight.

When:
Saturday June 13th 2015, 9 AM.

P.S. This is a talk of general interest and will appeal to those who enjoy a good story.

When & Where


SouthEast|LinuxFest

June 12-14, 2015
Sheraton Charlotte Airport
Charlotte, NC


Francois Dion
@f_dion

Monday, April 27, 2015

Excellent mission debrief tonight

Pictures brought back by NSC01


In the coming days and weeks we'll publish charts and graphs, and we'll be working on images and videos. For right now though, I don't really feel like typing much, so I'll leave you with a few pictures... (Captured using a webcam and pygame and an infrared Raspberry Pi camera, all from node #7 of the compute cluster)

Infrared image, lakes are easy to see on those (and our radar reflector)

About to be launching

Official launch image, April 21st 7:57:24
Francois Dion
@f_dion

Thursday, June 19, 2014

South East Linux Fest, Python Represent

Friday


I'll be presenting at South East Linux Fest (SELF) 2014. According to the final schedule, it is tomorrow, Friday the 20th at 4PM. Right after that will be a BOF in that same room. Come by and talk *nix and Python.

Last year Python was pretty much absent from the conference. Yet it is quite focused on security, and Python is just the right tool for that kind of stuff.

Brousse


That's one project among many I'll be talking about, bringing computing education to people who are usually left without.

Keep an eye on my twitter account and this blog for details. The core of the talk is about Brython.

Video


Apparently, videos of talks will be available after the conference.

@f_dion

Monday, February 3, 2014

Python tip[8]

Tip #8

Always use a good bit of data to test your data driven apps. Don't rely only on nose testing. But where to get data? Fake it. Never underestimate the power of import random. But when you need more than numbers:

pip install fake-factory

You can also take a look at faker, faker.py, ForgeryPy (and many more on pypi.python.org). Then there is fake-data-generator. Or if you want a csv or sql, try mockaroo.com

What it does: Although you could use real data, sometimes you don't have any. In fact, more than likely you probably wont be  able to generate a significant amount of data for weeks after going live with your web application. Or perhaps it is a desktop application and you'll never see the generated data. So just fake it. You need volume, and it's easy to create.

Another point to keep in mind is that using real data might be risky, depending on what it is. For sure you do not want real credit card numbers floating around on development instances.




François
@f_dion

Sunday, January 26, 2014

Python tip[7]

Tip #7

Today's tip is quite basic, but will require time and effort to master:

Master the shell environment

What it does: Mac, Windows, Linux, BSD or Unix (or even something else). Whatever your operating system, become really good at using the command line, the shell. Bash, Powershell, ksh93 etc. Learn it. Else, it's like learning a bunch of words in a new language, but never learning the correct constructs. You might be able to communicate, but it'll never be very efficient. So go and find tutorials.

And then find the tools that'll make your life easier.

For example, *nix users, are you familiar with autojump (plus it's written in python)?

Windows users, did you know there is an equivalent Jump-Location for powershell?


François
@f_dion

Monday, October 28, 2013

toolz and curry

Lightning talk


Doing a quick lightning talk tonight for PYPTUG @WFU and it wont be about spanners and food as the title might imply, but about...

Functional programming


Yes, about functional programming in an imperative by design language (Python). And it's a lightning talk, so it'll be very superficial. But hopefully interesting nonetheless.

My first experience with pure functional programming was in the 80s with the Miranda programming language. If one counts impure functional such as LISP, scheme etc, then that would be Logo as my first.

Back to Python

One of the most appealing Pythonic technique I use on a regular basis, is functional. But more on that later. Here in this talk, I'll focus on a new module called Toolz (the result of a merge of functoolz and itertoolz - with a z, not the standard library functools and itertools).


François
@f_dion

Thursday, February 7, 2013

sudo ./laserpulse.py

Tron, Laser, Lissajous, RaspberryPi


Am I throwing together random words for titles now, in a weird captcha induced moment? No,  just condensing my interest in lasers in a few words.

You might have seen the laser digitizer in Tron: Legacy


However, in my case, what triggered my interest in laser, was the original Tron laser digitizer


A few years later, I had the chance to play with a good old HeNe red laser, pumping a mighty 5mW (well, in the 80s, it was impressive) in the college lab. One of the things I did with it was to draw Lissajous figures (or curves) on a wall (a large wall outside, at night - even cooler), using two little speakers and mirrors I had brought (the lab was set up to only do prism and mirror experiments).

Googling, I see a nearby school (Appalachian State) has one such kit in their physics dept:
http://www1.appstate.edu/dept/physics/demos2/oscillations/3a80_40.html


Anyway, fun stuff, making math and physics a lot more interesting...

Electronica


There was the artistic connection that also further fueled my interest in lasers. There is a lot to talk about here, since I've composed and performed electronic music for many years (still write some) and hosted a radio show for about 10 years etc, so that'll be for another time.

I will bring up one point right now though: you cant talk about lasers in music shows, without mentioning Jean Michel Jarre.

Jean Michel Jarre, Houston TX 1986
From his incredible live outdoor shows with lasers, lights and fireworks (one, a tribute to oceanographer Cousteau, had an attendance of over 2 million people in France in 1990) to his laser harp. Jarre without lasers wouldn't be the same.

On the road


The Raspberry Pi has a lot of appeal by itself, but I figured that it would probably be a good idea to add a laser in the mix. Since I had a presentation at PyCarolinas, I figured I'd write a script with Python (laserpulse.py, hence the title of this article) and build a little rig to project interesting patterns on the wall behind me.

My 50mW laser rig (also 500mW for day use)

The code for the pulsing is basically what is found in the RPI.GPIO dot dash article, and for the motor, in the 2bit H bridge article and PWM article.

So, using a laser in presentations, does it work? Well, at PyCarolinas, I got a lot of feedback on this, both during the presentation, after the presentation and even during other talks (heard during another talk "so we've learned today that lasers are cool")

In the audience: "I just want to say that this is the coolest command, ever."

On twitter:

Calvin Spealman
@ironfroggy
sudo laserpulse.py with actual lasers! #pycarolinas
08:45 PM - 21 Oct 12

And so on and so forth. The conclusion is this: Science needs some showmanship. But please, be careful when playing with lasers!


Video


So I'll leave you with a video of my little rig above controlled by the Raspberry Pi, going to the music of a very British band, doing a cover of the theme of a very British TV show. Very apropos, since the Raspberry Pi is a very British computer, afterall.





Youtube video (Music by Orbital, Doctor? live at BBC)

[edit] I fixed the youtube link



François
@f_dion

Friday, February 1, 2013

Making your own RaspberryPi GPIO cable

Example of a DIY circuit, connected by DIY cable

One feature that has contributed to the Raspberry Pi's success is the possibility of interfacing the virtual (software) with the physical world. We are speaking of course of the "General Purpose Input and Output" pins, more commonly known as GPIO. They are available on the Pi at the P1 connector.

Making a GPIO cable


We are doing some green computing today! We are going to recycle some old computer cable and make a Raspberry Pi interface cable with it. We will then be able to connect motors, LEDs, buttons and other physical components.

The interface cable is a flat cable with 26 conductors. It is quite similar to an IDE hard disk cable (or ATA) with 40 conductors (avoid the ATA66/133 with 80 conductors):

Original IDE/ATA cable with 40 wires

Let's get to work


We will only need 2 connectors on our interface cable and not 3. With a cable with 3 connectors, we just need to cut one section off.

Cutting it with a pair of scissors

Before doing the cutting, we will do some marking. The reason is that we only need 26 wires, and we have 40. With the red wire on the left, we have to count 26 wires and mark the split with a fine permanent marker. We count on the right side to make sure we do have 14 conductors, not a single one more or less.


Using a permanent marker to write
We are going to divide the cable in two parts, using an x-acto style knife or scalpel: one with 26 wires and one with 14 wires.

splitting in two parts

We then have to cut one section of the connectors off, with a small saw, such as a metal saw (or a Dremel style cutting wheel).

we need to cut on the 7th column from the right

We remove the top part, then the cable section with 14 wires, and finally, after notching it, we remove the bottom part.

almost done, just remove the part on the right

We are done with the cutting. We can now connect the cable to the Raspberry Pi. The red wire is closest to the SD card side, and farthest from the RCA video out (yellow connector):



Connections


With the cable ready, we are now going to test it. Let's add 2 LEDs to do this test. We will use a red and a green LED, but you can use amber or yellow LEDs too. Blue, violet or white LEDs will not work, since they need more voltage.

The connection is really simple:

Red LED and green LED, short leg -> third hole on the left.
Red LED, long leg -> second hole on the right
Green LED, long leg -> third hole on the right



Python Code

First thing first, you have to get the  RPi.GPIO  Python module.  It is a module that will allow us to control the GPIO of the Raspberry Pi. On Raspbian, it is now included, but for another version of Linux, it can be installed with

sudo easy_install RPi.GPIO

Or through apt-get  (or equivalent package manager):
 
$ sudo apt-get install python-rpi.gpio
 
Here is the code:
 
#!/usr/bin/env python  
""" Setting up two pins for output """  
import RPi.GPIO as gpio  
import time  
PINR = 0  # this should be 2 on a V2 RPi  
PING = 1  # this should be 3 on a V2 RPi  
gpio.setmode(gpio.BCM)  # broadcom mode  
gpio.setup(PINR, gpio.OUT)  # set up red LED pin to OUTput  
gpio.setup(PING, gpio.OUT)  # set up green LED pin to OUTput 
#Make the two LED flash on and off forever  
try:
    while True:  
        gpio.output(PINR, gpio.HIGH)  
        gpio.output(PING, gpio.LOW)   
        time.sleep(1)  
        gpio.output(PINR, gpio.LOW)  
        gpio.output(PING, gpio.HIGH)  
        time.sleep(1)
except KeyboardInterrupt:
    gpio.cleanup()

Just save the code into a file named flashled.py.

  • PINR is the GPIO for the red LED (0 for Rpi V1 and 2 for V2)
  • PING is the GPIO for the green LED (1 for Rpi V1 and 3 for V2)
We select the Broadcom mode (BCM), and we activate the 2 GPIO as output (OUT). The loop will alternate between the red LED on / green LED off during 1 second, and red LED off / green LED on during one second ( time.sleep(1) ). By doing a CTRL-C during execution, the program will terminate after cleaning up after itself, through the gpio.cleanup() call.

Running the code


Usually, a LED should be protected with a resistor to limit the current going through it, but in this case it will blink intermittently, just to test the cable, so we don't need any.

For continuous use, it is recommended to put a resistor in series (about 220 Ohm to 360 Ohm).

Before we can run the program, we have to make it executable:
$ chmod +x flashled.py
$ sudo ./flashled.py
CTRL-C will stop the program.

Red LED

Green LED
This concludes our article. I hope it was satisfying making this cable and recycling at the same time.

The follow up to this will be about making our own breadboard adapter, and having fun with a transistor.


@f_dion

RaspberryPi talk @ForsythTechCC

Presentation

I'll be giving the talk "Raspberry Pi: From Kindergartners To Mad Scientists" at ForsythTech in Winston Salem, NC this coming Monday at 5:30pm (Feb 4th), and Thursday at 3pm (Feb 14th). It will be in the Hauser building, room 332.

Old school flyer

Just got a copy of the flyer:

It's that $25 computer talk

Each time I give this talk somewhere, it ends up quite different from the previous one. In part due to questions, and in part because I adjust the content to the target audience.

Should be fun, there is interest from several programs, so I'll cover a wide range of material.


@f_dion

Sunday, January 27, 2013

Python on RaspberryPi 01

Learn Python. Starting at the beginning...
  
Note: This is a translation of the popular basic guide to Python on the Raspberry Pi: Python sur RaspberryPi 01 (in french), adapted where it made sense.

For the experts, there's not much to see in this article. For everybody else who keep seeing references to Python in your research on the Raspberry Pi, and wondering why they keep talking about a snake, then this article will be perfect for you. Or perhaps, you do know that Python is a programming language.

Welcome to our series of tutorials on the Python programming language, with a specific application to the Raspberry Pi.

Sites


Before we get too far, I want to provide you with a few basic links. The first is to python.org.

If you spoke another language, such as Spanish, Portuguese, French, Italian or Russian, I would point you to several other websites, because for other languages, individuals tend to have more complete sites than the official one (or, I should say, more in tune with the culture). But since you are reading this in English, python.org will become your primary stop.

There, you will discover regional user groups, documentation, downloads, mailing lists, a wiki and eventually, a Jobs section. You can't get enough of documentation? Then readthedocs.org

If you are the visual type, check out also pyvideo.org

Books


In english, there are lots of choices. In fact, too much. For example, on Amazon, you'll find over 1000 books on Python. Even checking out only hardcovers, you'll still end up with over 85 books!

If you live in a big city, it is a good idea to go to your local book store, and check out what books they have. As I've taught some Python to others, and recommended some books based on their personality, I've noticed that almost everybody is different. One book that I like, you might hate, and vice versa, because we are all different.

So you'll have to dig and see what book appeals to you, based on styles that vary from "Python for Kids", "Hello Python" and "Head on Python" to "Core Python Applications Programming" or even a "Python Essential Reference". There are many textbooks available too, some are assigned reading material for Python classes in colleges and universities, worth your time to check them out.

Free eBooks


I won't hold back in recommending some books in this section. Considering how much you will pay for them... the value to cost ratio is difficult to beat :)

Green Tea Press has several free ebooks. These are also available in print and eBooks from OReilly, for a fee. Among them is the classic text (or I should say the new edition of the classic text):

How to Think Like a Computer Scientist: Think Python

There is also Think Complexity

Moving on to another editor, for many years, Dive into Python was another recommended book. It is available to download for free.

In the not quite ebook, it is an online book category:
Learn Python The Hard way
A Byte of Python
Code Like a Pythonista: Idiomatic Python

If you are into games or young, or you want to help younger folks to learn Python, you might want to look at:

Invent With Python
Snake Wrangling For Kids

Have you found a free ebook that should be mentionned here? If so, please leave a comment!

Python, the program



So, Python is a programming language, but it is also an executable program. It is included with the Raspberry Pi and with most Unix type systems (Solaris, OpenIndiana, Mac OS/X and the varieties of Linux and BSDs ). It can also be installed on Windows, iPhone, iPad, Android etc. In this article, I will differentiate the python program from the language, by writing it in bold characters.

It is possible to use python in various ways or mode of operations.


First mode 

 

In an interactive way, from the command line:


pi@raspberrypi ~ $ python
Python 2.7.3rc2 (default, May  6 2012, 20:02:25) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 


The python shell is now waiting for a command, to have something to do. We will ask it to print the words "Raspberry Pi!". In the same way that I had to put quotes around the words to clearly differentiate what I want to print from the rest of the text, in Python it is required to delimit a string of characters (a sentence) with simple (') or double (") quotes on each side of this string:

pi@raspberrypi ~ $ python
Python 2.7.3rc2 (default, May  6 2012, 20:02:25) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Raspberry Pi!"



To simulate this in your browser (with Brython), click python answered us:
Raspberry Pi!



If our string of characters extends beyond one line, then we will have to use the single or double quote symbol, three times on each side ("""I'm writing a lot of words, so you better be ready for me with a multiline string, since I will go on and on and on.""")


pi@raspberrypi ~ $ python
Python 2.7.3rc2 (default, May  6 2012, 20:02:25) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print """
... Raspberry Pi!
... I continue.
... I am done!
... """

Raspberry Pi!
I continue.
I am done!



python answered us:
Raspberry Pi!
I continue.
I am done!

However, in our case, we are not done at all, we are barely starting! It is as good a time as any to mention at this point that a string that starts and ends with the triple quote ("""string of characters""") by itself, without instructions, is what is called a docstring, a string of characters (or sentence) for documentation purpose. A form of commentary, in other words.

We can also use python like a calculator:


pi@raspberrypi ~ $ python
Python 2.7.3rc2 (default, May  6 2012, 20:02:25) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 2 * 32
64


To exit the python program, we must type the commant: exit()
The word exit, followed by a pair of parenthesis, indicates that exit() is a function. We will come back to functions later on (and we will learn that print is a strange animal, that should be written print(), but that's for another time).

Second mode


If our code is quite short, there are no issues with using the interactive mode. But it might become burdensome to write the same code again and again. It's a good thing then that we can save our code in a file, whose name will end with the .py extension and that we can execute again and again.

Let's save our program that prints "Raspberry Pi!" in a file. In order to do that, we will need an editor. For the experts, I would recommend something like scribes in graphical mode and vim in console mode (text).

Since we are starting out, I would recommend instead to install geany:

pi@raspberrypi ~ $ sudo apt-get install geany
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  geany-common
Suggested packages:
  doc-base
The following NEW packages will be installed:
  geany geany-common
0 upgraded, 2 newly installed, 0 to remove and 134 not upgraded.
Need to get 3,401 kB of archives.
After this operation, 8,682 kB of additional disk space will be used.
Do you want to continue [Y/n]? y
Get:1 http://mirrordirector.raspbian.org/raspbian/ wheezy/main
 geany-common all 1.22+dfsg-2 [2,336 kB]
Get:2 http://mirrordirector.raspbian.org/raspbian/ wheezy/main
 geany armhf 1.22+dfsg-2 [1,065 kB]
Fetched 3,401 kB in 6s (518 kB/s)                                              
Selecting previously unselected package geany-common.
(Reading database ... 91199 files and directories currently installed.)
Unpacking geany-common (from .../geany-common_1.22+dfsg-2_all.deb) ...
Selecting previously unselected package geany.
Unpacking geany (from .../geany_1.22+dfsg-2_armhf.deb) ...
Processing triggers for hicolor-icon-theme ...
Processing triggers for man-db ...
Processing triggers for menu ...
Processing triggers for desktop-file-utils ...
Setting up geany-common (1.22+dfsg-2) ...
Setting up geany (1.22+dfsg-2) ...
Processing triggers for menu ...
pi@raspberrypi ~ $ geany raspberry.py


We just launched our editor, with a filename of raspberry.py. We type our code in the window raspberry.py:

Geany code editor

We save, and we quite (for right now, so as to keep things simple).

How can we run our raspberry.py script? Quite easily:


pi@raspberrypi ~ $ python raspberry.py
Raspberry Pi!
pi@raspberrypi ~ $ 

This is the second mode of operation, python running a script.

Third mode


The third mode is available on Unix type computers, and as such, on the Raspberry Pi. Let's bring up our geany code editor once more:

pi@raspberrypi ~ $ geany raspberry.py 
 
We insert a new line 1


We save after adding the new line, and we quite. The line we've just added to the script tells the operating system shell which program will run this code. In our case, we specify python.

That is not all, however. We also have to change the file from a document mode, to an executable mode. We do this through the chmod command:

pi@raspberrypi ~ $ chmod +x raspberry.py

We are now ready to launch our script directly:

pi@raspberrypi ~ $ ./raspberry.py
Raspberry Pi!
pi@raspberrypi ~ $

With a little help from my friend


Wouldn't it be nice if we didn't have to leave the comfort of our editor each time we wanted to run the program after making a change? We can do this through the use of the F5 key, or through the Build->Execute menu, or even using the button with the gears (View or Execute):

Raspberry Pi! - press return to exit that screen


This concludes our first basic tutorial on Python on the Raspberry Pi. I hope that this was sufficient to get you started.

@f_dion

Sunday, January 20, 2013

Going in the wrong direction

$35 going once


XYZ is the new RaspberryPi. Replace XYZ by several small form computers that have hit the market in the past year (particularly those powered by ARM). That is the claim being made again and again.

Except that the Pi is small, and a lot of the contenders are bigger. Or dont have gpios. And we re not talking about embedded systems. We need an OS. And Python. But really, at the end of the day, they cost too much. How much is too much I hear you say...

We are already conditioned to a $35 price tag. A fully capable Linux computer with a fast GPU and gpios. And a DSI and CSI connector. You can bring more to the table, such as ADC, PWM, USB3, bluetooth or sata, but if the price is greater, then you are going in the wrong direction.

$35 going twice


To put things in perspective as to what $35 buys you, at a local retailer, an Arduino Uno (an embedded system, so in theory it should be cheaper) will set me back $35, and then I have to add a $40 ethernet shield if I want to get it on the network. I go to Barnes and Nobles, and I cant find a decent computer science book for that amount. So yes, the Raspberry Pi foundation set the bar high.

Yet, it is impossible to ignore that. And the fact is that while $35 got you a 256MB Pi model B some months back, it now gets you a 512MB Pi model B.

Sold for $25


Just as we got comfortable with the Raspberry Pi model B, we are about to get a $25 version, with a lower power consumption. For a lot of projects, the model B was already overkill, so the model A will really further increase the perceived value of the Raspberry Pi platform.

What's the deal?


Why does it matter? Because at that price level, we don't mind losing one in an experiment. That means that, no matter how young or old, we all have an opportunity to try something we would never have done if the Pi cost $100 or even $80, and even less so if we had to use a $1000 computer...

Let me illustrate. As a teenager, I almost cut short my career in technology. I was working with a friend on building a robot, controlled by an Apple ][ compatible. Even though it was not the real deal (it was a clone), that computer was very expensive to us (over $1000). But we had no other way. And all our knowledge came from books at the library or bulletin board systems. There was no world wide web. But hey, we found out that the game port not only had digital and analog inputs (for analog joysticks), it also had digital outputs (annunciator 0- 3):

Apple 16-pin DIP Game Port socket (on the motherboard)
  for II, II+, IIe, IIgs


                           =========
Pushbutton 3 (GS only)  9 | *     * | 8  Ground
 Gm Ctrl 1 (Stick-1 Y) 10 | *     * | 7  Gm Ctrl 2 (Stick-2 X)
 Gm Ctrl 3 (Stick-2 Y) 11 | *     * | 6  Gm Ctrl 0 (Stick-1 X)
        Annunciator 3  12 | *     * | 5  /$C040 Strobe
        Annunciator 2  13 | *     * | 4  Pushbutton 2
        Annunciator 1  14 | *     * | 3  Pushbutton 1
        Annunciator 0  15 | *     * | 2  Pushbutton 0
        No Connection  16 | *     * | 1  +5V
                           ===| |===
                               ^
                        Notch on socket
                (faces toward front of computer)

Still, we were a little concerned in hacking the expensive machine. And sure enough, during our experimenting over many weeks, we melted one of the trace on the motherboard. Smoke. Bad smell. Angry mom. Sad friend with a busted Apple ][ compatible. Well, the story does have a happy ending in that we were able to repair the computer and we both continued experimenting and going each our way in the field of technology, but I'm not sure what would have happened had we not been able to fix the computer...

That is why we need $25 computers. It wouldn't surprise me if we see $20, or even sub $20 computers... If you were thinking $60, then as I mentionned, you are going in the wrong direction.

Food for thought


Now that we've cleared this point up, makers of Raspberry Pi add-ons, you're the next contestants on the price is right.  

Are you going in the wrong direction?


@f_dion

Saturday, November 17, 2012

Python Speak Hint

A hint for our current python challenge:

$ sudo apt-get install espeak

or

import pycairo

Depending which challenge you picked... The answer will probably vary if you try it under Raspbian versus Debian, it is all in the library.

Monday, November 12, 2012

PiQuizMachine

This article continues documenting one of the PYPTUG Workshops: PyHack Workshop #01, and goes into writing the PiQuizMachine code.

The machine

The PiQuizMachine

The Circuit


Each button controller is made from 1/2" PVC parts and a momentary mini push button, connected by a wire to a board.

On the board, one 10K Ohm resistor pulls up the GPIO to high, while the push button is connected to the GPIO on one end and to ground through a 1K Ohm resistor on the other end.

 This last resistor is optional if you are certain you can avoid pressing the buttons whenever the GPIOs are configured as outputs instead of inputs...


This circuit is repeated for all 4 buttons

Source Code


Make sure you've installed Mercurial and pulled the code from bitbucket (as instructed in the previous article), and go into:

    $ cd fablocker/PyHack/workshop01
    $ cd trivia
    $ ls
    load.py  piquiz.py  piquizmachine.py  questions.txt  README.md short.txt

The load.py is the first piece of code we will review.

We have a text file (question.txt) with all the questions and answers for the quiz game. We generated this file using a python script to web-scrape the data from a few pages of triviachamp.com (you can also do this by hand, selecting all the questions on a screen, and copy-pasting into a text file).

There is also a shorter version, with 2 questions / answers. We will use that first to figure out how we will load them into memory in our program. Here is the content of short.txt:

 Louis Leterrier - This film was released in 2010.Who directed Clash of the Titans?  
   
     a. Rodrigo Garcia  
     b. Louis Leterrier  
     c. Joe Carnahan  
     d. Iain Softley  
   
   
 Chicago - This team is part of the NFL.If you wanted to see the Bears play football, which city would you need to visit?  
   
     a. Chicago  
     b. Houston  
     c. San Diego  
     d. Denver  
   

Wow... So what do we have here? We do not have the data nicely separated by a special delimiter or by a new line. We will have to figure out a way to ignore the blank lines, handle the slight variations and extract the data into various fields:

answer - trivia blah blah.question blah blah?
multiple choices of answers

The thing is, the trivia and question can have all kinds of punctuation marks such as comma, period, dash and varying amount of white spaces. Doing this by hand coding a function to do it would be a lot of work and quite boring.

There is something that can deal with this fairly easily. I'm referring again to Python's "batteries included", a library called re, for Regular Expressions.

Regular Expressions


Regular Expressions ( abbreviated as re, regex or regexp), is a language designed to create simple to complex matching against data ( a string or a file). It is about as much the opposite to Python as can be, as it is dense, hard to read and hard to debug.

But sometimes, it is the perfect solution to a problem, and it is fairly easy to use in the Python implementation (a full implementation on Python, just like in Perl - in some other languages, it is a partial implementation, and can be hard to use or at least way more involved).

At any rate, if you ever have a career in IT, chances are you will have to become familiar with them, from system administrators wanting to parse log files, to programmers doing EDI, to web developers doing URL matching (Django, Web.py, even config files for certain web servers), to loading and extracting data from a file that is not 100% structured to be read by a computer (as we will do here).

The official documentation of the re module can be found at docs.python.org

A quick cheat sheet on regular expressions can be found here at tartley.com

And for those who like to follow video tutorials, check out this google video tutorial by Nick Parlante, on youtube.

Let's now look at the code in load.py:

1:  #!/usr/bin/env python  
2:  # -*- coding: utf-8 -*-  
3:  """  
4:  load.py - just loading the question file  
5:  Loads questions and answers from quiz data file. It follows the format  
6:  from triviachamp.com  
7:  """  
8:  # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4  
9:    
10:  import re  
11:    
12:  with open('short.txt', 'r') as f:  
13:    for line in f:  
14:      if len(line) > 1:  
15:        match = re.search(r'^([\w ]+)-([\w ,-]+)\.(.+)', line)  
16:        if match:  
17:          answer = match.group(1).strip()  
18:          trivia = match.group(2).strip()  
19:          question = match.group(3).strip()  
20:          choices = []  
21:        else:  
22:          match = re.search(r'\s+(\w)\.([\w ,-]+)', line)  
23:          if match:  
24:            choices.append(match.group().strip())  
25:            choice = match.group(1)  
26:            description = match.group(2).strip()  
27:            if description == answer:  
28:              correct_response = choice  
29:            if choice == 'd':  
30:              print(question, choices[0], choices[1],  
31:                   choices[2], choices[3],  
32:                   correct_response, trivia)  
33:    


Line 1 through 7 are typical of what we've done for the past several scripts, with the exception of line 2. On that line we specify that this document or script is following not ASCII, not ISO8859-1 but UTF-8 for the encoding of the characters. In this particular case we do not need it, but if we had to use accented letters, or special glyphs (for a card game, the heart, spade, diamond and clover glyphs, for example) then we would need this. Python 3 defaults to UTF-8, so it is a good idea to start learning about unicode and UTF-8, even though we are writing Python 2.x code right now. Line 8 is simply some instructions for an editor named vim.

Line 10 is where we import the regular expression module we just discussed. This is part of the Python library, so no need to download anything. This follows the "batteries included" pattern of Python. For general programming, you typically dont need to download anything else. For domain specific applications however, you will need to download and install other modules (like web.py, matplotlib, pygame, scipy etc)

Line 12, we are opening a file named short.txt, in the 'r' (or read) mode.

12:  with open('short.txt', 'r') as f:  

This is quite alien looking for some having a background in another language, such as C. In fact, it is also possible to open a file this way:

f = open('short.txt', 'r')

However, by using the statement with, we get exception handling and graceful housekeeping for free. We dont have to use try, except and finally, it is done implicitly. So just use this form.

Line 13, we have a for loop, and just like we did with the PINS in the previous article, we are getting items from an object. For PINS it was either a tuple or a list, both of which can be iterated by a for loop. In this case, we use a file object named f, which we obtained by calling open(). This is different than, say, a file descriptor in C/C++ (which is what fopen() in these languages would return) where it is only a reference to be used by other functions to do stuff. In Python, it is an object that, when an iteration is requested, will give us one item. For files, it will be one line. We could have also used a different variable name: for blah in file would get me a whole line in variable blah.

Line 14, we use a built-in, len() to tell us if we are dealing with an actual line with some data, or just a blank line, based on the length of the line.

Let me isolate the next 5 lines so we can focus on them:

15:        match = re.search(r'^([\w ]+)-([\w ,-]+)\.(.+)', line)  
16:        if match:  
17:          answer = match.group(1).strip()  
18:          trivia = match.group(2).strip()  
19:          question = match.group(3).strip()

Now, the scary part, line 15. The regular expression. You'll just have to trust me that it works as intended. In the workshop I couldn't go into all the details. Similarly, this article would be way too long if I did, but I'll try to do it anyway... The actual regular expression is this:

^([\w ]+)-([\w ,-]+)\.(.+)

The caret (^) is to start the match at the beginning of the line. The first group in parenthesis will match an alphanumeric character (\w) or a space (anything listed between the two square braces), while the + says to repeat it for as long as you can:

([\w ]+)

But we also follow this with a dash (-) and so it will stop the first group just before the dash. This separates the answer, from the trivia about the answer. The square brackets delimit a set of what characters should match (think of it as a Python list with no commas). This is convenient, because in the second group, we want to get the trivia, which includes not only alphanumeric or 'word characters', but also spaces commas and dashes:

([\w ,-]+)

The + repeats the match until the next rule, the period. It has to be escaped, because a period means match any character. We want it to match an actual period, so we escape it with a backslash (\). The last group uses the period to match any character and wont stop until the end of the line.

To actually use this whole regular expression in our Python code, we have to put it in a string. In python we can use the single or double quote mark for strings ( 'a_string' , "also_a_string" ).

In this case however, not just any string, a raw string. We do this by adding a r at the beginning: r'a_string'. That way we do not have to escape the backslash. And we pass that, along with our line to the search() function of the re module.

This returns a match object only if there is an actual match, so we have to test for existence of such on line 16, before we can use it on lines 17-19. There, we get the data from the groups we defined (defined in the regular expression by the parenthesis pairs) and assign them to variables: answer, trivia and question.

Wow, lots of explanation for only 5 lines of code! But that is the nature of the regular expression beast. As I said, often, it is not the answer, but when it is, we just have to live with its denseness...

Line 20 is just setting up (or clearing) a list to store the multiple choice answers that will follow. Yes, that is right, we haven't dealt with those yet...

Line 21 is the else tied to the existence of a match. Basically, if we couldn't match the first regular expression we wrote, that means we are probably dealing with one of the multiple choice answers. This next part could have been done without regular expressions, but since we spent all this time explaining them, let's use them again on line 22, this time with only 2 groups defined. The first will have the a-d letter and the second the description.

Line 23, we test again for a match. Line 24, we get the match.group() without specifying which of the group we want. By doing this, we get the whole match. We further use the strip() function to remove any leading or trailing white spaces, and we then append this to our choices list. Initially it is empty, and we add to it the multiple choices until the last choice (d).

Let me put the last piece of code repeated here:
25:            choice = match.group(1)  
26:            description = match.group(2).strip()  
27:            if description == answer:  
28:              correct_response = choice  
29:            if choice == 'd':  
30:              print(question, choices[0], choices[1],  
31:                   choices[2], choices[3],  
32:                   correct_response, trivia)  

Here, on line 25 we get the letter (a-d) assigned to choice. We then get the description on line 26 (using strip() again to remove leading and trailing white spaces). We can then use this description to compare it  (line 27) to the answer we picked up earlier. If the answer is on that line, we then assign to correct_response that letter.

Furthermore, if we are on the last line of the multiple choice answers, we are now ready to either store the whole group of question, choices, correct response and trivia, or in this case (lines 30-32) to print it.

We could also have passed the file to the regular expression and write a single regular expression getting all the data we wanted on multiple lines at once, but the sheer complexity of it would have rendered this tutorial useless.

Simple Quiz


In piquiz.py, we keep things simple (relatively... !) again. It is a basis that can be evolved into something a bit more interesting. Just a straight script, a trivia game in 50 lines of code (a little bare bone obviously with no scoring):


1:  #!/usr/bin/env python  
2:  # -*- coding: utf-8 -*-  
3:  """  
4:  PiQuizMachine - A quiz game for the Raspberry Pi.  
5:  Loads questions and answers from quiz data file. It follows the format  
6:  from triviachamp.com  
7:  """  
8:  # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4  
9:    
10:  import re  
11:  import random  
12:    
13:  data = []  
14:  with open('questions.txt', 'r') as f:  
15:    for line in f:  
16:      if len(line) > 1:  
17:        match = re.search(r'^([\w ]+)-([\w ,-]+)\.(.+)', line)  
18:        if match:  
19:          answer = match.group(1).strip()  
20:          trivia = match.group(2).strip()  
21:          question = match.group(3).strip()  
22:          choices = []  
23:        else:  
24:          match = re.search(r'\s+(\w)\.([\w ,-]+)', line)  
25:          if match:  
26:            choices.append(match.group().strip())  
27:            choice = match.group(1)  
28:            description = match.group(2).strip()  
29:            if description == answer:  
30:              correct_response = choice  
31:            if choice == 'd':  
32:              entry = (question, choices[0], choices[1],  
33:                   choices[2], choices[3],  
34:                   correct_response, trivia)  
35:              data.append(entry)  
36:    
37:  random.shuffle(data)  
38:  for question,choice_a,choice_b,choice_c,choice_d,\  
39:      correct_response,trivia in data:  
40:    print question  
41:    print choice_a  
42:    print choice_b  
43:    print choice_c  
44:    print choice_d  
45:    team_answer = raw_input("Your answer:")  
46:    if team_answer == correct_response:  
47:      print "That is correct, the answer is",correct_response  
48:      print trivia  
49:    else:  
50:      print "Not correct."

Up to line 31, it is almost the same as we already discussed (but using the full size questions.txt file). 32-34, instead of printing, we now store this entry into a list named data, which we initialized empty on line 13.

We are now going to randomize or shuffle the list of questions on line 37. On line 11 we imported the random module which includes a shuffle function. This is very convenient for games, not just for a quiz, but really interesting for a card game. We could define a card deck as a list, then shuffle it.

On line 38 and 39 (the backslash makes it as if it was a single line), we now loop through all the questions in the data list using a for loop. We then print the question and multiple choices on lines 40 through 44. I'm using a print syntax of a statement, but make note that starting with Python 3, print is a function. The next code example uses the print() function syntax (works in python 2.7 and 3). Lines 38-44: This can all be coded in a prettier way, but in order to keep this as simple as I can, I just did it by specifying all the fields so it is very obvious what we are doing.

Line 45 allows us to get an answer from a keyboard, with a prompt of "Your answer:". We check if the answer is correct on line 46 and if so print a message and the trivia tied to the answer on lines 47 and 48. If the answer was wrong (else) we print a different message on line 50.

So that is the basic core of a quiz program.

The Real Deal

Combining the code we've done in the button/quiz*.py scripts in the previous article, with the code above, we have all the ingredients to make an interactive quiz machine, one where each of the four teams or players gets a game controller, and will be able to "buzz" in first to answer, much as in TV games, such as Jeopardy or Family Feud.

This code was designed to teach about Python and GPIOs for a workshop and it is what I would call "squeaky clean". It is kept on purpose simple, yet demoes several key features of Python and the GPIOs.

The code was run through pep8 and pylint and is properly documented and formatted (even having 2 blank lines between functions, no use of ; etc), is quite verbose (several things were done in multiple lines but in normal use I would probably do as one) and yet, is less than 100 physical lines of code.

1:  #!/usr/bin/env python  
2:  # -*- coding: utf-8 -*-  
3:  """  
4:  PiQuizMachine - A quiz game for the Raspberry Pi.  
5:  Loads questions and answers from quiz data file. It follows the format  
6:  from triviachamp.com. Lock out through pushbutton controllers  
7:  """  
8:    
9:  __author__ = "Francois Dion"  
10:  __email__ = "[email protected]"  
11:    
12:  import re  
13:  import random  
14:  import RPi.GPIO as gpio  
15:    
16:  PINS = (22, 23, 24, 25) # list of pins as tuple  
17:  OFFSET = 21 # team number to GPIO pin offset  
18:    
19:    
20:  def loadtrivia(filename):  
21:    """ Load the trivia into a list, after extracting the fields """  
22:    data = []  
23:    with open(filename, 'r') as f:  
24:      for line in f:  
25:        if len(line) > 1:  
26:          match = re.search(r'^([\w ]+)-([\w ,-]+)\.(.+)', line)  
27:          if match:  
28:            answer = match.group(1).strip()  
29:            trivia = match.group(2).strip()  
30:            question = match.group(3).strip()  
31:            choices = []  
32:          else:  
33:            match = re.search(r'\s+(\w)\.([\w ,-]+)', line)  
34:            if match:  
35:              choices.append(match.group().strip())  
36:              choice = match.group(1)  
37:              description = match.group(2).strip()  
38:              if description == answer:  
39:                correct_response = choice  
40:              if choice == 'd':  
41:                entry = (question, choices[0], choices[1],  
42:                     choices[2], choices[3],  
43:                     correct_response, trivia)  
44:                data.append(entry)  
45:    return data  
46:    
47:    
48:  def getteam(lockedout):  
49:    """ figure out which team presses their button first """  
50:    poll = [pin for pin in PINS if pin - OFFSET not in lockedout]  
51:    while True:  
52:      buttons = [gpio.input(pin) for pin in poll] # list comprehension  
53:      if False in buttons: # at least one button was pressed  
54:        if buttons.count(False) == 1:  
55:          return buttons.index(False) + 1  
56:        else: # trouble, multiple buttons  
57:          teams = [i for i, b in enumerate(buttons) if b is False]  
58:          return random.choice(teams)  
59:    
60:    
61:  def main():  
62:    """ our main program """  
63:    data = loadtrivia('questions.txt')  
64:    
65:    gpio.setmode(gpio.BCM) # broadcom mode, by GPIO  
66:    for pin in PINS:  
67:      gpio.setup(pin, gpio.IN) # set pins as INput  
68:    random.shuffle(data)  
69:    for question, choice_a, choice_b, choice_c, choice_d, \  
70:        correct_response, trivia in data:  
71:      # if we wanted to make a graphical game using pygame  
72:      # we would replace the print statements below  
73:      print(question)  
74:      print(choice_a)  
75:      print(choice_b)  
76:      print(choice_c)  
77:      print(choice_d)  
78:      lockedout = [] # we start with no team locked out  
79:      while len(lockedout) < 4:  
80:        team = getteam(lockedout)  
81:        prompt = "Your answer, team {0}? ".format(team)  
82:        team_answer = raw_input(prompt) # get an answer  
83:        if team_answer == correct_response:  
84:          print("That is correct, the answer is:")  
85:          print(correct_response)  
86:          print(trivia)  
87:          print("")  
88:          lockedout = [1, 2, 3, 4]  
89:        else:  
90:          print("That is not the answer.")  
91:          lockedout.append(team)  
92:    
93:    
94:  if __name__ == "__main__":  
95:    try:  
96:      main()  
97:    except KeyboardInterrupt:  
98:      print("Goodbye")  
99:      gpio.cleanup()

Lines 1 to 16 should be familiar. I did add two variables for author and email. This is just a convention some people do in their code. Line 17 I'm defining an offset between the team number (1,2,3,4) and the GPIOs (22,23,24,25).

Lines 20 through 45 is the code from the previous example, but put into a function that accepts a file name for the quiz data and that upon execution, will return a list containing all our questions.

lines 48 through 58 is our quiz4.py code from the previous article, put into a function, but with a twist:

On line 52, instead of using directly the PINS tuple, we filter it first on line 50 to see which pins we should really poll. When getteam() is called, a list of teams that have been locked out is provided. We are not even going to check these teams button controllers, because they answered this question already, with a wrong answer.

50:    poll = [pin for pin in PINS if pin - OFFSET not in lockedout]  

So, what is happening here merits an explanation. You've probably recognized this as a list comprehension (which we've introduced in the previous article). But it looks strange... Let's read it. We will add to this list a pin, from an iteration of the PINS tuple (containing 22,23,24,25), but we will do this only if the pin minus the offset (21) is not in the list of locked out teams. So, if we take 22 - 21, that is 1. If team 1 is locked out, the list stays empty and continues on to the next value and test it. So on and so forth.

I mentioned earlier we had just touched the tip of the list comprehensions. here we went a little deeper, but it goes on.

Lines 51-58, we loop until a button is pressed. If only one button was pressed at the exact same time, we are good to go, and return which of the teams (1 - 4) pressed the button first. But trouble is looming on the horizon. It is possible for 2 or more buttons to be pressed at the exact same moment.

We thus have to introduce some random process to select one of those that have been captured as pressed. We do that on lines 57 and 58. 58 uses the choice() function of the random module (imported on line 13), but 57 requires some explanation, for those who are just starting with Python:

57:          teams = [i + 1 for i, b in enumerate(buttons) if b is False]  

We want to generate a list of all the teams that had pressed their buttons. buttons is a list containing something like [False, True, True, False], indicating here that team 1 and 4 pressed their button at the same time.

What I now want is a list containing [1, 4] to select randomly from it. So what we do is to use a built in function called enumerate() on that buttons list. This returns the index (starting at zero) and the value, so we capture this with a for i, b. We will assign i (the zero based index) + 1 (to get a team number) to the list, but only if b (the value) is False. There, that wasn't so bad, after all!

We are now ready for our main() function, lines 61 to 91 (only 30 lines).

On line 63 we load the data from the file questions.txt

Lines 65-67, we set up the GPIOs, as we've done in quiz4.py.

Lines 68-77 is the logic we had in our previous example: piquiz.py

At line 78, we initialize the list of locked out teams to be empty, and start a loop on line 79 that will go on until we have 4 teams locked out by 4 wrong answers, or a right answer (which forces all 4 teams to be locked out).

Line 80 is where we poll the button controllers until we have somebody pressing a button.

81:        prompt = "Your answer, team {0}? ".format(team)  
82:        team_answer = raw_input(prompt) # get an answer  

Lines 81 and 82 are asking for an answer from the team that pushed their button first. This answer is given using the keyboard.  Line 81 could also have been written as:

prompt = "Your answer, team " + str(team) + "?"

This is closer to what is done in other languages, but each concatenation with + creates a new resulting object. As such, it is a less efficient way of doing it, and if used in a loop with lots of data, will consume a lot of memory and be slow.

lines 83-88 handle a correct answer (concluding by locking out all teams to force a new question), while lines 89-91handle a wrong one, adding that one team to the list of locked out teams (passed to the function on line 80)

94:  if __name__ == "__main__":  
95:    try:  
96:      main()  
97:    except KeyboardInterrupt:  
98:      print("Goodbye")  
99:      gpio.cleanup() 

Lines 94-99 repeat the safeguard pattern we established in our previous article, in quiz4.py on lines 21-25

There you go, a complete game with Raspberry Pi GPIO hardware integration, that can be played with friends, in less than 100 lines of python code.

Team 2 is smoking! Two correct answers in a row

Conclusion


I've avoided classes and methods on purpose. These would have complicated things too much for the workshop audience (which ranged from teenagers to adults and from some who had never programmed in python, to some who had written a good bit).

Several also had a background in basic and shell scripts, so I did a good bit as straight scripts, without functions, waiting to the end to introduce these concepts. I've also added a bit more code than in the workshop in order to provide a better reference after the fact.

I hope it is useful to others, and if you are in the area, make sure to keep an eye for our next PyHack Workshop. Let me know if I've provided enough details, what things I could have explained more etc.