diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d3d505..358ace2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.2.2] - 2024-01-08 +- Update readme with advanced interrupts insights + - add example +- Fix URL in examples +- minor edits + + ## [0.2.1] - 2023-12-29 - Fix #34 change addresses in examples. - add range check to **setAddress()**. diff --git a/LICENSE b/LICENSE index 42604f3..18dfaaf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2023 Rob Tillaart +Copyright (c) 2020-2024 Rob Tillaart Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/PCF8575.cpp b/PCF8575.cpp index 1781d83..b67816a 100644 --- a/PCF8575.cpp +++ b/PCF8575.cpp @@ -2,7 +2,7 @@ // FILE: PCF8575.cpp // AUTHOR: Rob Tillaart // DATE: 2020-07-20 -// VERSION: 0.2.1 +// VERSION: 0.2.2 // PURPOSE: Arduino library for PCF8575 - 16 channel I2C IO expander // URL: https://github.com/RobTillaart/PCF8575 diff --git a/PCF8575.h b/PCF8575.h index 0ca934f..ee836f3 100644 --- a/PCF8575.h +++ b/PCF8575.h @@ -3,7 +3,7 @@ // FILE: PCF8575.h // AUTHOR: Rob Tillaart // DATE: 2020-07-20 -// VERSION: 0.2.1 +// VERSION: 0.2.2 // PURPOSE: Arduino library for PCF8575 - 16 channel I2C IO expander // URL: https://github.com/RobTillaart/PCF8575 @@ -12,7 +12,7 @@ #include "Wire.h" -#define PCF8575_LIB_VERSION (F("0.2.1")) +#define PCF8575_LIB_VERSION (F("0.2.2")) #ifndef PCF8575_INITIAL_VALUE diff --git a/README.md b/README.md index 17a8047..cf06b50 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,6 @@ Arduino library for PCF8575 - 16 channel I2C IO expander. ## Description -Related to the PCF8574 8 channel IO expander library https://github.com/RobTillaart/PCF8574. - The library gives easy control over the 16 pins of the PCF8575 chips. Base address = 0x20 + 0..7 depending on address pins A0..A2. @@ -37,27 +35,63 @@ Be sure to have a well dimensioned power supply. The library allows to read and write both single pins or 16 pins at once. Furthermore some additional functions are implemented that are playful and useful. +Related to the PCF8574 8 channel IO expander library https://github.com/RobTillaart/PCF8574. -#### 0.2.0 Breaking change -Version 0.2.0 introduced a breaking change. -You cannot set the pins in **begin()** any more. -This reduces the dependency of processor dependent Wire implementations. -The user has to call **Wire.begin()** and can optionally set the Wire pins -before calling **begin()**. +#### Interrupts intro +The PCF8575 has an interrupt output line (INT) to notify an MCU that one of the input lines has changed. +This can be used to prevent active polling of the PCF8574, which can be more efficient. -#### Interrupts +From the datasheet: -The PCF8575 has an interrupt output line (INT) to notify an MCU that one of the input lines has changed. -This can be used to prevent active polling of the PCF8575, which can be more efficient. +_An interrupt is generated by any rising or falling edge of the port inputs in the input mode. +After time, (Tiv), INT is valid. Resetting and reactivating the interrupt circuit is achieved +when data on the port is **changed to the original setting** or data is **read from**, or +**written to**, the port that generated the interrupt. +Resetting occurs in the read mode at the acknowledge bit after the rising edge of the SCL signal, +or in the write mode at the acknowledge bit after the high-to-low transition of the SCL signal._ + +So there are three scenarios how the INT is reset. + +1. pins revert to original state (lesser known). +2. read from the device (well known) +3. write to the device (well known) + +This implies that polling the PCF8574 can miss an INT in scenario 1. (see #48) +In practice if you have faster polling than your signals changes this would not +be a problem. E.g. tactile switches and a polling frequency > 100 Hz will work. + + +#### Interrupts library The library cannot handle the PCF8575 interrupts as it has no code for it. -The user should catch the interrupt in his own code and can use the library to see which line has changed. +The user should catch the interrupt in his own code to set a flag and can use +the library to see which line has changed. -There is one example to show how interrupts can be used: +There is one example to show how interrupts can be handled: - PCF8575_interrupt.ino +A more advanced interrupt handler would not set a boolean flag in the interrupt +routine but increase a counter (uint8_t or larger). +Then it would be possible to see that: + +1. an interrupt occurred. (counter > 0) +2. if one or more interrupts are not handled (counter > 1) + +A minimal example that shows catching missed interrupts: + +- **PCF8575_interrupt_advanced.ino** + + +#### 0.2.0 Breaking change + +Version 0.2.0 introduced a breaking change. +You cannot set the pins in **begin()** any more. +This reduces the dependency of processor dependent Wire implementations. +The user has to call **Wire.begin()** and can optionally set the Wire pins +before calling **begin()**. + #### Related @@ -106,13 +140,11 @@ the include of "pcf8575.h" to overrule the default value used with the **begin()** call. -### Constructor +#### Constructor - **PCF8575(uint8_t deviceAddress = 0x20, TwoWire \*wire = &Wire)** Constructor with the optional I2C device address, default 0x20, and the optional Wire interface as parameter. - **bool begin(uint8_t value = PCF8575_INITIAL_VALUE)** set the initial value for the pins and masks. -- **bool begin(int dataPin, int clockPin, uint8_t value = PCF8575_INITIAL_VALUE)** idem, -for the ESP32 where one can choose the I2C pins. - **bool isConnected()** checks if the address is visible on the I2C bus. - **bool setAddress(const uint8_t deviceAddress)** sets the device address after construction. Can be used to switch between PCF8575 modules runtime. Note this corrupts internal buffered values, @@ -122,7 +154,7 @@ Returns true if address can be found on I2C bus. - **uint8_t getAddress()** returns the device address. -### Read and Write +#### Read and Write - **uint16_t read16()** reads all 16 pins at once. This one does the actual reading. - **uint8_t read(uint8_t pin)** reads a single pin; pin = 0..15. @@ -133,7 +165,7 @@ in the class this is faster than reread the pins. - **uint16_t valueOut()** returns the last written data. -### Button +#### Button The **"button"** functions are to be used when you mix input and output on one IC. It does not change / affect the pins used for output by masking these. @@ -150,7 +182,7 @@ Note this can be a subset of the pins set with **setButtonMask()** if one wants Background - https://github.com/RobTillaart/Arduino/issues/38 -### Special +#### Special - **void toggle(uint8_t pin)** toggles a single pin. - **void toggleMask(uint16_t mask)** toggles a selection of pins, @@ -164,7 +196,7 @@ Fills the lower lines with zero's. - **void reverse()** reverse the "bit pattern" of the lines, swapping pin 15 with 0, 14 with 1, 13 with 2 etc.. -### Select +#### Select Some convenience wrappers. @@ -178,7 +210,7 @@ This can typical be used to implement a VU meter. - **void selectAll()** sets all pins to HIGH. -### Miscellaneous +#### Miscellaneous - **int lastError()** returns the last error from the lib. (see .h file). @@ -210,20 +242,19 @@ It is advised to use pull-up or pull-down resistors so the lines have a defined #### Must - update documentation. - +- keep in sync with pcf8574 (as far as meaningful) #### Should -- keep in sync with pcf8574 (as far as meaningful) - verify difference between PCF8575 and PCF8575C version- see #39 #### Could -- **value()** => **lastRead16()** ?? - +- move code to .cpp #### Wont +- **value()** => **lastRead16()** ## Support diff --git a/examples/PCF8575_Wire2/.arduino-ci.yml b/examples/PCF8575_Wire1/.arduino-ci.yml similarity index 100% rename from examples/PCF8575_Wire2/.arduino-ci.yml rename to examples/PCF8575_Wire1/.arduino-ci.yml diff --git a/examples/PCF8575_Wire2/PCF8575_Wire2.ino b/examples/PCF8575_Wire1/PCF8575_Wire1.ino similarity index 93% rename from examples/PCF8575_Wire2/PCF8575_Wire2.ino rename to examples/PCF8575_Wire1/PCF8575_Wire1.ino index 9bce536..e9a82a5 100644 --- a/examples/PCF8575_Wire2/PCF8575_Wire2.ino +++ b/examples/PCF8575_Wire1/PCF8575_Wire1.ino @@ -1,15 +1,43 @@ // -// FILE: PCF8575_Wire2.ino +// FILE: PCF8575_Wire1.ino // AUTHOR: Rob Tillaart // DATE: 2021-01-03 // PURPOSE: demo +// URL: https://github.com/RobTillaart/PCF8575 #include "PCF8575.h" // adjust addresses if needed PCF8575 PCF(0x21, &Wire1); // or Wire2 if supported - + + +void doHigh() +{ + PCF.write(4, HIGH); + int x = PCF.read16(); + Serial.print("Read "); + Serial.println(x, HEX); +} + + +void doLow() +{ + PCF.write(4, LOW); + int x = PCF.read16(); + Serial.print("Read "); + Serial.println(x, HEX); +} + + +void doToggle() +{ + PCF.toggle(4); + int x = PCF.read16(); + Serial.print("Read "); + Serial.println(x, HEX); +} + void setup() { @@ -50,32 +78,5 @@ void loop() } -void doHigh() -{ - PCF.write(4, HIGH); - int x = PCF.read16(); - Serial.print("Read "); - Serial.println(x, HEX); -} - - -void doLow() -{ - PCF.write(4, LOW); - int x = PCF.read16(); - Serial.print("Read "); - Serial.println(x, HEX); -} - - -void doToggle() -{ - PCF.toggle(4); - int x = PCF.read16(); - Serial.print("Read "); - Serial.println(x, HEX); -} - - // -- END OF FILE -- diff --git a/examples/PCF8575_array/PCF8575_array.ino b/examples/PCF8575_array/PCF8575_array.ino index 24b913e..a75d84d 100644 --- a/examples/PCF8575_array/PCF8575_array.ino +++ b/examples/PCF8575_array/PCF8575_array.ino @@ -3,6 +3,7 @@ // AUTHOR: Rob Tillaart // DATE: 2021-12-13 // PURPOSE: demo array of PCF - not tested +// URL: https://github.com/RobTillaart/PCF8575 #include "PCF8575.h" diff --git a/examples/PCF8575_interrupt/PCF8575_interrupt.ino b/examples/PCF8575_interrupt/PCF8575_interrupt.ino index 76cf969..e5b8022 100644 --- a/examples/PCF8575_interrupt/PCF8575_interrupt.ino +++ b/examples/PCF8575_interrupt/PCF8575_interrupt.ino @@ -3,6 +3,7 @@ // AUTHOR: Rob Tillaart // DATE: 2021-01-03 // PURPOSE: test PCF8575 library +// URL: https://github.com/RobTillaart/PCF8575 // // TEST SETUP // Connect INT pin of the PCF8575 to UNO pin 2 diff --git a/examples/PCF8575_interrupt_advanced/PCF8575_interrupt_advanced.ino b/examples/PCF8575_interrupt_advanced/PCF8575_interrupt_advanced.ino new file mode 100644 index 0000000..dde421d --- /dev/null +++ b/examples/PCF8575_interrupt_advanced/PCF8575_interrupt_advanced.ino @@ -0,0 +1,74 @@ +// +// FILE: PCF8575_interrupt_advanced.ino +// AUTHOR: Rob Tillaart +// DATE: 2021-01-03 +// PURPOSE: test PCF8575 library +// URL: https://github.com/RobTillaart/PCF8575 +// +// TEST SETUP +// Connect INT pin of the PCF8575 to UNO pin 2 +// +// (from figure 4 datasheet +// Place a pull up resistor 4K7 between pin and 5V +// Place a capacitor 10-400 pF between pin and GND + + +#include "PCF8575.h" + +PCF8575 PCF(0x20); + + +//////////////////////////////////// +// +// INTERRUPT ROUTINE + FLAG +// +const int IRQPIN = 2; + +volatile bool flag = false; + +void pcf_irq() +{ + flag = true; +} + + +//////////////////////////////////// +// +// MAIN CODE +// +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("PCF8575_LIB_VERSION:\t"); + Serial.println(PCF8575_LIB_VERSION); + + Wire.begin(); + + PCF.begin(); + + pinMode(IRQPIN, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(IRQPIN), pcf_irq, FALLING); +} + + +void loop() +{ + uint32_t now = millis(); + if (flag) + { + flag = false; + uint16_t x = PCF.read16(); + Serial.print("READ:\t"); + Serial.print('\t'); + Serial.print(now); + Serial.print('\t'); + Serial.println(x, HEX); + } + // do other things here + delay(10); +} + + +// -- END OF FILE -- + diff --git a/examples/PCF8575_isConnected/PCF8575_isConnected.ino b/examples/PCF8575_isConnected/PCF8575_isConnected.ino index eb33766..a59a35b 100644 --- a/examples/PCF8575_isConnected/PCF8575_isConnected.ino +++ b/examples/PCF8575_isConnected/PCF8575_isConnected.ino @@ -3,6 +3,7 @@ // AUTHOR: Rob Tillaart // DATE: 2021-01-03 // PURPOSE: demo device detection +// URL: https://github.com/RobTillaart/PCF8575 #include "PCF8575.h" diff --git a/examples/PCF8575_performance/PCF8575_performance.ino b/examples/PCF8575_performance/PCF8575_performance.ino index 52bccaa..6051b09 100644 --- a/examples/PCF8575_performance/PCF8575_performance.ino +++ b/examples/PCF8575_performance/PCF8575_performance.ino @@ -3,6 +3,7 @@ // AUTHOR: Rob Tillaart // DATE: 2021-01-24 // PURPOSE: test PCF8575 library +// URL: https://github.com/RobTillaart/PCF8575 #include "PCF8575.h" @@ -25,21 +26,31 @@ void setup() PCF.begin(); Serial.println(PCF.isConnected()); + delay(100); // time to flush Serial - for (long clk = 100000; clk < 500000; clk += 50000) + + for (long clk = 100000; clk < 600000; clk += 50000) { - Serial.println(clk); + // setup and measure Wire.setClock(clk); start = micros(); x = PCF.read16(); stop = micros(); + + // output results + Serial.println(clk); Serial.print("Read:\t"); - Serial.println(stop - start); + Serial.print(stop - start); + Serial.print("\t"); + Serial.println(x); // keep build CI compiler happy delay(1000); + // measure start = micros(); PCF.write16(0xFFFF); stop = micros(); + + // output results Serial.print("Write:\t "); Serial.println(stop - start); delay(1000); diff --git a/examples/PCF8575_select/PCF8575_select.ino b/examples/PCF8575_select/PCF8575_select.ino index b487ed5..ecdb269 100644 --- a/examples/PCF8575_select/PCF8575_select.ino +++ b/examples/PCF8575_select/PCF8575_select.ino @@ -3,6 +3,7 @@ // AUTHOR: Rob Tillaart // DATE: 2022-06-18 // PURPOSE: demo PCF8575 library select functions +// URL: https://github.com/RobTillaart/PCF8575 #include "PCF8575.h" diff --git a/examples/PCF8575_test1/PCF8575_test1.ino b/examples/PCF8575_test1/PCF8575_test1.ino index 076c867..3b8b889 100644 --- a/examples/PCF8575_test1/PCF8575_test1.ino +++ b/examples/PCF8575_test1/PCF8575_test1.ino @@ -3,6 +3,7 @@ // AUTHOR: Rob Tillaart // DATE: 2021-01-03 // PURPOSE: demo +// URL: https://github.com/RobTillaart/PCF8575 #include "PCF8575.h" diff --git a/examples/PCF8575_test2/PCF8575_test2.ino b/examples/PCF8575_test2/PCF8575_test2.ino index 20d95bb..edcad17 100644 --- a/examples/PCF8575_test2/PCF8575_test2.ino +++ b/examples/PCF8575_test2/PCF8575_test2.ino @@ -3,6 +3,7 @@ // AUTHOR: Rob Tillaart // DATE: 2021-01-03 // PURPOSE: demo rotateLeft, -Right and toggleMask +// URL: https://github.com/RobTillaart/PCF8575 #include "PCF8575.h" diff --git a/library.json b/library.json index 2b1529d..5140602 100644 --- a/library.json +++ b/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/PCF8575.git" }, - "version": "0.2.1", + "version": "0.2.2", "license": "MIT", "frameworks": "*", "platforms": "*", diff --git a/library.properties b/library.properties index 03ff577..c0678c1 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=PCF8575 -version=0.2.1 +version=0.2.2 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for PCF8575 - 16 channel I2C IO expander