mirror of
https://github.com/xreef/PCF8574_library.git
synced 2024-08-30 18:12:18 +00:00
Add encoder features
This commit is contained in:
parent
f8d02a8b34
commit
c3b5ad65a1
107
PCF8574.cpp
107
PCF8574.cpp
@ -191,7 +191,7 @@ void PCF8574::begin(){
|
|||||||
// attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), FALLING );
|
// attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), FALLING );
|
||||||
DEBUG_PRINTLN("Using interrupt pin (not all pin is interrupted)");
|
DEBUG_PRINTLN("Using interrupt pin (not all pin is interrupted)");
|
||||||
::pinMode(_interruptPin, INPUT_PULLUP);
|
::pinMode(_interruptPin, INPUT_PULLUP);
|
||||||
attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), CHANGE );
|
attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), FALLING );
|
||||||
}
|
}
|
||||||
|
|
||||||
// inizialize last read
|
// inizialize last read
|
||||||
@ -268,12 +268,111 @@ void PCF8574::pinMode(uint8_t pin, uint8_t mode, uint8_t output_start){
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void PCF8574::encoder(uint8_t pinA, uint8_t pinB){
|
||||||
|
PCF8574::pinMode(pinA, INPUT_PULLUP);
|
||||||
|
PCF8574::pinMode(pinB, INPUT_PULLUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte getBit(byte n, byte position)
|
||||||
|
{
|
||||||
|
return (n >> position) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//int8_t PCF8574::readEncoderValue(uint8_t pinA, uint8_t pinB){
|
||||||
|
// bool changed = false;
|
||||||
|
//
|
||||||
|
// byte offset = 0;
|
||||||
|
//
|
||||||
|
// byte na = PCF8574::digitalRead(pinA);
|
||||||
|
// byte nb = PCF8574::digitalRead(pinB);
|
||||||
|
//
|
||||||
|
// byte encoderPinALast = (encoderValues & bit(pinA));
|
||||||
|
// byte encoderPinBLast = (encoderValues & bit(pinB));
|
||||||
|
//
|
||||||
|
// if ((encoderPinALast!=na || encoderPinBLast!=nb) && (encoderPinALast == LOW) && (na == HIGH)) {
|
||||||
|
// if (nb == LOW) {
|
||||||
|
// offset = - 1;
|
||||||
|
// changed = true;
|
||||||
|
// } else {
|
||||||
|
// offset = + 1;
|
||||||
|
// changed = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// encoderValues = (encoderPinALast!=na)?encoderValues ^ bit(pinA):encoderValues;
|
||||||
|
// encoderValues = (encoderPinBLast!=nb)?encoderValues ^ bit(pinB):encoderValues;
|
||||||
|
//
|
||||||
|
// return offset;
|
||||||
|
//}
|
||||||
|
|
||||||
|
bool PCF8574::checkProgression(byte oldValA, byte oldValB, byte newValA, byte newValB, byte validProgression){
|
||||||
|
bool findOldVal = false;
|
||||||
|
int posFinded = 0;
|
||||||
|
for (int pos = 0; pos<8; pos = pos + 2){
|
||||||
|
if ((oldValB == ((validProgression & bit(pos+1))>0?HIGH:LOW)) && (oldValA == ((validProgression & bit(pos+0))>0?HIGH:LOW)) ){
|
||||||
|
findOldVal = true;
|
||||||
|
posFinded = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!findOldVal) return false;
|
||||||
|
|
||||||
|
posFinded = posFinded + 2;
|
||||||
|
if (posFinded>8) posFinded = 0;
|
||||||
|
|
||||||
|
return ((newValB == ((validProgression & bit(posFinded+1))>0?HIGH:LOW)) && (newValA == ((validProgression & bit(posFinded+0))>0?HIGH:LOW)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PCF8574::readEncoderValue(uint8_t pinA, uint8_t pinB, volatile long *encoderValue){
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
byte na = PCF8574::digitalRead(pinA, true);
|
||||||
|
byte nb = PCF8574::digitalRead(pinB, true);
|
||||||
|
|
||||||
|
byte encoderPinALast = (encoderValues & bit(pinA))>0?HIGH:LOW;
|
||||||
|
byte encoderPinBLast = (encoderValues & bit(pinB))>0?HIGH:LOW;
|
||||||
|
|
||||||
|
if ((encoderPinALast!=na || encoderPinBLast!=nb) && (encoderPinALast == LOW) && (na == HIGH)) {
|
||||||
|
bool vCW = checkProgression(encoderPinALast, encoderPinBLast, na, nb, validCW);
|
||||||
|
bool vCCW = checkProgression(encoderPinALast, encoderPinBLast, na, nb, validCCW);
|
||||||
|
|
||||||
|
if (nb == LOW) {
|
||||||
|
// checkCW(encoderPinALast, encoderPinBLast, na, nb);
|
||||||
|
*encoderValue = *encoderValue - 1;
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
*encoderValue = *encoderValue + 1;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
// if (nb == LOW && vCW) {
|
||||||
|
// // checkCW(encoderPinALast, encoderPinBLast, na, nb);
|
||||||
|
// *encoderValue = *encoderValue - 1;
|
||||||
|
// changed = true;
|
||||||
|
// } else if (vCCW) {
|
||||||
|
// *encoderValue = *encoderValue + 1;
|
||||||
|
// changed = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
encoderValues = (encoderPinALast!=na)?encoderValues ^ bit(pinA):encoderValues;
|
||||||
|
encoderValues = (encoderPinBLast!=nb)?encoderValues ^ bit(pinB):encoderValues;
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t PCF8574::readEncoderValue(uint8_t pinA, uint8_t pinB) {
|
||||||
|
volatile long encoderValue = 0;
|
||||||
|
PCF8574::readEncoderValue(pinA, pinB, &encoderValue);
|
||||||
|
return encoderValue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read value from i2c and bufferize it
|
* Read value from i2c and bufferize it
|
||||||
* @param force
|
* @param force
|
||||||
*/
|
*/
|
||||||
void PCF8574::readBuffer(bool force){
|
void PCF8574::readBuffer(bool force){
|
||||||
if (millis() > PCF8574::lastReadMillis+READ_ELAPSED_TIME || _usingInterrupt || force){
|
if (millis() > PCF8574::lastReadMillis+latency || _usingInterrupt || force){
|
||||||
_wire->requestFrom(_address,(uint8_t)1);// Begin transmission to PCF8574 with the buttons
|
_wire->requestFrom(_address,(uint8_t)1);// Begin transmission to PCF8574 with the buttons
|
||||||
lastReadMillis = millis();
|
lastReadMillis = millis();
|
||||||
if(_wire->available()) // If bytes are available to be recieved
|
if(_wire->available()) // If bytes are available to be recieved
|
||||||
@ -371,7 +470,7 @@ void PCF8574::readBuffer(bool force){
|
|||||||
* @param pin
|
* @param pin
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
uint8_t PCF8574::digitalRead(uint8_t pin){
|
uint8_t PCF8574::digitalRead(uint8_t pin, bool forceReadNow){
|
||||||
uint8_t value = (bit(pin) & readModePullUp)?HIGH:LOW;
|
uint8_t value = (bit(pin) & readModePullUp)?HIGH:LOW;
|
||||||
DEBUG_PRINT("Read pin ");
|
DEBUG_PRINT("Read pin ");
|
||||||
DEBUG_PRINT (pin);
|
DEBUG_PRINT (pin);
|
||||||
@ -392,7 +491,7 @@ uint8_t PCF8574::digitalRead(uint8_t pin){
|
|||||||
}else{
|
}else{
|
||||||
value = LOW;
|
value = LOW;
|
||||||
}
|
}
|
||||||
}else if ((/*(bit(pin) & byteBuffered)<=0 && */millis() > PCF8574::lastReadMillis+READ_ELAPSED_TIME) /*|| _usingInterrupt*/){
|
}else if (forceReadNow || (millis() > PCF8574::lastReadMillis+latency)){
|
||||||
DEBUG_PRINT(" ...Read from buffer... ");
|
DEBUG_PRINT(" ...Read from buffer... ");
|
||||||
_wire->requestFrom(_address,(uint8_t)1);// Begin transmission to PCF8574 with the buttons
|
_wire->requestFrom(_address,(uint8_t)1);// Begin transmission to PCF8574 with the buttons
|
||||||
lastReadMillis = millis();
|
lastReadMillis = millis();
|
||||||
|
30
PCF8574.h
30
PCF8574.h
@ -61,7 +61,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PCF8574_LOW_LATENCY
|
#ifdef PCF8574_LOW_LATENCY
|
||||||
#define READ_ELAPSED_TIME 1
|
#define READ_ELAPSED_TIME 0
|
||||||
#else
|
#else
|
||||||
#define READ_ELAPSED_TIME 10
|
#define READ_ELAPSED_TIME 10
|
||||||
#endif
|
#endif
|
||||||
@ -110,8 +110,10 @@ public:
|
|||||||
void begin();
|
void begin();
|
||||||
void pinMode(uint8_t pin, uint8_t mode, uint8_t output_start = HIGH);
|
void pinMode(uint8_t pin, uint8_t mode, uint8_t output_start = HIGH);
|
||||||
|
|
||||||
|
void encoder(uint8_t pinA, uint8_t pinB);
|
||||||
|
|
||||||
void readBuffer(bool force = true);
|
void readBuffer(bool force = true);
|
||||||
uint8_t digitalRead(uint8_t pin);
|
uint8_t digitalRead(uint8_t pin, bool forceReadNow = false);
|
||||||
#ifndef PCF8574_LOW_MEMORY
|
#ifndef PCF8574_LOW_MEMORY
|
||||||
struct DigitalInput {
|
struct DigitalInput {
|
||||||
uint8_t p0;
|
uint8_t p0;
|
||||||
@ -131,6 +133,17 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
void digitalWrite(uint8_t pin, uint8_t value);
|
void digitalWrite(uint8_t pin, uint8_t value);
|
||||||
|
|
||||||
|
bool readEncoderValue(uint8_t pinA, uint8_t pinB, volatile long *encoderValue);
|
||||||
|
int8_t readEncoderValue(uint8_t pinA, uint8_t pinB);
|
||||||
|
|
||||||
|
int getLatency() const {
|
||||||
|
return latency;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLatency(int latency = READ_ELAPSED_TIME) {
|
||||||
|
this->latency = latency;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t _address;
|
uint8_t _address;
|
||||||
|
|
||||||
@ -163,6 +176,19 @@ private:
|
|||||||
|
|
||||||
byte writeByteBuffered = B00000000;
|
byte writeByteBuffered = B00000000;
|
||||||
|
|
||||||
|
byte encoderValues = B00000000;
|
||||||
|
|
||||||
|
uint8_t prevNextCode = 0;
|
||||||
|
uint16_t store=0;
|
||||||
|
|
||||||
|
int latency = READ_ELAPSED_TIME;
|
||||||
|
|
||||||
|
bool checkProgression(byte oldValA, byte newValA, byte oldValB, byte newValB, byte validProgression);
|
||||||
|
|
||||||
|
// byte validCW = B11100001;
|
||||||
|
// byte validCCW = B01001011;
|
||||||
|
byte validCW = B01001011;
|
||||||
|
byte validCCW = B11100001;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
KeyPressed and leds with interrupt
|
||||||
|
by Mischianti Renzo <http://www.mischianti.org>
|
||||||
|
|
||||||
|
https://www.mischianti.org/2019/01/02/pcf8574-i2c-digital-i-o-expander-fast-easy-usage/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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(0x38, ARDUINO_UNO_INTERRUPTED_PIN, keyPressedOnPCF8574);
|
||||||
|
unsigned long timeElapsed;
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
pcf8574.pinMode(P0, INPUT_PULLUP);
|
||||||
|
pcf8574.pinMode(P1, INPUT_PULLUP);
|
||||||
|
pcf8574.pinMode(P2, INPUT);
|
||||||
|
pcf8574.pinMode(P3, INPUT);
|
||||||
|
|
||||||
|
pcf8574.pinMode(P7, OUTPUT);
|
||||||
|
pcf8574.pinMode(P6, OUTPUT, HIGH);
|
||||||
|
pcf8574.pinMode(P5, OUTPUT);
|
||||||
|
pcf8574.pinMode(P4, OUTPUT, LOW);
|
||||||
|
|
||||||
|
pcf8574.begin();
|
||||||
|
|
||||||
|
timeElapsed = millis();
|
||||||
|
}
|
||||||
|
unsigned long lastSendTime = 0; // last send time
|
||||||
|
unsigned long interval = 4000; // interval between sends
|
||||||
|
|
||||||
|
bool startVal = HIGH;
|
||||||
|
|
||||||
|
bool keyPressed = false;
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if (keyPressed){
|
||||||
|
uint8_t val0 = pcf8574.digitalRead(P0);
|
||||||
|
uint8_t val1 = pcf8574.digitalRead(P1);
|
||||||
|
uint8_t val2 = pcf8574.digitalRead(P2);
|
||||||
|
uint8_t val3 = pcf8574.digitalRead(P3);
|
||||||
|
Serial.print("P0 ");
|
||||||
|
Serial.print(val0);
|
||||||
|
Serial.print(" P1 ");
|
||||||
|
Serial.print(val1);
|
||||||
|
Serial.print(" P2 ");
|
||||||
|
Serial.print(val2);
|
||||||
|
Serial.print(" P3 ");
|
||||||
|
Serial.println(val3);
|
||||||
|
keyPressed= false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (millis() - lastSendTime > interval) {
|
||||||
|
pcf8574.digitalWrite(P7, startVal);
|
||||||
|
if (startVal==HIGH) {
|
||||||
|
startVal = LOW;
|
||||||
|
}else{
|
||||||
|
startVal = HIGH;
|
||||||
|
}
|
||||||
|
lastSendTime = millis();
|
||||||
|
|
||||||
|
Serial.print("P7 ");
|
||||||
|
Serial.println(startVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyPressedOnPCF8574(){
|
||||||
|
// Interrupt called (No Serial no read no wire in this function, and DEBUG disabled on PCF library)
|
||||||
|
keyPressed = true;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* PCF8574 GPIO Port Expand
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* PCF8574 ----- WeMos
|
||||||
|
* A0 ----- GRD
|
||||||
|
* A1 ----- GRD
|
||||||
|
* A2 ----- GRD
|
||||||
|
* VSS ----- GRD
|
||||||
|
* VDD ----- 5V/3.3V
|
||||||
|
* SDA ----- D1(PullUp)
|
||||||
|
* SCL ----- D2(PullUp)
|
||||||
|
* INT ----- INT(PullUp)
|
||||||
|
*
|
||||||
|
* P0 ----------------- ENCODER PIN A
|
||||||
|
* P1 ----------------- ENCODER PIN B
|
||||||
|
* P2 ----------------- ENCODER BUTTON
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "PCF8574.h"
|
||||||
|
|
||||||
|
int encoderPinA = P0;
|
||||||
|
int encoderPinB = P1;
|
||||||
|
|
||||||
|
#define INTERRUPTED_PIN D7
|
||||||
|
|
||||||
|
void ICACHE_RAM_ATTR updateEncoder();
|
||||||
|
|
||||||
|
// initialize library
|
||||||
|
PCF8574 pcf8574(0x38, INTERRUPTED_PIN, updateEncoder);
|
||||||
|
|
||||||
|
volatile long encoderValue = 0;
|
||||||
|
uint8_t encoderButtonVal = HIGH;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin (9600);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// encoder pins
|
||||||
|
pcf8574.pinMode(encoderPinA, INPUT_PULLUP);
|
||||||
|
pcf8574.pinMode(encoderPinB, INPUT_PULLUP);
|
||||||
|
// encoder button
|
||||||
|
pcf8574.pinMode(P2, INPUT_PULLUP);
|
||||||
|
|
||||||
|
// Set low latency with this method or uncomment LOW_LATENCY define in the library
|
||||||
|
// Needed for encoder
|
||||||
|
pcf8574.setLatency(0);
|
||||||
|
|
||||||
|
// Start library
|
||||||
|
pcf8574.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if (changed){
|
||||||
|
Serial.print("ENCODER --> ");
|
||||||
|
Serial.print(encoderValue);
|
||||||
|
Serial.print(" - BUTTON --> ");
|
||||||
|
Serial.println(encoderButtonVal?"HIGH":"LOW");
|
||||||
|
changed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t encoderPinALast = LOW;
|
||||||
|
uint8_t valPrecEncoderButton = LOW;
|
||||||
|
|
||||||
|
void updateEncoder(){
|
||||||
|
// Encoder management
|
||||||
|
uint8_t n = pcf8574.digitalRead(encoderPinA);
|
||||||
|
if ((encoderPinALast == LOW) && (n == HIGH)) {
|
||||||
|
if (pcf8574.digitalRead(encoderPinB) == LOW) {
|
||||||
|
encoderValue--;
|
||||||
|
changed = true; // Chnged the value
|
||||||
|
} else {
|
||||||
|
encoderValue++;
|
||||||
|
changed = true; // Chnged the value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
encoderPinALast = n;
|
||||||
|
|
||||||
|
// Button management
|
||||||
|
encoderButtonVal = pcf8574.digitalRead(P2);
|
||||||
|
if (encoderButtonVal!=valPrecEncoderButton){
|
||||||
|
changed = true; // Chnged the value of button
|
||||||
|
valPrecEncoderButton = encoderButtonVal;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user