Skip to content

Commit

Permalink
Add mip support
Browse files Browse the repository at this point in the history
  • Loading branch information
mcauser committed Feb 11, 2024
1 parent 068a850 commit 8d4c54e
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 175 deletions.
98 changes: 79 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,39 @@ At power on, all pins are driven HIGH and can be immediately used as inputs.

Operating voltage: 2.5V - 5.5V

## Example

Copy the file to your device, using ampy, rshell, webrepl or compiling and deploying. eg.
## Installation

Using mip via mpremote:

```bash
$ ampy put pcf8575.py
$ mpremote mip install github:mcauser/micropython-pcf8575
$ mpremote mip install github:mcauser/micropython-pcf8575/examples
```

Using mip directly on a WiFi capable board:

```python
>>> import mip
>>> mip.install("github:mcauser/micropython-pcf8575")
>>> mip.install("github:mcauser/micropython-pcf8575/examples")
```

Manual installation:

Copy `src/pcf8575.py` to the root directory of your device.


## Examples

**Basic Usage**

```python
import pcf8575
from machine import I2C, Pin

# TinyPICO (ESP32)
i2c = I2C(scl=Pin(22), sda=Pin(21))
i2c = I2C(0)
pcf = pcf8575.PCF8575(i2c, 0x20)

# read pin 2
Expand All @@ -59,14 +76,21 @@ pcf.pin(4, 0)
pcf.toggle(5)

# set all pins at once with 16-bit int
pcf.port = 0xff00
pcf.port = 0xFF00

# read all pins at once as 16-bit int
pcf.port
# returns 65280 (0xFF00)
```

For more detailed examples, see [examples](/examples).

If you mip installed them above, you can run them like so:

```python
import pcf8575.examples.basic
```

## Methods

Construct with a reference to I2C and set the device address.
Expand All @@ -77,6 +101,12 @@ See below for address selection.
__init__(i2c, address=0x20)
```

Scans the I2C bus for the provided address and returns True if a device is present
otherwise raises an OSError.
```python
check()
```

Method for getting or setting a single pin.
If no value is provided, the port will be read and value of specified pin returned.
If a value is provided, the port will be updated and device written to.
Expand All @@ -93,6 +123,11 @@ Valid pin range 0-7 and 10-17.
toggle(pin)
```

Private method for checking the supplied pin number is within valid ranges.
```python
_validate_pin()
```

Private method for loading _port from the device.
```python
_read()
Expand All @@ -103,6 +138,7 @@ Private method for sending _port to the device.
_write()
```


## Properties

Getter reads the port from the device and returns a 16 bit integer.
Expand All @@ -114,9 +150,10 @@ Setter writes a 16-bit integer representing the port to the device.
If you are setting multiple pins at once, use this instead of the pin() method as
this writes the entire 16-bit port to the device once, rather than 16 separate writes.
```python
port = 0xffff
port = 0xFFFF
```


## Ports

* P00-P07 - Port A
Expand All @@ -126,9 +163,16 @@ Why is there no P08 and P09? Because they skipped them when naming the pins,
so that the lest significant digit is 0-7 for both ports. There's still only 16 bits.
Port B pins are just labelled +2.

This chip only has two ports (16 pins). If you only need 8 pins, the
[PCF8574](https://github.com/mcauser/micropython-pcf8574) has a single port (8 pins).


## Interrupts

* INT - Shared by both ports A and B
* INT - Active LOW

Shared by both ports A and B. Triggered by either.


## I2C Interface

Expand All @@ -152,28 +196,44 @@ GND | GND | 3V3 | 0x24
GND | 3V3 | 3V3 | 0x26
3V3 | 3V3 | 3V3 | 0x27


## Parts

* [TinyPICO](https://www.tinypico.com/) $20.00 USD
* [PCF8575](https://www.aliexpress.com/item/4000019921959.html) $2.85 AUD
* [PCF8575](https://www.aliexpress.com/item/32811949623.html) $3.12 AUD
* [PCF8575 blue module](https://s.click.aliexpress.com/e/_DdXNOaN)
* [PCF8575 blue module](https://s.click.aliexpress.com/e/_DFBcPc5)
* [PCF8575 blue module](https://s.click.aliexpress.com/e/_DDFiuqV)
* [PCF8575 red module](https://s.click.aliexpress.com/e/_DmRWVFx)
* [PCF8575 10x SSOP-24](https://s.click.aliexpress.com/e/_DDBKEJP)
* [TinyPICO](https://www.tinypico.com/)


## Connections

TinyPICO | PCF8575 Module
-------- | ----------
21 SDA | SDA
22 SCL | SCL
3V3 | VCC
G | GND
4 | INT (optional)
### TinyPICO ESP32

```python
from machine import SoftI2C, Pin
i2c = SoftI2C(scl=Pin(22), sda=Pin(21))

from machine import I2C, Pin
i2c = I2C(0)
```

PCF8575 Module | TinyPICO (ESP32)
-------------- | ----------------
SDA | 21 (SDA)
SCL | 22 (SCL)
VCC | 3V3
GND | GND
INT (optional) | 4


## Links

* [TinyPICO Getting Started](https://www.tinypico.com/gettingstarted)
* [micropython.org](http://micropython.org)
* [PCF8575 datasheet](docs/pcf8575.pdf)
* [Adafruit Ampy](https://learn.adafruit.com/micropython-basics-load-files-and-run-code/install-ampy)
* [TinyPICO Getting Started](https://www.tinypico.com/gettingstarted)


## License

Expand Down
35 changes: 35 additions & 0 deletions examples/basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# SPDX-FileCopyrightText: 2019 Mike Causer <https://github.com/mcauser>
# SPDX-License-Identifier: MIT

"""
MicroPython PCF8575 Basic example
Toggles pins individually, then all in a single call
"""

import pcf8575
from machine import I2C

# TinyPICO (ESP32)
i2c = I2C(0)

pcf = pcf8575.PCF8575(i2c, 0x20)

# read pin 2
pcf.pin(2)

# set pin 3 HIGH
pcf.pin(3, 1)

# set pin 4 LOW
pcf.pin(4, 0)

# toggle pin 5
pcf.toggle(5)

# set all pins at once with 16-bit int
pcf.port = 0xFF00

# read all pins at once as 16-bit int
print(pcf.port)
# returns 65280 (0xFF00)
42 changes: 25 additions & 17 deletions examples/interrupt/readme.md → examples/interrupts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Using Interrupts
# SPDX-FileCopyrightText: 2019 Mike Causer <https://github.com/mcauser>
# SPDX-License-Identifier: MIT

"""
MicroPython PCF8575 Interrupts example
Any pin that is set HIGH is in input mode and will fire an interrupt on the INT pin
on any rising or falling edge.
Expand All @@ -11,38 +15,42 @@
When released another interrupt will fire, if the previous interrupt has been cleared.
```python
Debouncing
----------
In some cases, debouncing isn't required. Depends on the hardware.
If you add a 100nF capacitor across the push button, it will add a
bit of a buffer and block rapid fires. 100nF blocks for around a second.
A 10nF capacitor blocks for roughly 1/10th of a second.
"""

import pcf8575
from machine import Pin, I2C
from machine import I2C, Pin

# TinyPICO
i2c = I2C(scl=Pin(22), sda=Pin(21))
# TinyPICO (ESP32)
i2c = I2C(0)

pcf = pcf8575.PCF8575(i2c, 0x20)

# set all pins as inputs (HIGH)
pcf.port = 0xffff
pcf.port = 0xFFFF

# attach an IRQ to any mcu pin that can be pulled high.
# INT is open drain, so the mcu pin needs a pull-up
# when the INT pin activates, it will go LOW
p4 = Pin(4, Pin.IN, Pin.PULL_UP)


# a simple interrupt handler
def _handler(p):
print('INT: {}, PORT: {}'.format(p.value(), pcf.port))
print(f"INT: {p.value()}, PORT: {pcf.port}")


# turn on interrupt handler
p4.irq(trigger=Pin.IRQ_RISING|Pin.IRQ_FALLING, handler=_handler)
p4.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=_handler)

# connect pin 7 to GND, interrupt handler will fire

# turn off interrupt handler
p4.irq(None)
```

## Debouncing

In some cases, debouncing isn't required. Depends on the hardware.

If you add a 100nF capacitor across the push button, it will add a
bit of a buffer and block rapid fires. 100nF blocks for around a second.
A 10nF capacitor blocks for roughly 1/10th of a second.
64 changes: 0 additions & 64 deletions examples/leds/readme.md

This file was deleted.

29 changes: 29 additions & 0 deletions examples/leds_sinking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SPDX-FileCopyrightText: 2019 Mike Causer <https://github.com/mcauser>
# SPDX-License-Identifier: MIT

"""
MicroPython PCF8575 LEDs sinking current example
Connect a LED between P01 and 3V3, via a current limiting resistor.
* LED positive anode (long leg) connected to 3V3.
* LED negative cathode (short leg) connected to P01.
Driving a pin LOW will illuminate the LED.
eg. for a red or blue LED, use a 330K and green LED 220K current limiting resistor.
"""

import pcf8575
from machine import I2C

# TinyPICO (ESP32)
i2c = I2C(0)

pcf = pcf8575.PCF8575(i2c, 0x20)

# set P01 LOW and all other pins HIGH
# turn LED on
pcf.port = 0xFFFE

# turn LED off
pcf.port = 0xFFFF
Loading

0 comments on commit 8d4c54e

Please sign in to comment.