First commit

This commit is contained in:
Renzo 2017-11-13 21:44:50 +01:00
commit 7d7ba7ea57
16 changed files with 3072 additions and 0 deletions

11
.project Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>PCF8574_library</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Renzo Mischianti
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2439
PCF8574.Doxyfile Normal file

File diff suppressed because it is too large Load Diff

276
PCF8574.cpp Normal file
View File

@ -0,0 +1,276 @@
#include "PCF8574.h"
#include "Wire.h"
/**
* Constructor
* @param address: i2c address
*/
PCF8574::PCF8574(uint8_t address){
_address = address;
};
/**
* Construcor
* @param address: i2c address
* @param interruptPin: pin to set interrupt
* @param interruptFunction: function to call when interrupt raised
*/
PCF8574::PCF8574(uint8_t address, uint8_t interruptPin, void (*interruptFunction)() ){
_address = address;
_interruptPin = interruptPin;
_interruptFunction = interruptFunction;
_usingInterrupt = true;
};
#ifndef __AVR
/**
* Constructor
* @param address: i2c address
* @param sda: sda pin
* @param scl: scl pin
*/
PCF8574::PCF8574(uint8_t address, uint8_t sda, uint8_t scl){
_address = address;
_sda = sda;
_scl = scl;
};
/**
* Constructor
* @param address: i2c address
* @param sda: sda pin
* @param scl: scl pin
* @param interruptPin: pin to set interrupt
* @param interruptFunction: function to call when interrupt raised
*/
PCF8574::PCF8574(uint8_t address, uint8_t sda, uint8_t scl, uint8_t interruptPin, void (*interruptFunction)() ){
_address = address;
_sda = sda;
_scl = scl;
_interruptPin = interruptPin;
_interruptFunction = interruptFunction;
_usingInterrupt = true;
};
#endif
/**
* wake up i2c controller
*/
void PCF8574::begin(){
#ifndef __AVR
Wire.begin(_sda, _scl);
#else
// Default pin for AVR some problem on software emulation
// #define SCL_PIN _scl
// #define SDA_PIN _sda
Wire.begin();
#endif
// Che if there are pins to set low
if (writeMode>0 || readMode>0){
DEBUG_PRINTLN("Set write mode");
Wire.beginTransmission(_address);
DEBUG_PRINT(" ");
DEBUG_PRINT("usedPin pin ");
byte usedPin = writeMode | readMode;
DEBUG_PRINTLN( ~usedPin, BIN);
Wire.write(~usedPin);
DEBUG_PRINTLN("Start end trasmission if stop here check pullup resistor.");
Wire.endTransmission();
}
// If using interrupt set interrupt value to pin
if (_usingInterrupt){
DEBUG_PRINTLN("Using interrupt pin (not all pin is interrupted)");
::pinMode(_interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), FALLING );
}
// inizialize last read
lastReadMillis = millis();
}
/**
* Set if fin is OUTPUT or INPUT
* @param pin: pin to set
* @param mode: mode, supported only INPUT or OUTPUT (to semplify)
*/
void PCF8574::pinMode(uint8_t pin, uint8_t mode){
DEBUG_PRINT("Set pin ");
DEBUG_PRINT(pin);
DEBUG_PRINT(" as ");
DEBUG_PRINTLN(mode);
if (mode == OUTPUT){
writeMode = writeMode | bit(pin);
readMode = readMode & ~bit(pin);
DEBUG_PRINT("writeMode: ");
DEBUG_PRINT(writeMode, BIN);
DEBUG_PRINT("readMode: ");
DEBUG_PRINTLN(readMode, BIN);
}else if (mode == INPUT){
writeMode = writeMode & ~bit(pin);
readMode = readMode | bit(pin);
DEBUG_PRINT("writeMode: ");
DEBUG_PRINT(writeMode, BIN);
DEBUG_PRINT("readMode: ");
DEBUG_PRINTLN(readMode, BIN);
}
else{
DEBUG_PRINTLN("Mode non supported by PCF8574")
}
DEBUG_PRINT("Write mode: ");
DEBUG_PRINTLN(writeMode, BIN);
};
/**
* Read value from i2c and bufferize it
* @param force
*/
void PCF8574::readBuffer(bool force){
if (millis() > PCF8574::lastReadMillis+READ_ELAPSED_TIME || _usingInterrupt || force){
Wire.requestFrom(_address,(uint8_t)1);// Begin transmission to PCF8574 with the buttons
lastReadMillis = millis();
if(Wire.available()) // If bytes are available to be recieved
{
byte iInput = Wire.read();// Read a byte
if ((iInput & readMode)>0){
byteBuffered = byteBuffered | (byte)iInput;
}
}
}
}
/**
* Read value of all INPUT pin
* Debounce read more fast than 10millis, non managed for interrupt mode
* @return
*/
PCF8574::DigitalInput PCF8574::digitalReadAll(void){
DEBUG_PRINTLN("Read from buffer");
Wire.requestFrom(_address,(uint8_t)1);// Begin transmission to PCF8574 with the buttons
lastReadMillis = millis();
if(Wire.available()) // If bytes are available to be recieved
{
DEBUG_PRINTLN("Data ready");
byte iInput = Wire.read();// Read a byte
if ((iInput & readMode)>0){
DEBUG_PRINT("Input ");
DEBUG_PRINTLN((byte)iInput, BIN);
byteBuffered = byteBuffered | (byte)iInput;
DEBUG_PRINT("byteBuffered ");
DEBUG_PRINTLN(byteBuffered, BIN);
}
}
DEBUG_PRINT("Buffer value ");
DEBUG_PRINTLN(byteBuffered, BIN);
if (bit(0)&readMode>0) digitalInput.p0 = (byteBuffered&bit(0)>0)?HIGH:LOW;
if (bit(1)&readMode>0) digitalInput.p1 = (byteBuffered&bit(1)>0)?HIGH:LOW;
if (bit(2)&readMode>0) digitalInput.p2 = (byteBuffered&bit(2)>0)?HIGH:LOW;
if (bit(3)&readMode>0) digitalInput.p3 = (byteBuffered&bit(3)>0)?HIGH:LOW;
if (bit(4)&readMode>0) digitalInput.p4 = (byteBuffered&bit(4)>0)?HIGH:LOW;
if (bit(5)&readMode>0) digitalInput.p5 = (byteBuffered&bit(5)>0)?HIGH:LOW;
if (bit(6)&readMode>0) digitalInput.p6 = (byteBuffered&bit(6)>0)?HIGH:LOW;
if (bit(7)&readMode>0) digitalInput.p7 = (byteBuffered&bit(7)>0)?HIGH:LOW;
if (readMode & byteBuffered>0){
byteBuffered = ~readMode & byteBuffered;
DEBUG_PRINT("Buffer hight value readed set readed ");
DEBUG_PRINTLN(byteBuffered, BIN);
}
DEBUG_PRINT("Return value ");
return digitalInput;
};
/**
* Read value of specified pin
* Debounce read more fast than 10millis, non managed for interrupt mode
* @param pin
* @return
*/
uint8_t PCF8574::digitalRead(uint8_t pin){
uint8_t value = LOW;
DEBUG_PRINT("Read pin ");
DEBUG_PRINTLN(pin);
// Check if pin already HIGH than read and prevent reread of i2c
if ((bit(pin) & byteBuffered)>0){
DEBUG_PRINTLN("Pin already up");
value = HIGH;
}else if ((/*(bit(pin) & byteBuffered)<=0 && */millis() > PCF8574::lastReadMillis+READ_ELAPSED_TIME) /*|| _usingInterrupt*/){
DEBUG_PRINTLN("Read from buffer");
Wire.requestFrom(_address,(uint8_t)1);// Begin transmission to PCF8574 with the buttons
lastReadMillis = millis();
if(Wire.available()) // If bytes are available to be recieved
{
DEBUG_PRINTLN("Data ready");
byte iInput = Wire.read();// Read a byte
if ((iInput & readMode)>0){
DEBUG_PRINT("Input ");
DEBUG_PRINTLN((byte)iInput, BIN);
byteBuffered = byteBuffered | (byte)iInput;
DEBUG_PRINT("byteBuffered ");
DEBUG_PRINTLN(byteBuffered, BIN);
if ((bit(pin) & byteBuffered)>0){
value = HIGH;
}
}
}
}
DEBUG_PRINT("Buffer value ");
DEBUG_PRINTLN(byteBuffered, BIN);
// If HIGH set to low to read buffer only one time
if (value==HIGH){
byteBuffered = ~bit(pin) & byteBuffered;
DEBUG_PRINT("Buffer hight value readed set readed ");
DEBUG_PRINTLN(byteBuffered, BIN);
}
DEBUG_PRINT("Return value ");
DEBUG_PRINTLN(value);
return value;
};
/**
* Write on pin
* @param pin
* @param value
*/
void PCF8574::digitalWrite(uint8_t pin, uint8_t value){
DEBUG_PRINTLN("Begin trasmission");
Wire.beginTransmission(_address); //Begin the transmission to PCF8574
if (value==HIGH){
writeByteBuffered = writeByteBuffered | bit(pin);
}else{
writeByteBuffered = writeByteBuffered & ~bit(pin);
}
DEBUG_PRINT("Write data ");
DEBUG_PRINT(writeByteBuffered, BIN);
DEBUG_PRINT(" for pin ");
DEBUG_PRINT(pin);
DEBUG_PRINT(" bin value ");
DEBUG_PRINT(bit(pin), BIN);
DEBUG_PRINT(" value ");
DEBUG_PRINTLN(value);
writeByteBuffered = writeByteBuffered & writeMode;
Wire.write(writeByteBuffered);
DEBUG_PRINTLN("Start end trasmission if stop here check pullup resistor.");
Wire.endTransmission();
};

101
PCF8574.h Normal file
View File

@ -0,0 +1,101 @@
/** \mainpage Thermistor library
*
* MIT license
* written by Renzo Mischianti
*/
#ifndef Thermistor_h
#define Thermistor_h
#include "Wire.h"
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
// Uncomment to enable printing out nice debug messages.
// #define PCF8574_DEBUG
// Define where debug output will be printed.
#define DEBUG_PRINTER Serial
// Setup debug printing macros.
#ifdef PCF8574_DEBUG
#define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
#define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
#else
#define DEBUG_PRINT(...) {}
#define DEBUG_PRINTLN(...) {}
#endif
#define READ_ELAPSED_TIME 10
//#define P0 B00000001
//#define P1 B00000010
//#define P2 B00000100
//#define P3 B00001000
//#define P4 B00010000
//#define P5 B00100000
//#define P6 B01000000
//#define P7 B10000000
//
#define P0 0
#define P1 1
#define P2 2
#define P3 3
#define P4 4
#define P5 5
#define P6 6
#define P7 7
#include <math.h>
class PCF8574 {
public:
struct DigitalInput {
uint8_t p0;
uint8_t p1;
uint8_t p2;
uint8_t p3;
uint8_t p4;
uint8_t p5;
uint8_t p6;
uint8_t p7;
} digitalInput;
PCF8574(uint8_t address);
PCF8574(uint8_t address, uint8_t sda, uint8_t scl);
PCF8574(uint8_t address, uint8_t interruptPin, void (*interruptFunction)() );
PCF8574(uint8_t address, uint8_t sda, uint8_t scl, uint8_t interruptPin, void (*interruptFunction)());
void begin();
void pinMode(uint8_t pin, uint8_t mode);
void readBuffer(bool force = true);
uint8_t digitalRead(uint8_t pin);
DigitalInput digitalReadAll(void);
void digitalWrite(uint8_t pin, uint8_t value);
private:
uint8_t _address;
uint8_t _sda = SDA;
uint8_t _scl = SCL;
bool _usingInterrupt = false;
uint8_t _interruptPin = 2;
void (*_interruptFunction)(){};
byte writeMode = B00000000;
byte readMode = B00000000;
byte byteBuffered = B00000000;
unsigned long lastReadMillis = 0;
byte writeByteBuffered = B00000000;
};
#endif

80
README.md Normal file
View File

@ -0,0 +1,80 @@
Library to use i2c analog IC with arduino and esp8266. Can read and write digital value with only 2 wire (perfect for ESP-01).
Tutorial:
To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder PCF8574. Check that the PCF8574 folder contains `PCF8574\\.cpp` and `PCF8574.h`. Place the DHT library folder your `<arduinosketchfolder>/libraries/` folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.
# Reef complete PCF8574 digital input and output expander with i2c bus.
I try to simplify the use of this IC, with a minimal set of operation.
Constructor:
you must pas the address of i2c (to check the adress use this guide [I2cScanner](https://playground.arduino.cc/Main/I2cScanner))
```cpp
PCF8574(uint8_t address);
```
for esp8266 if you want specify SDA e SCL pin use this:
```cpp
PCF8574(uint8_t address, uint8_t sda, uint8_t scl);
```
You must set input/output mode:
```cpp
pcf8574.pinMode(P0, OUTPUT);
pcf8574.pinMode(P1, INPUT);
pcf8574.pinMode(P2, INPUT);
```
then IC as you can see in the image have 8 digital input/output:
![PCF8574 schema](https://github.com/xreef/PCF8574_library/blob/master/resources/PCF8574-pins.gif)
So to read all analog input in one trasmission you can do (even if I use a 10millis debounce time to prevent too much read from i2c):
```cpp
PCF8574::DigitalInput di = PCF8574.digitalReadAll();
Serial.print(di.p0);
Serial.print(" - ");
Serial.print(di.p1);
Serial.print(" - ");
Serial.print(di.p2);
Serial.print(" - ");
Serial.println(pi.p3);
```
if you want read a single input:
```cpp
int p1Digital = PCF8574.digitalRead(P1); // read P1
```
If you want write a digital value you must do:
```cpp
PCF8574.digitalWrite(P1, HIGH);
```
or:
```cpp
PCF8574.digitalWrite(P1, LOW);
```
You can also use interrupt pin:
You must initialize the pin and the function to call when interrupt raised from PCF8574
```cpp
// Function interrupt
void keyPressedOnPCF8574();
// Set i2c address
PCF8574 pcf8574(0x39, ARDUINO_UNO_INTERRUPT_PIN, keyPressedOnPCF8574);
```
Remember you can't use Serial or Wire on interrupt function.
The better way is to set only a variable to read on loop:
```cpp
void keyPressedOnPCF8574(){
// Interrupt called (No Serial no read no wire in this function, and DEBUG disabled on PCF library)
keyPressed = true;
}
```
For the examples I use this wire schema on breadboard:
![Breadboard](https://github.com/xreef/PCF8574_library/blob/master/resources/testReadWriteLedButton_bb.png)

View File

@ -0,0 +1,23 @@
#include "Arduino.h"
#include "PCF8574.h"
// Set i2c address
PCF8574 pcf8574(0x39);
void setup()
{
Serial.begin(115200);
// Set pinMode to OUTPUT
pcf8574.pinMode(P0, OUTPUT);
pcf8574.pinMode(P1, INPUT);
pcf8574.begin();
}
void loop()
{
pcf8574.digitalWrite(P0, HIGH);
delay(1000);
pcf8574.digitalWrite(P0, LOW);
delay(1000);
}

View File

@ -0,0 +1,22 @@
#include "Arduino.h"
#include "PCF8574.h"
// Set i2c address
PCF8574 pcf8574(0x39);
unsigned long timeElapsed;
void setup()
{
Serial.begin(115200);
pcf8574.pinMode(P0, OUTPUT);
pcf8574.pinMode(P1, INPUT);
pcf8574.begin();
}
void loop()
{
uint8_t val = pcf8574.digitalRead(P1);
if (val==HIGH) Serial.println("KEY PRESSED");
delay(50);
}

View File

@ -0,0 +1,29 @@
#include "Arduino.h"
#include "PCF8574.h"
// Set i2c address
PCF8574 pcf8574(0x39);
unsigned long timeElapsed;
void setup()
{
Serial.begin(115200);
pcf8574.pinMode(P0, OUTPUT);
pcf8574.pinMode(P1, INPUT);
pcf8574.begin();
timeElapsed = millis();
}
void loop()
{
// Read and store on buffer all input (pinMode) that are going HIGHT
pcf8574.readBuffer();
if (millis()>timeElapsed+2000){
// read value on buffer than reset value for that pin
uint8_t val = pcf8574.digitalRead(P1);
if (val==HIGH) Serial.println("KEY PRESSED STORED ON BUFFER, NOW READED AND RESETTED.");
timeElapsed = millis();
}
}

View File

@ -0,0 +1,40 @@
#include "Arduino.h"
#include "PCF8574.h"
// For arduino uno only pin 1 and 2 are interrupted
#define ARDUINO_UNO_INTERRUPTED_PIN 2
// Function interrupt
void keyPressedOnPCF8574();
// Set i2c address
PCF8574 pcf8574(0x39, ARDUINO_UNO_INTERRUPTED_PIN, keyPressedOnPCF8574);
unsigned long timeElapsed;
void setup()
{
Serial.begin(115200);
pcf8574.pinMode(P0, OUTPUT);
pcf8574.pinMode(P1, INPUT);
pcf8574.begin();
timeElapsed = millis();
}
bool keyPressed = false;
void loop()
{
if (keyPressed){
uint8_t val = pcf8574.digitalRead(P1);
Serial.print("READ VALUE FROM PCF ");
Serial.println(val);
keyPressed= false;
}
}
void keyPressedOnPCF8574(){
// Interrupt called (No Serial no read no wire in this function, and DEBUG disabled on PCF library)
keyPressed = true;
}

21
keywords.txt Normal file
View File

@ -0,0 +1,21 @@
###########################################
# Syntax Coloring Map For Thermistor-library
###########################################
###########################################
# Datatypes (KEYWORD1)
###########################################
PCF8591 KEYWORD1
###########################################
# Methods and Functions (KEYWORD2)
###########################################
begin KEYWORD2
AnalogInput KEYWORD2
analogRead KEYWORD2
analogWrite KEYWORD2
voltageWrite KEYWORD2
voltageRead KEYWORD2

9
library.properties Normal file
View File

@ -0,0 +1,9 @@
name=PCF8574 library
version=0.9.0
author=Reef
maintainer=Renzo Mischianti <renzo.mischianti@gmail.com>
sentence=Arduino/ESP8266 library for PCF8574
paragraph=Arduino/ESP8266 library for PCF8574
category=Sensors
url=https://github.com/xreef/
architectures=*

BIN
resources/PCF8574-pins.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
resources/pcf8574.pdf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB