As I understand it, MPY's Unix build will run out of the box on a Raspberry Pi w/ Linux. What I haven't been able to find yet, is whether it will be possible to use the RPi's I/O, i.e. access to its GPIO pins, I2C buses, and SPI.
What I'm trying to evaluate, is whether MPY-on-RPI could be used as a convenient dev setup, before taking the code to one of the "real" embedded platforms supported by MPY. I.e. all the conveniences of editing, version control, speed, networking, no uploads, etc. Obviously not everything could be tested this way, but still.
I'm still learning and digging into the (great) docs and codebase. Will try it all out Real Soon Now, but tips and pointers appreciated.
-jcw
Raspberry Pi access to GPIO, I2C, SPI?
-
- Posts: 969
- Joined: Sat Feb 03, 2018 7:02 pm
Re: Raspberry Pi access to GPIO, I2C, SPI?
RPI GPIO can't directly be accessed by micropython.
However I did also try to get that working and came across some code that uses the GPIO file-like access:
I did test this once but it only allows for very basic GPIO access because it is extremely slow. You won't get any protocol working except simply switching GPIOs on and off or reading a value.
Certainly no I2C etc possible.
However I did also try to get that working and came across some code that uses the GPIO file-like access:
Code: Select all
# -*- coding: utf-8 -*-
__version__ = '0.1.0'
import os
class PinState(object):
"""An ultra simple pin-state object.
Keeps track data related to each pin.
Args:
value: the file pointer to set/read value of pin.
direction: the file pointer to set/read direction of the pin.
"""
def __init__(self, value, direction):
self.value = value
self.direction = direction
path = os.path
pjoin = os.path.join
gpio_root = '/sys/class/gpio'
gpiopath = lambda pin: os.path.join(gpio_root, 'gpio{0}'.format(pin))
_open = dict()
FMODE = 'w+'
IN, OUT = "in", "out"
LOW, HIGH = 0, 1
def _write(f, v):
print("writing: {}: {}".format(f, v))
f.write(str(v))
f.flush()
def _read(f):
print("Reading: {}".format(f))
f.seek(0)
return f.read().strip()
def _verify(function):
"""decorator to ensure pin is properly set up"""
def wrapped(pin, *args, **kwargs):
pin = int(pin)
if pin not in _open:
ppath = gpiopath(pin)
if not os.path.exists(ppath):
print("Creating Pin {0}".format(pin))
with open(pjoin(gpio_root, 'export'), 'w') as f:
_write(f, pin)
value = open(pjoin(ppath, 'value'), FMODE)
direction = open(pjoin(ppath, 'direction'), FMODE)
_open[pin] = PinState(value=value, direction=direction)
return function(pin, *args, **kwargs)
return wrapped
def cleanup(pin=None, assert_exists=False):
"""Cleanup the pin by closing and unexporting it.
Args:
pin (int, optional): either the pin to clean up or None (default).
If None, clean up all pins.
assert_exists: if True, raise a ValueError if the pin was not
setup. Otherwise, this function is a NOOP.
"""
if pin is None:
# Take a list of keys because we will be deleting from _open
for pin in list(_open):
cleanup(pin)
return
if not isinstance(pin, int):
raise TypeError("pin must be an int, got: {}".format(pin))
state = _open.get(pin)
if state is None:
if assert_exists:
raise ValueError("pin {} was not setup".format(pin))
return
state.value.close()
state.direction.close()
if os.path.exists(gpiopath(pin)):
print("Unexporting pin {0}".format(pin))
with open(pjoin(gpio_root, 'unexport'), 'w') as f:
_write(f, pin)
del _open[pin]
@_verify
def setup(pin, mode, pullup=None, initial=False):
'''Setup pin with mode IN or OUT.
Args:
pin (int):
mode (str): use either gpio.OUT or gpio.IN
pullup (None): rpio compatibility. If anything but None, raises
value Error
pullup (bool, optional): Initial pin value. Default is False
'''
if pullup is not None:
raise ValueError("sysfs does not support pullups")
if mode not in (IN, OUT):
raise ValueError(mode)
print("Setup {}: {}".format(pin, mode))
f = _open[pin].direction
_write(f, mode)
if mode == OUT:
if initial:
set(pin, 1)
else:
set(pin, 0)
# @_verify
def mode(pin):
'''get the pin mode
Returns:
str: "in" or "out"
'''
f = _open[pin].direction
return _read(f)
# @_verify
def read(pin):
'''read the pin value
Returns:
bool: 0 or 1
'''
f = _open[pin].value
out = int(_read(f))
print("Read {}: {}".format(pin, out))
return out
# @_verify
def set(pin, value):
'''set the pin value to 0 or 1'''
print("Write {}: {}".format(pin, value))
f = _open[pin].value
_write(f, value)
input = read
output = set
def setwarnings(value):
'''exists for rpio compatibility'''
pass
def setmode(value):
'''exists for rpio compatibility'''
pass
BCM = None # rpio compatibility
Certainly no I2C etc possible.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode
Re: Raspberry Pi access to GPIO, I2C, SPI?
Thx for that. Maybe a C-coded extension, similar to (or even based on) WiringPi could work.
I just found https://github.com/WiringPi/WiringPi-Python/ ... could be a starting point.
I just found https://github.com/WiringPi/WiringPi-Python/ ... could be a starting point.
-
- Posts: 969
- Joined: Sat Feb 03, 2018 7:02 pm
Re: Raspberry Pi access to GPIO, I2C, SPI?
I guess many people would be happy if you make it work
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode
-
- Posts: 28
- Joined: Sat Jan 24, 2015 10:34 pm
- Location: vancouver/kelowna/lethbridge
Re: Raspberry Pi access to GPIO, I2C, SPI?
openplc project may provide a leveraging point for many things. openplc has the goal to support iec61131-3 languages for automation programming. runs on raspberry pi, but also can run on similar embedded chips like stm32 and esp8266 (I believe).
1. openplc runs on multiple embedded platforms.
2. openplc can run on a dedicated core on raspberry pi.
3. leveraging off of openplc points towards codesys iec61131-3 compatibility. if it is possible to write a python wrapper to a codesys driver, or openplc driver, that might solve a lot of problems, or make gpio access easier.
I would like to suggest micropython as a IEC61131-3 language. I think that micropython will revolutionize the IEC61131 language standard.
1. openplc runs on multiple embedded platforms.
2. openplc can run on a dedicated core on raspberry pi.
3. leveraging off of openplc points towards codesys iec61131-3 compatibility. if it is possible to write a python wrapper to a codesys driver, or openplc driver, that might solve a lot of problems, or make gpio access easier.
I would like to suggest micropython as a IEC61131-3 language. I think that micropython will revolutionize the IEC61131 language standard.