Skip to content

Commit d292d57

Browse files
committed
Initial commit
0 parents  commit d292d57

File tree

5 files changed

+289
-0
lines changed

5 files changed

+289
-0
lines changed

LICENSE.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Mike Causer
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# MicroPython PCF8574
2+
3+
A MicroPython library for PCF8574 8-Bit I2C I/O Expander with Interrupt.
4+
5+
![demo](docs/demo.jpg)
6+
7+
The PCF8574 consists of a 8-bit quasi-bidirectional port and an I2C-bus interface.
8+
9+
The device includes latched outputs with high current drive capability for directly driving LEDs.
10+
11+
The interrupt has an open-drain output, which means you need a pull-up on your microcontroller
12+
to detect when the PCF8574 drives it LOW.
13+
14+
When setting a pin HIGH, it acts as both output AND input. The pin internally uses a weak
15+
current-source pull-up to latch output HIGH.
16+
When driven LOW, for example, with a push button, the pin will read as LOW.
17+
18+
An interrupt fires on any rising or falling edge of the pins in input mode (HIGH).
19+
Interrupt is cleared when the pins are changed or the port is read.
20+
21+
At power on, all pins are driven HIGH and can be immediately used as inputs.
22+
23+
Operating voltage: 2.5V - 5.5V
24+
25+
## Example
26+
27+
Copy the file to your device, using ampy, rshell, webrepl or compiling and deploying. eg.
28+
29+
```bash
30+
$ ampy put pcf8574.py
31+
```
32+
33+
**Basic Usage**
34+
35+
```python
36+
import pcf8574
37+
from machine import I2C, Pin
38+
39+
# TinyPICO (ESP32)
40+
i2c = I2C(scl=Pin(22), sda=Pin(21))
41+
pcf = pcf8574.PCF8574(i2c, 0x20)
42+
43+
# read pin 2
44+
pcf.pin(2)
45+
46+
# set pin 3 HIGH
47+
pcf.pin(3, 1)
48+
49+
# set pin 4 LOW
50+
pcf.pin(4, 0)
51+
52+
# toggle pin 5
53+
pcf.toggle(5)
54+
55+
# set all pins at once with 8-bit int
56+
pcf.port = 0xff
57+
58+
# read all pins at once as 8-bit int
59+
pcf.port
60+
```
61+
62+
For more detailed examples, see [examples](/examples).
63+
64+
#### Pins
65+
66+
Pin | Type | Description
67+
:---:|:----:|:----------------------------------------
68+
A0 | I | Address select 1, connect to VCC or GND
69+
A1 | I | Address select 2, connect to VCC or GND
70+
A2 | I | Address select 3, connect to VCC or GND
71+
INT | O | Interrupt output, open drain, active LOW
72+
P00 | I/O | Port A, Pin 0
73+
P01 | I/O | Port A, Pin 1
74+
P02 | I/O | Port A, Pin 2
75+
P03 | I/O | Port A, Pin 3
76+
P04 | I/O | Port A, Pin 4
77+
P05 | I/O | Port A, Pin 5
78+
P06 | I/O | Port A, Pin 6
79+
P07 | I/O | Port A, Pin 7
80+
SDA | I/O | I2C Serial Data, needs pull-up
81+
SCL | I | I2C Serial Clock, needs pull-up
82+
GND | PWR | Ground
83+
VCC | PWR | Supply voltage 3.3-5V
84+
85+
## Methods
86+
87+
Construct with a reference to I2C and set the device address.
88+
Valid address range 0x20-0x27.
89+
If are you not sure what it is, run an `i2c.scan()`.
90+
See below for address selection.
91+
```python
92+
__init__(i2c, address=0x20)
93+
```
94+
95+
Method for getting or setting a single pin.
96+
If no value is provided, the port will be read and value of specified pin returned.
97+
If a value is provided, the port will be updated and device written to.
98+
The port is written to after each call. If you intend to toggle many pins at once, use the
99+
port property instead. See below.
100+
Valid pin range 0-7.
101+
```python
102+
pin(pin, value=None)
103+
```
104+
105+
Method for flipping the value of a single pin.
106+
Valid pin range 0-7.
107+
```python
108+
toggle(pin)
109+
```
110+
111+
Private method for loading _port from the device.
112+
```python
113+
_read()
114+
```
115+
116+
Private method for sending _port to the device.
117+
```python
118+
_write()
119+
```
120+
121+
## Properties
122+
123+
Getter reads the port from the device and returns a 8-bit integer.
124+
```python
125+
port
126+
```
127+
128+
Setter writes an 8-bit integer representing the port to the device.
129+
If you are setting multiple pins at once, use this instead of the pin() method as
130+
this writes the entire 8-bit port to the device once, rather than 8 separate writes.
131+
```python
132+
port = 0xffff
133+
```
134+
135+
## Ports
136+
137+
* P00-P07 - Port A
138+
139+
This chip only has one port. If you need more pins, the [PCF8575](https://github.com/mcauser/micropython-pcf8575) has two ports (another 8 pins).
140+
141+
## Interrupts
142+
143+
* INT - Active LOW
144+
145+
## I2C Interface
146+
147+
If you are using a module, most contain 10k pull-ups on the SCL and SDA lines.
148+
149+
If you are using the PCF8574 chip directly, you'll need to add your own.
150+
151+
### I2C Address
152+
153+
The chip supports I2C addresses 0x20-0x27 and is customisable using address pins A0, A1, A2
154+
155+
A0 | A1 | A2 | I2C Address
156+
----|-----|-----|------------
157+
GND | GND | GND | 0x20 (default)
158+
3V3 | GND | GND | 0x21
159+
GND | 3V3 | GND | 0x22
160+
3V3 | 3V3 | GND | 0x23
161+
GND | GND | 3V3 | 0x24
162+
3V3 | GND | 3V3 | 0x25
163+
GND | 3V3 | 3V3 | 0x26
164+
3V3 | 3V3 | 3V3 | 0x27
165+
166+
## Parts
167+
168+
* [TinyPICO](https://www.tinypico.com/) $20.00 USD
169+
* [PCF8574 10x DIP](https://www.aliexpress.com/item/32933373566.html) $3.00 AUD
170+
* [PCF8574 blue board](https://www.aliexpress.com/item/32224660654.html) $0.83 AUD
171+
* [PCF8574 red board](https://www.aliexpress.com/item/32441163158.html) $0.95 AUD
172+
* [PCF8574 purple board](https://www.aliexpress.com/item/32805562508.html) $0.99 AUD
173+
* [PCF8574 as LCD backpack](https://www.aliexpress.com/item/32654514649.html) $0.98 AUD
174+
175+
## Connections
176+
177+
TinyPICO | PCF8574 Module
178+
-------- | ----------
179+
21 SDA | SDA
180+
22 SCL | SCL
181+
3V3 | VCC
182+
G | GND
183+
4 | INT (optional)
184+
185+
## Links
186+
187+
* [TinyPICO Getting Started](https://www.tinypico.com/gettingstarted)
188+
* [micropython.org](http://micropython.org)
189+
* [PCF8574 datasheet](docs/pcf8574.pdf)
190+
* [Adafruit Ampy](https://learn.adafruit.com/micropython-basics-load-files-and-run-code/install-ampy)
191+
192+
## License
193+
194+
Licensed under the [MIT License](http://opensource.org/licenses/MIT).
195+
196+
Copyright (c) 2019 Mike Causer

docs/demo.jpg

223 KB
Loading

docs/pcf8574.pdf

2.67 MB
Binary file not shown.

pcf8574.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
MicroPython PCF8574 8-Bit I2C I/O Expander with Interrupt
3+
https://github.com/mcauser/micropython-pcf8574
4+
5+
MIT License
6+
Copyright (c) 2019 Mike Causer
7+
8+
Permission is hereby granted, free of charge, to any person obtaining a copy
9+
of this software and associated documentation files (the "Software"), to deal
10+
in the Software without restriction, including without limitation the rights
11+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
copies of the Software, and to permit persons to whom the Software is
13+
furnished to do so, subject to the following conditions:
14+
15+
The above copyright notice and this permission notice shall be included in all
16+
copies or substantial portions of the Software.
17+
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
SOFTWARE.
25+
"""
26+
27+
class PCF8574:
28+
def __init__(self, i2c, address=0x20):
29+
self._i2c = i2c
30+
self._address = address
31+
self._port = bytearray(1)
32+
if i2c.scan().count(address) == 0:
33+
raise OSError('PCF8574 not found at I2C address {:#x}'.format(address))
34+
35+
@property
36+
def port(self):
37+
self._read()
38+
return self._port[0]
39+
40+
@port.setter
41+
def port(self, value):
42+
self._port[0] = value & 0xff
43+
self._write()
44+
45+
def pin(self, pin, value=None):
46+
pin = self.validate_pin(pin)
47+
if value is None:
48+
self._read()
49+
return (self._port[0] >> pin) & 1
50+
else:
51+
if value:
52+
self._port[0] |= (1 << (pin))
53+
else:
54+
self._port[0] &= ~(1 << (pin))
55+
self._write()
56+
57+
def toggle(self, pin):
58+
pin = self.validate_pin(pin)
59+
self._port[0] ^= (1 << (pin))
60+
self._write()
61+
62+
def validate_pin(self, pin):
63+
# pin valid range 0..7
64+
if not 0 <= pin <= 7:
65+
raise ValueError('Invalid pin {}. Use 0-7.'.format(pin))
66+
return pin
67+
68+
def _read(self):
69+
self._i2c.readfrom_into(self._address, self._port)
70+
71+
def _write(self):
72+
self._i2c.writeto(self._address, self._port)

0 commit comments

Comments
 (0)