0.3.0 rotaryDecoder

This commit is contained in:
Rob Tillaart 2024-02-23 09:44:55 +01:00
parent 586900a05a
commit ba49d8abf0
7 changed files with 120 additions and 41 deletions

View File

@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.3.0] - 2024-02-14
- Fix #10
- add **read1(pin)**
- add **write1(pin, value)** experimental see #10
- made **read8()** and **write8()** public for faster multi pin access
- update readme.md
----
## [0.2.1] - 2024-01-06
- Fix URL in examples
- minor edits

View File

@ -51,36 +51,59 @@ Returns true if the PCF8574 is on the I2C bus.
- **void readInitialState()** read the initial state of the 4 rotary encoders.
Typically called in setup only, or after a sleep e.g. in combination with **setValue()**
- **bool checkChange()** polling to see if one or more RE have changed,
without updating the counters.
without updating the internal counters.
- **void update()** update the internal counters of the RE.
These will add +1 or -1 depending on direction.
The counters will add +1 or -1 depending on rotation direction.
Need to be called before **getValue()** or before **getKeyPressed()**.
Note that **update()** must be called as soon as possible after the interrupt occurs (or as often as possible when polling).
- **void updateSingle()** update the internal counters of the RE.
This will add +1 +2 or +3 as it assumes that the rotary encoder
This will add +1 +2 or +3 as it assumes that the rotary encoder
only goes into a single direction.
#### Counters
- **uint32_t getValue(uint8_r re)** returns the RE counter.
- **void setValue(uint8_r re, uint32_t value = 0)** (re)set the internal counter to value,
default 0
- **void setValue(uint8_r re, uint32_t value = 0)** (re)set the internal counter to value, default 0
#### Read1 - Write1 - experimental
Warning the **write1(pin, value)** might alter the state of the rotary encoder pins.
So this functionality should be tested thoroughly for your application.
Especially the **write()** is **experimental**, see issue #10, feedback welcome.
**Read1()** and **write1()** are functions to access the pins of the PCF8574 that
are not used for rotary encoders.
The user must guard that especially writing the pins do not interfere with the rotary encoder pins.
- **uint8_t read1(uint8_t pin)** reads a single pin (0..7).
Returns HIGH or LOW.
- **bool write1(uint8_t pin, uint8_t value)** writes a single pin (0..7).
Value should be LOW (0) or HIGH (other values).
- **uint8_t read8()** read all pins in one I2C IO action. When one need to access multiple
input pins this is faster but need some bit masking.
- **bool write8(uint8_t value)** writes to multiple pins at once, e.g. to control multiple
LEDs in one IO action. As said before the user must guard not to interfere with the
rotary encoder pins.
#### Debugging
- **int8_t getLastPosition(uint8_r re)** returns last position.
- **int8_t getLastPosition(uint8_r re)** Returns last position.
## Performance
As the decoder is based upon a PCF8574, a I2C device, the performance is affected by the
clock speed of the I2C bus. All four core functions have one call to **\_read8()** which
is the most expensive part.
clock speed of the I2C bus.
All four core functions have one call to **\read8()** which is the most expensive part.
Early tests gave the following indicative times (Arduino UNO) for the **update()**
function (with no updates it is ~8 us faster).
Note that above 500 KHz the gain becomes less while reliability of signal decreases.
(500 KHz is about ~3x faster than 100 KHz in practice.)
Note that above 500 KHz the gain becomes less while reliability of signal decreases.
(500 KHz is about 3x faster than 100 KHz in practice.)
As 400 KHz is a standard I2C clock speed it is the preferred one.
@ -95,20 +118,15 @@ As 400 KHz is a standard I2C clock speed it is the preferred one.
| 700 KHz | 73 | 6 | 8% |
At @400KHz it can update 4 rotary encoders in ~100us.
At 400 KHz it can update 4 rotary encoders in ~100us.
At a 50% update percentage this implies a max of about
5000 **update()** calls per second in theory
5000 **update()** calls per second in theory.
**to be tested in practice**
Note that a high speed drill goes up to 30000 RPM = 500 RPS = 2000 interrupts per second,
assuming 4 pulses == 360°. (not tested)
## Operational
See examples..
## Future
#### Must

View File

@ -15,6 +15,11 @@ updateSingle KEYWORD2
getValue KEYWORD2
setValue KEYWORD2
read1 KEYWORD2
write1 KEYWORD2
read8 KEYWORD2
write8 KEYWORD2
getLastPosition KEYWORD2

View File

@ -1,7 +1,7 @@
{
"name": "rotaryDecoder",
"keywords": "rotary,encoder,PCF8574",
"description": "Arduino library to rotary decoder with a PCF8574\nSupports up to 4 RE's",
"keywords": "rotary,encoder,decoder,PCF8574",
"description": "Arduino library for rotary decoder with a PCF8574\nSupports up to 4 rotary encoders.",
"authors":
[
{
@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/rotaryDecoder.git"
},
"version": "0.2.1",
"version": "0.3.0",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,9 +1,9 @@
name=rotaryDecoder
version=0.2.1
version=0.3.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library to rotary decoder with a PCF8574
paragraph=Supports up to 4 RE's
sentence=Arduino library for rotary decoder with a PCF8574.
paragraph=Supports up to 4 rotary encoders.
category=Data Processing
url=https://github.com/RobTillaart/rotaryDecoder
architectures=*

View File

@ -1,9 +1,9 @@
//
// FILE: rotaryDecoder.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.1
// VERSION: 0.3.0
// DATE: 2021-05-08
// PURPOSE: rotary decoder library for Arduino
// PURPOSE: Arduino library for rotary decoder
// URL: https://github.com/RobTillaart/rotaryDecoder
@ -40,7 +40,7 @@ bool rotaryDecoder::isConnected()
void rotaryDecoder::readInitialState()
{
uint8_t value = _read8();
uint8_t value = read8();
_lastValue = value;
for (uint8_t i = 0; i < _count; i++)
{
@ -52,14 +52,14 @@ void rotaryDecoder::readInitialState()
bool rotaryDecoder::checkChange()
{
uint8_t value = _read8();
uint8_t value = read8();
return (_lastValue != value);
}
bool rotaryDecoder::update()
{
uint8_t value = _read8();
uint8_t value = read8();
if (_lastValue == value)
{
return false;
@ -93,7 +93,7 @@ bool rotaryDecoder::update()
bool rotaryDecoder::updateSingle()
{
uint8_t value = _read8();
uint8_t value = read8();
if (_lastValue == value)
{
return false;
@ -143,21 +143,61 @@ void rotaryDecoder::setValue(uint8_t re, int32_t value)
}
uint8_t rotaryDecoder::getLastPosition(uint8_t re)
/////////////////////////////////////////////////////
//
// READ - WRITE interface
//
uint8_t rotaryDecoder::read1(uint8_t pin)
{
return _lastPos[re];
};
uint8_t mask = 1 << pin;
uint8_t tmp = read8();
return (tmp & mask) > 0 ? HIGH : LOW;
}
bool rotaryDecoder::write1(uint8_t pin, uint8_t value)
{
uint8_t mask = 1 << pin;
uint8_t tmp = read8();
if (value == LOW) tmp &= ~mask;
else tmp |= mask;
return write8(tmp);
}
uint8_t rotaryDecoder::read8()
{
_wire->requestFrom(_address, (uint8_t)1);
uint8_t x = _wire->read();
// Serial.println(x, HEX);
return x;
}
bool rotaryDecoder::write8(uint8_t value)
{
_wire->beginTransmission(_address);
_wire->write(value);
return (_wire->endTransmission() == 0);
}
/////////////////////////////////////////////////////
//
// PRIVATE
// DEBUG
//
uint8_t rotaryDecoder::_read8()
uint8_t rotaryDecoder::getLastPosition(uint8_t re)
{
_wire->requestFrom(_address, (uint8_t)1);
return _wire->read();
return _lastPos[re];
}
/////////////////////////////////////////////////////
//
// PROTECTED
//
// -- END OF FILE --

View File

@ -2,16 +2,16 @@
//
// FILE: rotaryDecoder.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.1
// VERSION: 0.3.0
// DATE: 2021-05-08
// PURPOSE: rotary decoder library for Arduino
// PURPOSE: Arduino library for rotary decoder
// URL: https://github.com/RobTillaart/rotaryDecoder
#include "Arduino.h"
#include "Wire.h"
#define ROTARY_DECODER_LIB_VERSION (F("0.2.1"))
#define ROTARY_DECODER_LIB_VERSION (F("0.3.0"))
class rotaryDecoder
@ -37,17 +37,24 @@ public:
int32_t getValue(uint8_t re);
void setValue(uint8_t re, int32_t value = 0);
// READ - WRITE interface
uint8_t read1(uint8_t pin);
bool write1(uint8_t pin, uint8_t value);
uint8_t read8();
bool write8(uint8_t value);
// DEBUG
uint8_t getLastPosition(uint8_t re);
private:
protected:
uint8_t _count = 0;
uint8_t _lastValue = 0;
uint8_t _lastPos[4] = { 0, 0, 0, 0 };
int32_t _encoder[4] = { 0, 0, 0, 0 };
uint8_t _read8();
uint8_t _address;
TwoWire * _wire;
};