Skip to content

Commit

Permalink
Working GPIO Set/Get
Browse files Browse the repository at this point in the history
  • Loading branch information
michaellee1019 committed Nov 28, 2024
1 parent a1b27d0 commit 3a1945e
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ share/python-wheels/
.installed.cfg
*.egg
MANIFEST
module.tar.gz

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
16 changes: 6 additions & 10 deletions meta.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
{
"$schema": "https://dl.viam.dev/module.schema.json",
"module_id": "michaellee1019:mcp23017",
"visibility": "public",
"url": "",
"description": "Modular board component: board",
"visibility": "private",
"url": "https://github.com/michaellee1019/mcp23017",
"description": "Provides models for the mcp23017 GPIO expansion chip.",
"models": [
{
"api": "rdk:component:board",
"model": "michaellee1019:mcp23017:board"
}
],
"entrypoint": "dist/main",
"entrypoint": "reload.sh",
"first_run": "",
"build": {
"build": "./build.sh",
"build": "rm -f module.tar.gz && tar czf module.tar.gz requirements.txt src/*.py meta.json setup.sh reload.sh",
"setup": "./setup.sh",
"path": "dist/archive.tar.gz",
"arch": [
"linux/amd64",
"linux/arm64"
]
"path": "module.tar.gz"
}
}
14 changes: 14 additions & 0 deletions reload.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

# bash safe mode. look at `set --help` to see what these are doing
set -euxo pipefail

cd $(dirname $0)
MODULE_DIR=$(dirname $0)
VIRTUAL_ENV=$MODULE_DIR/.venv
PYTHON=$VIRTUAL_ENV/bin/python
./setup.sh

# Be sure to use `exec` so that termination signals reach the python process,
# or handle forwarding termination signals manually
exec $PYTHON src/main.py $@
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

viam-sdk==0.34.0

adafruit-circuitpython-mcp230xx==2.5.15
typing-extensions
4 changes: 2 additions & 2 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
cd `dirname $0`

# Create a virtual environment to run our code
VENV_NAME="venv"
VENV_NAME=".venv"
PYTHON="$VENV_NAME/bin/python"
ENV_ERROR="This module requires Python >=3.8, pip, and virtualenv to be installed."

Expand All @@ -19,7 +19,7 @@ if ! python3 -m venv $VENV_NAME >/dev/null 2>&1; then
$SUDO apt -qq update >/dev/null
fi
$SUDO apt install -qqy python3-venv >/dev/null 2>&1
if ! python3 -m venv $VENV_NAME >/dev/null 2>&1; then
if ! python3 -m .venv $VENV_NAME >/dev/null 2>&1; then
echo $ENV_ERROR >&2
exit 1
fi
Expand Down
89 changes: 76 additions & 13 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,56 @@
import asyncio
import sys

from datetime import timedelta
from typing import (Any, ClassVar, Dict, Final, List, Mapping, Optional,
Sequence)
from typing import Any, ClassVar, Dict, List, Mapping, Optional, Sequence

from typing_extensions import Self
from viam.components.board import *
from viam.components.board import Board, TickStream
from viam.module.module import Module
from viam.proto.app.robot import ComponentConfig
from viam.proto.common import ResourceName
from viam.proto.component.board import (PowerMode, ReadAnalogReaderResponse,
StreamTicksResponse)
from viam.proto.component.board import PowerMode
from viam.resource.base import ResourceBase
from viam.resource.easy_resource import EasyResource
from viam.resource.types import Model, ModelFamily
from viam.streams import Stream


class Board(Board, EasyResource):
import digitalio
import board
import busio
from adafruit_mcp230xx.mcp23017 import MCP23017
from adafruit_mcp230xx.digital_inout import DigitalInOut

MCP23017_IODIRA = 0x00
MCP23017_IPOLA = 0x02
MCP23017_GPINTENA = 0x04
MCP23017_DEFVALA = 0x06
MCP23017_INTCONA = 0x08
MCP23017_IOCONA = 0x0A
MCP23017_GPPUA = 0x0C
MCP23017_INTFA = 0x0E
MCP23017_INTCAPA = 0x10
MCP23017_GPIOA = 0x12
MCP23017_OLATA = 0x14

MCP23017_IODIRB = 0x01
MCP23017_IPOLB = 0x03
MCP23017_GPINTENB = 0x05
MCP23017_DEFVALB = 0x07
MCP23017_INTCONB = 0x09
MCP23017_IOCONB = 0x0B
MCP23017_GPPUB = 0x0D
MCP23017_INTFB = 0x0F
MCP23017_INTCAPB = 0x11
MCP23017_GPIOB = 0x13
MCP23017_OLATB = 0x15


class MCP23017Board(Board, EasyResource):
MODEL: ClassVar[Model] = Model(ModelFamily("michaellee1019", "mcp23017"), "board")
i2c: busio.I2C = None
i2c_address: int = 0x27
mcp: MCP23017 = None
pins: List[DigitalInOut]
pullups: List[int] = []

@classmethod
def new(
Expand Down Expand Up @@ -58,6 +90,24 @@ def reconfigure(
config (ComponentConfig): The new configuration
dependencies (Mapping[ResourceName, ResourceBase]): Any dependencies (both implicit and explicit)
"""
# if "i2c_bus" in config.attributes.fields:
# self.i2c_bus = int(config.attributes.fields["i2c_bus"].string_value)
self.i2c = busio.I2C(board.SCL, board.SDA)
if "i2c_address" in config.attributes.fields:
self.i2c_address = int(
config.attributes.fields["i2c_address"].string_value, base=16
)
if "pullups" in config.attributes.fields:
self.pullups = [int(x) for x in config.attributes.fields["pullups"].list_value]

self.mcp = MCP23017(self.i2c, self.i2c_address)
self.pins = [self.mcp.get_pin(i) for i in range(16)]
for i in range(16):
if i in self.pullups:
self.pins[i].pull = digitalio.Pull.UP
else:
self.pins[i].pull = None

return super().reconfigure(config, dependencies)

class Analog(Board.Analog):
Expand Down Expand Up @@ -93,6 +143,11 @@ async def value(
raise NotImplementedError()

class GPIOPin(Board.GPIOPin):
pin: DigitalInOut = None

def __init__(self, name: str, pin: DigitalInOut):
self.pin = pin
super().__init__(name)

async def set(
self,
Expand All @@ -102,7 +157,9 @@ async def set(
timeout: Optional[float] = None,
**kwargs
):
raise NotImplementedError()
if self.pin.direction:
self.pin.switch_to_output()
self.pin.value = high

async def get(
self,
Expand All @@ -111,7 +168,9 @@ async def get(
timeout: Optional[float] = None,
**kwargs
) -> bool:
raise NotImplementedError()
if not self.pin.direction:
self.pin.switch_to_input()
return self.pin.value

async def get_pwm(
self,
Expand Down Expand Up @@ -158,7 +217,12 @@ async def digital_interrupt_by_name(self, name: str) -> DigitalInterrupt:
raise NotImplementedError()

async def gpio_pin_by_name(self, name: str) -> GPIOPin:
raise NotImplementedError()
try:
pin_num = int(name)
pin = self.pins[pin_num]
return MCP23017Board.GPIOPin(name, pin)
except ValueError as ex:
raise ValueError("pin name must be an integer between 0-15") from ex

async def analog_names(self) -> List[str]:
raise NotImplementedError()
Expand Down Expand Up @@ -188,4 +252,3 @@ async def stream_ticks(

if __name__ == "__main__":
asyncio.run(Module.run_from_registry())

2 changes: 1 addition & 1 deletion test.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
#configue all PinB input
bus.write_byte_data(MCP23017_ADDRESS,MCP23017_IODIRB,0xFF)
#configue all PinB pullDOWN
bus.write_byte_data(MCP23017_ADDRESS,MCP23017_GPPUB,0x00)
bus.write_byte_data(MCP23017_ADDRESS,MCP23017_GPPUB,0x00)


#only for debug
Expand Down

0 comments on commit 3a1945e

Please sign in to comment.