===== Инструкция набора «Малина» с платой Rasberry Pi 3 Model B =====
Электронная версия книги из набора [[amp>product/malina?utm_source=announce&utm_campaign=malina&utm_medium=wiki|«Малина»]].
Здесь собраны все исходные коды экспериментов, подсказки и хаки по прохождению набора.
{{ :malina:titile.png?nolink |}}
===== Видеообзор =====
{{youtube>CNW2KdwlanE?large}}
===== Подключение и запуск ====
Если под рукой нет внешнего монитора, [[rpi:installation:ssh|настрой SSH]].
===== Настройка Wi-Fi =====
Подключись к Raspberry Pi по SSH.
Открой в текстовом редакторе «nano» файл настроек Wi-Fi.
Для этого введи команду
~ $ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
и нажми Enter.
Откроется файл, в конце добавь параметры сети.
network={
ssid="имя твоего wi-fi"
psk="пароль твоего wi-fi"
}
Закрой файл сочетанием клавиш ctrl+X (cmd+X для Mac OS) на клавиатуре. Редактор спросит, сохранить ли изменения. Нажми
клавишу Y (да), а затем Enter. Выполни перезагрузку системы командой ''sudo reboot''
~ $ sudo reboot
После перезагрузки отсоедини кабель Ethernet и работай с Расберри через Wi-Fi.
===== Ресурсы =====
* [[https://www.putty.org/|Putty]] — клиент для удалённого доступа к устройствам по протоколам SSH, Telnet и UART.
* [[https://filezilla-project.org/download.php?show_all=1|FileZilla]] — FTP-клиент.
* [[https://www.realvnc.com/en/connect/download/viewer/|RealVNC]] — клиент для удаленного доступа к рабочему столу устройства.
* [[https://angryip.org/download|Angry IP Scanner]] — утилита для сканирования IP-адресов в подключенной сети.
===== Эксперименты =====
==== 3. Маячок ====
При первом запуске редактора Thonny Python IDE главное меню скрыто. Чтоб сделать его видимым, нужно нажать на ссылку в верхнем правом углу окна IDE.
{{ :malina:1.png?nolink |}}
Подтвердите изменения
{{ :malina:2.png?nolink |}}
После перезапуска IDE изменения вступят в силу.
{{ :malina:3.png?nolink |}}
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
i = 0
while (i < 5):
i = i + 1
time.sleep(0.5)
GPIO.output(17, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(17, GPIO.LOW)
GPIO.cleanup()
==== 4. Выключатель ====
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)
==== 5. Переключатель ====
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(8, GPIO.IN)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(26, GPIO.OUT)
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)
==== 6. Управление яркостью ====
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)
while (True):
time.sleep(0.01)
dutyCycle = dutyCycle + 1
if (dutyCycle > 100):
dutyCycle = 0
pwm.ChangeDutyCycle(dutyCycle)
==== 7. Панель управления светом ====
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)
while (True):
isPressed(button1, led1)
isPressed(button2, led2)
==== 8. Массивная оптимизация ====
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()
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)
while (True):
for i in range(4):
isPressed(buttons[i], leds[i])
==== 9. Web-сервер ====
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-сервера.
http://amperka.github.io/malina_support/web-server.zip
from flask import Flask, send_file
app = Flask('landingPage')
@app.route('/')
def index():
return send_file('landing.html')
@app.route('/images/')
def get_image(filename):
return send_file('images/'+filename)
app.run(debug=True, port=3000, host='0.0.0.0')
Если при перезапуске сервера консоль ответит сообщением «socket.error: [Errno 98] Address already in use», набери команду
ps -u
В консоль выведется список запущенных процессов.
{{ :malina:ps.png?nolink |}}
Найди строку с файлом landing.py. Во второй колонке будет указан номер процесса. Отключи его командой
kill -9 2141
Где 2141 — номер процесса.
{{ :malina:kill.png?nolink |}}
Команда kill «убивает» процесс, иногда это называют «убить девяткой».
Запусти сервер заново.
==== 11. Интернет свет ====
from flask import Flask, send_file
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
led = 18
GPIO.setup(led, GPIO.OUT)
app = Flask('lightControl')
@app.route('/')
def index():
return send_file('light.html')
@app.route('/images/')
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'
app.run(debug=True, port=3000, host='0.0.0.0')
==== 12. Обратная связь ====
sudo pip3 install flask-socketio eventlet
from flask import Flask, send_file
from flask_socketio import SocketIO
import RPi.GPIO as GPIO
app = Flask('feedback')
socketio = SocketIO(app)
GPIO.setmode(GPIO.BCM)
btn = 2
GPIO.setup(btn, GPIO.IN)
@app.route('/')
def index():
return send_file('feedback.html')
@app.route('/images/')
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')
socketio.run(app, port=3000, host='0.0.0.0', debug=True)
Запусти сервер командой
python3 feedback.py
==== 13. Погодный фиджет ====
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. Бот ВКонтакте ====
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
})
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)
==== 18. Кинотеатр ====
amperka.github.io/malina_support/omx-web.zip
==== 19. Поставь торрент заранее ====
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,
})
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']
client.call('core.add_torrent_url', text, {
'download_location': '/home/pi/Torrents'
})
write_msg(my_id, 'Download started!', random)
time.sleep(1)
==== Включить все светодиоды на Облаке ====
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()