Skip to content

Commit 71b4275

Browse files
committed
refactor and sync rotaryDecoder8
1 parent ea5c3e0 commit 71b4275

File tree

10 files changed

+157
-60
lines changed

10 files changed

+157
-60
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

88

9+
## [0.4.0] - 2025-01-06
10+
- refactor to sync with rotaryDecoder8 (PCF8575)
11+
- add **reset()**
12+
- add **getRECount()**
13+
- update readme.md
14+
- update unit test
15+
16+
----
17+
918
## [0.3.1] - 2024-06-20
1019
- changed **uint8_t readInitialState()** to return the read state.
1120
- changed **bool setValue(uint8_t re, int32_t value = 0)** to return false

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2021-2024 Rob Tillaart
3+
Copyright (c) 2021-2025 Rob Tillaart
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,92 +16,111 @@ Arduino library for a PCF8574 based rotary decoder - supports 4 rotary encoders.
1616

1717
## Description
1818

19-
This experimental library uses a PCF8574 to read the pulses of a rotary encoder.
19+
This library uses a PCF8574 to read the pulses of a rotary encoder.
2020
As a PCF8574 has 8 lines up to 4 decoders can be read over I2C.
2121
The PCF interrupt line can be used to detect changes in the position of the encoders.
2222

2323
If less than 4 rotary encoders are connected one should use the lower bit lines as the
2424
library assumes these are used. Furthermore it is advised to connect the free PCF8574
2525
pins to GND so you will not get unintended interrupts.
2626

27+
Note: This library works (limited) with the PCF8575.
2728

28-
#### Related
29+
As always, feedback is welcome.
2930

31+
32+
### Related
33+
34+
- https://github.com/RobTillaart/rotaryDecoder
3035
- https://github.com/RobTillaart/rotaryDecoderSwitch
36+
- https://github.com/RobTillaart/rotaryDecoder8
37+
- https://github.com/RobTillaart/rotaryDecoderSwitch5
3138
- https://github.com/RobTillaart/PCF8574
39+
- https://github.com/RobTillaart/PCF8575
3240

3341

3442
## Interface
3543

3644
```cpp
37-
#include "rotaryEncoder.h"
45+
#include "rotaryDecoder.h"
3846
```
3947

40-
#### Constructor
48+
### Constructor
4149

4250
- **rotaryDecoder(const int8_t address, TwoWire \*wire = Wire)**
4351
constructor to set the address and optional the Wire bus.
4452
- **bool begin(uint8_t count = 4)** UNO ea. initializes the class.
4553
count is the number of rotary encoders connected. (Max 4 per PCF8574)
4654
Returns true if the PCF8574 is on the I2C bus.
4755
- **bool isConnected()** returns true if the PCF8574 is on the I2C bus.
56+
- **uint8_t getRECount()** returns number of RE's from begin(),
57+
convenience e.g. for for loops.
58+
- **void reset()** reset all internal counters to 0.
4859

49-
50-
#### Core functions
60+
### Core functions
5161

5262
- **uint8_t readInitialState()** read the initial state of the 4 rotary encoders.
5363
Typically called in setup only, or after a sleep e.g. in combination with **setValue()**.
54-
Since 0.3.1 this function returns the read state, saves an additional read8() call.
64+
This function returns the read state, saves an additional read8() call.
5565
- **bool checkChange()** used for polling to see if one or more RE have changed.
5666
This function does NOT update the internal counters.
5767
- **bool update()** returns true if there is a change detected.
5868
It updates the internal counters of the RE.
5969
The counters will add +1 or -1 depending on rotation direction.
60-
Need to be called before **getValue()** or before **getKeyPressed()**.
70+
Need to be called before **getValue()**.
6171
Note that **update()** must be called as soon as possible after the interrupt occurs
6272
or as often as possible when polling.
6373
Returns false if there is no change since last read.
6474
- **bool updateSingle()** returns true if there is a change detected.
6575
It updates the internal counters of the RE.
6676
This will add +1, +2 or +3 as it assumes that the rotary encoder
67-
only goes into a single direction.
77+
only goes into a single direction.
78+
Typical use is for a RPM measurement.
79+
Note that the **getValue()** can go 3x as fast if you turn in the other direction.
6880
Returns false if there is no change since last read.
6981

7082

71-
#### Counters
83+
### Counters
7284

7385
- **int32_t getValue(uint8_r re)** returns the RE counter.
7486
If the parameter re > 3 then 0 is returned.
87+
The max value is ± 2147483647.
7588
- **bool setValue(uint8_r re, int32_t value = 0)** (re)set the internal counter to value, default 0.
7689
If the parameter re > 3 then false is returned, true otherwise.
7790

7891

79-
#### Read1 - Write1 - experimental
92+
### Read1 - Write1
8093

81-
Warning the **write1(pin, value)** might alter the state of the rotary encoder pins.
94+
**Warning**
95+
96+
The **write1(pin, value)** might alter the state of the rotary encoder pins.
8297
So this functionality should be tested thoroughly for your application.
83-
Especially the **write()** is **experimental**, see issue #10, feedback welcome.
98+
Especially the **write1()** is **experimental**, feedback welcome.
8499

85-
See example **rotaryDecoder_demo_RE_IO.ino** (since 0.3.1).
100+
See example **rotaryDecoder_demo_RE_IO.ino**.
86101

87102
**Read1()** and **write1()** are functions to access the pins of the PCF8574 that
88103
are not used for rotary encoders.
89-
The user must guard that especially writing the pins do not interfere with the rotary encoder pins.
104+
The user must guard that especially writing the pins do not interfere with the
105+
rotary encoder pins.
90106

91107
- **uint8_t read1(uint8_t pin)** reads a single pin (0..7).
92108
Returns HIGH or LOW.
93109
- **bool write1(uint8_t pin, uint8_t value)** writes a single pin (0..7).
94110
Value should be LOW (0) or HIGH (other values).
111+
As said before the user must guard not to interfere with the
112+
rotary encoder pins.
95113
- **uint8_t read8()** read all pins in one I2C IO action. When one need to access multiple
96114
input pins this is faster but need some bit masking.
97-
- **bool write8(uint8_t value)** writes to multiple pins at once, e.g. to control multiple
115+
- **bool write8(uint8_t bitmask)** writes to multiple pins at once, e.g. to control multiple
98116
LEDs in one IO action. As said before the user must guard not to interfere with the
99117
rotary encoder pins.
100118

101119

102-
#### Debugging
120+
### Debugging
103121

104-
- **int8_t getLastPosition(uint8_r re)** Returns last position.
122+
- **int8_t getLastPosition(uint8_r re)** Returns last position.
123+
Returns 0 if re > 3.
105124

106125

107126
## Performance
@@ -143,6 +162,7 @@ assuming 4 pulses == 360
143162

144163
- update documentation
145164
- picture how to connect e.g two rotary encoders which pins to used
165+
- keep in sync with rotaryEncoder8 (PCF8575) class.
146166

147167
#### Should
148168

@@ -153,6 +173,7 @@ assuming 4 pulses == 360
153173
- invert flag to adjust to RE that give their pulse just the other way around?
154174
- setInvert(bool); getInvert();
155175
- per channel / all?
176+
- split **reset()** per var?
156177

157178
#### Wont
158179

examples/rotaryDecoder_performance/rotaryDecoder_performance.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ void setup()
4848
Serial.print("\t");
4949
Serial.print((stop - start) * 0.1);
5050
Serial.print("\n");
51+
delay(100);
5152
}
5253
}
5354

keywords.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ rotaryDecoder KEYWORD1
77
begin KEYWORD2
88
isConnected KEYWORD2
99

10+
getRECount KEYWORD2
11+
reset KEYWORD2
1012
readInitialState KEYWORD2
13+
1114
checkChange KEYWORD2
1215
update KEYWORD2
1316
updateSingle KEYWORD2
@@ -25,3 +28,4 @@ getLastPosition KEYWORD2
2528

2629
# Constants (LITERAL1)
2730
ROTARY_DECODER_LIB_VERSION LITERAL1
31+

library.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "rotaryDecoder",
33
"keywords": "rotary,encoder,decoder,PCF8574",
4-
"description": "Arduino library for rotary decoder with a PCF8574\nSupports up to 4 rotary encoders.",
4+
"description": "Arduino library for a PCF8574 rotary decoder.\nSupports up to 4 rotary encoders.",
55
"authors":
66
[
77
{
@@ -15,7 +15,7 @@
1515
"type": "git",
1616
"url": "https://github.com/RobTillaart/rotaryDecoder.git"
1717
},
18-
"version": "0.3.1",
18+
"version": "0.4.0",
1919
"license": "MIT",
2020
"frameworks": "*",
2121
"platforms": "*",

library.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
name=rotaryDecoder
2-
version=0.3.1
2+
version=0.4.0
33
author=Rob Tillaart <[email protected]>
44
maintainer=Rob Tillaart <[email protected]>
5-
sentence=Arduino library for rotary decoder with a PCF8574.
5+
sentence=Arduino library for a PCF8574 based rotary decoder.
66
paragraph=Supports up to 4 rotary encoders.
77
category=Data Processing
88
url=https://github.com/RobTillaart/rotaryDecoder

rotaryDecoder.cpp

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//
22
// FILE: rotaryDecoder.cpp
33
// AUTHOR: Rob Tillaart
4-
// VERSION: 0.3.1
4+
// VERSION: 0.4.0
55
// DATE: 2021-05-08
6-
// PURPOSE: Arduino library for rotary decoder
6+
// PURPOSE: Arduino library for a PCF8574 based rotary decoder
77
// URL: https://github.com/RobTillaart/rotaryDecoder
88

99

@@ -24,7 +24,7 @@ rotaryDecoder::rotaryDecoder(const int8_t address, TwoWire *wire)
2424
bool rotaryDecoder::begin(uint8_t count)
2525
{
2626
_count = count;
27-
if (_count > 4) _count = 4;
27+
if (_count > ROTDEC_MAX_COUNT) _count = ROTDEC_MAX_COUNT;
2828

2929
if (! isConnected()) return false;
3030
return true;
@@ -38,6 +38,23 @@ bool rotaryDecoder::isConnected()
3838
}
3939

4040

41+
uint8_t rotaryDecoder::getRECount()
42+
{
43+
return _count;
44+
}
45+
46+
47+
void rotaryDecoder::reset()
48+
{
49+
for (int i = 0 ; i < ROTDEC_MAX_COUNT; i++)
50+
{
51+
_lastPos[i] = 0;
52+
_encoder[i] = 0;
53+
}
54+
_lastValue = 0;
55+
}
56+
57+
4158
uint8_t rotaryDecoder::readInitialState()
4259
{
4360
uint8_t value = read8();
@@ -69,8 +86,8 @@ bool rotaryDecoder::update()
6986
_lastValue = value;
7087
for (uint8_t i = 0; i < _count; i++, value >>= 2)
7188
{
72-
uint8_t currentpos = (value & 0x03);
73-
uint8_t change = (_lastPos[i] << 2) | currentpos;
89+
uint8_t currentPos = (value & 0x03);
90+
uint8_t change = (_lastPos[i] << 2) | currentPos;
7491
switch (change)
7592
{
7693
case 0b0001: // fall through..
@@ -86,7 +103,7 @@ bool rotaryDecoder::update()
86103
_encoder[i]--;
87104
break;
88105
}
89-
_lastPos[i] = currentpos;
106+
_lastPos[i] = currentPos;
90107
}
91108
return true;
92109
}
@@ -103,8 +120,8 @@ bool rotaryDecoder::updateSingle()
103120
_lastValue = value;
104121
for (uint8_t i = 0; i < _count; i++, value >>= 2)
105122
{
106-
uint8_t currentpos = (value & 0x03);
107-
uint8_t change = (_lastPos[i] << 2) | currentpos;
123+
uint8_t currentPos = (value & 0x03);
124+
uint8_t change = (_lastPos[i] << 2) | currentPos;
108125
switch (change)
109126
{
110127
case 0b0001: // fall through..
@@ -126,22 +143,22 @@ bool rotaryDecoder::updateSingle()
126143
_encoder[i] += 3;
127144
break;
128145
}
129-
_lastPos[i] = currentpos;
146+
_lastPos[i] = currentPos;
130147
}
131148
return true;
132149
}
133150

134151

135152
int32_t rotaryDecoder::getValue(uint8_t re)
136153
{
137-
if (re > 3) return 0;
154+
if (re >= ROTDEC_MAX_COUNT) return 0;
138155
return _encoder[re];
139156
}
140157

141158

142159
bool rotaryDecoder::setValue(uint8_t re, int32_t value)
143160
{
144-
if (re > 3) return false;
161+
if (re >= ROTDEC_MAX_COUNT) return false;
145162
_encoder[re] = value;
146163
return true;
147164
}
@@ -172,16 +189,15 @@ bool rotaryDecoder::write1(uint8_t pin, uint8_t value)
172189
uint8_t rotaryDecoder::read8()
173190
{
174191
_wire->requestFrom(_address, (uint8_t)1);
175-
uint8_t x = _wire->read();
176-
// Serial.println(x, HEX);
177-
return x;
192+
uint8_t a = _wire->read();
193+
return a;
178194
}
179195

180196

181-
bool rotaryDecoder::write8(uint8_t value)
197+
bool rotaryDecoder::write8(uint8_t bitmask)
182198
{
183199
_wire->beginTransmission(_address);
184-
_wire->write(value);
200+
_wire->write(bitmask);
185201
return (_wire->endTransmission() == 0);
186202
}
187203

@@ -192,6 +208,7 @@ bool rotaryDecoder::write8(uint8_t value)
192208
//
193209
uint8_t rotaryDecoder::getLastPosition(uint8_t re)
194210
{
211+
if (re >= ROTDEC_MAX_COUNT) return 0;
195212
return _lastPos[re];
196213
}
197214

0 commit comments

Comments
 (0)