Τετάρτη 26 Δεκεμβρίου 2012

Learning to Program with Python


Here we will use the python programming language to make a game of hangman, starting from scratch, working on Raspberry-pi. Python comes with Raspberry-Pi, so nothing special needs to be installed to follow along on your Raspberry-Pi. We will learn about:
  • Memory and naming 
  • Computer arithmetic 
  • Using and learning libraries 
  • How to make a program 
  • Input and output 
  • Loops and choices 
  • Connecting to the internet
At the end we will have a game we can play.

This page was originally posted at http://davidbau.com/python for teaching a small group of third-graders. (Slides here.) (Printable here.)

Running Python

Connect to raspberry-pi through ssh or telnet. It will look something like this:
Last login: Sun Dec 30 15:59:06 2012 from 192.168.1.100
pi@raspberrypi ~ $ 


Now type "python" and press the return button. Your screen should look like this now:
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 >>>; means that python is waiting for you to program something.

Keeping a Secret

Python can remember things, so let's tell it to remember our secret word.
>>> secret = 'crocodile'
>>>


You can tell it to print something by saying print.
>>> print secret
crocodile
>>>


Python will remember the secret until you quit. So you can always go back and print your secret again by saying "print secret." Now try to print something python doesn't know.
>>> print number
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'number' is not defined
>>>


Don't worry. This is fine. You can just teach python what "number" is and try again.
>>> number = 43
>>> print number
43
>>>


Computers are Good Calculators

Your computer is better than any calculator at doing math. Let's try some.
>>> print  2+33+66
101
>>> print 33333333*44444444
1481481451851852
>>> n = 123456789
>>> print n*n*n
1881676371789154860897069
>>>


In Python, plus and minus are normal but times and divide are done using the * and / symbol. Some other symbols to know:
+plus
-minus
*times
/divide, rounding down
x = 95save 95 as x
x == 24is x equal to 24?
x < 24is x less than 24?
x > 24is x more than 24?
len(word)the length of word
str(num)turns num into a string of digits
int(digits)makes a number from a string

What will it do when we say "len(str(1234))"?
Try your own fancy formulas. Don't worry if you get errors.

Picking a Random Number

Python comes with libraries of functions that do almost anything.
Let's tell Python to pick a random number. Get the "random" library by typing this:
>>> import random
>>>

Now we can say "random.randint(1,100)" to pick a random number from 1 to 100.
>>> random.randint(1,100)
25
>>>


Which number did you get?
You can learn about libraries by saying help. Try typing this:
>>> help(random)
Help on module random:

NAME
    random - Random variable generators.
(...and on and on...)

It will show lots of information, and you can press the space bar to see a screenfull at a time. Eventually you will see a long list of all the functions in the library. We don't have time to read it all now, so you can press "q" when you have seen enough. You can use help() to ask about most things in python.

Words and Numbers

What do you think happens when you try to do math with words?
>>> print 'red' + 'yellow'
redyellow
>>> print 'red' * 3
redredred
>>> print 'red' + 3
Traceback (most recent call last):
  File "", line 1, in 
TypeError: cannot concatenate 'str' and 'int' objects
>>>



If you add two words, it sticks them together. If you times a word by 3, it makes three copies. Python doesn't know how to add a word and a number, so it says "cannot concatenate 'str' and 'int' objects." A word that you put in quotes is just a string of letters called a "str" in python. Numbers that don't have a decimal point are integers and are called "int" in python.
You can't add a str and an int. But you can turn a number into a string if you use the str() function.
>>> print 'red' + str(3)
red3
>>>

Using "for" to Repeat

You can repeat something with the "for" command.
If you say "for something in something:" with a colon (:) at the end, python will look for any indented lines afterwards and repeat them. Try this:
>>> for letter in secret:
...   print letter
...
c
r
o
c
o
d
i
l
e
>>>


Think about your program - it is saying "for every letter in the secret, do this next thing." The computer repeats "print letter" nine times, once for each letter.
If it didn't work for you, don't worry. Press return and try again. Check that you put in the extra spaces and the punctuation. Spaces at the beginning of a line do make a difference in python.
Of course, in our game we shouldn't give away our secret word right away. So once you have the hang of it, try this:
>>> for letter in secret:
...   print '_',
_ _ _ _ _ _ _ _ _ 
>>> 

The comma at the end of print tells it not to start a new line.

Making Your Own Program

A program is just a file with code in it. Let's make one.
  1. Start TextEdit from your Applications folder.
  2. Go to the "Format" menu and say "Make Plain Text".
  3. Now type this in:
#!/usr/bin/env python

print 'time to play hangman'

The first line tells the computer which what language the program is written in: python.
After that, you can write as many lines of python code as you like.
Save the file with the name "game.py" on your current folder.

Running Your Program

Go back to Terminal. If you are still in python, press control-D to get out. The magic way to make a file into a program is "chmod +x filename" like this:
pi@raspberrypi ~ $ chmod +x game.py
pi@raspberrypi ~ $


The "chmod" command stands for "change mode" and "+x" means "make it executable." You just marked your file as a program.
Now you can run your program by typing its name.
pi@raspberrypi ~ $ ./game.py
time to play hangman
pi@raspberrypi ~ $


That's it. You've made your first program!

Programs are just Scripts

A program is just a script that a computer reads as quickly as it can. If we put a lot of lines of code into a program, the computer will do them all, one after the other.
Try typing these extra lines into your TextEdit. Don't forget to save the file again.
#!/usr/bin/env python

print 'time to play hangman'
secret = 'crocodile'
for letter in secret:
  print '_',

Now run the program in Terminal.
You can use the up-arrow if you don't want to bother typing the name of your program again. After you have the name of your program, press return.
laptop:~ student$ Desktop/game.py
time to play hangman
_ _ _ _ _ _ _ _
laptop:~ student$  

See what happens? Everthing in your program ran very quickly.

Using "if" to Choose

In our hangman game, we should show where any guessed letters are. To decide whether to print a line or a letter, we will need to use "if" and "else".
Try changing your program inside TextEdit like this:
#!/usr/bin/env python

print 'time to play hangman'
secret = 'crocodile'
guesses = 'aeiou'

for letter in secret:
  if letter in guesses:
    print letter,
  else:
    print '_',

Don't forget to line everything up, and remember to save it.
What happens when you run it?
The line "if something in something:" makes a choice. If the letter is in our guesses, it prints the letter. Otherwise it prints a little line ("else:" is how you say "otherwise" in python).
Since the whole thing is under the "for something in something", this choice is repeated for every letter.
laptop:~ student$ Desktop/game.py
_ _ o _ o _ i _ e
laptop:~ student$  

Check your spelling and spacing and punctuation if you get errors. Take your time to get it to work.

Input with "raw_input"

Our game is no good if you can't guess. To let the player guess we will use a function called "raw_input()."
It works like this:
answer = raw_input('my question')

So try changing your program to look like this:
#!/usr/bin/env python

print 'time to play hangman'
secret = 'crocodile'
guesses = 'aeiou'

guess = raw_input('guess a letter: ')
guesses += guess

for letter in secret:
  if letter in guesses:
    print letter,
  else:
    print '_',

The "guesses += guess" line add the guess to the string of guesses. If the string of guesses was "aeiou" and the new guess is "c", then the string of guesses will become "aeiouc".
Let's run it.
laptop:~ student$ Desktop/game.py
guess a letter: c
c _ o _ o _ i _ e
laptop:~ student$  

You can guess any letter and it will show it to you.

Using "while" to Repeat

We need to let the player take more than one turn.
The "while" command can repeat our program until the player is out of turns.
#!/usr/bin/env python

print 'time to play hangman'
secret = 'crocodile'
guesses = 'aeiou'
turns = 5

while turns > 0:
  for letter in secret:
    if letter in guesses:
      print letter,
    else:
      print '_',

  print
  guess = raw_input('guess a letter: ')
  guesses += guess
  turns -= 1

You need to indent everything under the "while" command to make this work. So you will need to add some spaces in front of most of your program.
Let's also move the guessing after the hint instead of before.
The command "turns -= 1" means subtract one from "turns," so if it used to be 5, it will be 4. Then the next time around it will be 3 and so on. When turns is finally zero, the "while" command will stop repeating.
Try running your program. Does it work?

Improving Our Game

We can already play our game. Now we need to fix it up so that it is fun.
  1. The player should win right away when there are no missing letters.
  2. The player should only lose a turn on a wrong guess.
  3. When the player loses, the game should tell the secret.
Here is one way to improve it.
#!/usr/bin/env python

print 'time to play hangman'
secret = 'crocodile'
guesses = 'aeiou'
turns = 5

while turns > 0:
  missed = 0
  for letter in secret:
    if letter in guesses:
      print letter,
    else:
      print '_',
      missed += 1

  print

  if missed == 0:
    print 'You win!'
    break

  guess = raw_input('guess a letter: ')
  guesses += guess

  if guess not in secret:
    turns -= 1
    print 'Nope.'
    print turns, 'more turns'
    if turns == 0:
      print 'The answer is', secret

The "missed" number counts how many blanks we are still missing. If if is zero, it means we won, and the "break" command breaks out of the "while" section early.
The "if guess not in secret" line checks if the guess was wrong. We only count down the "turns" if our guess was wrong.
When we guess wrong, we also print a bunch of stuff like "Nope" and how many more turns we have. When we are wrong for the last time we print the secret.

Making it Look Like Hangman

It will be more fun if we make our game look like Hangman.
All we need to do is print parts of the poor hangman person when there is a wrong guess. Try adding something like this to the wrong guess part:
...
    print 'Nope.'
    print turns, 'more turns'
    if turns < 5: print '   O   '
    if turns < 4: print ' \_|_/ '
    if turns < 3: print '   |   '
    if turns < 2: print '  / \  '
    if turns < 1: print ' d   b '
    if turns == 0:
      print 'The answer is', secret

You can try drawing your own person with punctuation symbols like this.

Picking a Random Secret

The only problem with the game is that it always plays the same secret word. We should use the random library to choose a random word.
Add "import random" to the top of your program and change the line that sets up the secret so that it looks like this:
#!/usr/bin/env python

import random

print 'time to play hangman'
secret = random.choice(['tiger', 'panda', 'mouse'])
guesses = 'aeiou'
...
The square brackets [ ] and commas make a list, and the random.choice picks one thing randomly from the list.
Of course, you can make the list as long as you like. Here is a longer list:
...
print 'time to play hangman'
secret = random.choice([
  'crocodile',
  'elephant',
  'penguin',
  'pelican',
  'leopard',
  'hamster',
])
...
You can write a long list on lots of lines like this, as long as you remember to end any parentheses () and brackets [ ] that you started. Don't forget to put a comma after each thing in the list.

Loading a List from the Internet

I have an even longer list of animals on the internet, at http://davidbau.com/data/animals.
If your computer happens to be connected to the internet, you can load this data in python using a function called "urllib.urlopen". (URLs are what web addresses are called, so urllib stands for "URL library," and urlopen means "open a URL.")
The code looks like this:
import urllib

animals = urllib.urlopen('http://davidbau.com/data/animals').read().split()
secret = random.choice(animals)

What this means is:
import urllib
Import the library called "urllib" to use.
animals = urllib.urlopen('http://davidbau.com/data/animals').read().split()
Open up the address http://davidbau.com/data/animals
animals = urllib.urlopen('http://davidbau.com/data/animals').read().split()
Read the whole webpage into a big string.
animals = urllib.urlopen('http://davidbau.com/data/animals').read().split()
Split the string into a list of words.
animals = urllib.urlopen('http://davidbau.com/data/animals').read().split()
Call the whole list "animals".
secret = random.choice(animals)
Choose a random one and call it "secret."
You can use urllib to load up more data than you could ever type in yourself.

The Whole Hangman Program

Here is the whole program from beginning to end:
#!/usr/bin/env python

import random
import urllib

print 'time to play hangman'
animals = urllib.urlopen('http://davidbau.com/data/animals').read().split()
secret = random.choice(animals)
guesses = 'aeiou'
turns = 5

while turns > 0:
  missed = 0
  for letter in secret:
    if letter in guesses:
      print letter,
    else:
      print '_',
      missed += 1

  print

  if missed == 0:
    print 'You win!'
    break

  guess = raw_input('guess a letter: ')
  guesses += guess

  if guess not in secret:
    turns -= 1
    print 'Nope.'
    print turns, 'more turns'
    if turns < 5: print '   O   '
    if turns < 4: print ' \_|_/ '
    if turns < 3: print '   |   '
    if turns < 2: print '  / \  '
    if turns < 1: print ' d   b '
    if turns == 0:
      print 'The answer is', secret

More About Programming

The best part of programming is customizing your program to make it your own.
Can you make your hangman program harder or easier?
Can you make it automatically play again at the end of the game?
This webpage at python.org has more about programming in python.

Fitting the raspberry-pi display on my SAMSUNG 40" TV

In order to fit the raspberry-pi display on my SAMSUNG 40" TV I had to edit the config.txt file. This file is an optional file on the boot partition. It would normally be accessible as /boot/config.txt from Linux.

The Raspberry Pi config.txt file is read by the GPU before the ARM core is initialised. It can be used to set various system configuration parameters. The format is "property=value" where value is an integer. You may specify only one option per line. Comments may be added by starting a line with the '#' character.

I had to follow the following steps:

1. First I defined the hdmi_group and hdmi_mode. I checked the valid modes of my tv set by executing:

#> /opt/vc/bin/tvservice -m CEA


hdmi_group=1
hdmi_mode=4


2. Then the display was outside the visible area of the screen. That meant I couldn't see the edges of the display, including the command line prompt and the LXDE toolbar. The fix is to edit the file /boot/config.txt, containing the lines:

overscan_left=25
overscan_right=25
overscan_top=16
overscan_bottom=16


Relative links:

http://elinux.org/RPiconfig#Video_mode_options
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=7&t=4684http://wrightrocket.blogspot.gr/2012/06/openelec-on-raspberry-pi.html


Adding a KeySonic bluetooth keyboard to Raspberry-Pi

This post explains how to connect a Bluetooth keyboard to raspberry pi.


Bluez installation

First of all install the Linux’s Bluez Bluetooth stack. In raspberry this is as easy as type :
apt-get install bluez bluez-utils bluez-compat bluez-hcidump



Bluetooth daemon

Modify the /etc/default/bluetooth file changing:

BLUETOOTH_ENABLED=1
HID2HCI_ENABLED=1
HID2HCI_UNDO=0

Restart bluetooth:
#> invoke-rc.d bluetooth restart 



Scan for the available devices

Scan for the available devices. Make sure your keyboard is in discoverable mode (push the button) before running the scan command. This provides with the device ID, similar to the MAC address of a network card. 



Pairing using the bluetooth Agent

Start bluetooth-agent (as root), giving an arbitrary PIN, such as 1234

Connect to the device

connect to the device using the command hidd --connect XX:XX:XX:XX:XX:XX


Request authentication from the device

Request the device to authenicate using the command hcitool auth XX:XX:XX:XX:XX:XX. Enter the PIN from your keyboard pressing at the end.


Relative Links:

http://wiki.debian.org/BluetoothUser




Κυριακή 23 Δεκεμβρίου 2012

Τετάρτη 19 Δεκεμβρίου 2012

alix 6f2 with novatel 3G module

 _  __

 \ \/ /___ __  __ ___  ___  ___    Useful Commands:
  \  // _ \\ \/ /,-_ |/ _ |/ -_)     remountrw - mount disk as read-write
   \/ \___/ \  / \___,\_  |\___|     remountro - mount disk as read-only
           _/_/        _'_|          remove.docs - remove all docs and manpages
     { V o y a g e } - L i n u x
      < http://linux.voyage.hk >   Version: 0.9 (Build Date 20120927)

root@voyage:/etc# vi wvdial.conf

[Dialer Defaults]
Init1 = ATZ
#Init2 = AT V1 E1 S0=0 &C1 &D2 +FCLASS=0
#Init2 = AT&F E1 V1 X1 &D2 &C1 S0=0
Modem Type = USB Modem
Baud = 460800
New PPPD = yes
Modem = /dev/ttyUSB0
#Modem = /dev/ttyUSB2
ISDN = 0
[Dialer vodafone]
Phone = *99#
Stupid Mode = 1
Init2=ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3=AT+COPS=3,2
Init4=AT+CGDCONT=1,"IP","internet"
Username = ;
Password = ;
; Phone =
; Password =
; Username =

root@voyage:/etc# vi /etc/ppp/peers/wvdial


noauth
passive
kdebug 4
noccp
#persist
name wvdial
noipdefault
usepeerdns
defaultroute
replacedefaultroute


proxy.sh


#!/bin/sh
echo "Setting up IPTABLES proxy..."
#
# enabling IP forwarding...
#
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr
#
# Flushing packet filtering rules
#
iptables -t filter -F INPUT
iptables -t filter -F OUTPUT
iptables -t filter -F FORWARD
iptables -t nat -F
#
# Setting up default policies
#
iptables -t filter -P INPUT ACCEPT
iptables -t filter -P OUTPUT ACCEPT
iptables -t filter -P FORWARD DROP
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

#
# Setting up NAT
#
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
iptables -t filter -A FORWARD -i ppp0 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t filter -A FORWARD -i eth0 -o ppp0 -j ACCEPT

echo "proxy setup done."





Κυριακή 16 Δεκεμβρίου 2012

Book Selection

Τα μυστήρια των αριθμώνΤο τετράδιο της ΜάγιαΟ μέτοικος και η συμμετρία



Τρίτη 4 Δεκεμβρίου 2012

Using Python and MQTT on a Rasberry Pi

Mosquitto Mosquitto (mosquitto.org) is an open source message broker that implements the MQ Telemetry Transport protocol. MQTT (mqtt.org) privides a lightweight method of carrying out messaging using a publish/subscribe model. More about the MQTT protocol you can read at http://mosquitto.org/man/mqtt-7.html


After installing mosquitto 1.0.5 on my rasberry pi  I wrote the following two python scripts to experiment myself.

The code is shown below and it is self explanatory:

mosqsrv.py

#!/usr/bin/python

import mosquitto

#define what happens after connection
def on_connect (mosq, obj, rc):
        if rc==0:
                print "connected"

#On receipt of a message create a message
def on_message(mosq, obj, msg):
        print msg.topic+', '+msg.payload

#create a roker
mqttc = mosquitto.Mosquitto("python_sub")

#define the callbacks
mqttc.on_connect = on_connect
mqttc.on_message = on_message

#connect
mqttc.connect("localhost", 1883, 60)

#subscribe to topic test
mqttc.subscribe("test", 0)

#keep connected to broker
while mqttc.loop()==0:
        pass


mosqcl.py

#!/usr/bin/python

import mosquitto

#define what happens after connection
def on_connect (mosq, obj, rc):
        print("connected")

#create a broker
mqttc = mosquitto.Mosquitto("python_test")

#connect
mqttc.connect("192.168.1.105",1883, 60)

#publish to broker
mqttc.publish("test", "hello world!", 1)

mqttc.disconnect()

To test it I run mosquitto broker from the command line after editing the mosquitto.conf file to define the run user.