Showing posts with label raspbian. Show all posts
Showing posts with label raspbian. Show all posts

Tuesday, July 28, 2015

Linux, not chmod, groups!

In english

I was reviewing my logs, and I was surprised to see that every week, hundreds of people were going to this page (even though it was posted well over 2 years ago):
http://raspberry-python.blogspot.com/2012/09/pas-chmod-groupes.html

This is great if you can read french, but if not... here's a translation.

Groups

The use of chmod to resolve permission issues appear on a regular basis on forums and in tutorials for Linux.

This is quite a risky proposition, particularly if you are very permissive (chmod 777 !!)

Or another option I've seen is to simply use sudo.

By simply mastering one thing, most of the time you can make this problem go away: using groups.

For example, if we have something like this:

fdion@raspberrypi ~ $ ls -al /dev/fb0
crw-rw---- 1 root video 29, 0 Dec 31 1969 /dev/fb0

Permissions on this file are defined as:
c, owner (root): read write, no exec, group (video): read write, no exec, and for everybody else, no access.

If I would like for my python script under my fdion account, or really any program that I run, to read and write the framebuffer (any program using the SDL would be a candidate), I only need to do:

usermod -a -G video fdion  and in this way I added fdion to the video group.

That is it. While on the topic of SDL, I would recommend doing at a minimum:

sudo usermod -a -G video fdion
sudo usermod -a -G audio fdion
sudo usermod -a -G input fdion

This way you'll be able to use the video, audio, mouse etc.

Francois Dion
@f_dion

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

Thursday, April 30, 2015

The computer network in space - Part 2


- You're flying! How?
- Python!
( https://xkcd.com/353/ )

Continued


Part one of this series of articles on Team Near Space Circus flight NSC-01 can be found  >here<. It covered the physical layout of the 7 Raspberry Pis, 8 cameras and power system. It left off as we were about to go into the details of the network topology itself.

A satellite or a bowl of spaghetti?

Plan A: 2 Pi in a Pod...


The initial plan was for 2 Raspberry Pi using a serial communication protocol. The Model A+ does not have an ethernet port. Of course a Raspberry Pi 2 has one, and is more powerful, but it also consumes a lot more power than the A+. Our battery pack would have had to be much larger if we went down that path, and that meant significantly heavier. We had a goal of 2Kg for the payload itself, and we were getting close, so serial it was...

Serial communication


DB25 (serial or parallel)
DB9 (serial)

Many early personal computers typically had two interfaces, either built in or available through an expansion card: a serial (either a DB9 or DB25 connector) and a parallel interface (either a DB25 or 36 pins Centronics connector, aka IEE1824). The parallel interface was typically used for printers (and great for DIY DACs with resistor ladders, but that's a story for another time), while the serial port was mostly used for modems or scientific equipment.

RS-232 was introduced in 1962, so it's been around for quite a while now. Many serial connections were actually TTL (5V), such as on the Digital Decwriter III, but it was quite easy to convert them to a +/- voltage range (and even more so since the mid 80s with ICs such as the MAX232). The initial purpose was to connect a DTE (Data Terminal Equipment), a fancy way of saying a computer, and a DCE (Data Communication or Circuit-terminating Equipment).

On a DB9 connector, the pins would be (DB9 male connector pictured):

RxD is Receive Data and TxD is Transmit Data. What if you need to connect two DTE together? You need a Null-Modem adapter or cable. The simplest Null-Modem circuit requires 3 wires (2 if you can guarantee the ground on each end to be the same):

GND(7) to GND(7), TxD(5) to RxD(4), RxD(4) to TxD(5)

Raspberry Pi Header


The Raspberry Pi doesn't have a DB9 or DB25 connector. But if you look at the 40 pin header, notice on the top row, the 4th and 5th pins:
Raspberry Pi Model A+ with pinout as overlay

TXD and RXD. It is a serial port, but it is *not* RS-232 compatible as far as voltage levels are concerned (a 1 is marked by a negative voltage in the range -3V to -15V, and a 0 by a positive voltage in the range +3V to +15V), as it is a TTL interface (a 1 is marked by a positive voltage, either 3V3 or 5V and a 0 is marked by 0V). But that is fine, we are only connecting to another Raspberry Pi.

The primary issue with this serial port is that the Raspbian operating system has a console (TTY) associated it. Meaning that you could connect this to a computer, with the right cable, and see the boot process and get a console prompt, and be able to type commands, as if you had a keyboard and monitor connected directly to the Raspberry Pi.

In our case, however, we want to use the port for something else, our own communication network, so we have to disable this feature. It was once a manual process, and I had written a script to do it, but...

Configuration


sudo raspi-config

The raspi-config now has an option under the Advanced Options selection to disable the serial port console, so we can use it directly:

Advanced -> Serial
Once we have reconfigured the serial port, we can quit raspi-config and reboot. For each compute node, beside disabling the serial port console, we also enabled on the advanced page the SPI and I2C options, and on the main page we configured the time zone, enabled the camera and expanded the filesystem. We also overclocked nodes 1-3 to 800 MHz while nodes 4-6 ran at 700 MHz (so we can measure the impact of overclocking).

Plan B: A Pi cluster

By using a pair of Raspberry Pi, the communication process is pretty straightforward. With two nodes, we can use SLIP or Point to Point Protocol (PPP). Initially, this was the thought for NSC-01 and we would not have to write the code for the network layer.

6 Raspberry Pi cameras
1 Infrared Raspberry Pi camera (pointing down)

But without a functioning camera switcher, the only option was to use one node per camera (each Raspberry Pi has 1 CSI camera connector, even thought the Broadcom chip supports 2 - most cell phones have a front and rear camera). With 7 CSI cameras in total, that meant 7 Raspberry Pi.

Time to dig in our bag of tricks...

Token Ring

4 Node token ring network architecture


As I was going through the options, I started thinking about good old IBM Token Ring (and FDDI). Conceptually, at least. I wasn't going to make something compatible with 802.5, but instead reuse the concept with the serial UART, transmit to receive from one node to the next.

Conceptually, a node is always listening to the serial port. Is this data for me? (if it's a broadcast or if it's addressed to me) If not or if a broadcast, I send it right away to the next node, and process it if it is addressed to me. So let's get into the details.

The diagram


7 Raspberry Pi networked together
In the previous article, one of the pictures clearly showed 7 Raspberry Pi connected together inside the payload. I've included here a fritzing diagram to help in detailing what is going on here.

In the diagram above, I didn't have a Raspberry Pi model A+ for fritzing, so I used the closest thing for our purpose, a Raspberry Pi model B+. Both of them have a 40 pins GPIO header. First row at the top, from left to right has 5V, 5V, GND, TxD and RxD. We'll stop there for right now.

Here I've simply connected node 1 TxD to node 2 RxD (blue wire), node 2 TxD to node 3 RxD (pink), node 3 TxD to node 4 RxD (brown), node 4 TxD to node 5 RxD (cyan), node 5 TxD to node 6 RxD (orange), node 6 TxD to node 7 RxD (yellow) and finally node 7 TxD to node 1 RxD (green), in a nice circular (or ring) fashion.

The GND are not daisy chained from one Pi to the next, because they are all powered by the same source, through their microusb plugs.

Initially, I tried to power the Pi directly from the 5V pin on the GPIO header, but the signal was decoding only partly. By further connecting the 3.3V (that was key, the UART operates at 3V3 so the HIGH signal was not detected reliably when powered with only 5V) and GND together, it made it more reliable, but also more complicated. I reverted back to powering all the 7 nodes using microusb (as detailed in the previous article).

Python


What's great about Raspbian is that not only do we have Python installed, but Python 2.x and 3.x are there, along with many things that are normally optional, such as pygame, pyserial, RPi.GPIO etc. Batteries are quite definitely included with Python on the Raspberry Pi.

Still, for the networking software, we did install two modules from pypi using pip3 (we are using Python 3), docopt and sh.

For the bulk of the development, I used a Raspberry Pi Model B+ connected to my laptop and to a second Raspberry Pi using the serial port and the network switch. That way my laptop could see both Raspberry Pi and I could push new versions of the software using scp.

I also had a "field" version, in case I needed to do last minute changes:

Raspberry Pi sidekick in sidecar configuration (DHCP server on laptop)

Docopt


docopt: helps you to define interface for your command-line app, and automatically generate a parser for it.

For example, in the case of the network controller, token.py, it accepted one argument, the node number. In the future, we'll probably derive the node number from a personality module on the GPIO header, but it was a simple solution that could be done in software, not adding any weight to the payload. The downside was having to keep track of all the microsd cards:

micro SD card transport - For nodes 1 to 7 plus 1 backup


And, so back to docopt, here is how it was used for token.py. At the top of the file, after the shebang line (so the script can be an executable), I included the docstring which defines the interface (lines 2 to 5), which is a required field <address>. This is a simple case, but as cases get more complicated, it really pays off to use docopt.

Then on line 14 I import the docopt module (I group imports alphabetically first by what's included, then a blank line, then again alphabetically I add the imports that have to be installed - just a convention):

1 :  #!/usr/bin/env python3  
2 :  """  
3 :    
4 :  Usage: token.py <address>  
5 :  """  
6 :  from datetime import datetime  
7 :  import logging  
8 :  from logging.handlers import SysLogHandler  
9 :  import RPi.GPIO as gpio  
10:  import serial  
11:  import subprocess  
12:  from time import sleep, time  
13:    
14:  from docopt import docopt  


I then conclude the script by passing the arguments that docopt figured out are there (and validated) in the docstring (__doc__), to the main function:

168:  if __name__ == "__main__":  
169:    arguments = docopt(__doc__)  
170:    main(arguments)  
171:    


And how does one use it in the code itself? In the body of the main function I do the following:

97 :    
98 :  def main(args):  
99 :      my_addr = int(args['<address>'])  
100:




In case an air traveler wants to check our website...

SH

sh: is a full-fledged subprocess replacement for Python 2.6 - 3.4 that allows you to call any program as if it were a function:

`python from sh import ifconfig print ifconfig("eth0") `

Continuing with the code in token.py, you simply import what you need from the shell and sh transparently builds a function for you to call. In this case I needed access to date and rmmod:

1:  #!/usr/bin/env python3  
2:  """  
3:    
4:  Usage: token.py <address>  
5:  """  
6:  from datetime import datetime  
7:  import logging  
8:  from logging.handlers import SysLogHandler  
9:  import RPi.GPIO as gpio  
10:  import serial  
11:  import subprocess  
12:  from time import sleep, time  
13:    
14:  from docopt import docopt  
15:  from sh import date, rmmod  


Then further down in the code I can call date() to call the actual date command from the OS so it is not only in the right format, but in the right timezone (there are other ways to do this, but sh was going to be used heavily for gathering stats, so it made sense to introduce it here):

154:      # synchronize time  
155:      s = str(date())+' \n' # from the OS  
156:      bin = bytes(s, "ascii")  



Pyserial


So, how about accessing a serial port in Python? And are there things to keep in mind when using Python 3?

First thing first, we import serial (line 10). This module is already installed on the Raspberry Pi.

Then, within the body of the main function, we establish a serial connection (line 101). We specify the device that corresponds to the serial UART. This is /dev/ttyAMA0. We also specify the bitrate, expressed in bits per seconds (bps). 115200 is the fastest we can use with the default clock settings for the UART, and is what was used for the flight. As a reference, acoustic coupler modems worked at 300 bps...

We felt that at higher rates it might not give us as reliable a signal, but we will experience with faster rates on future flights (we only had time to do 1 flight within the Global Space Balloon Challenge window). Back in 2012, Gert Van Loo stated:

"The UART and the SPI can be driven by DMA so there is no SW limitation.The real maximum for all those interfaces is only set by the signal integrity.This is certainly the case for I2C as it has to use pull-up resistors to get the signals high again.I know the clocking is rather confused. I built the damn chip and I still have no idea how to control all the clocks.The clocking structure is very complex with a limited number of resources (PLL's) which are used for aplethora of things to drive. (A quick count shows 36! clocks being generated) There will be many cases where it is just not possible to give you ALL the frequencies you want."
And in fact, it is possible to get up to 921600 bps (8 times what we used) in a controlled environment, at the OS level In an environment full of RF, including a 10W 2M transmitter, with a python module, I'd be happy with 4 times (460800) or even twice (230400) our rate. If nothing else, it would drive our latency down some.

Wow, that was quite the detour, anyway, back to our establishing the serial connection. The last thing we specify  on line 101 is timeout=1. This is a 1 second timeout. We will be blocking on reads (line 113), but don't want to wait more than 1 second for the data. 

In the original token ring world, a frame is defined in the following way:



A start delimiter, access control, frame control, destination address and source address, then the data, and finally a frame check sequence, end delimiter and frame status. I found this later, after I designed the frame for our system, and it is interesting that it is quite similar, in functionality, but implemented slightly differently.

In our case, the frames are small in size, they should never go above 1 second to transmit. And if they do, then we kick out that partial request and the balance of the request and we'll get the next one that is complete. So, we assume that if we get a full frame, the first byte is always first, and the frame always conclude with a newline (that way the ser.readline() returns before the 1 second timeout). We thus avoid the start delimiter (the end delimiter is newline). 




The first byte for our protocol is the source address (1 byte = 254 addresses, 0 and 255 have special meaning). The second byte is the destination. On an 8 node setting (the default), this is a bitmask, and 255 (FF) is broadcast. On a "large" cluster,  this address is the individual node address, and 255 (FF) is still broadcast. You gain number of nodes, but loose directed broadcast (say, I want to send something to node 1, 2 and 6, I would use a destination of 9 in the 8 node mode, but in extended mode I have to send 3 individual frames). Then the status. This can be a static status (the packet gets back to the originator) or a counter status (each time a node processes the frame, it decreases the status) or a no status needed, where the nodes simple forward the original frame, but do not send a status. This is followed by a command. This allows for shorter data segments, since we just need the variable part of the command. Finally, the data, a variable number of bytes terminated by newline (\n).

As we get to higher speeds, I will definitely add the frame check sequence of the original token ring to our design.

10 :  import serial  
11 :  import subprocess  
12 :  from time import sleep, time  
13 :    
14 :  from docopt import docopt  
15 :  from sh import date, rmmod  
[...]
97:    
98 :  def main(args):  
99 :    my_addr = int(args['<address>'])  
100:    
101:    ser = serial.Serial('/dev/ttyAMA0', 115200, timeout=1)  
[...]
111:    while not master:  
112:      logger.debug("I am SLAVE") # Everywhere but node 1  
113:      tokens = ser.readline()
114:
115:      if len(tokens) == 0:  
116:        logger.debug("No token received in the past 1 second")


What about writes? As an example, in the case of the master controller, it starts its job by sending a KEEPALIVE frame. This is defined by a series of bytes on line 36. Source is 01 (master node), destination is 255 (FF) broadcast, status is FF (no response needed), then command 05 which is a keepalive. Data segment is of length 0 since \n is encountered immediately. This is the shortest well formed frame that can be sent. And that is what the master controller sends on line 152 using ser.write. As long as we keep everything as type bytes, the serial module works well in Python 3.

Pretty simple, overall (!). Well, considering this was all designed over the course of a handful of days. Python really helped.

[...]
36:  KEEPALIVE = b'\x01\xff\xff\x05\n' # keepalive packet  
[...]
149:    # I am master, or I am taking over   
150:    if my_addr == 1:  
151:      sleep(15)  
152:      ser.write(KEEPALIVE)  
153:      sleep(1)  

We will be creating a module for reuse out of the token.py application, so that other people can use a serial token ring setup themselves. This should be published to pypi. We'll also publish a demo implementation for a master/slave setup.

Deadman's Switch

I'm concluding this article here, as it is already quite long. But I invite you to read about a most interesting device, the Deadman's switch. This was used in our High Altitude Balloon, but it can be used in all kinds of scenarios. Read about it here: http://raspberry-python.blogspot.com/2015/04/deadmans-switch.html

And don't forget to check back regularly for more updates, such as part 3 of this series of articles (the data gathering aspects).

Francois Dion
@f_dion

Saturday, February 14, 2015

Raspberry Pi 2 and RPi.GPIO...

Raspberry Pi 2

So, you just bought a new Raspberry Pi 2 Model B. The one with 4 cores and 1GB of RAM. You want to run some python code that uses RPi.GPIO. You have the January 2015 Raspbian. You should be good to go, right?

RPi.GPIO

Let's revisit RPi.GPIO, the python module for interfacing with hardware on the Pi. Yes, it does come pre-installed. Latest Raspbian (January 2015) includes RPi.GPIO 0.5.9. But then, you try to run your script and it tells you




pi@raspberrypi ~ $ sudo python myscript.py
RuntimeError: This module can only be run on a Raspberry Pi!

Hmm, ok, whatever, this is a Raspberry Pi! So we will have to upgrade the RPi.GPIO python module. While at it, let's install the python dev, setuptools and pip:




pi@raspberrypi ~ $ sudo apt-get install python-dev python-setuptools
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  libexpat1-dev libssl-dev libssl-doc python-pkg-resources python2.7-dev
Suggested packages:
  python-distribute python-distribute-doc
The following NEW packages will be installed:
  libexpat1-dev libssl-dev libssl-doc python-dev python-pkg-resources
  python-setuptools python2.7-dev
0 upgraded, 7 newly installed, 0 to remove and 23 not upgraded.
Need to get 32.1 MB of archives.
After this operation, 43.5 MB of additional disk space will be used.
Do you want to continue [Y/n]? y
Get:1 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libexpat1-dev armhf 2.1.0-1+deb7u1 [210 kB]
Get:2 http://mirrordirector.raspbian.org/raspbian/ wheezy/main python-dev all 2.7.3-4+deb7u1 [920 B]
Get:3 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libssl-dev armhf 1.0.1e-2+rvt+deb7u14 [1,505 kB]
Get:4 http://mirrordirector.raspbian.org/raspbian/ wheezy/main libssl-doc all 1.0.1e-2+rvt+deb7u14 [1,206 kB]
Get:5 http://mirrordirector.raspbian.org/raspbian/ wheezy/main python2.7-dev armhf 2.7.3-6+deb7u2 [28.7 MB]
Get:6 http://mirrordirector.raspbian.org/raspbian/ wheezy/main python-pkg-resources all 0.6.24-1 [63.6 kB]
Get:7 http://mirrordirector.raspbian.org/raspbian/ wheezy/main python-setuptools all 0.6.24-1 [449 kB]
Fetched 32.1 MB in 2min 3s (260 kB/s)
Selecting previously unselected package libexpat1-dev.
(Reading database ... 88962 files and directories currently installed.)
Unpacking libexpat1-dev (from .../libexpat1-dev_2.1.0-1+deb7u1_armhf.deb) ...
Selecting previously unselected package libssl-dev.
Unpacking libssl-dev (from .../libssl-dev_1.0.1e-2+rvt+deb7u14_armhf.deb) ...
Selecting previously unselected package libssl-doc.
Unpacking libssl-doc (from .../libssl-doc_1.0.1e-2+rvt+deb7u14_all.deb) ...
Selecting previously unselected package python2.7-dev.
Unpacking python2.7-dev (from .../python2.7-dev_2.7.3-6+deb7u2_armhf.deb) ...
Selecting previously unselected package python-dev.
Unpacking python-dev (from .../python-dev_2.7.3-4+deb7u1_all.deb) ...
Selecting previously unselected package python-pkg-resources.
Unpacking python-pkg-resources (from .../python-pkg-resources_0.6.24-1_all.deb) ...
Selecting previously unselected package python-setuptools.
Unpacking python-setuptools (from .../python-setuptools_0.6.24-1_all.deb) ...
Processing triggers for man-db ...
Setting up libexpat1-dev (2.1.0-1+deb7u1) ...
Setting up libssl-dev (1.0.1e-2+rvt+deb7u14) ...
Setting up libssl-doc (1.0.1e-2+rvt+deb7u14) ...
Setting up python2.7-dev (2.7.3-6+deb7u2) ...
Setting up python-dev (2.7.3-4+deb7u1) ...
Setting up python-pkg-resources (0.6.24-1) ...
Setting up python-setuptools (0.6.24-1) ...

pi@raspberrypi ~ $ sudo easy_install pip
Searching for pip
Reading http://pypi.python.org/simple/pip/
Best match: pip 6.0.8
Downloading https://pypi.python.org/packages/source/p/pip/pip-6.0.8.tar.gz#md5=2332e6f97e75ded3bddde0ced01dbda3
Processing pip-6.0.8.tar.gz
Running pip-6.0.8/setup.py -q bdist_egg --dist-dir /tmp/easy_install-pPyrAv/pip-6.0.8/egg-dist-tmp-UwhkN5
warning: no previously-included files found matching '.coveragerc'
warning: no previously-included files found matching '.mailmap'
warning: no previously-included files found matching '.travis.yml'
warning: no previously-included files found matching 'pip/_vendor/Makefile'
warning: no previously-included files found matching 'tox.ini'
warning: no previously-included files found matching 'dev-requirements.txt'
no previously-included directories found matching '.travis'
no previously-included directories found matching 'docs/_build'
no previously-included directories found matching 'contrib'
no previously-included directories found matching 'tasks'
no previously-included directories found matching 'tests'
Adding pip 6.0.8 to easy-install.pth file
Installing pip script to /usr/local/bin
Installing pip2.7 script to /usr/local/bin
Installing pip2 script to /usr/local/bin

Installed /usr/local/lib/python2.7/dist-packages/pip-6.0.8-py2.7.egg
Processing dependencies for pip
Finished processing dependencies for pip


pip install RPi.GPIO

Now, if we try to install RPi.GPIO, it'll complain that it is already installed. So we will have to use the --upgrade option:



pi@raspberrypi ~ $ sudo pip install RPi.GPIO
Requirement already satisfied (use --upgrade to upgrade): RPi.GPIO in /usr/lib/python2.7/dist-packages

Let's try --upgrade

pi@raspberrypi ~ $ sudo pip install --upgrade RPi.GPIO
Collecting RPi.GPIO from https://pypi.python.org/packages/source/R/RPi.GPIO/RPi.GPIO-0.5.10.tar.gz#md5=f1c67de40bf99e0612d75538b06a2181
  Downloading RPi.GPIO-0.5.10.tar.gz
Installing collected packages: RPi.GPIO
  Found existing installation: RPi.GPIO 0.5.9
    DEPRECATION: Uninstalling a distutils installed project (RPi.GPIO) has been deprecated and will be removed in a future version. This is due to the fact that uninstalling a distutils project will only partially uninstall the project.
    Uninstalling RPi.GPIO-0.5.9:
      Successfully uninstalled RPi.GPIO-0.5.9
  Running setup.py install for RPi.GPIO
    building 'RPi.GPIO' extension
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/py_gpio.c -o build/temp.linux-armv7l-2.7/source/py_gpio.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/c_gpio.c -o build/temp.linux-armv7l-2.7/source/c_gpio.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/cpuinfo.c -o build/temp.linux-armv7l-2.7/source/cpuinfo.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/event_gpio.c -o build/temp.linux-armv7l-2.7/source/event_gpio.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/soft_pwm.c -o build/temp.linux-armv7l-2.7/source/soft_pwm.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/py_pwm.c -o build/temp.linux-armv7l-2.7/source/py_pwm.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/common.c -o build/temp.linux-armv7l-2.7/source/common.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source/constants.c -o build/temp.linux-armv7l-2.7/source/constants.o
    gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro build/temp.linux-armv7l-2.7/source/py_gpio.o build/temp.linux-armv7l-2.7/source/c_gpio.o build/temp.linux-armv7l-2.7/source/cpuinfo.o build/temp.linux-armv7l-2.7/source/event_gpio.o build/temp.linux-armv7l-2.7/source/soft_pwm.o build/temp.linux-armv7l-2.7/source/py_pwm.o build/temp.linux-armv7l-2.7/source/common.o build/temp.linux-armv7l-2.7/source/constants.o -o build/lib.linux-armv7l-2.7/RPi/GPIO.so
Successfully installed RPi.GPIO-0.5.10
pi@raspberrypi ~ $ 

OK, we are now ready to get to work. 0.5.10 works with the Raspberry Pi 2 model B.

Francois
@f_dion

Wednesday, February 4, 2015

Text editor (command line)

Raspberry pi text editor (command line)

Note: This is a translation of the Spanish version of my blog article I posted some years back

Before even mastering the command line, you will need to learn a way to edit text files from the command line. Be it to make configuration changes, or write a script (sequence of commands), you'll be a lot more productive if you learn how to use one.

Raspbian comes equipped with nano (easy to use when starting out) and vi (the standard - found on all *nix servers and desktops), but, there is something even better: vim (VI iMproved)

If you've never used vi before, might want to start with nano instead, or read a vi tutorial or even better, an interactive vim tutorial (highly recommended!!), and cheat sheet)

Normally, on Linux and modern Unix, vi is really vim, but on Raspbian, vi is vi. Let's change this:
fdion@raspberrypi ~ $ sudo apt-get install vim
There are a few things to add to .vimrc to make it better (in /home/user):

syntax on
filetype indent plugin on
set modeline

fdion@raspberrypi ~ $ pwd
/home/fdion
fdion@raspberrypi ~ $ vi .vimrc
(type i for insert, type the above 3 lines, hit Escape and :wq)
fdion@raspberrypi ~ $ ls .vimrc
.vimrc
Excellent, now scripts and code (like Python) will look much better, easier to read in color:


fdion@raspberrypi ~ $ vi file.py 




There are a few lines you will want to use specifically for Python scripts:


The first line is always the "shebang" line:

#!/usr/bin/env python

Here, we tell the operating system shell executor to pass the script to the python interpreter. For other interpreters, just replace python with whichever interpreter will handle the script.

Another thing for a python script that I like to use, a docstring (description) for the script, between """ and """. 

The seventh line above (in the code example) is for vim itself for proper tabs as 4 spaces (you want that for aligning your Python code, and is a nice to have in general for shell scripting):

# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4


If you are dealing with utf-8 code (for example accents or special characters) then you need to define the following:

# vim: set fileencoding=utf-8


Francois
@f_dion

Sunday, January 25, 2015

Rocket man and the Near Space Circus

Space = rockets


That's what we tend to equate, cause we love them rockets... And, to reach space, it does require a rocket of some sort, at this point. To "explore" space however, at a minimum, only requires a cloudless night, away from the city, and there, with the naked eyes, you can watch the stars, not just a few, but hundreds (some apparently can see upwards of 3000!). Or perhaps you choose a full moon. One can get pretty close even with a 35mm or digital camera with a modest zoom and a tripod.

The Moon, Sept. 9th 2014, DSLR at 270MM

Albedo 0.39


The Moon is nice and all, and is great for black and white photography. And there is nothing wrong with that. In fact, there was an interesting talk back in 2012 by Fred Alger, at PyCarolinas: "Sysadmining Python to the Moon". But the blue planet, the earth is a lot more impressive (picture from that talk):

curvature.jpg

Except that we are back to rockets again? Or are we? Both Fred's talk and mine that year talked about a near space option.

Near Space


Weather balloons will get you into near space. Space officially starts at 100KM, but one can reach 35-40KM with a latex balloon filled with Helium. Add a parachute, a radar reflector and a payload, and you have your own little private launch and recovery system.

And nowadays, the payload options are numerous. The main thing is that we are no longer limited to sending microcontrollers, but can send actual computers running an operating system, and executing Python code.

An obvious candidate is the Raspberry Pi. Dave Akerman (whom I had mentionned in my talk) has been sending them into space for well over two years now. So when he sent a tweet earlier this month about the Global Space Balloon Challenge, I knew this would be the perfect project for our local Python user group, using a payload with Raspbian Linux and Python on a Raspberry Pi model A+. So many projects are possible within this project.

Hence, Team Near Space (Flying) Circus was born. Let's hope the snake and the penguin will play nice up there...

François
@f_dion

Friday, September 20, 2013

RPi MOOC en espanol

Donde

http://telescopio.galileo.edu/curso/raspberry-pi/

Cuando

El 14 de octubre 2013.

Información

Indican en la pagina que van a abarcar todo eso:

  • Instalación, Configuración, Accesorios y demás aspectos a considerar
  • Demos de instalación Wheezy y otras distribuciones
  • Introducción a Python
  • Introducción a la programación en Python para Raspberry Pi
  • Ejemplo completo Python
  • Modulo GPIO del Raspberry Pi para conexiones externas
  • Elementos básicos de hardware y como controlarlos con el GPIO
  • Próximos Pasos: Proyectos y Comunidad

Me parece muy genial. Es algo similar a los taller PyHack que hacemos en Carolina del Norte, pero en la red.

François
@f_dion

Wednesday, February 13, 2013

Minecraft Pi Edition available

The RaspberryPi edition download

minecraft-pi-0.1.1.tar.gz

The install

fdion@raspberrypi ~ $ gunzip minecraft-pi-0.1.1.tar.gz
fdion@raspberrypi ~ $ tar -xvf minecraft-pi-0.1.1.tar

More detail

Mojang.com
pi.minecraft.net

Python


So, before we get started in writing some python (such as the code I put here: minecraft python ), let's check out block.py in the mcpi/api/python/mcpi directory. It contains the types of materials that can be used:

AIR                 = Block(0)
STONE               = Block(1)
GRASS               = Block(2)
DIRT                = Block(3)
COBBLESTONE         = Block(4)
WOOD_PLANKS         = Block(5)
SAPLING             = Block(6)
BEDROCK             = Block(7)
WATER_FLOWING       = Block(8)
WATER               = WATER_FLOWING
WATER_STATIONARY    = Block(9)
LAVA_FLOWING        = Block(10)
LAVA                = LAVA_FLOWING
LAVA_STATIONARY     = Block(11)
SAND                = Block(12)
GRAVEL              = Block(13)
GOLD_ORE            = Block(14)
IRON_ORE            = Block(15)
COAL_ORE            = Block(16)
WOOD                = Block(17)
LEAVES              = Block(18)
GLASS               = Block(20)
LAPIS_LAZULI_ORE    = Block(21)
LAPIS_LAZULI_BLOCK  = Block(22)
SANDSTONE           = Block(24)
BED                 = Block(26)
COBWEB              = Block(30)
GRASS_TALL          = Block(31)
WOOL                = Block(35)
FLOWER_YELLOW       = Block(37)
FLOWER_CYAN         = Block(38)
MUSHROOM_BROWN      = Block(39)
MUSHROOM_RED        = Block(40)
GOLD_BLOCK          = Block(41)
IRON_BLOCK          = Block(42)
STONE_SLAB_DOUBLE   = Block(43)
STONE_SLAB          = Block(44)
BRICK_BLOCK         = Block(45)
TNT                 = Block(46)
BOOKSHELF           = Block(47)
MOSS_STONE          = Block(48)
OBSIDIAN            = Block(49)
TORCH               = Block(50)
FIRE                = Block(51)
STAIRS_WOOD         = Block(53)
CHEST               = Block(54)
DIAMOND_ORE         = Block(56)
DIAMOND_BLOCK       = Block(57)
CRAFTING_TABLE      = Block(58)
FARMLAND            = Block(60)
FURNACE_INACTIVE    = Block(61)
FURNACE_ACTIVE      = Block(62)
DOOR_WOOD           = Block(64)
LADDER              = Block(65)
STAIRS_COBBLESTONE  = Block(67)
DOOR_IRON           = Block(71)
REDSTONE_ORE        = Block(73)
SNOW                = Block(78)
ICE                 = Block(79)
SNOW_BLOCK          = Block(80)
CACTUS              = Block(81)
CLAY                = Block(82)
SUGAR_CANE          = Block(83)
FENCE               = Block(85)
GLOWSTONE_BLOCK     = Block(89)
BEDROCK_INVISIBLE   = Block(95)
STONE_BRICK         = Block(98)
GLASS_PANE          = Block(102)
MELON               = Block(103)
FENCE_GATE          = Block(107)
GLOWING_OBSIDIAN    = Block(246)
NETHER_REACTOR_CORE = Block(247)

That's a lot. So, next post I'll try to build something using Python with all the materials, to get a feel for what they are.

François
@f_dion

Thursday, February 7, 2013

L'autoréplication


de RaspberryPi a SD


Il y a un certain challenge a faire une carte SD pour le Raspberry Pi.

Ceci est du en partie a la grande variété de systèmes d’opération et d'ordinateurs (et leur matériel). D'autre part, beaucoup de personnes n'ont que le Raspberry Pi comme ordinateur, les autres étant hors de portée du au prix.

Il y a certains groupes d'usagers ici et la qui se débrouillent pour aider les usagers a faire leur propre carte SD, alors que d'autres doivent acheter des cartes SD avec le système d’opération déjà installé. Mais comment faire pour faire une copie de cette carte SD, n'est on pas de retour a la case départ?

Le lecteur


En fait, une fois que l'on a un système d’opération  sur la carte SD, on peut alors faire de l'autoréplication. Quésaco? me direz vous... Et bien, c'est quand un système d’opération peut se répliquer lui même (faire une copie de carte SD seulement avec le Raspberry Pi).

Pour ce faire, il faut un lecteur de carte SD, car le Pi n'a qu'une seule fente SD. Un lecteur comme celui ci, par exemple (ici, avec une carte 16GB, mais on peut faire 4GB ou 8GB ou plus, de la même façon):




Et on le branche (avec un câble ou en direct) au port USB.



dd


La version la plus recente de Raspbian Wheezy est de Decembre 2012:
http://files.velocix.com/c1410/images/raspbian/2012-12-16-wheezy-raspbian/2012-12-16-wheezy-raspbian.zip

Ici, les instructions se basent sur une version plus vieille, mais c'est le meme principe. Il suffit de remplacer l'url http://www.gtlib.gatech.edu/pub/raspberrypi/images/raspbian/2012-09-18-wheezy-raspbian/2012-09-18-wheezy-raspbian.zip par une de cette liste ici (choisir un serveur plus pres de soi): http://downloads.raspberrypi.org/download.php?file=/images/raspbian/2012-12-16-wheezy-raspbian/2012-12-16-wheezy-raspbian.zip


Avant de commencer, il faut s'assurer d'avoir au moins 2.5GB de libre (df -h me donne 2.9G ici). On insere la carte SD vide dans le lecteur et on verra apparaitre /dev/sda ou sdb.



fdion@raspberrypi ~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
rootfs           15G   11G  2.9G  80% /
/dev/root        15G   11G  2.9G  80% /
devtmpfs        109M     0  109M   0% /dev
tmpfs            22M  248K   22M   2% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs            44M     0   44M   0% /run/shm
/dev/mmcblk0p1   56M   35M   22M  62% /boot
fdion@raspberrypi ~ $ wget http://www.gtlib.gatech.edu/pub/raspberrypi/images/raspbian/2012-09-18-wheezy-raspbian/2012-09-18-wheezy-raspbian.zip
fdion@raspberrypi ~ $ unzip 2012-09-18-wheezy-raspbian.zip
fdion@raspberrypi ~ $ ls /dev/sd*
ls: cannot access /dev/sd*: No such file or directory
fdion@raspberrypi ~ $ ls /dev/sd*
ls: cannot access /dev/sd*: No such file or directory
fdion@raspberrypi ~ $ ls /dev/sd*
/dev/sda  /dev/sda1
fdion@raspberrypi ~ $ ls *.img
2012-09-18-wheezy-raspbian.img


Ici, le lecteur de carte avec SD est /dev/sda (si c'est sdb, il faut ajuster la commande ci dessous avec of=/dev/sdb). On est pret a faire la copie de l'image de la carte SD (le fichier .img), a partir du Pi (on peut aussi utiliser bs=4M qui va beaucoup plus vite avec certaines cartes):


fdion@raspberrypi ~ $ sudo dd bs=1M if=2012-09-18-wheezy-raspbian.img of=/dev/sda
1850+0 records in
1850+0 records out
1939865600 bytes (1.9 GB) copied, 428.218 s, 4.5 MB/s
fdion@raspberrypi ~ $ sudo sync


Le sudo sync est très important. Si on ne le fait pas, ça ne fonctionnera pas.

Et c'est tout! On peut maintenant donner cette copie a une autre personne. Tres pratique pour les clubs.

Il existe aussi une méthode pour faire une copie, sans utiliser de fichier .img, mais cela sera pour une autre fois...


François
@f_dion

Tuesday, February 5, 2013

Improved Pi-A-Sketch video

Mighty RaspberryPi drawing

I've made a new video of the Pi-A-Sketch:




youtube page

Not quite as circular

One thing you will notice is that the circles have a kink on each sides (at the interface of each quadrant). With time, it appears that the compensation factor for the slop has to be adjusted. I've demoed this so much that I guess there is a little less slop than there was before. That is quite curious. It also means that I will have to add a calibration mode, perhaps a little jumper or switch, and when the Pi boots, it will run the calibration mode instead of the drawing mode.

This will definitely increase the code in a significant way (currently less than 200 lines of Python)

François
@f_dion

Gráficos en la consola

Pygame, RaspberryPi, Webcams.


Pygame utiliza SDL para los gráficos, así que soporta directamente la consola o X windows. Es el caso en todas la plataformas (Unix, Linux, Mac, no solo en Raspbian sobre el RaspberryPi).

Si no conocen nada de Pygame, hay tutoriales en espanol aqui:
razonartificial.com

En mi caso, necesitaba código para capturar imágenes de una webcam (por un taller PyHack). con Python y Pygame, es muy sencillo. Hacer el import y init de los modulos, crear un objeto cam (de resolución 320x240), iniciar la camara, obtener una imagen (cam.get_image), y grabar como png.


import pygame
import pygame.camera  # experimental
from pygame.locals import *

pygame.init()
pygame.camera.init()

cam = pygame.camera.Camera("/dev/video0", (320,240))  # webcam

cam.start()
image = cam.get_image()
pygame.image.save(image,'fablocker.png')
cam.stop()

El mismo código funciona en la consola o el escritorio, perfecto con los cron jobs.


Matplotlib


Hay otros módulos Python que dependen de un servidor X windows. En casos de que no se require OpenGL (no hay en Raspberry Pi) o OpenGL ES, hay un servidor basico que podemos utilizar: xvfb.

Primeramente hay que hacer la instalación de xvfb:


$ sudo apt-get install xvfb


Matplotlib es bueno para hacer imagenes y incluirles en informes de actividad de servidor, por ejemplo. Un servidor web no requiere X windows, asi que porque deberiamos utilizar LXDE o otro escritorio grafico, solo por hacer imagenes que vamos a incluir en una pagina web?

Con xvfb, no hay problemas. Un script que contiene el código Python siguiente (poner en un fichero mpl.py):


from matplotlib.pyplot import *

plot([2,4,2,5,6,3,1])
savefig("graph.png")

Es lo que haria normalmente. Pero si tratamos de ejecutar el script directamente, vamos a recibir un error. A utilizar xvfb, eliminamos el error, así:

$ xvfb-run python mpl.py
  Va a generar un fichero graph.png que se vera asi:


Todo de la consola, sin escritorio gráfico.


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