├── 3D_file
├── README.md
├── c.stl
├── d.stl
└── e.stl
├── lib
├── ai-esp32-rotary-encoder-master
│ ├── src
│ │ ├── AiEsp32RotaryEncoderNumberSelector.cpp
│ │ ├── AiEsp32RotaryEncoderNumberSelector.h
│ │ ├── AiEsp32RotaryEncoder.h
│ │ └── AiEsp32RotaryEncoder.cpp
│ ├── .gitignore
│ ├── .gitattributes
│ ├── library.properties
│ ├── examples
│ │ ├── Esp32RotaryEncoderTheShortestExample
│ │ │ └── Esp32RotaryEncoderTheShortestExample.ino
│ │ ├── FM-radio-tuner
│ │ │ └── FM-radio-tuner.ino
│ │ ├── Number-select
│ │ │ └── Number-select.ino
│ │ ├── Esp32RotaryEncoderTestAcceleration
│ │ │ └── Esp32RotaryEncoderTestAcceleration.ino
│ │ ├── Esp32RotaryEncoderBasics
│ │ │ └── Esp32RotaryEncoderBasics.ino
│ │ ├── Multi-select
│ │ │ └── Multi-select.ino
│ │ └── Esp32RotaryEncoderTestBoundaries
│ │ │ └── Esp32RotaryEncoderTestBoundaries.ino
│ ├── README.md
│ ├── README_old.md
│ └── LICENSE.md
└── README
├── T-Encoder.dxf
├── schematic.pdf
├── image
├── IMAGE1.jpg
└── T-Encoder-EN.jpg
├── .gitignore
├── .vscode
└── extensions.json
├── example
├── EspNow_test
│ ├── T-Encoder_Unicast
│ │ ├── README.md
│ │ └── T-Encoder_Unicast.ino
│ └── T-Encoder_Broadcast
│ │ ├── README.md
│ │ └── T-Encoder_Broadcast.ino
├── base
│ └── base.ino
└── base_WS2812C
│ └── base_WS2812C.ino
├── test
└── README
├── platformio.ini
├── LICENSE
├── README_CN.MD
├── README.md
├── include
└── README
└── src
└── main.cpp
/3D_file/README.md:
--------------------------------------------------------------------------------
1 | ## This is 3d file
2 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/src/AiEsp32RotaryEncoderNumberSelector.cpp:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/3D_file/c.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xinyuan-LilyGO/T-Encoder/HEAD/3D_file/c.stl
--------------------------------------------------------------------------------
/3D_file/d.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xinyuan-LilyGO/T-Encoder/HEAD/3D_file/d.stl
--------------------------------------------------------------------------------
/3D_file/e.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xinyuan-LilyGO/T-Encoder/HEAD/3D_file/e.stl
--------------------------------------------------------------------------------
/T-Encoder.dxf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xinyuan-LilyGO/T-Encoder/HEAD/T-Encoder.dxf
--------------------------------------------------------------------------------
/schematic.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xinyuan-LilyGO/T-Encoder/HEAD/schematic.pdf
--------------------------------------------------------------------------------
/image/IMAGE1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xinyuan-LilyGO/T-Encoder/HEAD/image/IMAGE1.jpg
--------------------------------------------------------------------------------
/image/T-Encoder-EN.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Xinyuan-LilyGO/T-Encoder/HEAD/image/T-Encoder-EN.jpg
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .pio
2 | .vscode/.browse.c_cpp.db*
3 | .vscode/c_cpp_properties.json
4 | .vscode/launch.json
5 | .vscode/ipch
6 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "platformio.platformio-ide"
6 | ],
7 | "unwantedRecommendations": [
8 | "ms-vscode.cpptools-extension-pack"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/example/EspNow_test/T-Encoder_Unicast/README.md:
--------------------------------------------------------------------------------
1 |
🌟LILYGO T-Encoder🌟
2 |
3 | This example needs to be used in conjunction with [T-color](https://github.com/Xinyuan-LilyGO/T-Color/tree/main/example/EspNow_test_receiver)
4 |
5 | Esp-now unicast example .Adjust the brightness left and right, press on and off the light
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/EspNow_test/T-Encoder_Broadcast/README.md:
--------------------------------------------------------------------------------
1 | 🌟LILYGO T-Encoder🌟
2 |
3 | This example needs to be used in conjunction with [T-color](https://github.com/Xinyuan-LilyGO/T-Color/tree/main/example/EspNow_test_receiver)
4 |
5 | Esp-now broadcast example .Adjust the brightness left and right, press on and off the light
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 |
19 | # Compiled Static libraries
20 | *.lai
21 | *.la
22 | *.a
23 | *.lib
24 |
25 | # Executables
26 | *.exe
27 | *.out
28 | *.app
29 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/test/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for PlatformIO Unit Testing and project tests.
3 |
4 | Unit Testing is a software testing method by which individual units of
5 | source code, sets of one or more MCU program modules together with associated
6 | control data, usage procedures, and operating procedures, are tested to
7 | determine whether they are fit for use. Unit testing finds problems early
8 | in the development cycle.
9 |
10 | More information about PlatformIO Unit Testing:
11 | - https://docs.platformio.org/page/plus/unit-testing.html
12 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/library.properties:
--------------------------------------------------------------------------------
1 | name=Ai Esp32 Rotary Encoder
2 | version=1.2
3 | author=Igor Antolic (adapted code from github.com/marcmerlin/IoTuz)
4 | maintainer=Igor Antolic
5 | sentence=Easy implement rotary encoder to your application
6 | paragraph=Supports acceleration, setting boundaries. Works with ESP32. New in version 1.2: AiEsp32RotaryEncoderNumberSelector introduced to help selecting for example range -12 do 31.5 in steps of 0.5.
7 | category=Device Control
8 | url=https://github.com/iantolic/ai-esp32-rotary-encoder.git
9 | architectures=esp32
10 |
--------------------------------------------------------------------------------
/platformio.ini:
--------------------------------------------------------------------------------
1 | ; PlatformIO Project Configuration File
2 | ;
3 | ; Build options: build flags, source filter
4 | ; Upload options: custom upload port, speed and extra flags
5 | ; Library options: dependencies, extra library storages
6 | ; Advanced options: extra scripting
7 | ;
8 | ; Please visit documentation for the other options and examples
9 | ; https://docs.platformio.org/page/projectconf.html
10 |
11 | [env:pico32]
12 | platform = espressif32
13 | board = pico32
14 | framework = arduino
15 | monitor_speed = 115200
16 | ;monitor_port = COM505
17 | ;upload_port= COM505
18 |
19 | lib_deps = igorantolic/Ai Esp32 Rotary Encoder@^1.4
20 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/examples/Esp32RotaryEncoderTheShortestExample/Esp32RotaryEncoderTheShortestExample.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #define ROTARY_ENCODER_A_PIN 32
3 | #define ROTARY_ENCODER_B_PIN 21
4 | #define ROTARY_ENCODER_BUTTON_PIN 25
5 | #define ROTARY_ENCODER_STEPS 4
6 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS);
7 |
8 | void rotary_onButtonClick()
9 | {
10 | Serial.println("button pressed");
11 | }
12 |
13 | void setup()
14 | {
15 | Serial.begin(115200);
16 | rotaryEncoder.begin();
17 | rotaryEncoder.setup(
18 | [] { rotaryEncoder.readEncoder_ISR(); },
19 | [] { rotary_onButtonClick(); });
20 | rotaryEncoder.setBoundaries(0, 1000, false); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
21 | rotaryEncoder.setAcceleration(250);
22 | }
23 |
24 | void loop()
25 | {
26 | if (rotaryEncoder.encoderChanged())
27 | {
28 | Serial.println(rotaryEncoder.readEncoder());
29 | }
30 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Xinyuan-LilyGO
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.
22 |
--------------------------------------------------------------------------------
/README_CN.MD:
--------------------------------------------------------------------------------
1 |
2 |
3 | 🌟LILYGO T-Encoder🌟
4 |
5 | ## **[English](./README.MD) | [中文](./README_CN.MD)**
6 |
7 | Quick start:
8 |
9 | **使用Arduino IDE**
10 | 1. 安装 Arduino IDE [Arduino website](http://www.arduino.cc/en/main/software).
11 | 2. 打开Arduino,打开“文件” ->“首选项”,附加开发板管理器的url添加: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
12 | 3. 选择“工具” -> 开发板管理器 -> 搜索ESP32,选择版本并安装
13 | 4. 选择“工具” -> 开发板选择 -> ESP32 Pico
14 | 5. 复制lib的文件到 "C:\User\\Documents\Arduino\libraries"
15 |
16 | **使用PlatformIO**
17 | 1. 安装vscode
18 | 2. 在vscode安装PlatformIO扩展
19 |
20 |
21 | Product 📷:
22 |
23 | | Product | Product Link |
24 | | :-------: | :-----------------------------------------------------------------------------------------------------------------: |
25 | | T-Encoder | [淘宝](https://item.taobao.com/item.htm?spm=a213gs.20824378.0.0.2d1f4831p4yecp&id=661592187686&qq-pf-to=pcqq.group) |
26 |
27 | ## Pinout
28 |
29 | 
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/lib/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for project specific (private) libraries.
3 | PlatformIO will compile them to static libraries and link into executable file.
4 |
5 | The source code of each library should be placed in a an own separate directory
6 | ("lib/your_library_name/[here are source files]").
7 |
8 | For example, see a structure of the following two libraries `Foo` and `Bar`:
9 |
10 | |--lib
11 | | |
12 | | |--Bar
13 | | | |--docs
14 | | | |--examples
15 | | | |--src
16 | | | |- Bar.c
17 | | | |- Bar.h
18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
19 | | |
20 | | |--Foo
21 | | | |- Foo.c
22 | | | |- Foo.h
23 | | |
24 | | |- README --> THIS FILE
25 | |
26 | |- platformio.ini
27 | |--src
28 | |- main.c
29 |
30 | and a contents of `src/main.c`:
31 | ```
32 | #include
33 | #include
34 |
35 | int main (void)
36 | {
37 | ...
38 | }
39 |
40 | ```
41 |
42 | PlatformIO Library Dependency Finder will find automatically dependent
43 | libraries scanning project source files.
44 |
45 | More information about PlatformIO Library Dependency Finder
46 | - https://docs.platformio.org/page/librarymanager/ldf.html
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 🌟LILYGO T-Encoder🌟
4 |
5 | ## **[English](./README.MD) | [中文](./README_CN.MD)**
6 |
7 |
8 | Quick start:
9 |
10 | **USE Arduino IDE**
11 | 1. Install Arduino IDE [Arduino website](http://www.arduino.cc/en/main/software).
12 | 2. Start Arduino and open Preferences window. In additional board manager add url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json .separating them with commas.
13 | 3. Select Tools -> Board Management -> Search for ESP32 and install
14 | 4. Select Tools -> Board -> ESP32 Pico
15 | 5. Copy all the folders in the lib directory to "C:\User\\Documents\Arduino\libraries"
16 |
17 | **USE PlatformIO**
18 | 1. Install VSCode
19 | 2. Install the PlatformIO extension in VSCode
20 |
21 | 
22 |
23 | Product 📷:
24 |
25 | | Product | Product Link |
26 | | :-------: | :-----------------------------------------------------------------: |
27 | | T-Encoder | [AliExpress](https://www.aliexpress.com/item/1005003587776302.html) |
28 |
29 | ## Pinout
30 |
31 | 
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/include/README:
--------------------------------------------------------------------------------
1 |
2 | This directory is intended for project header files.
3 |
4 | A header file is a file containing C declarations and macro definitions
5 | to be shared between several project source files. You request the use of a
6 | header file in your project source file (C, C++, etc) located in `src` folder
7 | by including it, with the C preprocessing directive `#include'.
8 |
9 | ```src/main.c
10 |
11 | #include "header.h"
12 |
13 | int main (void)
14 | {
15 | ...
16 | }
17 | ```
18 |
19 | Including a header file produces the same results as copying the header file
20 | into each source file that needs it. Such copying would be time-consuming
21 | and error-prone. With a header file, the related declarations appear
22 | in only one place. If they need to be changed, they can be changed in one
23 | place, and programs that include the header file will automatically use the
24 | new version when next recompiled. The header file eliminates the labor of
25 | finding and changing all the copies as well as the risk that a failure to
26 | find one copy will result in inconsistencies within a program.
27 |
28 | In C, the usual convention is to give header files names that end with `.h'.
29 | It is most portable to use only letters, digits, dashes, and underscores in
30 | header file names, and at most one dot.
31 |
32 | Read more about using header files in official GCC documentation:
33 |
34 | * Include Syntax
35 | * Include Operation
36 | * Once-Only Headers
37 | * Computed Includes
38 |
39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
40 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/examples/FM-radio-tuner/FM-radio-tuner.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #define ROTARY_ENCODER_A_PIN 32
3 | #define ROTARY_ENCODER_B_PIN 21
4 | #define ROTARY_ENCODER_BUTTON_PIN 25
5 | #define ROTARY_ENCODER_STEPS 4
6 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS);
7 |
8 | /*
9 | FM radio tunner is suposed to set frequency between 88.0 MHz and 104.0 MHz by 0.1MHz steps
10 | Rotary encoder works with integers so we will map 88.0 to 166 and then divide by 10 to get 0.1 steps
11 | frequency = rotaryValue / 2;
12 | */
13 |
14 | float getFrequency()
15 | {
16 | return (float)rotaryEncoder.readEncoder() / 10.0;
17 | }
18 |
19 | void rotary_onButtonClick()
20 | {
21 | static unsigned long lastTimePressed = 0;
22 | if (millis() - lastTimePressed < 200)
23 | return;
24 | lastTimePressed = millis();
25 |
26 | Serial.print("Radio station set to ");
27 | Serial.print(getFrequency());
28 | Serial.println(" MHz ");
29 | }
30 |
31 | void setup()
32 | {
33 | Serial.begin(115200);
34 | rotaryEncoder.begin();
35 | rotaryEncoder.setup(
36 | [] { rotaryEncoder.readEncoder_ISR(); },
37 | [] { rotary_onButtonClick(); });
38 | rotaryEncoder.setBoundaries(88 * 10, 104 * 10, true); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
39 | rotaryEncoder.setAcceleration(50);
40 | rotaryEncoder.setEncoderValue(92.1 * 10); //set default to 92.1 MHz
41 | Serial.println("FM Radio");
42 | Serial.print("Radio station initially set to ");
43 | Serial.print(getFrequency());
44 | Serial.println(" MHz. Tune to some other station like 103.2... and press button ");
45 | }
46 |
47 | void loop()
48 | {
49 | if (rotaryEncoder.encoderChanged())
50 | {
51 | Serial.print(getFrequency(), 1);
52 | Serial.println(" MHz ");
53 | }
54 | }
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/examples/Number-select/Number-select.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #include "AiEsp32RotaryEncoderNumberSelector.h"
3 | #define ROTARY_ENCODER_A_PIN 32
4 | #define ROTARY_ENCODER_B_PIN 21
5 | #define ROTARY_ENCODER_BUTTON_PIN 25
6 | #define ROTARY_ENCODER_STEPS 4
7 | AiEsp32RotaryEncoder *rotaryEncoder = new AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS);
8 | AiEsp32RotaryEncoderNumberSelector numberSelector = AiEsp32RotaryEncoderNumberSelector();
9 | /*
10 | In this example an additional functionality is used.
11 |
12 | AiEsp32RotaryEncoderNumberSelector is that additional helper which will hide calculation for a rotary encoder.
13 |
14 | In example 1 - you can select some temperature between -12 and +31.5 degrees in steps by 0.5 degrees; using precision of 1 decimal
15 | In example 2 - you can select some frequency between 6999000 and 7000000 Hz in steps by 10 Hz; using precision of 0 decimal (integer)
16 |
17 | Internally AiEsp32RotaryEncoderNumberSelector will do the math and set the most apropriate acceleration, min and max values for you
18 |
19 | use setRange to set parameters
20 | use setValue for a default/initial value
21 | and finally read the value with getValue
22 |
23 | So, this value is actually value you need
24 |
25 | In code bellow comment / uncomment example 1 or 2
26 | */
27 |
28 | void rotary_onButtonClick()
29 | {
30 | static unsigned long lastTimePressed = 0;
31 | if (millis() - lastTimePressed < 200)
32 | return;
33 | lastTimePressed = millis();
34 |
35 | Serial.print("Selected value is ");
36 | Serial.print(numberSelector.getValue(), 1);
37 | Serial.println(" ***********************");
38 | }
39 |
40 | void setup()
41 | {
42 | Serial.begin(115200);
43 | rotaryEncoder->begin();
44 | rotaryEncoder->setup(
45 | [] { rotaryEncoder->readEncoder_ISR(); },
46 | [] { rotary_onButtonClick(); });
47 |
48 | numberSelector.attachEncoder(rotaryEncoder);
49 | //example 1
50 | //numberSelector.setRange(-12.0, 31.5, 0.5, false, 1);
51 | //numberSelector.setValue(24.3);
52 | //example 2
53 | numberSelector.setRange(6999000.0, 7000000.0, 10, false, 0);
54 | numberSelector.setValue(6999500.0);
55 | }
56 |
57 | void loop()
58 | {
59 | if (rotaryEncoder->encoderChanged())
60 | {
61 | Serial.print(numberSelector.getValue());
62 | Serial.println(" ");
63 | }
64 | }
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/src/AiEsp32RotaryEncoderNumberSelector.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "AiEsp32RotaryEncoder.h"
5 | /*
6 | setRange (float min, max, step)
7 | 100,500,25
8 | 88 , 104 , 0.05
9 |
10 | coef = 1/step
11 | range min/step, max/step -> 4 - 20
12 | realValue = value*step -> 6*25 =150
13 |
14 | */
15 | //#define DEBUG_NUM_SEL
16 |
17 | class AiEsp32RotaryEncoderNumberSelector
18 | {
19 | private:
20 | float minValue = 0;
21 | float maxValue = 100;
22 | float step = 2;
23 | float coeficient = 1;
24 | AiEsp32RotaryEncoder *encoder;
25 |
26 | public:
27 | AiEsp32RotaryEncoderNumberSelector(AiEsp32RotaryEncoder *encoderInstance = NULL)
28 | {
29 | encoder = encoderInstance;
30 | }
31 |
32 | void attachEncoder(AiEsp32RotaryEncoder *encoderInstance = NULL)
33 | {
34 | encoder = encoderInstance;
35 | }
36 |
37 | void setRange(float minValue, float maxValue, float step, bool cycleValues, unsigned int decimals = 0)
38 | {
39 | this->minValue = minValue;
40 | this->maxValue = maxValue;
41 | this->coeficient = pow(10.0, decimals);
42 | if (maxValue < minValue)
43 | coeficient *= -1.0;
44 | this->step = step * this->coeficient;
45 |
46 | long minEncoderValue = (long)((this->coeficient * this->minValue) / this->step);
47 | long maxEncoderValue = (long)((this->coeficient * this->maxValue) / this->step);
48 | long range = maxEncoderValue - minEncoderValue;
49 |
50 | encoder->setBoundaries(minEncoderValue, maxEncoderValue, cycleValues);
51 |
52 | if (range < 20)
53 | encoder->setAcceleration(0);
54 | else if (range < 60)
55 | encoder->setAcceleration(20);
56 | else if (range < 200)
57 | encoder->setAcceleration(100);
58 | else if (range < 1000)
59 | encoder->setAcceleration(300);
60 | else
61 | encoder->setAcceleration(500);
62 |
63 | #ifdef DEBUG_NUM_SEL
64 | Serial.println(minEncoderValue);
65 | Serial.println(maxEncoderValue);
66 | Serial.println(range);
67 | Serial.println(step);
68 | Serial.println(coeficient);
69 |
70 | #endif
71 | }
72 |
73 | void setValue(float value)
74 | {
75 | long encoderValue = (long)((coeficient * value) / step);
76 | encoder->setEncoderValue(encoderValue);
77 | }
78 |
79 | float getValue()
80 | {
81 | float encoderValue = 1.0 * encoder->readEncoder();
82 | float value = encoderValue * step / coeficient;
83 |
84 | #ifdef DEBUG_NUM_SEL
85 | Serial.print(encoderValue);
86 | Serial.print(" -> ");
87 | Serial.println(value);
88 | #endif
89 | return value;
90 | }
91 | };
92 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/src/AiEsp32RotaryEncoder.h:
--------------------------------------------------------------------------------
1 | // AiEsp32RotaryEncoder.h
2 | // based on https://github.com/marcmerlin/IoTuz code - extracted and modified Encoder code
3 |
4 | #ifndef _AIESP32ROTARYENCODER_h
5 | #define _AIESP32ROTARYENCODER_h
6 |
7 | #if defined(ARDUINO) && ARDUINO >= 100
8 | #include "Arduino.h"
9 | #else
10 | #include "WProgram.h"
11 | #endif
12 |
13 | // Rotary Encocer
14 | #define AIESP32ROTARYENCODER_DEFAULT_A_PIN 32
15 | #define AIESP32ROTARYENCODER_DEFAULT_B_PIN 21
16 | #define AIESP32ROTARYENCODER_DEFAULT_BUT_PIN 25
17 | #define AIESP32ROTARYENCODER_DEFAULT_VCC_PIN -1
18 | #define AIESP32ROTARYENCODER_DEFAULT_STEPS 2
19 |
20 | typedef enum
21 | {
22 | BUT_DOWN = 0,
23 | BUT_PUSHED = 1,
24 | BUT_UP = 2,
25 | BUT_RELEASED = 3,
26 | BUT_DISABLED = 99,
27 | } ButtonState;
28 |
29 | class AiEsp32RotaryEncoder
30 | {
31 |
32 | private:
33 | portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
34 | portMUX_TYPE buttonMux = portMUX_INITIALIZER_UNLOCKED;
35 | volatile long encoder0Pos = 0;
36 |
37 | volatile int8_t lastMovementDirection = 0; //1 right; -1 left
38 | volatile unsigned long lastMovementAt = 0;
39 | unsigned long rotaryAccelerationCoef = 150;
40 |
41 | bool _circleValues = false;
42 | bool isEnabled = true;
43 |
44 | uint8_t encoderAPin = AIESP32ROTARYENCODER_DEFAULT_A_PIN;
45 | uint8_t encoderBPin = AIESP32ROTARYENCODER_DEFAULT_B_PIN;
46 | uint8_t encoderButtonPin = AIESP32ROTARYENCODER_DEFAULT_BUT_PIN;
47 | uint8_t encoderVccPin = AIESP32ROTARYENCODER_DEFAULT_VCC_PIN;
48 | long encoderSteps = AIESP32ROTARYENCODER_DEFAULT_STEPS;
49 |
50 | long _minEncoderValue = -1 << 15;
51 | long _maxEncoderValue = 1 << 15;
52 |
53 | uint8_t old_AB;
54 | long lastReadEncoder0Pos;
55 | bool previous_butt_state;
56 |
57 | ButtonState buttonState;
58 |
59 | int8_t enc_states[16] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
60 | void (*ISR_callback)();
61 | void (*ISR_button)();
62 |
63 | public:
64 | AiEsp32RotaryEncoder(
65 | uint8_t encoderAPin = AIESP32ROTARYENCODER_DEFAULT_A_PIN,
66 | uint8_t encoderBPin = AIESP32ROTARYENCODER_DEFAULT_B_PIN,
67 | uint8_t encoderButtonPin = AIESP32ROTARYENCODER_DEFAULT_BUT_PIN,
68 | uint8_t encoderVccPin = AIESP32ROTARYENCODER_DEFAULT_VCC_PIN,
69 | uint8_t encoderSteps = AIESP32ROTARYENCODER_DEFAULT_STEPS);
70 | void setBoundaries(long minValue = -100, long maxValue = 100, bool circleValues = false);
71 | void IRAM_ATTR readEncoder_ISR();
72 | void IRAM_ATTR readButton_ISR();
73 |
74 | void setup(void (*ISR_callback)(void));
75 | void setup(void (*ISR_callback)(void), void (*ISR_button)(void));
76 | void begin();
77 | void reset(long newValue = 0);
78 | void enable();
79 | void disable();
80 | long readEncoder();
81 | void setEncoderValue(long newValue);
82 | long encoderChanged();
83 | ButtonState currentButtonState();
84 | unsigned long getAcceleration() { return this->rotaryAccelerationCoef; }
85 | void setAcceleration(unsigned long acceleration) { this->rotaryAccelerationCoef = acceleration; }
86 | void disableAcceleration() { setAcceleration(0); }
87 | };
88 | #endif
89 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/README.md:
--------------------------------------------------------------------------------
1 | # New feature added 02/2021 - accelerated movement
2 |
3 | In case a range to select is large, for example - select a value between 0 and 1000 and we want 785, without accelerateion you need long time to get to that number.
4 | However using new implemented acceleration, faster you turn, faster will the value raise.For fine tuning just slow down.
5 | In new example imagine any random naumber between 1 and 1000 and try to select it as fast as you can using example code, and after that disable acceleration and try again.
6 |
7 | rotaryEncoder.setAcceleration(250);
8 | this will set acceleration; larger number = more accelearation; 0 or 1 means disabled acceleration
9 |
10 |
11 | rotaryEncoder.disableAcceleration();
12 | This will disable acceleration (now enabled by default) in case you dont need one.
13 |
14 | Recomendation - turn off for small ranges; but turn on when you select from more than 50 values in range.
15 |
16 |
17 | # Arduino Esp32 Encoder Library
18 |
19 | Rotary encoder main interrupt code is extracted from (https://github.com/marcmerlin/IoTuz) and some additional features are included here.
20 |
21 | ## Description
22 |
23 | This library enables easy implementation of rotary encoder functionality in your application for ESP32, ESP8266 (or similar microcontroller).
24 |
25 | ## Installing
26 |
27 | The downloaded code can be included as a new library into the IDE selecting the menu:
28 |
29 | Sketch / include Library / Add .Zip library
30 |
31 | Restart the Arduino IDE and follow the examples located at
32 |
33 | File -> Examples -> Ai Esp32 Rotary Encoder
34 |
35 | ## Connecting Rotary Encoder Module to your microcontroller ESP32, ESP8266 (or similar)
36 |
37 | This are instructions for "Rotary Encoder Module" which is actually Rotary Encoder with 2 resistors on board.
38 |
39 | CLK (A pin) - connect to any microcontroler intput pin with interrupt -> in this example pin 32
40 |
41 | DT (B pin) - connect to any microcontroler intput pin with interrupt -> in this example pin 21
42 |
43 | SW (button pin) - connect to any microcontroler intput pin -> in this example pin 25
44 |
45 | VCC - for this you can two options:
46 |
47 | a) connect to microcontroler VCC (then set ROTARY_ENCODER_VCC_PIN -1) or
48 |
49 | b) connect to any microcontroler output pin - in this example pin 25
50 |
51 | GND - connect to microcontroler GND
52 |
53 | ## How to use
54 |
55 | I suggest you should start using built in example. After installing library (and reopening Arduino IDE if required) open
56 |
57 | File -> Examples -> Ai Esp32 Rotary Encoder
58 |
59 | If you didnt use suggested pins, adjust defines
60 |
61 | ```c
62 | #define ROTARY_ENCODER_A_PIN 32
63 | #define ROTARY_ENCODER_B_PIN 21
64 | #define ROTARY_ENCODER_BUTTON_PIN 25
65 | #define ROTARY_ENCODER_VCC_PIN 27
66 | ```
67 |
68 | For ESP8266 you can use Dx as pin names like in example:
69 | ```c
70 | #define ROTARY_ENCODER_A_PIN D3
71 | #define ROTARY_ENCODER_B_PIN D2
72 | #define ROTARY_ENCODER_BUTTON_PIN D4
73 | ```
74 | Then upload code to microcontroller.
75 |
76 | README_old.md contains more information but some parts are obsolete.
77 |
78 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/examples/Esp32RotaryEncoderTestAcceleration/Esp32RotaryEncoderTestAcceleration.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #include "Arduino.h"
3 |
4 | /*
5 | connecting Rotary encoder
6 |
7 | Rotary encoder side MICROCONTROLLER side
8 | ------------------- ---------------------------------------------------------------------
9 | CLK (A pin) any microcontroler intput pin with interrupt -> in this example pin 32
10 | DT (B pin) any microcontroler intput pin with interrupt -> in this example pin 21
11 | SW (button pin) any microcontroler intput pin with interrupt -> in this example pin 25
12 | GND - to microcontroler GND
13 | VCC microcontroler VCC (then set ROTARY_ENCODER_VCC_PIN -1)
14 |
15 | ***OR in case VCC pin is not free you can cheat and connect:***
16 | VCC any microcontroler output pin - but set also ROTARY_ENCODER_VCC_PIN 25
17 | in this example pin 25
18 |
19 | */
20 | #define ROTARY_ENCODER_A_PIN 32
21 | #define ROTARY_ENCODER_B_PIN 21
22 | #define ROTARY_ENCODER_BUTTON_PIN 25
23 | #define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
24 |
25 | //depending on your encoder - try 1,2 or 4 to get expected behaviour
26 | //#define ROTARY_ENCODER_STEPS 1
27 | //#define ROTARY_ENCODER_STEPS 2
28 | #define ROTARY_ENCODER_STEPS 4
29 |
30 | //instead of changing here, rather change numbers above
31 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
32 |
33 | void rotary_onButtonClick()
34 | {
35 | static unsigned long lastTimePressed = 0;
36 | if (millis() - lastTimePressed < 500)
37 | return; //ignore multiple press in that time milliseconds
38 | lastTimePressed = millis();
39 |
40 | unsigned long acceletation = rotaryEncoder.getAcceleration() + 50;
41 | if (acceletation > 400)
42 | acceletation = 0;
43 | rotaryEncoder.setAcceleration(acceletation);
44 |
45 | Serial.print("new acceleration is ");
46 | Serial.println(acceletation);
47 | Serial.print("Try to set value: ");
48 | Serial.println(random(-999, 999));
49 | Serial.println("Set as fast as you can. If it is too hard or you suceeded, press the button again.");
50 | }
51 |
52 | void rotary_loop()
53 | {
54 | if (rotaryEncoder.encoderChanged())
55 | {
56 | Serial.print("Value: ");
57 | Serial.println(rotaryEncoder.readEncoder());
58 | }
59 | }
60 |
61 | void setup()
62 | {
63 | Serial.begin(115200);
64 | rotaryEncoder.begin();
65 |
66 | rotaryEncoder.setup(
67 | [] { rotaryEncoder.readEncoder_ISR(); },
68 | [] { rotary_onButtonClick(); });
69 | bool circleValues = false;
70 | rotaryEncoder.setBoundaries(-1000, 1000, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
71 | rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
72 | Serial.println("Ready");
73 | Serial.print("Try to set value: ");
74 | Serial.println(752);
75 | Serial.println("If it is too hard press the button.");
76 | }
77 |
78 | void loop()
79 | {
80 | rotary_loop();
81 | delay(50);
82 | }
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/examples/Esp32RotaryEncoderBasics/Esp32RotaryEncoderBasics.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #include "Arduino.h"
3 |
4 | /*
5 | connecting Rotary encoder
6 |
7 | Rotary encoder side MICROCONTROLLER side
8 | ------------------- ---------------------------------------------------------------------
9 | CLK (A pin) any microcontroler intput pin with interrupt -> in this example pin 32
10 | DT (B pin) any microcontroler intput pin with interrupt -> in this example pin 21
11 | SW (button pin) any microcontroler intput pin with interrupt -> in this example pin 25
12 | GND - to microcontroler GND
13 | VCC microcontroler VCC (then set ROTARY_ENCODER_VCC_PIN -1)
14 |
15 | ***OR in case VCC pin is not free you can cheat and connect:***
16 | VCC any microcontroler output pin - but set also ROTARY_ENCODER_VCC_PIN 25
17 | in this example pin 25
18 |
19 | */
20 | #define ROTARY_ENCODER_A_PIN 32
21 | #define ROTARY_ENCODER_B_PIN 21
22 | #define ROTARY_ENCODER_BUTTON_PIN 25
23 | #define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
24 |
25 | //depending on your encoder - try 1,2 or 4 to get expected behaviour
26 | //#define ROTARY_ENCODER_STEPS 1
27 | //#define ROTARY_ENCODER_STEPS 2
28 | #define ROTARY_ENCODER_STEPS 4
29 |
30 | //instead of changing here, rather change numbers above
31 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
32 |
33 | void rotary_onButtonClick()
34 | {
35 | static unsigned long lastTimePressed = 0;
36 | //ignore multiple press in that time milliseconds
37 | if (millis() - lastTimePressed < 500)
38 | {
39 | return;
40 | }
41 | lastTimePressed = millis();
42 | Serial.print("button pressed at ");
43 | Serial.println(millis());
44 | }
45 |
46 | void rotary_loop()
47 | {
48 | //dont print anything unless value changed
49 | if (!rotaryEncoder.encoderChanged())
50 | {
51 | return;
52 | }
53 |
54 | Serial.print("Value: ");
55 | Serial.println(rotaryEncoder.readEncoder());
56 | }
57 |
58 | void setup()
59 | {
60 | Serial.begin(115200);
61 |
62 | //we must initialize rotary encoder
63 | rotaryEncoder.begin();
64 |
65 | rotaryEncoder.setup(
66 | [] { rotaryEncoder.readEncoder_ISR(); },
67 | [] { rotary_onButtonClick(); });
68 |
69 | //set boundaries and if values should cycle or not
70 | //in this example we will set possible values between 0 and 1000;
71 | bool circleValues = false;
72 | rotaryEncoder.setBoundaries(0, 1000, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
73 |
74 | /*Rotary acceleration introduced 25.2.2021.
75 | * in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
76 | * without accelerateion you need long time to get to that number
77 | * Using acceleration, faster you turn, faster will the value raise.
78 | * For fine tuning slow down.
79 | */
80 | //rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
81 | rotaryEncoder.setAcceleration(250); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
82 | }
83 |
84 | void loop()
85 | {
86 | //in loop call your custom function which will process rotary encoder values
87 | rotary_loop();
88 | delay(50); //or do whatever you need to do...
89 | }
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/examples/Multi-select/Multi-select.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #define ROTARY_ENCODER_A_PIN 32
3 | #define ROTARY_ENCODER_B_PIN 21
4 | #define ROTARY_ENCODER_BUTTON_PIN 25
5 | #define ROTARY_ENCODER_STEPS 4
6 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS);
7 |
8 | /*
9 | Select fast food - Hot dog, Pizza, Hamburger, Cheeseburger
10 | Then select how many pieces 1 to 10
11 | At the end select if you want fast delivery for extra 2$
12 | */
13 | String options[] = {"Select fast food", "How many (1...10)", "Do you want fast delicery for 2$?"};
14 |
15 | String foods[] = {"Hot dog", "Pizza", "Hamburger", "Cheeseburger"};
16 | String selectedFood = "";
17 |
18 | String delivery[] = {"Normal", "Fast for extra 2$"};
19 | String selectedDelivery = "";
20 |
21 | int selectedQuantity = 1;
22 |
23 | int currentOption = 0;
24 |
25 | void setForOption(int newOption)
26 | {
27 | currentOption = newOption;
28 |
29 | switch (newOption)
30 | {
31 | case 0:
32 | rotaryEncoder.setBoundaries(0, 3, true); //food type 0..3
33 | rotaryEncoder.setEncoderValue(0);
34 | break;
35 | case 1:
36 | rotaryEncoder.setBoundaries(1, 10, false); //how many pieces 1 to 10; do not go from 10 to 1
37 | rotaryEncoder.setEncoderValue(1);
38 | break;
39 | case 2:
40 | rotaryEncoder.setBoundaries(0, 1, true); //select delivery
41 | rotaryEncoder.setEncoderValue(0);
42 | break;
43 |
44 | default:
45 | break;
46 | }
47 |
48 | Serial.println(options[currentOption]);
49 | showSelection();
50 | }
51 |
52 | void rotary_onButtonClick()
53 | {
54 | static unsigned long lastTimePressed = 0;
55 | if (millis() - lastTimePressed < 200)
56 | return;
57 | lastTimePressed = millis();
58 |
59 | int selecedValue = rotaryEncoder.readEncoder();
60 |
61 | switch (currentOption)
62 | {
63 | case 0: //"Select fast food"
64 | selectedFood = foods[selecedValue];
65 | setForOption(1);
66 | break;
67 | case 1: //"Select quantity"
68 | selectedQuantity = selecedValue;
69 | setForOption(2);
70 | break;
71 | case 2: //"Select delivery"
72 | selectedDelivery = delivery[selecedValue];
73 | showOrder();
74 | setForOption(0);
75 | break;
76 |
77 | default:
78 | break;
79 | }
80 | }
81 |
82 | void showOrder()
83 | {
84 | Serial.println("++++++++++++++++++++++++ ORDER DETAILS ++++++++++++++++++++++++++++++++++++++++++");
85 | Serial.print("You ordered ");
86 | Serial.print(selectedFood);
87 | Serial.print(", quantity: ");
88 | Serial.print(selectedQuantity);
89 | Serial.print(". Delivery: ");
90 | Serial.println(selectedDelivery);
91 | Serial.println("---------------------------------------------------------------------------------");
92 | Serial.println("");
93 |
94 | Serial.print("NEW ORDER ");
95 | }
96 |
97 | void setup()
98 | {
99 | Serial.begin(115200);
100 | rotaryEncoder.begin();
101 | rotaryEncoder.setup(
102 | [] { rotaryEncoder.readEncoder_ISR(); },
103 | [] { rotary_onButtonClick(); });
104 | rotaryEncoder.setAcceleration(0);
105 | setForOption(0);
106 | }
107 |
108 | void showSelection()
109 | {
110 | int selecedValue = rotaryEncoder.readEncoder();
111 |
112 | switch (currentOption)
113 | {
114 | case 0: //"Select fast food"
115 | Serial.println(foods[selecedValue]);
116 | break;
117 | case 1: //"Select quantity"
118 | Serial.print("Quantity: ");
119 | Serial.println(selecedValue);
120 | break;
121 | case 2: //"Select delivery"
122 | Serial.println(delivery[selecedValue]);
123 | break;
124 | default:
125 | break;
126 | }
127 | }
128 |
129 | void loop()
130 | {
131 | if (rotaryEncoder.encoderChanged())
132 | {
133 | showSelection();
134 | }
135 | }
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/examples/Esp32RotaryEncoderTestBoundaries/Esp32RotaryEncoderTestBoundaries.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #include "Arduino.h"
3 |
4 | /*
5 | connecting Rotary encoder
6 |
7 | Rotary encoder side MICROCONTROLLER side
8 | ------------------- ---------------------------------------------------------------------
9 | CLK (A pin) any microcontroler intput pin with interrupt -> in this example pin 32
10 | DT (B pin) any microcontroler intput pin with interrupt -> in this example pin 21
11 | SW (button pin) any microcontroler intput pin with interrupt -> in this example pin 25
12 | GND - to microcontroler GND
13 | VCC microcontroler VCC (then set ROTARY_ENCODER_VCC_PIN -1)
14 |
15 | ***OR in case VCC pin is not free you can cheat and connect:***
16 | VCC any microcontroler output pin - but set also ROTARY_ENCODER_VCC_PIN 25
17 | in this example pin 25
18 |
19 | */
20 | #define ROTARY_ENCODER_A_PIN 32
21 | #define ROTARY_ENCODER_B_PIN 21
22 | #define ROTARY_ENCODER_BUTTON_PIN 25
23 | #define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
24 |
25 | //depending on your encoder - try 1,2 or 4 to get expected behaviour
26 | //#define ROTARY_ENCODER_STEPS 1
27 | //#define ROTARY_ENCODER_STEPS 2
28 | #define ROTARY_ENCODER_STEPS 4
29 |
30 | //instead of changing here, rather change numbers above
31 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
32 |
33 | int16_t test_limits = 2;
34 |
35 | void rotary_onButtonClick()
36 | {
37 | static unsigned long lastTimePressed = 0;
38 | if (millis() - lastTimePressed < 500)
39 | return; //ignore multiple press in that time milliseconds
40 | lastTimePressed = millis();
41 | //rotaryEncoder.reset();
42 | //rotaryEncoder.disable();
43 | rotaryEncoder.setBoundaries(-test_limits, test_limits, false);
44 | Serial.print("new boundaries are between minimumn value ");
45 | Serial.print(-test_limits);
46 | Serial.print(" and maximum value");
47 | Serial.println(-test_limits);
48 | rotaryEncoder.reset();
49 |
50 | if (test_limits >= 2048)
51 | test_limits = 2;
52 | test_limits *= 2;
53 | }
54 |
55 | void rotary_loop()
56 | {
57 | //lets see if anything changed
58 | int16_t encoderDelta = rotaryEncoder.encoderChanged();
59 |
60 | //optionally we can ignore whenever there is no change
61 | if (encoderDelta == 0)
62 | return;
63 |
64 | //for some cases we only want to know if value is increased or decreased (typically for menu items)
65 | if (encoderDelta > 0)
66 | Serial.print("+");
67 | if (encoderDelta < 0)
68 | Serial.print("-");
69 |
70 | //for other cases we want to know what is current value. Additionally often we only want if something changed
71 | //example: when using rotary encoder to set termostat temperature, or sound volume etc
72 |
73 | //if value is changed compared to our last read
74 | if (encoderDelta != 0)
75 | {
76 | //now we need current value
77 | int16_t encoderValue = rotaryEncoder.readEncoder();
78 | //process new value. Here is simple output.
79 | Serial.print("Value: ");
80 | Serial.println(encoderValue);
81 | }
82 | }
83 |
84 | void setup()
85 | {
86 |
87 | Serial.begin(115200);
88 |
89 | //we must initialize rotary encoder
90 | rotaryEncoder.begin();
91 |
92 | rotaryEncoder.setup(
93 | [] { rotaryEncoder.readEncoder_ISR(); },
94 | [] { rotary_onButtonClick(); });
95 | //optionally we can set boundaries and if values should cycle or not
96 | bool circleValues = false;
97 | rotaryEncoder.setBoundaries(0, 1000, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
98 |
99 | /*Rotary acceleration introduced 25.2.2021.
100 | * in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
101 | * without accelerateion you need long time to get to that number
102 | * Using acceleration, faster you turn, faster will the value raise.
103 | * For fine tuning slow down.
104 | */
105 | //rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
106 | rotaryEncoder.setAcceleration(250); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
107 | }
108 |
109 | void loop()
110 | {
111 | //in loop call your custom function which will process rotary encoder values
112 | rotary_loop();
113 |
114 | delay(50);
115 | if (millis() > 20000)
116 | rotaryEncoder.enable();
117 | }
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #include "Arduino.h"
3 |
4 | /*
5 | connecting Rotary encoder
6 |
7 | Rotary encoder side MICROCONTROLLER side
8 | ------------------- ---------------------------------------------------------------------
9 | CLK (A pin) any microcontroler intput pin with interrupt -> in this example pin 36
10 | DT (B pin) any microcontroler intput pin with interrupt -> in this example pin 37
11 | SW (button pin) any microcontroler intput pin with interrupt -> in this example pin 38
12 | GND - to microcontroler GND
13 | VCC microcontroler VCC (then set ROTARY_ENCODER_VCC_PIN -1)
14 |
15 | */
16 | #define LED_GREEG 25
17 | #define LED_BLUE 26
18 | #define LED_RED 27
19 | #define BUZZER 19
20 | #define ROTARY_ENCODER_A_PIN 36
21 | #define ROTARY_ENCODER_B_PIN 37
22 | #define ROTARY_ENCODER_BUTTON_PIN 38
23 | #define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
24 |
25 | //depending on your encoder - try 1,2 or 4 to get expected behaviour
26 | //#define ROTARY_ENCODER_STEPS 1
27 | #define ROTARY_ENCODER_STEPS 2
28 | //#define ROTARY_ENCODER_STEPS 4
29 |
30 | //instead of changing here, rather change numbers above
31 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
32 |
33 | int16_t test_limits = 2;
34 |
35 | int led_red();
36 | int led_green();
37 | int led_blue();
38 | int buzzer();
39 |
40 | void rotary_loop();
41 | void rotary_onButtonClick();
42 |
43 |
44 | // use first channel of 16 channels (started from zero)
45 | #define LEDC_CHANNEL_0 0
46 |
47 | // use 13 bit precission for LEDC timer
48 | #define LEDC_TIMER_13_BIT 13
49 |
50 | // use 5000 Hz as a LEDC base frequency
51 | #define LEDC_BASE_FREQ 2000
52 |
53 | bool on_Button_down = false;
54 | void setup() {
55 | Serial.begin(115200);
56 |
57 | // initialize digital pin output.
58 | pinMode(LED_RED, OUTPUT);
59 | pinMode(LED_GREEG, OUTPUT);
60 | pinMode(LED_BLUE, OUTPUT);
61 | pinMode(BUZZER, OUTPUT);
62 |
63 | ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
64 | ledcAttachPin(BUZZER, LEDC_CHANNEL_0);
65 |
66 |
67 | led_blue(); // blue led
68 |
69 |
70 | //we must initialize rotary encoder
71 | rotaryEncoder.begin();
72 |
73 | rotaryEncoder.setup(
74 | [] { rotaryEncoder.readEncoder_ISR(); },
75 | [] { on_Button_down=true; });
76 | //optionally we can set boundaries and if values should cycle or not
77 | bool circleValues = false;
78 | rotaryEncoder.setBoundaries(0, 1000, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
79 |
80 | /*Rotary acceleration introduced 25.2.2021.
81 | * in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
82 | * without accelerateion you need long time to get to that number
83 | * Using acceleration, faster you turn, faster will the value raise.
84 | * For fine tuning slow down.
85 | */
86 | //rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
87 | rotaryEncoder.setAcceleration(250); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
88 |
89 |
90 |
91 | }
92 |
93 | // the loop function runs over and over again forever
94 | void loop() {
95 |
96 | //in loop call your custom function which will process rotary encoder values
97 | if (millis() > 20000)
98 | rotaryEncoder.enable();
99 |
100 | rotary_loop();
101 | delay(50);
102 |
103 | }
104 |
105 | void rotary_onButtonClick()
106 | {
107 |
108 | if(on_Button_down){
109 |
110 | static unsigned long lastTimePressed = 0;
111 | if (millis() - lastTimePressed < 500)
112 | return; //ignore multiple press in that time milliseconds
113 | lastTimePressed = millis();
114 |
115 |
116 | buzzer();
117 | Serial.print(" buzzer");
118 |
119 | rotaryEncoder.setBoundaries(-test_limits, test_limits, false);
120 | Serial.print("new boundaries are between minimumn value ");
121 | Serial.print(-test_limits);
122 | Serial.print(" and maximum value");
123 | Serial.println(-test_limits);
124 | rotaryEncoder.reset();
125 |
126 | if (test_limits >= 2048)
127 | test_limits = 2;
128 | test_limits *= 2;
129 |
130 | on_Button_down = false;
131 | }
132 | }
133 |
134 | void rotary_loop()
135 | {
136 | rotary_onButtonClick();
137 | //lets see if anything changed
138 | int16_t encoderDelta = rotaryEncoder.encoderChanged();
139 |
140 | //optionally we can ignore whenever there is no change
141 | if (encoderDelta == 0)
142 | return;
143 |
144 | //for some cases we only want to know if value is increased or decreased (typically for menu items)
145 | if (encoderDelta > 0)
146 | {
147 | led_green();
148 | Serial.print("+");
149 | }
150 |
151 | if (encoderDelta < 0)
152 | {
153 | led_red();
154 | Serial.print("-");
155 |
156 | }
157 |
158 |
159 | //for other cases we want to know what is current value. Additionally often we only want if something changed
160 | //example: when using rotary encoder to set termostat temperature, or sound volume etc
161 |
162 | //if value is changed compared to our last read
163 | if (encoderDelta != 0)
164 | {
165 | //now we need current value
166 | int16_t encoderValue = rotaryEncoder.readEncoder();
167 | //process new value. Here is simple output.
168 | Serial.print("Value: ");
169 | Serial.println(encoderValue);
170 | }
171 | }
172 | int buzzer(){
173 |
174 | ledcWriteTone(LEDC_CHANNEL_0, LEDC_BASE_FREQ);
175 | ledcWrite(LEDC_CHANNEL_0, 150);
176 | delay(300);
177 | ledcWrite(LEDC_CHANNEL_0, 0);
178 |
179 | return 1;
180 | }
181 |
182 | int led_red(){
183 | digitalWrite(LED_RED, LOW);
184 | digitalWrite(LED_GREEG, HIGH);
185 | digitalWrite(LED_BLUE, HIGH);
186 | return 1;
187 | }
188 | int led_green(){
189 | digitalWrite(LED_RED, HIGH);
190 | digitalWrite(LED_GREEG, LOW);
191 | digitalWrite(LED_BLUE, HIGH);
192 | }
193 | int led_blue(){
194 | digitalWrite(LED_RED, HIGH);
195 | digitalWrite(LED_GREEG, HIGH);
196 | digitalWrite(LED_BLUE, LOW);
197 | return 1;
198 | }
--------------------------------------------------------------------------------
/example/base/base.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #include "Arduino.h"
3 |
4 | /*
5 | connecting Rotary encoder
6 |
7 | Rotary encoder side MICROCONTROLLER side
8 | ------------------- ---------------------------------------------------------------------
9 | CLK (A pin) any microcontroler intput pin with interrupt -> in this example pin 36
10 | DT (B pin) any microcontroler intput pin with interrupt -> in this example pin 37
11 | SW (button pin) any microcontroler intput pin with interrupt -> in this example pin 38
12 | GND - to microcontroler GND
13 | VCC microcontroler VCC (then set ROTARY_ENCODER_VCC_PIN -1)
14 |
15 | */
16 | #define LED_GREEG 25
17 | #define LED_BLUE 26
18 | #define LED_RED 27
19 | #define BUZZER 19
20 | #define ROTARY_ENCODER_A_PIN 36
21 | #define ROTARY_ENCODER_B_PIN 37
22 | #define ROTARY_ENCODER_BUTTON_PIN 38
23 | #define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
24 |
25 | //depending on your encoder - try 1,2 or 4 to get expected behaviour
26 | //#define ROTARY_ENCODER_STEPS 1
27 | #define ROTARY_ENCODER_STEPS 2
28 | //#define ROTARY_ENCODER_STEPS 4
29 |
30 | //instead of changing here, rather change numbers above
31 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
32 |
33 | int16_t test_limits = 2;
34 |
35 | int led_red();
36 | int led_green();
37 | int led_blue();
38 | int buzzer();
39 |
40 | void rotary_loop();
41 | void rotary_onButtonClick();
42 |
43 |
44 | // use first channel of 16 channels (started from zero)
45 | #define LEDC_CHANNEL_0 0
46 |
47 | // use 13 bit precission for LEDC timer
48 | #define LEDC_TIMER_13_BIT 13
49 |
50 | // use 5000 Hz as a LEDC base frequency
51 | #define LEDC_BASE_FREQ 2000
52 |
53 | bool on_Button_down = false;
54 | void setup() {
55 | Serial.begin(115200);
56 |
57 | // initialize digital pin output.
58 | pinMode(LED_RED, OUTPUT);
59 | pinMode(LED_GREEG, OUTPUT);
60 | pinMode(LED_BLUE, OUTPUT);
61 | pinMode(BUZZER, OUTPUT);
62 |
63 | ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
64 | ledcAttachPin(BUZZER, LEDC_CHANNEL_0);
65 |
66 |
67 | led_blue(); // blue led
68 |
69 |
70 | //we must initialize rotary encoder
71 | rotaryEncoder.begin();
72 |
73 | rotaryEncoder.setup(
74 | [] { rotaryEncoder.readEncoder_ISR(); },
75 | [] { on_Button_down=true; });
76 | //optionally we can set boundaries and if values should cycle or not
77 | bool circleValues = false;
78 | rotaryEncoder.setBoundaries(0, 1000, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
79 |
80 | /*Rotary acceleration introduced 25.2.2021.
81 | * in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
82 | * without accelerateion you need long time to get to that number
83 | * Using acceleration, faster you turn, faster will the value raise.
84 | * For fine tuning slow down.
85 | */
86 | //rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
87 | rotaryEncoder.setAcceleration(250); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
88 |
89 |
90 |
91 | }
92 |
93 | // the loop function runs over and over again forever
94 | void loop() {
95 |
96 | //in loop call your custom function which will process rotary encoder values
97 | if (millis() > 20000)
98 | rotaryEncoder.enable();
99 |
100 | rotary_loop();
101 | delay(50);
102 |
103 | }
104 |
105 | void rotary_onButtonClick()
106 | {
107 |
108 | if(on_Button_down){
109 |
110 | static unsigned long lastTimePressed = 0;
111 | if (millis() - lastTimePressed < 500)
112 | return; //ignore multiple press in that time milliseconds
113 | lastTimePressed = millis();
114 |
115 |
116 | buzzer();
117 | Serial.print(" buzzer");
118 |
119 | rotaryEncoder.setBoundaries(-test_limits, test_limits, false);
120 | Serial.print("new boundaries are between minimumn value ");
121 | Serial.print(-test_limits);
122 | Serial.print(" and maximum value");
123 | Serial.println(-test_limits);
124 | rotaryEncoder.reset();
125 |
126 | if (test_limits >= 2048)
127 | test_limits = 2;
128 | test_limits *= 2;
129 |
130 | on_Button_down = false;
131 | }
132 | }
133 |
134 | void rotary_loop()
135 | {
136 | rotary_onButtonClick();
137 | //lets see if anything changed
138 | int16_t encoderDelta = rotaryEncoder.encoderChanged();
139 |
140 | //optionally we can ignore whenever there is no change
141 | if (encoderDelta == 0)
142 | return;
143 |
144 | //for some cases we only want to know if value is increased or decreased (typically for menu items)
145 | if (encoderDelta > 0)
146 | {
147 | led_green();
148 | Serial.print("+");
149 | }
150 |
151 | else if (encoderDelta < 0)
152 | {
153 | led_red();
154 | Serial.print("-");
155 |
156 | }
157 |
158 |
159 | //for other cases we want to know what is current value. Additionally often we only want if something changed
160 | //example: when using rotary encoder to set termostat temperature, or sound volume etc
161 |
162 | //if value is changed compared to our last read
163 | if (encoderDelta != 0)
164 | {
165 | //now we need current value
166 | int16_t encoderValue = rotaryEncoder.readEncoder();
167 | //process new value. Here is simple output.
168 | Serial.print("Value: ");
169 | Serial.println(encoderValue);
170 | }
171 | }
172 | int buzzer(){
173 |
174 | ledcWriteTone(LEDC_CHANNEL_0, LEDC_BASE_FREQ);
175 | ledcWrite(LEDC_CHANNEL_0, 150);
176 | delay(300);
177 | ledcWrite(LEDC_CHANNEL_0, 0);
178 |
179 | return 1;
180 | }
181 |
182 | int led_red(){
183 | digitalWrite(LED_RED, LOW);
184 | digitalWrite(LED_GREEG, HIGH);
185 | digitalWrite(LED_BLUE, HIGH);
186 | return 1;
187 | }
188 | int led_green(){
189 | digitalWrite(LED_RED, HIGH);
190 | digitalWrite(LED_GREEG, LOW);
191 | digitalWrite(LED_BLUE, HIGH);
192 | }
193 | int led_blue(){
194 | digitalWrite(LED_RED, HIGH);
195 | digitalWrite(LED_GREEG, HIGH);
196 | digitalWrite(LED_BLUE, LOW);
197 | return 1;
198 | }
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/src/AiEsp32RotaryEncoder.cpp:
--------------------------------------------------------------------------------
1 | // based on https://github.com/marcmerlin/IoTuz code - extracted and modified Encoder code
2 | //
3 | //
4 |
5 | #include "esp_log.h"
6 | #define LOG_TAG "AiEsp32RotaryEncoder"
7 |
8 | #include "AiEsp32RotaryEncoder.h"
9 |
10 | void IRAM_ATTR AiEsp32RotaryEncoder::readEncoder_ISR()
11 | {
12 |
13 | unsigned long now = millis();
14 | portENTER_CRITICAL_ISR(&(this->mux));
15 | if (this->isEnabled)
16 | {
17 | // code from https://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino/
18 | /**/
19 | this->old_AB <<= 2; //remember previous state
20 |
21 | int8_t ENC_PORT = ((digitalRead(this->encoderBPin)) ? (1 << 1) : 0) | ((digitalRead(this->encoderAPin)) ? (1 << 0) : 0);
22 |
23 | this->old_AB |= (ENC_PORT & 0x03); //add current state
24 |
25 | //this->encoder0Pos += ( this->enc_states[( this->old_AB & 0x0f )]);
26 | int8_t currentDirection = (this->enc_states[(this->old_AB & 0x0f)]); //-1,0 or 1
27 |
28 | if (currentDirection != 0)
29 | {
30 | long prevRotaryPosition = this->encoder0Pos / this->encoderSteps;
31 | this->encoder0Pos += currentDirection;
32 | long newRotaryPosition = this->encoder0Pos / this->encoderSteps;
33 |
34 | if (newRotaryPosition != prevRotaryPosition && rotaryAccelerationCoef > 1)
35 | {
36 | //additional movements cause acceleration?
37 | // at X ms, there should be no acceleration.
38 | unsigned long accelerationLongCutoffMillis = 200;
39 | // at Y ms, we want to have maximum acceleration
40 | unsigned long accelerationShortCutffMillis = 4;
41 |
42 | // compute linear acceleration
43 | if (currentDirection == lastMovementDirection &&
44 | currentDirection != 0 &&
45 | lastMovementDirection != 0)
46 | {
47 | // ... but only of the direction of rotation matched and there
48 | // actually was a previous rotation.
49 | unsigned long millisAfterLastMotion = now - lastMovementAt;
50 |
51 | if (millisAfterLastMotion < accelerationLongCutoffMillis)
52 | {
53 | if (millisAfterLastMotion < accelerationShortCutffMillis)
54 | {
55 | millisAfterLastMotion = accelerationShortCutffMillis; // limit to maximum acceleration
56 | }
57 | if (currentDirection > 0)
58 | {
59 | this->encoder0Pos += rotaryAccelerationCoef / millisAfterLastMotion;
60 | }
61 | else
62 | {
63 | this->encoder0Pos -= rotaryAccelerationCoef / millisAfterLastMotion;
64 | }
65 | }
66 | }
67 | this->lastMovementAt = now;
68 | this->lastMovementDirection = currentDirection;
69 | }
70 |
71 | //respect limits
72 | if (this->encoder0Pos > (this->_maxEncoderValue))
73 | this->encoder0Pos = this->_circleValues ? this->_minEncoderValue : this->_maxEncoderValue;
74 | if (this->encoder0Pos < (this->_minEncoderValue))
75 | this->encoder0Pos = this->_circleValues ? this->_maxEncoderValue : this->_minEncoderValue;
76 | }
77 | }
78 | portEXIT_CRITICAL_ISR(&(this->mux));
79 | }
80 |
81 | void IRAM_ATTR AiEsp32RotaryEncoder::readButton_ISR()
82 | {
83 | portENTER_CRITICAL_ISR(&(this->buttonMux));
84 |
85 | uint8_t butt_state = !digitalRead(this->encoderButtonPin);
86 |
87 | if (!this->isEnabled)
88 | {
89 | buttonState = BUT_DISABLED;
90 | }
91 | else if (butt_state && !this->previous_butt_state)
92 | {
93 | this->previous_butt_state = true;
94 | //Serial.println("Button Pushed");
95 | buttonState = BUT_PUSHED;
96 | }
97 | else if (!butt_state && this->previous_butt_state)
98 | {
99 | this->previous_butt_state = false;
100 | //Serial.println("Button Released");
101 | buttonState = BUT_RELEASED;
102 | }
103 | else
104 | {
105 | buttonState = (butt_state ? BUT_DOWN : BUT_UP);
106 | }
107 |
108 | portEXIT_CRITICAL_ISR(&(this->buttonMux));
109 | }
110 |
111 | AiEsp32RotaryEncoder::AiEsp32RotaryEncoder(uint8_t encoder_APin, uint8_t encoder_BPin, uint8_t encoder_ButtonPin, uint8_t encoder_VccPin, uint8_t encoderSteps)
112 | {
113 | this->old_AB = 0;
114 |
115 | this->encoderAPin = encoder_APin;
116 | this->encoderBPin = encoder_BPin;
117 | this->encoderButtonPin = encoder_ButtonPin;
118 | this->encoderVccPin = encoder_VccPin;
119 | this->encoderSteps = encoderSteps;
120 |
121 | pinMode(this->encoderAPin, INPUT_PULLDOWN);
122 | pinMode(this->encoderBPin, INPUT_PULLDOWN);
123 | }
124 |
125 | void AiEsp32RotaryEncoder::setBoundaries(long minEncoderValue, long maxEncoderValue, bool circleValues)
126 | {
127 | this->_minEncoderValue = minEncoderValue * this->encoderSteps;
128 | this->_maxEncoderValue = maxEncoderValue * this->encoderSteps;
129 |
130 | this->_circleValues = circleValues;
131 | }
132 |
133 | long AiEsp32RotaryEncoder::readEncoder()
134 | {
135 | return (this->encoder0Pos / this->encoderSteps);
136 | }
137 |
138 | void AiEsp32RotaryEncoder::setEncoderValue(long newValue)
139 | {
140 | reset(newValue);
141 | }
142 |
143 | long AiEsp32RotaryEncoder::encoderChanged()
144 | {
145 | long _encoder0Pos = readEncoder();
146 | long encoder0Diff = _encoder0Pos - this->lastReadEncoder0Pos;
147 |
148 | this->lastReadEncoder0Pos = _encoder0Pos;
149 |
150 | return encoder0Diff;
151 | }
152 |
153 | void AiEsp32RotaryEncoder::setup(void (*ISR_callback)(void), void (*ISR_button)(void))
154 | {
155 | attachInterrupt(digitalPinToInterrupt(this->encoderAPin), ISR_callback, CHANGE);
156 | attachInterrupt(digitalPinToInterrupt(this->encoderBPin), ISR_callback, CHANGE);
157 | attachInterrupt(digitalPinToInterrupt(this->encoderButtonPin), ISR_button, RISING);
158 | }
159 |
160 | void AiEsp32RotaryEncoder::begin()
161 | {
162 | this->lastReadEncoder0Pos = 0;
163 | if (this->encoderVccPin >= 0)
164 | {
165 | pinMode(this->encoderVccPin, OUTPUT);
166 | digitalWrite(this->encoderVccPin, 1); //Vcc for encoder
167 | }
168 |
169 | // Initialize rotary encoder reading and decoding
170 | this->previous_butt_state = 0;
171 | if (this->encoderButtonPin >= 0)
172 | {
173 | pinMode(this->encoderButtonPin, INPUT_PULLUP);
174 | }
175 | }
176 |
177 | ButtonState AiEsp32RotaryEncoder::currentButtonState()
178 | {
179 | return buttonState;
180 | }
181 |
182 | void AiEsp32RotaryEncoder::reset(long newValue_)
183 | {
184 | newValue_ = newValue_ * this->encoderSteps;
185 | this->encoder0Pos = newValue_;
186 | this->lastReadEncoder0Pos = this->encoder0Pos;
187 | if (this->encoder0Pos > this->_maxEncoderValue)
188 | this->encoder0Pos = this->_circleValues ? this->_minEncoderValue : this->_maxEncoderValue;
189 | if (this->encoder0Pos < this->_minEncoderValue)
190 | this->encoder0Pos = this->_circleValues ? this->_maxEncoderValue : this->_minEncoderValue;
191 | }
192 |
193 | void AiEsp32RotaryEncoder::enable()
194 | {
195 | this->isEnabled = true;
196 | }
197 | void AiEsp32RotaryEncoder::disable()
198 | {
199 | this->isEnabled = false;
200 | }
201 |
--------------------------------------------------------------------------------
/example/EspNow_test/T-Encoder_Unicast/T-Encoder_Unicast.ino:
--------------------------------------------------------------------------------
1 |
2 | #include "AiEsp32RotaryEncoder.h"
3 | #include "Arduino.h"
4 | #include
5 | #include
6 |
7 | #define LED_GREEG 25
8 | #define LED_BLUE 26
9 | #define LED_RED 27
10 | #define BUZZER 19
11 | #define ROTARY_ENCODER_A_PIN 36
12 | #define ROTARY_ENCODER_B_PIN 37
13 | #define ROTARY_ENCODER_BUTTON_PIN 38
14 | #define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
15 | //depending on your encoder - try 1,2 or 4 to get expected behaviour
16 | //#define ROTARY_ENCODER_STEPS 1
17 | #define ROTARY_ENCODER_STEPS 2
18 | //#define ROTARY_ENCODER_STEPS 4
19 |
20 | //instead of changing here, rather change numbers above
21 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
22 |
23 | int16_t test_limits = 2;
24 |
25 |
26 | int led_red();
27 | int led_green();
28 | int led_blue();
29 | int buzzer();
30 |
31 | void rotary_loop();
32 | void rotary_onButtonClick();
33 |
34 |
35 | // use first channel of 16 channels (started from zero)
36 | #define LEDC_CHANNEL_0 0
37 |
38 | // use 13 bit precission for LEDC timer
39 | #define LEDC_TIMER_13_BIT 13
40 |
41 | // use 5000 Hz as a LEDC base frequency
42 | #define LEDC_BASE_FREQ 2000
43 |
44 | bool on_Button_down = false;
45 |
46 |
47 | int ledState = HIGH;
48 |
49 |
50 | //T-color MAC address
51 | uint8_t broadcastAddress[] = {0x7C, 0xDF, 0xA1, 0xB6, 0x5E, 0x54};
52 |
53 |
54 | //Data send callback function
55 | void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
56 | {
57 | char macStr[18];
58 | Serial.print("Packet to: ");
59 | snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
60 | mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
61 | Serial.println(macStr);
62 | Serial.print("Send status: ");
63 | Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
64 | Serial.println();
65 | }
66 |
67 |
68 | void setup()
69 | {
70 | Serial.begin(115200);
71 | Serial.println();
72 |
73 | // initialize digital pin output.
74 | pinMode(LED_RED, OUTPUT);
75 | pinMode(LED_GREEG, OUTPUT);
76 | pinMode(LED_BLUE, OUTPUT);
77 | pinMode(BUZZER, OUTPUT);
78 |
79 | ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
80 | ledcAttachPin(BUZZER, LEDC_CHANNEL_0);
81 |
82 | led_blue(); // blue led
83 |
84 |
85 | //we must initialize rotary encoder
86 | rotaryEncoder.begin();
87 |
88 | rotaryEncoder.setup(
89 | [] { rotaryEncoder.readEncoder_ISR(); },
90 | [] { on_Button_down = true; });
91 | //optionally we can set boundaries and if values should cycle or not
92 | bool circleValues = false;
93 | rotaryEncoder.setBoundaries(-2048, 2048, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
94 |
95 | /*Rotary acceleration introduced 25.2.2021.
96 | * in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
97 | * without accelerateion you need long time to get to that number
98 | * Using acceleration, faster you turn, faster will the value raise.
99 | * For fine tuning slow down.
100 | */
101 | //rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
102 | rotaryEncoder.setAcceleration(250); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
103 |
104 |
105 | // 初始化 ESP-NOW
106 | WiFi.mode(WIFI_STA);
107 | if (esp_now_init() != ESP_OK) {
108 | Serial.println("Error initializing ESP-NOW");
109 | return;
110 | }
111 |
112 | //Set the send data callback function
113 | esp_now_register_send_cb(OnDataSent);
114 |
115 | //Bind the data receiver
116 | esp_now_peer_info_t peerInfo;
117 | memcpy(peerInfo.peer_addr, broadcastAddress, 6);
118 | peerInfo.channel = 0;
119 | peerInfo.encrypt = false;
120 |
121 | //Check whether devices are paired successfully
122 | if (esp_now_add_peer(&peerInfo) != ESP_OK) {
123 | Serial.println("Failed to add peer");
124 | return;
125 | }
126 |
127 |
128 | }
129 |
130 | void sendMessage()
131 | {
132 | char msg[80];
133 | int len = snprintf(msg, sizeof(msg), "Toggles the T-color state from %s at %lu",
134 | WiFi.softAPmacAddress().c_str(), millis());
135 |
136 | esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &msg, sizeof(msg));
137 |
138 |
139 | if (result == ESP_OK) {
140 | Serial.println("Sent with success");
141 | } else {
142 | Serial.println("Error sending the data");
143 | }
144 |
145 | }
146 |
147 | void loop()
148 | {
149 | //in loop call your custom function which will process rotary encoder values
150 | if (millis() > 20000)
151 | rotaryEncoder.enable();
152 |
153 | rotary_loop();
154 | delay(10);
155 | }
156 |
157 |
158 | void rotary_onButtonClick()
159 | {
160 |
161 | if (on_Button_down) {
162 |
163 | static unsigned long lastTimePressed = 0;
164 | if (millis() - lastTimePressed < 500)
165 | return; //ignore multiple press in that time milliseconds
166 | lastTimePressed = millis();
167 |
168 |
169 | buzzer();
170 | Serial.print(" buzzer");
171 |
172 | sendMessage();
173 | on_Button_down = false;
174 | }
175 | }
176 |
177 | void rotary_loop()
178 | {
179 | rotary_onButtonClick();
180 | //lets see if anything changed
181 | int16_t encoderDelta = rotaryEncoder.encoderChanged();
182 |
183 | //optionally we can ignore whenever there is no change
184 | if (encoderDelta == 0)
185 | return;
186 |
187 | //for some cases we only want to know if value is increased or decreased (typically for menu items)
188 | if (encoderDelta > 0) {
189 | led_green();
190 | Serial.print("+");
191 | char msg[2];
192 | int len = snprintf(msg, sizeof(msg), "+");
193 | esp_now_send(broadcastAddress, (uint8_t *) &msg, sizeof(msg));
194 | // WifiEspNow.send(PEER, reinterpret_cast(msg), len);
195 | }
196 |
197 | else if (encoderDelta < 0) {
198 | led_red();
199 | Serial.print("-");
200 | char msg[2];
201 | int len = snprintf(msg, sizeof(msg), "-");
202 | esp_now_send(broadcastAddress, (uint8_t *) &msg, sizeof(msg));
203 | //WifiEspNow.send(PEER, reinterpret_cast(msg), len);
204 |
205 | }
206 |
207 |
208 | //for other cases we want to know what is current value. Additionally often we only want if something changed
209 | //example: when using rotary encoder to set termostat temperature, or sound volume etc
210 |
211 | //if value is changed compared to our last read
212 | if (encoderDelta != 0) {
213 | //now we need current value
214 | int16_t encoderValue = rotaryEncoder.readEncoder();
215 | //process new value. Here is simple output.
216 | Serial.print("Value: ");
217 | Serial.println(encoderValue);
218 |
219 | }
220 | }
221 |
222 | int buzzer()
223 | {
224 |
225 | ledcWriteTone(LEDC_CHANNEL_0, LEDC_BASE_FREQ);
226 | ledcWrite(LEDC_CHANNEL_0, 150);
227 | delay(300);
228 | ledcWrite(LEDC_CHANNEL_0, 0);
229 |
230 | return 1;
231 | }
232 |
233 | int led_red()
234 | {
235 | digitalWrite(LED_RED, LOW);
236 | digitalWrite(LED_GREEG, HIGH);
237 | digitalWrite(LED_BLUE, HIGH);
238 | return 1;
239 | }
240 | int led_green()
241 | {
242 | digitalWrite(LED_RED, HIGH);
243 | digitalWrite(LED_GREEG, LOW);
244 | digitalWrite(LED_BLUE, HIGH);
245 | }
246 | int led_blue()
247 | {
248 | digitalWrite(LED_RED, HIGH);
249 | digitalWrite(LED_GREEG, HIGH);
250 | digitalWrite(LED_BLUE, LOW);
251 | return 1;
252 | }
253 |
254 |
--------------------------------------------------------------------------------
/example/base_WS2812C/base_WS2812C.ino:
--------------------------------------------------------------------------------
1 | #include "AiEsp32RotaryEncoder.h"
2 | #include "Arduino.h"
3 |
4 | // Which pin on the Arduino is connected to the NeoPixels?
5 | #define LED_PIN 25// On Trinket or Gemma, suggest changing this to 1
6 | #define BUZZER 19
7 | #define ROTARY_ENCODER_A_PIN 36
8 | #define ROTARY_ENCODER_B_PIN 37
9 | #define ROTARY_ENCODER_BUTTON_PIN 38
10 | #define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
11 |
12 | //depending on your encoder - try 1,2 or 4 to get expected behaviour
13 | //#define ROTARY_ENCODER_STEPS 1
14 | #define ROTARY_ENCODER_STEPS 2
15 | //#define ROTARY_ENCODER_STEPS 4
16 |
17 | //instead of changing here, rather change numbers above
18 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
19 |
20 | int16_t test_limits = 2;
21 |
22 |
23 | #include
24 |
25 | // How many NeoPixels are attached to the Arduino?
26 | #define NUMPIXELS 2 // Popular NeoPixel ring size
27 |
28 | // When setting up the NeoPixel library, we tell it how many pixels,
29 | // and which pin to use to send signals. Note that for older NeoPixel
30 | // strips you might need to change the third parameter -- see the
31 | // strandtest example for more information on possible values.
32 | Adafruit_NeoPixel pixels(NUMPIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
33 |
34 | #define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
35 |
36 |
37 | int led_red();
38 | int led_green();
39 | int led_blue();
40 | int buzzer();
41 |
42 | void rotary_loop();
43 | void rotary_onButtonClick();
44 |
45 |
46 | // use first channel of 16 channels (started from zero)
47 | #define LEDC_CHANNEL_0 0
48 |
49 | // use 13 bit precission for LEDC timer
50 | #define LEDC_TIMER_13_BIT 13
51 |
52 | // use 5000 Hz as a LEDC base frequency
53 | #define LEDC_BASE_FREQ 2000
54 |
55 | bool on_Button_down = false;
56 | void setup()
57 | {
58 | Serial.begin(115200);
59 |
60 | // initialize digital pin output.
61 | pinMode(LED_PIN, OUTPUT);
62 | pinMode(BUZZER, OUTPUT);
63 |
64 |
65 | ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
66 | ledcAttachPin(BUZZER, LEDC_CHANNEL_0);
67 |
68 |
69 | led_blue(); // blue led
70 |
71 | pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
72 |
73 | //we must initialize rotary encoder
74 | rotaryEncoder.begin();
75 |
76 | rotaryEncoder.setup(
77 | [] { rotaryEncoder.readEncoder_ISR(); },
78 | [] { on_Button_down = true; });
79 | //optionally we can set boundaries and if values should cycle or not
80 | bool circleValues = false;
81 | rotaryEncoder.setBoundaries(0, 1000, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
82 |
83 | /*Rotary acceleration introduced 25.2.2021.
84 | * in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
85 | * without accelerateion you need long time to get to that number
86 | * Using acceleration, faster you turn, faster will the value raise.
87 | * For fine tuning slow down.
88 | */
89 | //rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
90 | rotaryEncoder.setAcceleration(250); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
91 |
92 |
93 |
94 | }
95 |
96 | // the loop function runs over and over again forever
97 | void loop()
98 | {
99 |
100 | //in loop call your custom function which will process rotary encoder values
101 | if (millis() > 20000)
102 | rotaryEncoder.enable();
103 |
104 | rotary_loop();
105 | delay(50);
106 |
107 |
108 | }
109 |
110 | void rotary_onButtonClick()
111 | {
112 |
113 | if (on_Button_down) {
114 |
115 | static unsigned long lastTimePressed = 0;
116 | if (millis() - lastTimePressed < 500)
117 | return; //ignore multiple press in that time milliseconds
118 | lastTimePressed = millis();
119 | buzzer();
120 | Serial.print(" buzzer");
121 |
122 | rotaryEncoder.setBoundaries(-test_limits, test_limits, false);
123 | Serial.print("new boundaries are between minimumn value ");
124 | Serial.print(-test_limits);
125 | Serial.print(" and maximum value");
126 | Serial.println(-test_limits);
127 | rotaryEncoder.reset();
128 |
129 | if (test_limits >= 2048)
130 | test_limits = 2;
131 | test_limits *= 2;
132 |
133 | on_Button_down = false;
134 | }
135 | }
136 |
137 | void rotary_loop()
138 | {
139 | rotary_onButtonClick();
140 | //lets see if anything changed
141 | int16_t encoderDelta = rotaryEncoder.encoderChanged();
142 |
143 | //optionally we can ignore whenever there is no change
144 | if (encoderDelta == 0)
145 | return;
146 |
147 | //for some cases we only want to know if value is increased or decreased (typically for menu items)
148 | if (encoderDelta > 0) {
149 | led_green();
150 | Serial.print("+");
151 | }
152 |
153 | if (encoderDelta < 0) {
154 | led_red();
155 | Serial.print("-");
156 |
157 | }
158 |
159 |
160 | //for other cases we want to know what is current value. Additionally often we only want if something changed
161 | //example: when using rotary encoder to set termostat temperature, or sound volume etc
162 |
163 | //if value is changed compared to our last read
164 | if (encoderDelta != 0) {
165 | //now we need current value
166 | int16_t encoderValue = rotaryEncoder.readEncoder();
167 | //process new value. Here is simple output.
168 | Serial.print("Value: ");
169 | Serial.println(encoderValue);
170 | }
171 | }
172 | int buzzer()
173 | {
174 |
175 | ledcWriteTone(LEDC_CHANNEL_0, LEDC_BASE_FREQ);
176 | ledcWrite(LEDC_CHANNEL_0, 150);
177 | delay(300);
178 | ledcWrite(LEDC_CHANNEL_0, 0);
179 |
180 | return 1;
181 | }
182 |
183 | int led_red()
184 | {
185 | pixels.clear(); // Set all pixel colors to 'off'
186 | // The first NeoPixel in a strand is #0, second is 1, all the way up
187 | // to the count of pixels minus one.
188 | for (int i = 0; i < NUMPIXELS; i++) { // For each pixel...
189 | // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
190 | // Here we're using a moderately bright green color:
191 | pixels.setPixelColor(i, pixels.Color(150, 0, 0));
192 | pixels.show(); // Send the updated pixel colors to the hardware.
193 | delay(1); // Pause before next pass through loop
194 | }
195 |
196 | return 1;
197 | }
198 | int led_green()
199 | {
200 | pixels.clear(); // Set all pixel colors to 'off'
201 | // The first NeoPixel in a strand is #0, second is 1, all the way up
202 | // to the count of pixels minus one.
203 | for (int i = 0; i < NUMPIXELS; i++) { // For each pixel...
204 | // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
205 | // Here we're using a moderately bright green color:
206 | pixels.setPixelColor(i, pixels.Color(0, 150, 0));
207 | pixels.show(); // Send the updated pixel colors to the hardware.
208 | delay(1); // Pause before next pass through loop
209 | }
210 | return 1;
211 | }
212 | int led_blue()
213 | {
214 |
215 | pixels.clear(); // Set all pixel colors to 'off'
216 | // The first NeoPixel in a strand is #0, second is 1, all the way up
217 | // to the count of pixels minus one.
218 | for (int i = 0; i < NUMPIXELS; i++) { // For each pixel...
219 | // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
220 | // Here we're using a moderately bright green color:
221 | pixels.setPixelColor(i, pixels.Color(0, 0, 150));
222 | pixels.show(); // Send the updated pixel colors to the hardware.
223 | delay(1); // Pause before next pass through loop
224 | }
225 | return 1;
226 | }
--------------------------------------------------------------------------------
/example/EspNow_test/T-Encoder_Broadcast/T-Encoder_Broadcast.ino:
--------------------------------------------------------------------------------
1 |
2 | #include "AiEsp32RotaryEncoder.h"
3 | #include "Arduino.h"
4 | #include
5 | #include
6 |
7 | #define LED_GREEG 25
8 | #define LED_BLUE 26
9 | #define LED_RED 27
10 | #define BUZZER 19
11 | #define ROTARY_ENCODER_A_PIN 36
12 | #define ROTARY_ENCODER_B_PIN 37
13 | #define ROTARY_ENCODER_BUTTON_PIN 38
14 | #define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
15 | //depending on your encoder - try 1,2 or 4 to get expected behaviour
16 | //#define ROTARY_ENCODER_STEPS 1
17 | #define ROTARY_ENCODER_STEPS 2
18 | //#define ROTARY_ENCODER_STEPS 4
19 |
20 | //instead of changing here, rather change numbers above
21 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
22 |
23 | int16_t test_limits = 2;
24 |
25 |
26 |
27 | int led_red();
28 | int led_green();
29 | int led_blue();
30 | int buzzer();
31 |
32 | void rotary_loop();
33 | void rotary_onButtonClick();
34 |
35 |
36 | // use first channel of 16 channels (started from zero)
37 | #define LEDC_CHANNEL_0 0
38 |
39 | // use 13 bit precission for LEDC timer
40 | #define LEDC_TIMER_13_BIT 13
41 |
42 | // use 5000 Hz as a LEDC base frequency
43 | #define LEDC_BASE_FREQ 2000
44 |
45 | bool on_Button_down = false;
46 |
47 |
48 | int ledState = HIGH;
49 |
50 |
51 | // REPLACE WITH THE RECEIVER'S MAC Address
52 | uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
53 | //uint8_t broadcastAddress2[] = {0xFF, , , , , };
54 | //uint8_t broadcastAddress3[] = {0xFF, , , , , };
55 |
56 | //Data send callback function
57 | void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
58 | {
59 | char macStr[18];
60 | Serial.print("Packet to: ");
61 | snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
62 | mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
63 | Serial.println(macStr);
64 | Serial.print("Send status: ");
65 | Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
66 | Serial.println();
67 | }
68 |
69 | void setup()
70 | {
71 | Serial.begin(115200);
72 | Serial.println();
73 |
74 | // initialize digital pin output.
75 | pinMode(LED_RED, OUTPUT);
76 | pinMode(LED_GREEG, OUTPUT);
77 | pinMode(LED_BLUE, OUTPUT);
78 | pinMode(BUZZER, OUTPUT);
79 |
80 | ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
81 | ledcAttachPin(BUZZER, LEDC_CHANNEL_0);
82 |
83 | led_blue(); // blue led
84 |
85 |
86 | //we must initialize rotary encoder
87 | rotaryEncoder.begin();
88 |
89 | rotaryEncoder.setup(
90 | [] { rotaryEncoder.readEncoder_ISR(); },
91 | [] { on_Button_down = true; });
92 | //optionally we can set boundaries and if values should cycle or not
93 | bool circleValues = false;
94 | rotaryEncoder.setBoundaries(-2048, 2048, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
95 |
96 | /*Rotary acceleration introduced 25.2.2021.
97 | * in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
98 | * without accelerateion you need long time to get to that number
99 | * Using acceleration, faster you turn, faster will the value raise.
100 | * For fine tuning slow down.
101 | */
102 | //rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
103 | rotaryEncoder.setAcceleration(250); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
104 |
105 | //init ESP-NOW
106 | WiFi.mode(WIFI_STA);
107 | if (esp_now_init() != ESP_OK) {
108 | Serial.println("Error initializing ESP-NOW");
109 | return;
110 | }
111 |
112 | //Set the send data callback function
113 | esp_now_register_send_cb(OnDataSent);
114 |
115 |
116 |
117 | // Register peer
118 | esp_now_peer_info_t peerInfo;
119 | memcpy(peerInfo.peer_addr, broadcastAddress, 6);
120 | peerInfo.channel = 0;
121 | peerInfo.encrypt = false;
122 |
123 | // Add peer
124 | if (esp_now_add_peer(&peerInfo) != ESP_OK) {
125 | Serial.println("Failed to add peer");
126 | return;
127 | }
128 | /*
129 | // register third peer
130 | memcpy(peerInfo.peer_addr, broadcastAddress2, 6);
131 | if (esp_now_add_peer(&peerInfo) != ESP_OK){
132 | Serial.println("Failed to add peer");
133 | return;
134 | }*/
135 | }
136 |
137 | void sendMessage()
138 | {
139 | char msg[80];
140 | int len = snprintf(msg, sizeof(msg), "Toggles the T-color state from %s at %lu",
141 | WiFi.softAPmacAddress().c_str(), millis());
142 | //send
143 | esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &msg, sizeof(msg));
144 | if (result == ESP_OK) {
145 | Serial.println("Sent with success");
146 | } else {
147 | Serial.println("Error sending the data");
148 | }
149 |
150 | }
151 |
152 | void loop()
153 | {
154 | //in loop call your custom function which will process rotary encoder values
155 | if (millis() > 20000)
156 | rotaryEncoder.enable();
157 |
158 | rotary_loop();
159 | delay(10);
160 | }
161 |
162 |
163 | void rotary_onButtonClick()
164 | {
165 |
166 | if (on_Button_down) {
167 |
168 | static unsigned long lastTimePressed = 0;
169 | if (millis() - lastTimePressed < 500)
170 | return; //ignore multiple press in that time milliseconds
171 | lastTimePressed = millis();
172 |
173 | buzzer();
174 | Serial.print(" buzzer");
175 | sendMessage();
176 | on_Button_down = false;
177 | }
178 | }
179 |
180 | void rotary_loop()
181 | {
182 | rotary_onButtonClick();
183 | //lets see if anything changed
184 | int16_t encoderDelta = rotaryEncoder.encoderChanged();
185 |
186 | //optionally we can ignore whenever there is no change
187 | if (encoderDelta == 0)
188 | return;
189 |
190 | //for some cases we only want to know if value is increased or decreased (typically for menu items)
191 | if (encoderDelta > 0) {
192 | led_green();
193 | Serial.print("+");
194 | char msg[2];
195 | int len = snprintf(msg, sizeof(msg), "+");
196 | esp_now_send(broadcastAddress, (uint8_t *) &msg, sizeof(msg));
197 | }
198 |
199 | else if (encoderDelta < 0) {
200 | led_red();
201 | Serial.print("-");
202 | char msg[2];
203 | int len = snprintf(msg, sizeof(msg), "-");
204 | esp_now_send(broadcastAddress, (uint8_t *) &msg, sizeof(msg));
205 |
206 | }
207 |
208 |
209 | //for other cases we want to know what is current value. Additionally often we only want if something changed
210 | //example: when using rotary encoder to set termostat temperature, or sound volume etc
211 |
212 | //if value is changed compared to our last read
213 | if (encoderDelta != 0) {
214 | //now we need current value
215 | int16_t encoderValue = rotaryEncoder.readEncoder();
216 | //process new value. Here is simple output.
217 | Serial.print("Value: ");
218 | Serial.println(encoderValue);
219 |
220 | }
221 | }
222 |
223 | int buzzer()
224 | {
225 |
226 | ledcWriteTone(LEDC_CHANNEL_0, LEDC_BASE_FREQ);
227 | ledcWrite(LEDC_CHANNEL_0, 150);
228 | delay(300);
229 | ledcWrite(LEDC_CHANNEL_0, 0);
230 |
231 | return 1;
232 | }
233 |
234 | int led_red()
235 | {
236 | digitalWrite(LED_RED, LOW);
237 | digitalWrite(LED_GREEG, HIGH);
238 | digitalWrite(LED_BLUE, HIGH);
239 | return 1;
240 | }
241 | int led_green()
242 | {
243 | digitalWrite(LED_RED, HIGH);
244 | digitalWrite(LED_GREEG, LOW);
245 | digitalWrite(LED_BLUE, HIGH);
246 | }
247 | int led_blue()
248 | {
249 | digitalWrite(LED_RED, HIGH);
250 | digitalWrite(LED_GREEG, HIGH);
251 | digitalWrite(LED_BLUE, LOW);
252 | return 1;
253 | }
254 |
255 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/README_old.md:
--------------------------------------------------------------------------------
1 | # Arduino Esp32 / ESP8266 MULTIPLE Encoder Library
2 |
3 | This project is based on the (https://github.com/igorantolic/ai-esp32-rotary-encoder) with only main difference that it supports
4 | multiple instances on encoders. Original library supported only one instance, but this project allows you to create more instance of encoders like this:
5 |
6 | ```c
7 | #include "AiEsp32RotaryEncoder.h"
8 | #define ROTARY_ENCODER2_A_PIN GPIO_NUM_16
9 | #define ROTARY_ENCODER2_B_PIN GPIO_NUM_4
10 | #define ROTARY_ENCODER1_A_PIN GPIO_NUM_17
11 | #define ROTARY_ENCODER1_B_PIN GPIO_NUM_5
12 |
13 | AiEsp32RotaryEncoder rotaryEncoder1 = AiEsp32RotaryEncoder(ROTARY_ENCODER1_A_PIN, ROTARY_ENCODER1_B_PIN, -1, -1);
14 | AiEsp32RotaryEncoder rotaryEncoder2 = AiEsp32RotaryEncoder(ROTARY_ENCODER2_A_PIN, ROTARY_ENCODER2_B_PIN, -1, -1);
15 | ```
16 |
17 | in setup() of arduino:
18 | ```c
19 | rotaryEncoder1.begin();
20 | rotaryEncoder1.setup([]{rotaryEncoder1.readEncoder_ISR();});
21 |
22 | rotaryEncoder2.begin();
23 | rotaryEncoder2.setup([]{rotaryEncoder2.readEncoder_ISR();});
24 | ```
25 |
26 | Rotary encoder main interrupt code is extracted from (https://github.com/marcmerlin/IoTuz) and some additional features are included here.
27 |
28 | ## Description
29 |
30 | This library enables easy implementation of rotary encoder functionality in your application for ESP32, ESP8266 (or similar microcontroller).
31 |
32 | ## Installing
33 |
34 | The downloaded code can be included as a new library into the IDE selecting the menu:
35 |
36 | Sketch / include Library / Add .Zip library
37 |
38 | Restart the Arduino IDE and follow the examples located at
39 |
40 | File -> Examples -> Ai Esp32 Rotary Encoder
41 |
42 | ## Connecting Rotary Encoder Module to your microcontroller ESP32, ESP8266 (or similar)
43 |
44 | This are instructions for "Rotary Encoder Module" which is actually Rotary Encoder with 2 resistors on board.
45 |
46 | CLK (A pin) - connect to any microcontroler intput pin with interrupt -> in this example pin 32
47 |
48 | DT (B pin) - connect to any microcontroler intput pin with interrupt -> in this example pin 21
49 |
50 | SW (button pin) - connect to any microcontroler intput pin -> in this example pin 25
51 |
52 | VCC - for this you can two options:
53 |
54 | a) connect to microcontroler VCC (then set ROTARY_ENCODER_VCC_PIN -1) or
55 |
56 | b) connect to any microcontroler output pin - in this example pin 25
57 |
58 | GND - connect to microcontroler GND
59 |
60 | ## How to use
61 |
62 | I suggest you should start using built in example. After installing library (and reopening Arduino IDE if required) open
63 |
64 | File -> Examples -> Ai Esp32 Rotary Encoder
65 |
66 | If you didnt use suggested pins, adjust defines
67 |
68 | ```c
69 | #define ROTARY_ENCODER_A_PIN 32
70 | #define ROTARY_ENCODER_B_PIN 21
71 | #define ROTARY_ENCODER_BUTTON_PIN 25
72 | #define ROTARY_ENCODER_VCC_PIN 27
73 | ```
74 |
75 | For ESP8266 you can use Dx as pin names like in example:
76 | ```c
77 | #define ROTARY_ENCODER_A_PIN D3
78 | #define ROTARY_ENCODER_B_PIN D2
79 | #define ROTARY_ENCODER_BUTTON_PIN D4
80 | ```
81 | Then upload code to microcontroller.
82 |
83 | This example is initally set that you can adjust values 0 to 10. If you try to go beyond upper limit 10, since cycle option is set to true, it will restart from 0. Also tryinf to adjust lower than 0 will go back to 10.
84 |
85 | If you press button first time, new limits -2 ... 2 are set. But this time cycle is set to false, so you have real minimum and maximum values.
86 |
87 | Further pressing button will double the same limit to -4 ... 4. Then -8...8 and so on. I wonder how far will you go. Real limt is int16 limit (signed int16) which should be sufficient for most applications.
88 |
89 | ## Details
90 |
91 | ### step 1) include library using
92 |
93 | ```c
94 | #include "AiEsp32RotaryEncoder.h"
95 | ```
96 |
97 | ### step 2) set pins used. Important: A and B pins must support interrupts.
98 |
99 | ```c
100 | #define ROTARY_ENCODER_A_PIN 32
101 | #define ROTARY_ENCODER_B_PIN 21
102 | #define ROTARY_ENCODER_BUTTON_PIN 25
103 | #define ROTARY_ENCODER_VCC_PIN 27 /*put -1 of Rotary encoder Vcc is
104 | connected directly to 3,3V;
105 | else you can use declared output pin
106 | for powering rotary encoder */
107 | ```
108 |
109 | ### step 3) declare your variable like rotaryEncoder
110 |
111 | ```c
112 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(
113 | ROTARY_ENCODER_A_PIN,
114 | ROTARY_ENCODER_B_PIN,
115 | ROTARY_ENCODER_BUTTON_PIN,
116 | ROTARY_ENCODER_VCC_PIN
117 | );
118 | ```
119 |
120 | ### step 4) in setup() function you should call begin method to initialize encoder.
121 |
122 | ```c
123 | rotaryEncoder.begin();
124 | ```
125 |
126 | ### step 4a) in setup() function you should call begin method to initialize encoder.
127 |
128 | ```c
129 | rotaryEncoder.setup([]{rotaryEncoder.readEncoder_ISR();});
130 | ```
131 |
132 | ### step 5) in loop() call some function like rotary_loop();
133 |
134 | ```c
135 | rotary_loop();
136 | ```
137 |
138 | ### step 6) define function rotary_loop()
139 |
140 | Example:
141 |
142 | ```c
143 |
144 | void rotary_loop() {
145 | //first lets handle rotary encoder button click
146 | if (rotaryEncoder.currentButtonState() == BUT_RELEASED) {
147 | //we can process it here or call separate function like:
148 | rotary_onButtonClick();
149 | }
150 |
151 | //lets see if anything changed
152 | int8_t encoderDelta = rotaryEncoder.encoderChanged();
153 |
154 | //optionally we can ignore whenever there is no change
155 | if (encoderDelta == 0) return;
156 |
157 | //for some cases we only want to know if value is
158 | //increased or decreased (typically for menu items)
159 | if (encoderDelta>0) Serial.print("+");
160 | if (encoderDelta<0) Serial.print("-");
161 |
162 | //for other cases we want to know what is current value.
163 | //Additionally often we only want if something changed
164 | //example: when using rotary encoder to set termostat temperature, or sound volume etc
165 |
166 | //if value is changed compared to our last read
167 | if (encoderDelta!=0) {
168 | //now we need current value
169 | int16_t encoderValue = rotaryEncoder.readEncoder();
170 |
171 | //process new value. Here is simple output.
172 | Serial.print("Value: ");
173 | Serial.println(encoderValue);
174 |
175 | }
176 | }
177 | ```
178 |
179 | ### step 7) if you use separate function for processing rotary encoder button click, implmement it
180 |
181 | In step 6 we call rotary_onButtonClick();
182 |
183 | example:
184 |
185 | ```c
186 | void rotary_onButtonClick() {
187 |
188 | rotaryEncoder.disable();
189 |
190 | }
191 | ```
192 |
193 | In this example we disable encoder on first click on button. Dont expect any further effects before you call
194 |
195 | ```c
196 | rotaryEncoder.enable();
197 | ```
198 |
199 | ...for obvious reasons
200 |
201 | ## List of methods
202 |
203 | ### Constructor
204 |
205 |
206 | Call to define local variable. 4 parameters are pin numbers.
207 | ```c
208 | #define ROTARY_ENCODER_A_PIN 32
209 | #define ROTARY_ENCODER_B_PIN 21
210 | #define ROTARY_ENCODER_BUTTON_PIN 25
211 | #define ROTARY_ENCODER_VCC_PIN 27
212 |
213 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(
214 | ROTARY_ENCODER_A_PIN,
215 | ROTARY_ENCODER_B_PIN,
216 | ROTARY_ENCODER_BUTTON_PIN,
217 | ROTARY_ENCODER_VCC_PIN
218 | );
219 | //or empty constructor
220 | AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder();
221 | /* Note: in case of empty constructor these are fefault pins:
222 | #define ROTARY_ENCODER_A_PIN 32
223 | #define ROTARY_ENCODER_B_PIN 21
224 | #define ROTARY_ENCODER_BUTTON_PIN 25
225 | #define ROTARY_ENCODER_VCC_PIN 27
226 | */
227 | ```
228 |
229 | ### setBoundaries (optional)
230 |
231 | sets minimum and maximum value.
232 | Additionally set circleValues to false if you want to stop at min or max limits.
233 | If you want to min to continue with max value or vice versa set to true,
234 |
235 | For example when using menu with 4 items you can call
236 | ```c
237 | rotaryEncoder.setBoundaries(1,4,true);
238 | ```
239 | rotating right will select valus 1, 2, 3, 4, 1 ,2, 3, ....
240 |
241 | while rotating left will select valus 1, 4, 3,2,1,4,3, ....
242 |
243 | ### begin - initialization method
244 |
245 | You must call this in setup()
246 | ```c
247 | void setup() {
248 | rotaryEncoder.begin();
249 | //...
250 | }
251 | ```
252 |
253 | ### reset to zero or selected value
254 |
255 | selected value will change to selected value. If value not provided 0 is assumed.
256 | Please note that there is a limit check. If value is lower than low limit low limit will be set. The same is for maximum limit.
257 |
258 | ```c
259 | //reaset to 0
260 | rotaryEncoder.reset();
261 | //reaset to 3
262 | rotaryEncoder.reset(3);
263 | ```
264 |
265 | ### disable and enable
266 |
267 | This will disable rotary movement or button events. You must call enable to contunue getting new values or button clicks.
268 | ```c
269 | rotaryEncoder.disable();
270 | rotaryEncoder.enable();
271 | ```
272 |
273 |
274 | ### readEncoder
275 |
276 | This methot will fetch current value of encoder.
277 | ```c
278 | int16_t currentValue = rotaryEncoder.readEncoder();
279 | ```
280 |
281 | ### encoderChanged
282 |
283 | This methot will return delta (absolute difference) comparing to previous read.
284 | ```c
285 | //you can react only on changes
286 | int16_t encoderDelta = rotaryEncoder.encoderChanged();
287 | if (encoderDelta>0) Serial.print("+");
288 | if (encoderDelta<0) Serial.print("-");
289 | ```
290 |
291 | ### currentButtonState
292 |
293 | This methor returns value of enum - current button state
294 | ```c
295 | ButtonState current = rotaryEncoder.currentButtonState();
296 | // or
297 | if (rotaryEncoder.currentButtonState() == BUT_RELEASED) {
298 | Serial.println("Click!");
299 | }
300 |
301 | /*
302 | Button values are:
303 | typedef enum {
304 | BUT_DOWN = 0,
305 | BUT_PUSHED = 1,
306 | BUT_UP = 2,
307 | BUT_RELEASED = 3,
308 | BUT_DISABLED = 99, //this state is after you call rotaryEncoder.disable();
309 | } ButtonState;
310 | */
311 |
312 | ```
313 |
314 |
315 |
--------------------------------------------------------------------------------
/lib/ai-esp32-rotary-encoder-master/LICENSE.md:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------