Basics of Raspberry Pi


By Prof. Seungchul Lee
http://iai.postech.ac.kr/
Industrial AI Lab at POSTECH

Table of Contents

1. Introduction of Raspberry Pi

1.1. Raspberry Pi 3 Hardware Spec

Raspberry Pi 3 Hardware Spec

  • Broadcom BCM2837
    • 1.2GHz, 1Gb RAM
  • 40 GPIO pins
  • BCM43143 WiFi on board
  • 4 x USB 2 Port
  • Full Size HDMI
  • CSI camera port
  • DSI display port
  • Micro SD card slot
  • etc.

Raspberry Pi 3 vs. Arduino

  • Raspberry Pi 3 procesesor is faster
    • 1.2GHz vs 16MHz
  • 32-bit processor vs. 8-bit
    • Bigger address space, number representations
  • Raspberry Pi has more memory
    • Arduino : 32K Flash, 2K SRAM, 1K EEPROM
    • Raspberry Pi : 512K SRAM, 4Gb Flash, micro SD
  • Raspberry Pi has lower I/O voltage levels
    • 3.3 V vs. 5V
  • Using an Operating System
    • Raspbian vs. None

1.2. Raspbery Pi Setup

Setup of the Raspberry Pi

Step 1: Plug in a monitor (via HDMI) and a keyboard and mouse (via USB)

  • Need an interface to the device

Step 2: Get an operating system

  • Raspberry Pi needs an operating system
  • Operating system image must be present on the micro SD card

Installing an Operating System

  • Use New Out-Of-Box Software (NOOBS)
    • Comes preinstalled on micro SD bundled with Raspberry Pi boards
    • Otherwise, download it for free from https://www.raspberrypi.org/downloads
    • If NOOBS is not preinstalled on micro SD, you'll need to:
      1. Format the micro SD (need an SD reader)
      2. Extract the NOOBS download
      3. Put it on the micro SD
  • NOOBS will install an operation system on your micro SD card

1.3. Basics of Linux

1.3.1. The Shell

  • Interprets user input and executes commands
  • Text-based user interface of an operating system
  • bash (bourne again shell) is the default shell for Raspian
  • Gives more precise control to the user
  • Requires memorization for efficiency

  • The console or terminal is a text entry and display device

    • Used to be a physical device (vt100 terminal)
    • Virtual consoles are typical now
  • LXTerminal is the terminal used in Raspian

1.3.2. Login

Accounts

  • There are be many user accounts on a Linux system
  • Each account has a username and password for identification
  • When you first start the machine you are prompted for username and password
  • Default username is "pi", password is "raspberry"

Man(ual) Pages

  • "man" gives information about a Linux command

1.3.3. Linux Filesystem

Hierarchy of directories and files

pwd

  • Show current location

cd

  • To a specific directory

ls

  • Show the contents of a diretory
    • Files and other directories
  • Show all detail with -l option

mkdir, rmdir

  • mkdir creates a directory
  • rmdir removes a directory
  • rmdir only works if directory is empty

1.3.4. Text Editors

nano

  • Run it by typing "nano" at the prompt
    • ex) vi test.py

Viewing a File

  • "cat" prints the files to the terminal
  • "head" prints the first 10 lines
  • "last" prints the last 10 lines

cp

  • Make a copy of a file
    • ex) cp origin.py duplicated.py

mv

  • Move a file
  • Rename it or move it to a new directory
    • ex) mv origin.py subdir/origin.py
    • ex) mv origin.py modified.py

1.3.5. Permissions

File Permissions

  • Files have owners
    • User who created the file
  • Files have access permissions
    • Read (r), write (w), execute (x)
  • Different permissions can be assigned according to type
    1. User: the file owner
    2. Group: a permission group
    3. Other: all users

Viewing File Permissions

  • ls -l

Root Account

  • The root account has highest permission level
  • Key files and directories are only accessible by root
  • Sometimes you need root privileges
    • Install a program
    • Change the operating system
  • Use the "sudo" command to gain root permission for a single command

1.3.6. Shutdown

  • Should not just unplug a Linux machine
  • Proper shutdown procedure is needed to place data
    • Flush all buffers, close files, etc.
  • Use the "shutdown" command

2. Programming on Raspberry Pi

2.1. Python on Raspberry Pi

Python Language

  • High-level language, easy to use

    • Do not need to explicitly declare data types
    • No pointers
    • Object-oriented programming, classes
  • Slow compared to C, C++

    • Interpreted, not compiled
  • Two versions : Python 2.x and Python 3.x

    • Python 2.x is still supported
    • Programming differences are small
    • Will use Python 3.x

Run Python Code

  • Use VI editor to make Python code
  • Run it by typing python3 in terminal
    • ex) python3 pyfile.py
    • ex) python3 (it runs python3 with typing and execute python code line by line)

2.2. Basic of Python

2.2.1. Python Expression (Python 3)

Algebraic Expressions

  • Python shell can evaluate algebraic expressions
  • Many algebraic functions are available
    • abs()
    • min()
    • max()
      >>> 2 + 2
      4
      >>> 8 - 5
      3
      >>> 2*(3 + 2)
      10
      >>> 7/2
      3.5
      

Boolean Expressions

  • Evaluate to True or False
  • Often involve comparison operators <, >, ==, !=, <=, and >=
    >>> 2 < 4
    True
    >>> 1 > 3
    False
    >>> 2 == 4
    False
    >>> 2 != 3
    True
    >>> 1 <= 3
    True
    >>> 2 >= 4
    False
    

Boolean Operators

  • Evaluate to True or False
  • May include Boolean operators and, or, not
    >>> 2 < 3 and 3 < 4
    True
    >>> 4 == 5 and 3 < 4
    False
    >>> False and True
    False
    >>> Ture and True
    True
    >>> 4 == 5 or 3 < 4
    True
    >>> False or Ture
    True
    >>> False or False
    False
    >>> not(3 < 4)
    False
    

Variables, Assignments

  • variable types are not declared
  • Interpreter determines type by usage
    >>> x = 3
    >>> x
    3
    >>> 4 * x
    12
    >>> y = 4 * x
    >>> y
    12
    

2.2.2. Strings

Strings

  • A sequence of characters enclosed in quotes 'Hello, world'
  • Can be assigned to a variable
  • Can be manipulated using string operators and functions
    >>> 'Hello, World'
    'Hello, World'
    >>> s = 'still'
    >>> t = 'life'
    

String Operators

Operator Definition
x in s x is a substring of s
x not in s x is not a substring of s
s + t Concatenation of s and t
s n, n s Concatenation of n copies of s
s[i] Character at index i of s
len(s) (function) Length of string s
>>> 'Hello, World!'
'Hello, World!'
>>> s = 'still'
>>> t = 'life'
>>> s == 'still'
True
>>> s != t
True
>>> s < t
False
>>> s > t
True

String Operator Examples

>>> s = 'still'
>>> t = 'life'
>>> s + t
'stilllife'
>>> s + ' ' + t
'still life'
>>> 5 * s
'stillstillstillstillstill'
>>> 20 * '_'
'____________________'
>>> 'i' in s
True
>>> 'o' in t
False
>>> 'li' in t
True
>>> len(t)
4

Indexing Operator

  • Index of an item in a sequence is its position in the sequence
  • Indexing operator is [], takes an index as argument
  • Indices start at 0
  • Can be used to identify characters in a string
    >>> s = 'Apple'
    >>> s[0]
    'A'
    >>> s[1]
    'p'
    >>> s[4]
    'e'
    

2.2.3. Functions

  • A sequence of instructions associated with a function name
  • Function definition starts with def
  • Followed by function name, open/close parentheses, and colon
    >>> def test():
              print ('A test function')
    >>> test()
    A test function
    >>>
    

2.2.4. Function Arguments

Function Parameters/Arguments

  • A function can take arguments which are values bound to variables inside the function
  • Arguments are listed between parenthesis in the function call
    >>> def circle_area(rad):
              print (3.14 * rad * rad)
    >>> circle_area(2)
    12.56
    

Function Return Values

  • Functions can return values with the return instruction
  • A function call is substituted for its return value in an expression
    >>> def circle_area(rad):
              return 3.14 * rad * rad
    >>> circle_area(2)
    12.56
    >>> 3 + circle_area(2)
    15.56
    

2.3. List & Control Flow

2.3.1. List

Lists

  • A comma-separated sequence of items enclosed in square brackets
  • Items can be numbers, strings, other lists, etc.
    >>> pets = ['ant', 'bat', 'cod', 'dog']
    >>> lst = [0, 1, 'two', [4, 'five']]
    >>> nums = [0, 1, 2, 3, 4, 5, 6, 7, 8]
    

List Operators and Functions

Operator Definition
x in lst x is an item of lst
x not in lst x is not an item of lst
lst + lstB Concatenation of lst and lstB
lstn, nlst Concatenation of n copies of lst
lst[i] Item at index i of lst
len(lst) Number of items in lst
min(lst) Minimum item in lst
max(lst) Maximum item in lst
sum(lst) Sum of items in lst

2.3.2. List Methods

List Methods

  • List operators that are called on the list that they operate on
    >>> lst = [1, 2, 3]
    >>> lst.append(8)
    >>> lst
    

List Methods

Method Definition
lst.append(item) adds item to the end of lst
lst.count(item) returns the number of times item occurs in lst
lst.index(item) Returns index of (first occurrence of) item in lst
lst.pop() Removes and returns the last item in lst
lst.remove(item) Removes (the first occurrence of) item from lst
lst.reverse(item) Reverses the order of items in lst
lst.sort(item) Sorts the items of lst in increasing order
  • append(), remove(), reverse(), and sort() do not return values

2.3.3. Control Flow

Control Flow

  • Statements that change the order in which lines of code are executed :
    1. if statement

If statement

  • Template:
    if <condition>:
          <indented code block>
    <non-indented statement>
    
  • Example:
    if temp > 80:
          print ('It is hot!')
    print ('Goodbye.')
    

If-else statement

  • Template:
    if <condition>:
          <indented code 1>
    else :
          <indented code 2>
    <non-indented statement>
    
  • Example:
    if temp > 80:
          print ('hot!')
    else:
          print ('not hot.')
    print ('Goodbye.')
    

For Loop

  • Executes a block of code for every element in a sequence
>>> name = 'Ian'
>>> for char in name:
            print(char)
I
a
n
>>>

For Example

  • Any sequence can be used
  • All code in loop must be indented
>>> for name in ['Jon', 'Mary', 'Pete']:
            print(name)
Jon
Mary
Pete
>>>

While Loop

  • Execute indented block of code while condition is True
    >>> i = 0
    >>> while i < 3:
              print (i)
              i = i + 1
    0
    1
    2
    >>>
    

2.4. Exceptions

Errors During Execution

  • Errors may happen when working with sockets
    • Socket cannot be opened
    • Data cannot be sent
  • Errors occurring during execution are called Exceptions
  • There are many kinds for each function
    • ZeroDivisionError
    • TypeError

Handling Exceptions

  • When an error happens, you might want your code to do something appropriate
  • Use try and except statements
  • Place code with possible error inside the try clause
  • Code in the except clause is executed when an exception occurs
    try:
          z = x / y
    except ZeroDivisionError:
          print("Divide by zero")
    

3. General Purpose IO pins

import

  • Use Python3 Module which is already constucted
    • ex) import RPi.GPIO as GPIO

Pin Direction and Assignment

GPIO.setup(13, GPIO.OUT)
  • Set the pin direction
  • Like pinMode(13, OUTPUT) for Arduino
GPIO.output(13, True)
  • Assign value to output pin
  • Like digitalWrite(11, HIGH) for Arduino
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(13, GPIO.OUT)
while True:
    GPIO.output(13, True)
    time.sleep(1)
    GPIO.output(13, False)
    time.sleep(1)

3.2. Button

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(18, GPIO.IN)
while True:
    if GPIO.input(18) == 1:
        print("Button Pressed")
        time.sleep(0.5)
    else:
        print("Button Unpressed")
        time.sleep(0.5)

3.3. PWM on RPI

Pulse Width Modulation

  • Duty cycle is the percent of time the pulse is high
  • Increasing duty cycle increases perceived voltage
  • PWM functions in GPIO library

PWM initialization

pwm_obj = GPIO.PWM(18, 400)
- Mark pin for PWM
- Second argument is frequency

pwm_obj.start(100)
- Start generating PWM signal
- Argument is duty cycle, 0 to 100

PWM Control

pwm_obj.ChangeDutyCycle(50)
  • Assign new duty cycle
  • PWM frequency is not accurate
    • Off by over 50% at 10kHz

Frequency Control

  • Cannot easily control frequency
    • No tone() function as on Arduino -Need to do it manually
while True:
    GPIO.output(18, True)
    time.sleep(0.5)
    GPIO.output(18, False)
    time.sleep(0.5)
  • 1Hz frequency

PWM Example

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(13, GPIO.OUT)

pwm = GPIO.PWM(13, 50)
pwm.start(0)
for i in range(100):
    pwm.ChangeDutyCycle(i)
    time.sleep(0.1)
for i in range(100, 0, -1):
    pwm.ChangeDutyCycle(i)
    time.sleep(0.5)

3.4. DC Motor

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(13, GPIO.OUT)

pwm = GPIO.PWM(13, 50)
pwm.start(0)
for i in range(100):
    pwm.ChangeDutyCycle(i)
    time.sleep(0.1)
for i in range(100, 0, -1):
    pwm.ChangeDutyCycle(i)
    time.sleep(0.5)

3.5. Servo Motor Control

Servo Motors

  • Motors whose rotation angle can be precisely controlled
  • Pulse width controls rotation anlge
    • 50Hz frequency is normal
    • 1.0 ms width = 0 degrees
    • 2.0 ms width = 180 degrees

Servo Control

Servo Motor Wiring

  • Three wires:
    • Power (Red)
    • Ground (Black)
    • Signal (White or Yellow)
  • PWM applied to signal wire
  • Power should supply sufficient current

Servo Motor Power

  • External power supply should be used
    • ~5 Volts
  • Raspberry Pi cannot supply enough current to drive typical motors
    • ~1 Amp
  • External supply has power and ground wires
    • Wire external power wire to Servo power wire
    • External ground wired to Raspberry Pi ground

Servo Wiring

  • Only pins 12 and 24 (BOARD numbering) can produce PWM signals
  • Resistor might be used to isolate pins from servo

Servo Example 1

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
pwm = GPIO.PWM(12, 50)
pwm.start(0)
for i in range(100)
    pwm.ChangeDutyCycle(i)
    print(i)
    time.sleep(0.5)
for i in range(100, 0, -1):
    pwm.ChangeDutyCycle(i)
    print(i)
    time.sleep(0.5)

Servo Example 2

import RPi.GPIO as GPIO
import numpy as np
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(8, GPIO.OUT)

pwm = GPIO.PWM(8, 50)
pwm.start(0)

while True:
    for i in np.arange(2.5, 12.5, 0.1):
        pwm.ChangeDutyCycle(i)
        time.sleep(0.1)
    for i in np.arange(12.5, 2.5,-0.1):
        pwm.ChangeDutyCycle(i)
        time.sleep(0.1)

4. Advanced

4.1. I2C Communication

  • Set Raspberry Pi to activate I2C communication as follows
#!/usr/bin/python

import smbus
import math
import time
import os

# Power management registers

power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c

def read_byte(adr):
    return bus.read_byte_data(address, adr)

def read_word(adr):
    high = bus.read_byte_data(address, adr)
    low = bus.read_byte_data(address, adr+1)
    val = (high << 8) + low
    return val

def read_word_2c(adr):
    val = read_word(adr)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val

def dist(a,b):
    return math.sqrt((a*a)+(b*b))

def get_y_rotation(x,y,z):
    radians = math.atan2(x, dist(y,z))
    return -math.degrees(radians)

def get_x_rotation(x,y,z):
    radians = math.atan2(y, dist(x,z))
    return math.degrees(radians)

bus = smbus.SMBus(1) # or bus = smbus.SMBus(1) for Revision 2 boards
address = 0x68       # This is the address value read via the i2cdetect command

# Now wake the 6050 up as it starts in sleep mode

bus.write_byte_data(address, power_mgmt_1, 0)

while True:
    os.system('cls' if os.name == 'nt' else 'clear')

    print("gyro data")
    print("---------")

    gyro_xout = read_word_2c(0x43)
    gyro_yout = read_word_2c(0x45)
    gyro_zout = read_word_2c(0x47)

    print("gyro_xout: ", gyro_xout)
    print("scaled   : ", (gyro_xout / 131))
    print("gyro_yout: ", gyro_yout)
    print("scaled   : ", (gyro_yout / 131))
    print("gyro_zout: ", gyro_zout)
    print("scaled   : ", (gyro_zout / 131))
    print()
    print("accelerometer data")
    print("------------------")

    accel_xout = read_word_2c(0x3b)
    accel_yout = read_word_2c(0x3d)
    accel_zout = read_word_2c(0x3f)

    accel_xout_scaled = accel_xout / 16384.0
    accel_yout_scaled = accel_yout / 16384.0
    accel_zout_scaled = accel_zout / 16384.0

    print("accel_xout: ", accel_xout)
    print("scaled    : ", accel_xout_scaled)
    print("accel_yout: ", accel_yout)
    print("scaled    : ", accel_yout_scaled)
    print("accel_zout: ", accel_zout)
    print("scaled    : ", accel_zout_scaled)
    print()
    print("x rotation: " , get_x_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))
    print("y rotation: " , get_y_rotation(accel_xout_scaled, accel_yout_scaled, accel_zout_scaled))

    time.sleep(0.5)

4.2. AD Converter

  • Set Raspberry Pi to activate SPI communication as follows
# Simple example of reading the MCP3008 analog input channels and printing
# them all out.
# Author: Tony DiCola
# License: Public Domain
import time

# Import SPI library (for hardware SPI) and MCP3008 library.
import Adafruit_GPIO.SPI as SPI
import Adafruit_MCP3008


# Software SPI configuration:
CLK  = 18
MISO = 23
MOSI = 24
CS   = 25
mcp = Adafruit_MCP3008.MCP3008(clk=CLK, cs=CS, miso=MISO, mosi=MOSI)

# Hardware SPI configuration:
# SPI_PORT   = 0
# SPI_DEVICE = 0
# mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))


print('Reading MCP3008 values, press Ctrl-C to quit...')
# Print nice channel column headers.
print('| {0:>4} | {1:>4} | {2:>4} | {3:>4} | {4:>4} | {5:>4} | {6:>4} | {7:>4} |'.format(*range(8)))
print('-' * 57)
# Main program loop.
while True:
    # Read all the ADC channel values in a list.
    values = [0]*8
    for i in range(0, 3):
        # The read_adc function will get the value of the specified channel (0-3).
        values[i] = mcp.read_adc(i)
    # Print the ADC values.
    print('| {0:>4} | {1:>4} | {2:>4} | {3:>4} | {4:>4} | {5:>4} | {6:>4} | {7:>4} |'.format(*values))
    # Pause for half a second.
    time.sleep(0.1)

4.3. Threading

import threading
import time

def every_second(msg):
    i = 0
    while True:
        time.sleep(1)
        i += 1
        print(msg, i)

def every_five_second(msg):
    i = 0
    while True:
        time.sleep(5)
        i += 5
        print(msg, i)

t1 = threading.Thread(target = every_second, args = ("t1 :",))
t2 = threading.Thread(target = every_five_second, args = ("t2 :",))
t1.daemon = True
t2.daemon = True
t1.start()
t2.start()

while True:
    pass

4.4. Camera

4.4.1. Camera Module

Raspberry Pi Camera Module

  • Cameras are useful sensors
  • There are many cameras that can be used with Raspberry Pis(USB)
  • The Raspberry Pi Camera module is useful
    • Camera serial Interface (CSI) to the processor
  • Good Libraries for control

Enabling the Camera

  • Use raspi-config to enable the CSI interface sudo raspi-config
  • Select Enable Camera, Finish

4.4.2. Picamera Library

python-picamera Library

  • Install the library
    sudo apt-get updata
    sudo apt-get install python3picamera
    picamera
  • Using the librarty
    import picamera
    
  • Instantiate an object of the PiCamera class
    camera = picamera.PiCamera()
    

Camera Functions

  • Take a picture
    camera.capture("pict.jpg")
    
  • Changing camera settings
    • There are many
      camera.hflip = True
      camera.vflip = True
      camera.brightness = 50
      camera.sharpness = 0
      
  • View vido on RPi screen
    camera.start_preview()
    camera.stop_preview()
    

Video Recording

import picamera
import time

camera.start_recording("vid.h264")
time.sleep(10)
camera.stop_recording()

4.4.3. Capturing Images

Sending an Image on the Network

  • What if you want to a remote site?
    • Home security system
  • Capture an image, send it on a connection
mysocket = socket.socket()
mysocket.connect(('aserver', 8000))
conn = mysocket.makefile('wb')
camera.capture(conn, 'jpeg')
  • Need a file-like object to capture to

Timelapse Photography

  • camera.capture_continuous() takes photos over time
  • Takes one argument, a file name
  • {counter} and {timestamp} can be substituted
  • ex."picture{counter}.jpg" produces picture1.jpg, picture2.jpg, etc.

Continuous Capture

camera = picamera.PiCamera()
for filename in camera.capture_continuous('img(counter).jpg'):
        time.sleep(300)
  • Iterate through all images
    • Infinite loop
  • 5 minute delay between images

Example

import picamera
camera = picamera.PiCamera()
camera.capture('test_image.jpg')
In [1]:
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')