Skip to content

Commit eccbb94

Browse files
committed
add rotaryDecoderSwitch
1 parent 5d1c45a commit eccbb94

File tree

15 files changed

+772
-0
lines changed

15 files changed

+772
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
compile:
2+
# Choosing to run compilation tests on 2 different Arduino platforms
3+
platforms:
4+
- uno
5+
- leonardo
6+
- due
7+
- zero
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
name: Arduino CI
3+
4+
on: [push, pull_request]
5+
6+
jobs:
7+
arduino_ci:
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: actions/checkout@v2
12+
- uses: Arduino-CI/action@master
13+
# Arduino-CI/action@v0.1.1
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: JSON check
2+
3+
on:
4+
push:
5+
paths:
6+
- '**.json'
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
- name: json-syntax-check
15+
uses: limitusus/json-syntax-check@v1
16+
with:
17+
pattern: "\\.json$"
18+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021-2021 Rob Tillaart
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
2+
[![Arduino CI](https://github.com/RobTillaart/rotaryDecoderSwitch/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
3+
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/rotaryDecoderSwitch/blob/master/LICENSE)
4+
[![GitHub release](https://img.shields.io/github/release/RobTillaart/rotaryDecoderSwitch.svg?maxAge=3600)](https://github.com/RobTillaart/rotaryDecoderSwitch/releases)
5+
6+
7+
# rotaryDecoderSwitch
8+
9+
Arduino library for a PCF8574 based rotary decoder - supports 2 rotary encoders with a switch
10+
11+
12+
## Description
13+
14+
Experimental - not tested extensively
15+
16+
related to https://github.com/RobTillaart/rotaryDecoder
17+
interface is kept same as much as possible.
18+
19+
```cpp
20+
// connect up to 2 rotary encoders with a switch to 1 PCF8574.
21+
//
22+
// RotaryEncoder PCF8574 UNO REMARKS
23+
// -----------------------------------------------------------
24+
// 1 pin A pin 0
25+
// 1 pin B pin 1
26+
// 1 switch pin 2 (switch to gnd)
27+
// pin 3 (reserved)
28+
// 2 pin A pin 4
29+
// 2 pin B pin 5
30+
// 2 switch pin 6 (switch to gnd)
31+
// pin 7 (reserved)
32+
//
33+
// SDA A4
34+
// SCL A5
35+
//
36+
```
37+
38+
Note the above mapping is sort of compatible to using the rotaryDecoder class and using device 0 and 2 only,
39+
40+
41+
42+
## Interface
43+
44+
- **rotaryDecoderSwitch(const int8_t address, TwoWire \*wire = Wire);** constructor to set the address and optional the Wire bus.
45+
- **bool begin(uint8_t sda, uint8_t scl, uint8_t cnt = 2)** ESP32 ea initializes the class.
46+
sets I2C pins.
47+
cnt is the number of rotary encoders connected.
48+
returns true if the PCF8574 is on the I2C bus.
49+
- **bool begin(uint8_t cnt = 2)** UNO ea. initializes the class.
50+
cnt is the number of rotary encoders connected.
51+
returns true if the PCF8574 is on the I2C bus.
52+
- **bool isConnected()** returns true if the PCF8574 is on the I2C bus.
53+
54+
55+
## Core functions
56+
57+
- **void readInitialState()** read the inital state of the 2 rotary encoders. typically called in setup only, or after a sleep e.g. in combination with **setValue()**
58+
- **bool checkChange()** polling to see if one or more RE have changed, without updating the counters.
59+
- **void update()** update the internal counters of the RE, and the flags if a key is pressed. The counters will add +1 or -1 depending on 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).
60+
- **void updateSingle()** update the internal counters of the RE. This will add +1 +2 or +3 as it assumes that the rotary encoder only goes into a single direction.
61+
62+
63+
## Counters & keypresses
64+
65+
- **uint32_t getValue(uint8_r re)** returns the RE counter. (re = 0 or 1).
66+
- **void setValue(uint8_r re, uint32_t val = 0)** (re)set the internal counter to val, default 0
67+
- **bool isKeyPressed(uint8_t re)** returns true is the switch is pressed of the RE selected (re = 0 or 1). Note one needs to call **update()** first!
68+
69+
70+
## Debugging
71+
72+
- **int8_t getLastPosition(uint8_r re)** (re = 0 or 1).
73+
- **int8_t getRaw()**
74+
75+
76+
## Performance
77+
78+
As the decoder is based upon a PCF8574, a I2C device, the performance is affected by the
79+
clockspeed of the I2C bus. All four core functions have one call to **\_read()** which is the most expensive part.
80+
81+
Early tests gave the following indicative times (Arduino UNO) for the **update()**
82+
function. Note that above 500KHz the gain becomes less
83+
while reliability of signal decreases. (500KHz is ~3x faster than 100 KHz)
84+
85+
| I2C speed | time (us) | delta | %% |
86+
|:---------:|:---------:|:-----:|:-----:|
87+
| 100 KHz | 234 | | |
88+
| 200 KHz | 136 | 98 | 42% |
89+
| 300 KHz | 100 | 36 | 26% |
90+
| 400 KHz | 85 | 15 | 15% | preferred max
91+
| 500 KHz | 78 | 7 | 8% |
92+
| 600 KHz | 67 | 11 | 14% | (strange outlier)
93+
| 700 KHz | 63 | 4 | 6% |
94+
95+
At @400KHz it can update 2 rotary encoders in less than 90 us.
96+
At a 50% update percentage this implies a max of about
97+
5000 **update()** calls per second in theory
98+
**to be tested in practice**
99+
100+
Note that a high speed drill goes up to 30000 RPM = 500 RPS = 2000 interrupts per second,
101+
assuming 4 pulses == 360°. (not tested)
102+
103+
104+
## Operational
105+
106+
See examples..
107+
108+
## TODO
109+
110+
- think of what to do with the two "idle lines"
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//
2+
// FILE: rotaryDecoderSwitch_demo_interrupt.ino
3+
// AUTHOR: Rob Tillaart
4+
// DATE: 2021-05-17
5+
//
6+
// PUPROSE: demo
7+
8+
// connect up to 2 rotary encoders with a switch to 1 PCF8574.
9+
//
10+
// RotaryEncoder PCF8574 UNO
11+
// --------------------------------------
12+
// 1 pin A pin 0
13+
// 1 pin B pin 1
14+
// 1 switch pin 2
15+
// pin 3 (reserved)
16+
// 2 pin A pin 4
17+
// 2 pin B pin 5
18+
// 2 switch pin 6
19+
// pin 7 (reserved)
20+
//
21+
// SDA A4
22+
// SCL A5
23+
//
24+
25+
26+
#include "Wire.h"
27+
#include "rotaryDecoderSwitch.h"
28+
29+
rotaryDecoderSwitch decoder(0x20);
30+
31+
volatile bool flag = false;
32+
33+
void moved()
34+
{
35+
flag = true;
36+
}
37+
38+
39+
void setup()
40+
{
41+
Serial.begin(115200);
42+
Serial.println(__FILE__);
43+
Serial.print("ROTARY_DECODER_SWITCH_LIB_VERSION:\t");
44+
Serial.println(ROTARY_DECODER_SWITCH_LIB_VERSION);
45+
46+
pinMode(2, INPUT_PULLUP);
47+
attachInterrupt(0, moved, FALLING);
48+
flag = false;
49+
50+
Wire.begin();
51+
Wire.setClock(100000);
52+
decoder.begin(2);
53+
decoder.readInitialState();
54+
}
55+
56+
57+
void loop()
58+
{
59+
if (flag)
60+
{
61+
decoder.update();
62+
flag = false;
63+
for (uint8_t i = 0; i < 2; i++)
64+
{
65+
Serial.print("\t");
66+
Serial.print(decoder.getValue(i));
67+
Serial.print("\t");
68+
Serial.print(decoder.isKeyPressed(i));
69+
}
70+
Serial.println();
71+
}
72+
73+
// other tasks...
74+
}
75+
76+
77+
// -- END OF FILE --
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// FILE: rotaryDecoderSwitch_demo_polling.ino
3+
// AUTHOR: Rob Tillaart
4+
// DATE: 2021-05-17
5+
//
6+
// PUPROSE: demo
7+
8+
// connect up to 2 rotary encoders with a switch to 1 PCF8574.
9+
//
10+
// RotaryEncoder PCF8574 UNO
11+
// --------------------------------------
12+
// 1 pin A pin 0
13+
// 1 pin B pin 1
14+
// 1 switch pin 2
15+
// pin 3 (reserved)
16+
// 2 pin A pin 4
17+
// 2 pin B pin 5
18+
// 2 switch pin 6
19+
// pin 7 (reserved)
20+
//
21+
// SDA A4
22+
// SCL A5
23+
//
24+
25+
#include "Wire.h"
26+
#include "rotaryDecoderSwitch.h"
27+
28+
rotaryDecoderSwitch decoder(0x20);
29+
30+
void setup()
31+
{
32+
Serial.begin(115200);
33+
Serial.println(__FILE__);
34+
Serial.print("ROTARY_DECODER_SWITCH_LIB_VERSION:\t");
35+
Serial.println(ROTARY_DECODER_SWITCH_LIB_VERSION);
36+
37+
Wire.begin();
38+
Wire.setClock(100000);
39+
decoder.begin(2);
40+
decoder.readInitialState();
41+
}
42+
43+
44+
void loop()
45+
{
46+
if (decoder.checkChange())
47+
{
48+
decoder.update();
49+
for (uint8_t i = 0; i < 2; i++)
50+
{
51+
Serial.print("\t");
52+
Serial.print(decoder.getValue(i));
53+
Serial.print("\t");
54+
Serial.print(decoder.isKeyPressed(i));
55+
}
56+
Serial.println();
57+
}
58+
59+
// other tasks...
60+
}
61+
62+
63+
// -- END OF FILE --
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//
2+
// FILE: rotaryDecoderSwitch_demo_simple.ino
3+
// AUTHOR: Rob Tillaart
4+
// DATE: 2021-05-17
5+
//
6+
// PUPROSE: demo
7+
8+
// connect up to 2 rotary encoders with a switch to 1 PCF8574.
9+
//
10+
// RotaryEncoder PCF8574 UNO
11+
// --------------------------------------
12+
// 1 pin A pin 0
13+
// 1 pin B pin 1
14+
// 1 switch pin 2
15+
// pin 3 (reserved)
16+
// 2 pin A pin 4
17+
// 2 pin B pin 5
18+
// 2 switch pin 6
19+
// pin 7 (reserved)
20+
//
21+
// SDA A4
22+
// SCL A5
23+
//
24+
25+
#include "Wire.h"
26+
#include "rotaryDecoderSwitch.h"
27+
28+
rotaryDecoderSwitch decoder(0x20);
29+
30+
void setup()
31+
{
32+
Serial.begin(115200);
33+
Serial.println(__FILE__);
34+
Serial.print("ROTARY_DECODER_SWITCH_LIB_VERSION:\t");
35+
Serial.println(ROTARY_DECODER_SWITCH_LIB_VERSION);
36+
37+
Wire.begin();
38+
Wire.setClock(100000);
39+
decoder.begin(2);
40+
decoder.readInitialState();
41+
}
42+
43+
44+
void loop()
45+
{
46+
// if one of the counters is updated, print them.
47+
// update() will not check if a key is pressed.
48+
if (decoder.update())
49+
{
50+
for (uint8_t i = 0; i < 2; i++)
51+
{
52+
Serial.print("\t");
53+
Serial.print(decoder.getValue(i));
54+
Serial.print("\t");
55+
Serial.print(decoder.isKeyPressed(i));
56+
}
57+
Serial.println();
58+
}
59+
60+
// other tasks...
61+
}
62+
63+
64+
// -- END OF FILE --

0 commit comments

Comments
 (0)