Инструкция набора «Малина»

Электронная версия книги из набора «Малина». Здесь собраны нужные ссылки, исходный код всех экспериментов, подсказки и хаки по прохождению набора.

Обрати внимание!

Господа из Rasberry Foundation не устают радовать нас новыми версиями плат. Мы в свою очередь стремимся не отставать и обновляем наш набор согласно выходу новых железок. Проверь, какая версия досталась тебе! Для этого посмотри на обратную сторону обложки буклета. Если на ней нет значка с текстом «b1», «b2» или «b3» как на картинке снизу, то тебе сюда.

Видеообзор

Ресурсы

  • FileZillaFTP-клиент.
  • RealVNC — клиент для удаленного доступа к рабочему столу устройства.
  • Angry IP Scanner — утилита для сканирования IP-адресов в подключенной сети.

Эксперименты

3. Маячок

blink.py
import RPi.GPIO as GPIO
import time
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
 
try:
    while True:
        time.sleep(0.5)
        GPIO.output(17, GPIO.HIGH)
        time.sleep(0.5)
        GPIO.output(17, GPIO.LOW)
except KeyboardInterrupt:
    print('The program was stopped by keyboard.')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed.')

4. Выключатель

toggle.py
import RPi.GPIO as GPIO
import time
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(2, GPIO.IN)
 
while True:
    time.sleep(0.5)
    button = GPIO.input(2)
    print(button)

Передай переменную button в функцию output, чтобы управлять светодиодом.

while True:
    button = GPIO.input(2)
    GPIO.output(24, button)

Не забудь добавить строку инициализации пина на выход.

GPIO.setup(24, GPIO.OUT)

Вместе с обработкой исключений, код будет выглядеть так:

toggle.py
import RPi.GPIO as GPIO
import time
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(2, GPIO.IN)
GPIO.setup(24, GPIO.OUT)
 
try:
    while True:
        button = GPIO.input(2)
        GPIO.output(24, button)
except KeyboardInterupt:
    print('The program was stopped by keyboard.')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed')

5. Переключатель

switch.py
import RPi.GPIO as GPIO
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(8, GPIO.IN)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(26, GPIO.OUT)
 
try:
    while True:
        button = GPIO.input(8)
        if button == False:
            GPIO.output(24, GPIO.HIGH)
            GPIO.output(26, GPIO.LOW)
        else:
            GPIO.output(24, GPIO.LOW)
            GPIO.output(26, GPIO.HIGH)
 
except KeyboardInterrupt:
    print('The program was stopped by keyboard.')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed.')

6. Управление яркостью

brightnessControl.py
import RPi.GPIO as GPIO
import time
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
pwm = GPIO.PWM(18, 1000)
dutyCycle = 50
pwm.start(dutyCycle)
 
try:
    while True:
        time.sleep(0.01)
        dutyCycle = dutyCycle + 1
        if dutyCycle > 100:
            dutyCycle = 0
        pwm.ChangeDutyCycle(dutyCycle)
 
except KeyboardInterrupt:
    print('The program was stopped by keyboard.')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed.')

7. Панель управления светом

function.py
import RPi.GPIO as GPIO
 
 
def isPressed(btn, led):
    if GPIO.input(btn) == False:
        GPIO.output(led, GPIO.HIGH)
    else:
        GPIO.output(led, GPIO.LOW)
 
 
button1 = 3
button2 = 4
led1 = 14
led2 = 15
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(button1, GPIO.IN)
GPIO.setup(button2, GPIO.IN)
GPIO.setup(led1, GPIO.OUT)
GPIO.setup(led2, GPIO.OUT)
 
try:
    while True:
        isPressed(button1, led1)
        isPressed(button2, led2)
except KeyboardInterrupt:
    print('The program was stopped by keyboard.')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed.')

8. Массивная оптимизация

oneMassive.py
import RPi.GPIO as GPIO
import time
 
GPIO.setmode(GPIO.BCM)
leds = [12, 13, 14, 18]
 
for led in leds:
    GPIO.setup(led, GPIO.OUT)
    GPIO.output(led, GPIO.HIGH)
 
time.sleep(3)
 
for led in leds:
    GPIO.output(led, GPIO.LOW)
 
GPIO.cleanup()
twoMassive.py
import RPi.GPIO as GPIO
 
 
def isPressed(btn, led):
    state = 1 - GPIO.input(btn)
    GPIO.output(led, state)
 
 
leds = [12, 13, 14, 18]
buttons = [2, 3, 4, 8]
 
GPIO.setmode(GPIO.BCM)
for i in range(4):
    GPIO.setup(leds[i], GPIO.OUT)
    GPIO.setup(buttons[i], GPIO.IN)
 
try:
    while True:
        for i in range(4):
            isPressed(buttons[i], leds[i])
except KeyboardInterrupt:
    print('The program was stopped by keyboard.')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed.')

9. Web-сервер

simpleServer.py
from flask import Flask
 
app = Flask('simpleServer')
 
 
@app.route('/')
def index():
    return 'Hello, Amperka!'
 
 
app.run(port=3000, host='0.0.0.0')

10. Landing page

Ссылка на архив с файлами web-сервера.

web-server.zip

landing.py
from flask import Flask, send_file
 
app = Flask('landingPage')
 
@app.route('/')
def index():
    return send_file('landing.html')
 
@app.route('/images/<filename>')
def get_image(filename):
    return send_file('images/'+filename)
 
app.run(port=3000, host='0.0.0.0')

Если при перезапуске сервера консоль ответит сообщением «socket.error: [Errno 98] Address already in use», набери команду

ps -u

В консоль выведется список запущенных процессов. Найди строку с файлом landing.py. Во второй колонке будет указан номер процесса. Отключи его командой

kill -9 2141

Где 2141 — номер процесса. Команда kill «убивает» процесс, иногда это называют «убить девяткой».

Запусти сервер заново.

11. Интернет свет

light.py
from flask import Flask, send_file
import RPi.GPIO as GPIO
 
led = 18
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(led, GPIO.OUT)
 
app = Flask('lightControl')
 
 
@app.route('/')
def index():
    return send_file('light.html')
 
 
@app.route('/images/<filename>')
def get_image(filename):
    return send_file('images/' + filename)
 
 
@app.route('/turnOn')
def turnOn():
    GPIO.output(led, GPIO.HIGH)
    return 'turnedOn'
 
 
@app.route('/turnOff')
def turnOff():
    GPIO.output(led, GPIO.LOW)
    return 'turnedOff'
 
try: 
    app.run(port=3000, host='0.0.0.0')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed.')

12. Обратная связь

feedback.py
from flask import Flask, send_file
from flask_socketio import SocketIO
import RPi.GPIO as GPIO
 
app = Flask('feedback')
socketio = SocketIO(app)
 
btn = 2
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(btn, GPIO.IN)
 
 
@app.route('/')
def index():
    return send_file('feedback.html')
 
 
@app.route('/images/<filename>')
def get_image(filename):
    return send_file('images/' + filename)
 
 
@socketio.on('isPressed')
def checkButton(receivedData):
    if GPIO.input(btn) == False:
        socketio.emit('button', 'pressed')
    else:
        socketio.emit('button', 'released')
 
 
try: 
    socketio.run(app, port=3000, host='0.0.0.0')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed.')

13. Погодный фиджет

API ключ OpenWeatherMap будет работать после 10 мин. после создания

phidget.py
import requests, json
 
url = "http://api.openweathermap.org/data/2.5/forecast"
 
payload = {
    "lat": "широта_твоего_города",
    "lon": "долгота_твоего_города",
    "units": "metric",
    "appid": "твой_ключ",
}
 
res = requests.get(url, params=payload)
data = json.loads(res.text)
 
weather = data["list"][0]
 
 
def pars_weather(weatherType, timeRange, measurementUnits):
    if (weatherType in weather) and (
        timeRange in weather[weatherType].keys()
    ):
        print(
            weatherType,
            ": ",
            weather[weatherType][timeRange],
            measurementUnits,
        )
    else:
        print(weatherType, ": ", "none")
 
 
pars_weather("clouds", "all", "%")
pars_weather("rain", "3h", "mm")
pars_weather("snow", "3h", "mm")
print("temp:", weather["main"]["temp"], "C")

14. Бот ВКонтакте

vk.py
import time
import vk_api
 
vk = vk_api.VkApi(token = 'твой_ключ')
 
param = {
    'count': 1,
    'time_offset': 5,
    'filter': 'unread'
}
 
 
def write_msg(user_id, msg, random): 
    vk.method('messages.send', { 
        'user_id': user_id, 
        'message': msg,
        'random_id': random
    }) 
 
 
try:
    while True: 
        response = vk.method('messages.getConversations', param) 
        if response['items']: 
            item = response['items'][0] 
            last_mess = item['last_message'] 
            random = last_mess['random_id'] 
            my_id = last_mess['peer_id'] 
            text = last_mess['text'] 
            write_msg(my_id, text, random) 
        time.sleep(1) 
except KeyboardInterrupt:
    print('Keyboard interrupt detected.')
finally:
    print('The program was stopped.')
vk2.py
import time
import vk_api
import RPi.GPIO as GPIO
 
vk = vk_api.VkApi(token = 'твой_ключ') 
 
param = { 
    'count' : 1, 
    'time_offset' : 5, 
    'filter' : 'unread' 
}
 
led = 18
 
GPIO.setmode(GPIO.BCM) 
GPIO.setup(led, GPIO.OUT) 
 
 
def write_msg(user_id, msg, random): 
    vk.method('messages.send', { 
        'user_id': user_id, 
        'message': msg, 
        'random_id':random, 
    }) 
 
 
try: 
    while True: 
        response = vk.method('messages.getConversations', param) 
        if response['items']: 
            item = response['items'][0] 
            last_mess = item['last_message'] 
            random = last_mess['random_id'] 
            my_id = last_mess['peer_id'] 
            text = last_mess['text'] 
            if text == 'On': 
                GPIO.output(led, GPIO.HIGH) 
                write_msg(my_id, 'LED ' + text, random) 
            elif text == 'Off': 
                GPIO.output(led, GPIO.LOW) 
                write_msg(my_id, 'LED ' + text, random) 
            else: 
                err_msg = 'Send "On" or "Off"' 
                write_msg(my_id, err_msg, random) 
        time.sleep(1) 
except KeyboardInterrupt:
    print('The program was stopped by keyboard.')
finally:
    GPIO.cleanup()
    print('GPIO cleanup completed.')

17. Карамба

18. Кинотеатр

19. Поставь торрент заранее

deluge_vk.py
import time
import vk_api
 
from deluge_client import DelugeRPCClient
 
vk = vk_api.VkApi(token = 'твой_ключ')
 
values = {
    'count' : 1, 
    'time_offset' : 5, 
    'filter' : 'unread' 
}
 
client = DelugeRPCClient(
    '127.0.0.1',
    58846,
    'pi',
    'пароль_твоей_Raspberry'
)
 
client.connect()
 
def write_msg(user_id, msg , random):
    vk.method('messages.send', {
        'user_id': user_id,
        'message': msg,
        'random_id': random
    })
 
try:
    while True:
        response = vk.method('messages.getConversations', values)
        if response['items']:
            item = response['items'][0]
            last_mess = item['last_message']
            random = last_mess['random_id']
            my_id = last_mess['peer_id']
            text = last_mess['text'] 
            try:
                client.call('core.add_torrent_url', text, {
                    'download_location': '/home/pi/Torrents'
                })
            except Exception:
                write_msg(my_id, 'Link doesn\'t work', random)
            else: 	
                write_msg(my_id, 'Download started!', random)
        time.sleep(1)
except KeyboardInterrupt:
    print('Keyboard interrupt detected.')
finally:
    print('Program was stopped.')

Включить все светодиоды на Облаке

import RPi.GPIO as GPIO
import time
 
GPIO.setmode(GPIO.BCM)
leds = [10, 12, 13, 14, 15, 16, 17, 18, 19, 21, 24, 26]
 
for led in leds:
    GPIO.setup(led, GPIO.OUT)
    GPIO.output(led, GPIO.HIGH)
 
time.sleep(3)
 
for led in leds:
    GPIO.output(led, GPIO.LOW)
 
GPIO.cleanup()