diff --git a/plugins/rpi/README.md b/plugins/rpi/README.md
new file mode 100644
index 00000000..b693ff6e
--- /dev/null
+++ b/plugins/rpi/README.md
@@ -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.
+
+
+
+
+
+
+# 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
+
+
+
+
+
+
+
+# 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//
+
+```
+
+
+
+
+## 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
+
+
+
+# Screenshots
+
+**Oled Display:**
+
+
+
+**Push Button:**
+
+
\ No newline at end of file
diff --git a/plugins/rpi/__init__.py b/plugins/rpi/__init__.py
new file mode 100755
index 00000000..e2bf024e
--- /dev/null
+++ b/plugins/rpi/__init__.py
@@ -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""")
diff --git a/plugins/rpi/functions.py b/plugins/rpi/functions.py
new file mode 100755
index 00000000..101b3094
--- /dev/null
+++ b/plugins/rpi/functions.py
@@ -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)
diff --git a/plugins/rpi/icons/RaspberryPioff.svg b/plugins/rpi/icons/RaspberryPioff.svg
new file mode 100755
index 00000000..c666111f
--- /dev/null
+++ b/plugins/rpi/icons/RaspberryPioff.svg
@@ -0,0 +1,21 @@
+
+
diff --git a/plugins/rpi/icons/RaspberryPioff2.svg b/plugins/rpi/icons/RaspberryPioff2.svg
new file mode 100755
index 00000000..0f111368
--- /dev/null
+++ b/plugins/rpi/icons/RaspberryPioff2.svg
@@ -0,0 +1,14 @@
+
+
diff --git a/plugins/rpi/icons/RaspberryPion.svg b/plugins/rpi/icons/RaspberryPion.svg
new file mode 100755
index 00000000..a45de14b
--- /dev/null
+++ b/plugins/rpi/icons/RaspberryPion.svg
@@ -0,0 +1,26 @@
+
+
diff --git a/plugins/rpi/req.txt b/plugins/rpi/req.txt
new file mode 100644
index 00000000..9fd7116b
--- /dev/null
+++ b/plugins/rpi/req.txt
@@ -0,0 +1,6 @@
+RPi.GPIO
+adafruit-blinka
+adafruit-circuitpython-displayio-ssd1306
+adafruit-circuitpython-ssd1306
+adafruit-circuitpython-display-text
+adafruit-circuitpython-hcsr04
\ No newline at end of file
diff --git a/plugins/rpi/rpi.py b/plugins/rpi/rpi.py
new file mode 100755
index 00000000..3915229e
--- /dev/null
+++ b/plugins/rpi/rpi.py
@@ -0,0 +1,208 @@
+from plugins.plugin import Plugin
+from gettext import gettext as _
+import plugins.rpi.__init__ as init
+if init.req_met:
+ import plugins.rpi.functions as fns
+from TurtleArt.taprimitive import ArgSlot, Primitive
+from TurtleArt.tatype import TYPE_NUMBER, TYPE_OBJECT, TYPE_BOOL
+from TurtleArt.tawindow import TurtleArtWindow
+from TurtleArt.tapalette import make_palette
+
+import logging
+_logger = logging.getLogger("turtleart-activity RPi plugin")
+
+
+class Rpi(Plugin):
+ def __init__(self, parent: TurtleArtWindow):
+ Plugin.__init__(self)
+ self._parent = parent
+ self.running_sugar = self._parent.running_sugar
+
+ def setup(self):
+ palette = make_palette(
+ "RaspberryPi",
+ colors=["#abe6ff", "#008080"],
+ help_string=_("Palette of RPi pins"),
+ position=6,
+ )
+
+ # check if req is met, if not then show only install block
+ if not init.req_met:
+ palette.add_block(
+ "req",
+ style="basic-style",
+ label="install requirements",
+ prim_name="req",
+ logo_command="req",
+ )
+ self._parent.lc.def_prim(
+ "req",
+ 0,
+ Primitive(
+ init.install_req,
+ ),
+ )
+ raise
+
+ # Digital Output
+ palette.add_block(
+ "digitalWrite",
+ style="basic-style-2arg",
+ label=[_("GPIO"), _("set"), _("to")],
+ default="Dx",
+ prim_name="digitalWrite",
+ help_string=_("sets pin to high/low"),
+ logo_command="digitalWrite",
+ )
+ self._parent.lc.def_prim(
+ "digitalWrite",
+ 2,
+ Primitive(
+ fns.digitalWrite, arg_descs=[ArgSlot(TYPE_OBJECT),
+ ArgSlot(TYPE_NUMBER)]
+ ),
+ )
+ # Digital Input
+ palette.add_block(
+ "digitalRead",
+ style="basic-style-1arg",
+ label=["GPIO\t ", "read"],
+ default="Dx",
+ prim_name="digitalRead",
+ help_string=_("sets pin to high/low"),
+ logo_command="digitalRead",
+ )
+ self._parent.lc.def_prim(
+ "digitalRead",
+ 1,
+ Primitive(fns.digitalRead, arg_descs=ArgSlot(TYPE_OBJECT),
+ return_type=TYPE_BOOL))
+
+ # Delay
+ palette.add_block(
+ "delay",
+ style="basic-style-1arg",
+ label="delay (ms)",
+ prim_name="delay",
+ logo_command="delay",
+ default=1000,
+ )
+ self._parent.lc.def_prim(
+ "delay", 1, Primitive(fns.delay, arg_descs=ArgSlot(TYPE_NUMBER))
+ )
+
+ # Button
+ palette.add_block(
+ "btn",
+ style="boolean-1arg-block-style",
+ label=_("button"),
+ prim_name="btn",
+ default="Dx",
+ help_string=_("sets pin to high/low"),
+ logo_command="btn",
+ )
+ self._parent.lc.def_prim(
+ "btn",
+ 1,
+ Primitive(
+ fns.btn, return_type=TYPE_BOOL,
+ arg_descs=([ArgSlot(TYPE_OBJECT)])
+ ),
+ )
+
+ # HIGH/LOW Blocks
+ palette.add_block(
+ "high",
+ style="box-style",
+ label=_("HIGH"),
+ prim_name="high",
+ help_string=_("toggles gpio pin high"),
+ )
+
+ def _high():
+ return 1
+
+ self._parent.lc.def_prim("high", 0, Primitive(_high,
+ return_type=TYPE_NUMBER))
+
+ palette.add_block(
+ "low",
+ style="box-style",
+ label=_("LOW"),
+ prim_name="low",
+ help_string=_("toggles gpio pin low"),
+ )
+
+ def _low():
+ return 0
+
+ self._parent.lc.def_prim("low", 0, Primitive(_low,
+ return_type=TYPE_NUMBER))
+
+ # HC-SR04 distance sensor
+ palette.add_block("dist", style="box-style",
+ prim_name="dist", label="distance")
+ self._parent.lc.def_prim(
+ "dist", 0, Primitive(fns.dist.dst, return_type=TYPE_NUMBER)
+ )
+
+ palette.add_block(
+ "def_dist",
+ style="basic-style-2arg",
+ label=["HCSR04", "trig pin", "echo pin"],
+ default=["Dx", "Dx"],
+ prim_name="def_dist",
+ help_string=_(
+ "measure distance using HC-SR04,\
+ distance sensor"
+ ),
+ )
+ self._parent.lc.def_prim(
+ "def_dist",
+ 2,
+ Primitive(
+ fns.dist.def_dist,
+ arg_descs=([ArgSlot(TYPE_OBJECT), ArgSlot(TYPE_OBJECT)]),
+ ),
+ )
+
+ # String editable blocks
+ # palette.add_block('string',
+ # style='box-style',
+ # help_string=_('text'))
+
+ # OLED-Display
+ palette.add_block(
+ "define_oled_display",
+ style="basic-style-3arg",
+ label=[_("OLED\t\t"), _("height"), _("width"),
+ _("text color\n(0 or 1) ")],
+ default=[128, 32, 1],
+ prim_name="define_oled_display",
+ logo_command="define_oled_display",
+ )
+ self._parent.lc.def_prim(
+ "define_oled_display",
+ 3,
+ Primitive(
+ fns.oled.define,
+ arg_descs=(
+ [ArgSlot(TYPE_NUMBER),
+ ArgSlot(TYPE_NUMBER),
+ ArgSlot(TYPE_NUMBER)]
+ ),
+ ),
+ )
+
+ palette.add_block(
+ "oled_print",
+ style="basic-style-1arg",
+ default="text",
+ label="Display",
+ prim_name="oled_print",
+ )
+ self._parent.lc.def_prim(
+ "oled_print",
+ 1,
+ Primitive(fns.oled.print, arg_descs=([ArgSlot(TYPE_OBJECT)])),
+ )
diff --git a/plugins/rpi/screenshots/after_req.png b/plugins/rpi/screenshots/after_req.png
new file mode 100644
index 00000000..ab598505
Binary files /dev/null and b/plugins/rpi/screenshots/after_req.png differ
diff --git a/plugins/rpi/screenshots/before_req.png b/plugins/rpi/screenshots/before_req.png
new file mode 100644
index 00000000..a515d6e5
Binary files /dev/null and b/plugins/rpi/screenshots/before_req.png differ
diff --git a/plugins/rpi/screenshots/btn.gif b/plugins/rpi/screenshots/btn.gif
new file mode 100644
index 00000000..6b1d6f4b
Binary files /dev/null and b/plugins/rpi/screenshots/btn.gif differ
diff --git a/plugins/rpi/screenshots/oled.jpg b/plugins/rpi/screenshots/oled.jpg
new file mode 100644
index 00000000..2c6dafe5
Binary files /dev/null and b/plugins/rpi/screenshots/oled.jpg differ
diff --git a/plugins/rpi/screenshots/pinout_rpi.png b/plugins/rpi/screenshots/pinout_rpi.png
new file mode 100644
index 00000000..87263297
Binary files /dev/null and b/plugins/rpi/screenshots/pinout_rpi.png differ
diff --git a/plugins/rpi/screenshots/ta_btn.png b/plugins/rpi/screenshots/ta_btn.png
new file mode 100644
index 00000000..18c86f4d
Binary files /dev/null and b/plugins/rpi/screenshots/ta_btn.png differ
diff --git a/plugins/rpi/screenshots/ta_oled.png b/plugins/rpi/screenshots/ta_oled.png
new file mode 100644
index 00000000..ccb5c1d5
Binary files /dev/null and b/plugins/rpi/screenshots/ta_oled.png differ
diff --git a/plugins/rpi/sensors/oled_display.py b/plugins/rpi/sensors/oled_display.py
new file mode 100755
index 00000000..50375174
--- /dev/null
+++ b/plugins/rpi/sensors/oled_display.py
@@ -0,0 +1,59 @@
+import sys
+import time
+import board
+import displayio
+from i2cdisplaybus import I2CDisplayBus
+from fourwire import FourWire
+import terminalio
+from adafruit_display_text import label
+import adafruit_displayio_ssd1306
+
+
+def main(width, height, text_color, text):
+ height = int(height)
+ width = int(width)
+ text_color = int(text_color)
+ displayio.release_displays()
+ oled_reset = board.D27
+
+ # Use for I2C
+ i2c = board.I2C()
+ display_bus = I2CDisplayBus(i2c, device_address=0x3C, reset=oled_reset)
+
+ # Use for SPI
+ # spi = board.SPI()
+ # oled_cs = board.D5
+ # oled_dc = board.D6
+ # display_bus = FourWire(spi, command=oled_dc, chip_select=oled_cs,
+ # reset=oled_reset, baudrate=1000000)
+ display = adafruit_displayio_ssd1306.SSD1306(
+ display_bus, width=width, height=height
+ )
+ splash = displayio.Group()
+ display.root_group = splash
+
+ # clear oled
+ color_bitmap = displayio.Bitmap(width, height, 1)
+ color_palette = displayio.Palette(1)
+ color_palette[0] = 0xFFFFFF if text_color == 0 else 0x000000
+ bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette,
+ x=0, y=0)
+ splash.append(bg_sprite)
+
+ # print on oled
+ if text != "":
+ if len(text) > 20:
+ text = text[:20]
+ text_area = label.Label(
+ terminalio.FONT,
+ text=text,
+ color=0x000000 if text_color == 0 else 0xFFFFFF,
+ x=5,
+ y=5,
+ )
+ splash.append(text_area)
+ time.sleep(0.2)
+
+
+if __name__ == "__main__":
+ main(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
diff --git a/plugins/rpi/setup.py b/plugins/rpi/setup.py
new file mode 100755
index 00000000..e69de29b