Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions plugins/rpi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# RPi Plugin

This plugin will leverage the pins of Raspberry Pi to attach and control several peripherals to it. This plugin uses the *adafruit_blinka* library to communicate with sensors and components. Combining them with turtle blocks makes things as simple as they can get.

This plugin is compatible not only with Raspberry Pi but also with several other linux SBCs; OrangePi, BeagleBone, Google Coral Dev Boad, Jetson, Banana Pi, and NanoPi to name a few.

In Raspberry Pi, for using each component/sensor you will have to enter the pin number they are connected to with a 'D' in front of them. For example, **D7** for **GPIO 7** as you can see in the pinout diagram (standard for zero/3/4/5) below.\
Note that GPIO numbers and pin numbers (in the circle) are different. We need the GPIO numbers.


![RPi standard pinout](screenshots/pinout_rpi.png)

<br>

# Installation
Installation is pretty straightforward. Make sure you have an internet access.


- Install pip with `sudo apt install python3-pip`
- To install the dependencies for using RPi sensors:
- Go to Raspberry Pi palette and simply run the **"install requirements"** block as shown in the image below. The requirements will start to download in the background.
- After 1-2 minutes restart the TurtleArt Activity, all the blocks will be visible now

<br>

<img src="screenshots/before_req.png"> &nbsp;&nbsp;&nbsp; <img src="screenshots/after_req.png">

<br>

# For developers
Improvements and additions are very much welcomed.

Structure:

```
rpi
├── rpi.py (contains blocks linked to functions)
├── functions.py (contains all callable functions)
├── __init__.py (checks if the device is RPi and installs requirements)
├── req.txt (requirements file)
├── sensors
│   └── //scripts to run sensors//
└── //some other files//

```

<!-- ## Use sensors in your activities -->


## How to contribute
For adding more sensors/components you can add turtle blocks in `rpi.py`, their corresponding functions in `functions.py`, and add their requirements in the `req.txt` file.

The pallet is only visible if the device is Raspberry Pi, so don't forget to disable the check in `__init__.py` when running on a PC

## Dependencies
- pip
- pip packages
- adafruit-blinka
- adafruit-circuitpython-displayio-ssd1306
- adafruit-circuitpython-ssd1306
- adafruit-circuitpython-display-text
- adafruit-circuitpython-hcsr04

<br>

# Screenshots

**Oled Display:**

<img src="screenshots/ta_oled.png"> <img src="screenshots/oled.jpg">

**Push Button:**

<img src="screenshots/ta_btn.png"> <img src="screenshots/btn.gif">
47 changes: 47 additions & 0 deletions plugins/rpi/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import os
import subprocess
cwd = os.getcwd()

# check if the system is Raspberry Pi, if not, raise exception
# Eg. output: Raspberry Pi 5 Model B Rev 1.0
try:
with open('/sys/firmware/devicetree/base/model', 'r') as file:
info = file.read()
if "Raspberry" in info:
is_rpi = True
else:
raise
except Exception: # file not found
raise # change to None if on a PC


# check if requirements are met
req_met = True
with open(cwd + '/plugins/rpi/req.txt', 'r') as file:
req_list = file.read().split("\n")
installed_modules = os.popen("pip freeze").read()

for req in req_list:
if (req not in installed_modules):
req_met = False


# to install req. - called from rpi.py
def install_req():
subprocess.Popen(['pip', 'install', '--break-system-packages', '-r',
cwd + '/plugins/rpi/req.txt'])
# todo: send notif to restart after a minute
# todo: send notif if no internet

# configure i2c, spi, etc comms
os.system('''sudo raspi-config nonint do_i2c 0 &&
sudo raspi-config nonintdo_spi 0 &&
sudo raspi-config nonint do_serial_hw 0 &&
sudo raspi-config nonint do_ssh 0 &&
sudo raspi-config nonint do_camera 0 &&
sudo raspi-config nonint disable_raspi_config_at_boot 0''')


# -- Add this line to config.txt to increase the speed of i2c devices -- #
# os.system("""sudo sed -i '$ a\dtparam=i2c_baudrate=1000000'
# /boot/firmware/config.txt""")
101 changes: 101 additions & 0 deletions plugins/rpi/functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import time
import os
import board
import digitalio
import adafruit_hcsr04
import subprocess

cwd = os.getcwd()
import logging

_logger = logging.getLogger("turtleart-activity RPi plugin")


# Digital output
def digitalWrite(pin_no: str, val: float):
if not hasattr(board, pin_no):
return # + send a message
pin = digitalio.DigitalInOut(getattr(board, pin_no))
pin.direction = digitalio.Direction.OUTPUT
pin.value = int(val)


# Digital input
def digitalRead(pin_no: str):
if not hasattr(board, pin_no):
return
pin = digitalio.DigitalInOut(getattr(board, pin_no))
pin.direction = digitalio.Direction.INPUT
return bool(pin.value)


# delay
def delay(ms: int):
time.sleep(ms / 1000)


# Button
def btn(pin: str):
button = 0
try:
button = digitalio.DigitalInOut(getattr(board, pin))
button.direction = digitalio.Direction.INPUT
except Exception:
None
button.pull = digitalio.Pull.UP
return not button.value


# HC-SR04 Ultrasonic distance sensor
class _dist:
def def_dist(self, trigger: str, echo: str):
try:
self.sonar = adafruit_hcsr04.HCSR04(
trigger_pin=getattr(board, trigger),
echo_pin=getattr(board, echo)
)
except Exception:
return

def dst(self):
try:
s = 0.0
for i in range(20):
if self.sonar.distance < 1:
i = i - 1
continue
s += self.sonar.distance
return round(s / 20, 1)
except Exception:
return 0.0


dist = _dist()


# OLED display
class _oled:
def define(self, _height, _width, _text_color):
self.width = int(_width)
self.height = int(_height)
self.text_color = int(_text_color)

def print(self, text):
subprocess.Popen(
"python3 " + cwd + "/plugins/rpi/sensors/oled_display.py "
+ str(self.height)
+ " "
+ str(self.width)
+ " "
+ str(self.text_color)
+ " '"
+ str(text)
+ "'",
shell=True,
)


oled = _oled()

# except Exception as err:
# print(Exception, err)
21 changes: 21 additions & 0 deletions plugins/rpi/icons/RaspberryPioff.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading