diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 94868c4f..24de6b59 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -44,3 +44,4 @@ add_subdirectory(badger2040) add_subdirectory(interstate75) add_subdirectory(servo2040) add_subdirectory(motor2040) +add_subdirectory(encoder) diff --git a/examples/encoder/CMakeLists.txt b/examples/encoder/CMakeLists.txt new file mode 100644 index 00000000..4311badb --- /dev/null +++ b/examples/encoder/CMakeLists.txt @@ -0,0 +1,5 @@ +include(encoder_item_selector.cmake) +include(encoder_read_change.cmake) +include(encoder_read_counts.cmake) +include(encoder_read_speed.cmake) +include(encoder_value_dial.cmake) \ No newline at end of file diff --git a/examples/encoder/README.md b/examples/encoder/README.md new file mode 100644 index 00000000..2fb5d7e9 --- /dev/null +++ b/examples/encoder/README.md @@ -0,0 +1,40 @@ +# Encoder C++ Examples + +- [Examples](#examples) + - [Read Counts](#read-counts) + - [Read Change](#read-change) + - [Read Speed](#read-speed) + - [Value Dial](#value-dial) + - [Item Selector](#item-selector) + + +## Examples + +### Read Counts +[encoder_read_counts.cpp](encoder_read_counts.cpp) + +An example of how to read a mechanical rotary encoder. + + +### Read Change +[encoder_read_change.cpp](encoder_read_change.cpp) + +An example of how to read a mechanical rotary encoder, only when a change has occurred. + + +### Read Speed +[encoder_read_speed.cpp](encoder_read_speed.cpp) + +An example of how to read the speed a mechanical rotary encoder is being turned at. + + +### Value Dial +[encoder_value_dial.cpp](encoder_value_dial.cpp) + +A demonstration of a rotary encoder being used to control a value. + + +### Item Selector +[encoder_item_selector.cpp](encoder_item_selector.cpp) + +A demonstration of a rotary encoder being used to select items based on its physical position. diff --git a/examples/encoder/encoder_item_selector.cmake b/examples/encoder/encoder_item_selector.cmake new file mode 100644 index 00000000..b0ad3744 --- /dev/null +++ b/examples/encoder/encoder_item_selector.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME encoder_item_selector) +add_executable(${OUTPUT_NAME} encoder_item_selector.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + encoder + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/encoder/encoder_item_selector.cpp b/examples/encoder/encoder_item_selector.cpp new file mode 100644 index 00000000..f5829e66 --- /dev/null +++ b/examples/encoder/encoder_item_selector.cpp @@ -0,0 +1,54 @@ +#include +#include "pico/stdlib.h" + +#include "encoder.hpp" + +/* +A demonstration of a rotary encoder being used to +select items based on its physical position. + +This requires that the encoder is positioned in the same +direction at the start of every program run (e.g. upwards). +""" +*/ + +using namespace encoder; + +// Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0 +const uint PIN_A = 26; // The A channel pin +const uint PIN_B = 28; // The B channel pin +const uint PIN_C = 27; // The common pin +Encoder enc(pio0, 0, {PIN_A, PIN_B}, PIN_C); + + +// An array of items, up to the encoder's counts_per_rev +const char* ITEMS[] = {"Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet", "Black", "White"}; +const int16_t NUM_ITEMS = count_of(ITEMS); + +int16_t last_step = -1; + + +int main() { + stdio_init_all(); + + // Sleep 8 seconds to give enough time to connect up a terminal + sleep_ms(8000); + + // Uncomment the below line to reverse the counting direction + // enc.direction(REVERSED_DIR); + + // Initialise the encoder + enc.init(); + + // Loop forever + while(true) { + int16_t step = enc.step(); + if(step != last_step) { + if(step < NUM_ITEMS) + printf("%d/%d: %s\n", step, (int)enc.counts_per_rev() - 1, ITEMS[step]); + else + printf("%d/%d: %s\n", step, (int)enc.counts_per_rev() - 1, "Undefined"); + last_step = step; + } + } +} diff --git a/examples/encoder/encoder_read_change.cmake b/examples/encoder/encoder_read_change.cmake new file mode 100644 index 00000000..b9d6df96 --- /dev/null +++ b/examples/encoder/encoder_read_change.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME encoder_read_change) +add_executable(${OUTPUT_NAME} encoder_read_change.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + encoder + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/encoder/encoder_read_change.cpp b/examples/encoder/encoder_read_change.cpp new file mode 100644 index 00000000..660032e8 --- /dev/null +++ b/examples/encoder/encoder_read_change.cpp @@ -0,0 +1,45 @@ +#include +#include "pico/stdlib.h" + +#include "encoder.hpp" + +/* +An example of how to read a mechanical rotary encoder, only when a change has occurred. +*/ + +using namespace encoder; + +// Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0 +const uint PIN_A = 26; // The A channel pin +const uint PIN_B = 28; // The B channel pin +const uint PIN_C = 27; // The common pin +Encoder enc(pio0, 0, {PIN_A, PIN_B}, PIN_C); + + +int main() { + stdio_init_all(); + + // Sleep 8 seconds to give enough time to connect up a terminal + sleep_ms(8000); + + // Uncomment the below line to reverse the counting direction + // enc.direction(REVERSED_DIR); + + // Initialise the encoder + enc.init(); + + // Print out the initial count, step, and turn (they should all be zero) + printf("Count = %ld, ", enc.count()); + printf("Step = %d, ", enc.step()); + printf("Turn = %d\n", enc.turn()); + + // Loop forever + while(true) { + if(enc.delta() != 0) { + // Print out the new count, step, and turn + printf("Count = %ld, ", enc.count()); + printf("Step = %d, ", enc.step()); + printf("Turn = %d\n", enc.turn()); + } + } +} diff --git a/examples/encoder/encoder_read_counts.cmake b/examples/encoder/encoder_read_counts.cmake new file mode 100644 index 00000000..843ac3d2 --- /dev/null +++ b/examples/encoder/encoder_read_counts.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME encoder_read_counts) +add_executable(${OUTPUT_NAME} encoder_read_counts.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + encoder + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/encoder/encoder_read_counts.cpp b/examples/encoder/encoder_read_counts.cpp new file mode 100644 index 00000000..85831089 --- /dev/null +++ b/examples/encoder/encoder_read_counts.cpp @@ -0,0 +1,38 @@ +#include +#include "pico/stdlib.h" + +#include "encoder.hpp" + +/* +An example of how to read a mechanical rotary encoder. +*/ + +using namespace encoder; + +// Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0 +const uint PIN_A = 26; // The A channel pin +const uint PIN_B = 28; // The B channel pin +const uint PIN_C = 27; // The common pin +Encoder enc(pio0, 0, {PIN_A, PIN_B}, PIN_C); + + +int main() { + stdio_init_all(); + + // Uncomment the below line to reverse the counting direction + // enc.direction(REVERSED_DIR); + + // Initialise the encoder + enc.init(); + + // Loop forever + while(true) { + // Print out the count, delta, step, and turn + printf("Count = %ld, ", enc.count()); + printf("Delta = %ld, ", enc.delta()); + printf("Step = %d, ", enc.step()); + printf("Turn = %d\n", enc.turn()); + + sleep_ms(100); + } +} diff --git a/examples/encoder/encoder_read_speed.cmake b/examples/encoder/encoder_read_speed.cmake new file mode 100644 index 00000000..5914bf41 --- /dev/null +++ b/examples/encoder/encoder_read_speed.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME encoder_read_speed) +add_executable(${OUTPUT_NAME} encoder_read_speed.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + encoder + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/encoder/encoder_read_speed.cpp b/examples/encoder/encoder_read_speed.cpp new file mode 100644 index 00000000..e50e59f6 --- /dev/null +++ b/examples/encoder/encoder_read_speed.cpp @@ -0,0 +1,39 @@ +#include +#include "pico/stdlib.h" + +#include "encoder.hpp" + +/* +An example of how to read the speed a mechanical rotary encoder is being turned at. +*/ + +using namespace encoder; + +// Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0 +const uint PIN_A = 26; // The A channel pin +const uint PIN_B = 28; // The B channel pin +const uint PIN_C = 27; // The common pin +Encoder enc(pio0, 0, {PIN_A, PIN_B}, PIN_C); + + +int main() { + stdio_init_all(); + + // Uncomment the below line to reverse the counting direction + // enc.direction(REVERSED_DIR); + + // Initialise the encoder + enc.init(); + + // Loop forever + while(true) { + Encoder::Capture capture = enc.capture(); + + printf("Count = %ld, ", capture.count()); + printf("Angle = %f, ", capture.degrees()); + printf("Freq = %f, ", capture.frequency()); + printf("Speed = %f\n", capture.degrees_per_second()); + + sleep_ms(100); + } +} diff --git a/examples/encoder/encoder_value_dial.cmake b/examples/encoder/encoder_value_dial.cmake new file mode 100644 index 00000000..fa9fdf83 --- /dev/null +++ b/examples/encoder/encoder_value_dial.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME encoder_value_dial) +add_executable(${OUTPUT_NAME} encoder_value_dial.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + encoder + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/encoder/encoder_value_dial.cpp b/examples/encoder/encoder_value_dial.cpp new file mode 100644 index 00000000..e2cf4ef8 --- /dev/null +++ b/examples/encoder/encoder_value_dial.cpp @@ -0,0 +1,54 @@ +#include +#include "pico/stdlib.h" + +#include "encoder.hpp" + +/* +A demonstration of a rotary encoder being used to control a value. +*/ + +using namespace encoder; + +// Create an encoder on the 3 ADC pins, using PIO 0 and State Machine 0 +const uint PIN_A = 26; // The A channel pin +const uint PIN_B = 28; // The B channel pin +const uint PIN_C = 27; // The common pin +Encoder enc(pio0, 0, {PIN_A, PIN_B}, PIN_C); + + +// The min and max value +const int MIN_VALUE = 0; +const int MAX_VALUE = 100; + +int value = 50; + + +int main() { + stdio_init_all(); + + // Sleep 8 seconds to give enough time to connect up a terminal + sleep_ms(8000); + + // Uncomment the below line to reverse the counting direction + // enc.direction(REVERSED_DIR); + + // Initialise the encoder + enc.init(); + + // Print out the initial value + printf("Value = %d\n", value); + + // Loop forever + while(true) { + int32_t delta = enc.delta(); + if(delta != 0) { + if(delta > 0) + value = MIN(value + 1, MAX_VALUE); + else + value = MAX(value - 1, MIN_VALUE); + + // Print out the new value + printf("Value = %d\n", value); + } + } +} diff --git a/micropython/examples/encoder/README.md b/micropython/examples/encoder/README.md index 92c6ea76..6e89a78e 100644 --- a/micropython/examples/encoder/README.md +++ b/micropython/examples/encoder/README.md @@ -1,7 +1,7 @@ # Encoder MicroPython Examples - [Examples](#examples) - - [Read Encoder](#read-encoder) + - [Read Counts](#read-counts) - [Read Change](#read-change) - [Read Speed](#read-speed) - [Value Dial](#value-dial) @@ -10,8 +10,8 @@ ## Examples -### Read Encoder -[read_encoder.py](read_encoder.py) +### Read Counts +[read_counts.py](read_counts.py) An example of how to read a mechanical rotary encoder. diff --git a/micropython/examples/encoder/item_selector.py b/micropython/examples/encoder/item_selector.py index 78dc97e7..58ff8f6f 100644 --- a/micropython/examples/encoder/item_selector.py +++ b/micropython/examples/encoder/item_selector.py @@ -1,13 +1,13 @@ import gc -from encoder import Encoder, ROTARY_CPR -# from encoder import REVERSED +from encoder import Encoder +# from encoder import REVERSED_DIR """ A demonstration of a rotary encoder being used to select items based on its physical position. This requires that the encoder is positioned in the same -direction (e.g. upwards) at the start of every program run. +direction at the start of every program run (e.g. upwards). """ # Free up hardware resources ahead of creating a new Encoder @@ -17,10 +17,10 @@ gc.collect() PIN_A = 26 # The A channel pin PIN_B = 28 # The B channel pin PIN_C = 27 # The common pin -enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C, counts_per_rev=ROTARY_CPR) +enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C) # Uncomment the below line (and the top import) to reverse the counting direction -# enc.direction(REVERSED) +# enc.direction(REVERSED_DIR) # A list of items, up to the encoder's counts_per_rev @@ -33,7 +33,7 @@ while True: step = enc.step() if step != last_step: if step < len(ITEMS): - print(step, ": ", ITEMS[step], sep="") + print(step, "/", int(enc.counts_per_rev()) - 1, ": ", ITEMS[step], sep="") else: - print(step, ": ", "Undefined", sep="") + print(step, "/", int(enc.counts_per_rev()) - 1, ": ", "Undefined", sep="") last_step = step diff --git a/micropython/examples/encoder/read_change.py b/micropython/examples/encoder/read_change.py index 1adda86c..17748d90 100644 --- a/micropython/examples/encoder/read_change.py +++ b/micropython/examples/encoder/read_change.py @@ -1,6 +1,6 @@ import gc from encoder import Encoder -# from encoder import REVERSED +# from encoder import REVERSED_DIR """ An example of how to read a mechanical rotary encoder, only when a change has occurred. @@ -16,7 +16,7 @@ PIN_C = 27 # The common pin enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C) # Uncomment the below line (and the top import) to reverse the counting direction -# enc.direction(REVERSED) +# enc.direction(REVERSED_DIR) # Print out the initial count, step, and turn (they should all be zero) diff --git a/micropython/examples/encoder/read_encoder.py b/micropython/examples/encoder/read_counts.py similarity index 92% rename from micropython/examples/encoder/read_encoder.py rename to micropython/examples/encoder/read_counts.py index 3f8e7a23..46d71add 100644 --- a/micropython/examples/encoder/read_encoder.py +++ b/micropython/examples/encoder/read_counts.py @@ -1,7 +1,7 @@ import gc import time from encoder import Encoder -# from encoder import REVERSED +# from encoder import REVERSED_DIR """ An example of how to read a mechanical rotary encoder. @@ -17,7 +17,7 @@ PIN_C = 27 # The common pin enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C) # Uncomment the below line (and the top import) to reverse the counting direction -# enc.direction(REVERSED) +# enc.direction(REVERSED_DIR) # Loop forever diff --git a/micropython/examples/encoder/read_speed.py b/micropython/examples/encoder/read_speed.py index 78ecbbcf..7ad81619 100644 --- a/micropython/examples/encoder/read_speed.py +++ b/micropython/examples/encoder/read_speed.py @@ -1,7 +1,7 @@ import gc import time from encoder import Encoder -# from encoder import REVERSED +# from encoder import REVERSED_DIR """ An example of how to read the speed a mechanical rotary encoder is being turned at. @@ -17,7 +17,7 @@ PIN_C = 27 # The common pin enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C) # Uncomment the below line (and the top import) to reverse the counting direction -# enc.direction(REVERSED) +# enc.direction(REVERSED_DIR) # Loop forever diff --git a/micropython/examples/encoder/value_dial.py b/micropython/examples/encoder/value_dial.py index 1e8c773b..c498792c 100644 --- a/micropython/examples/encoder/value_dial.py +++ b/micropython/examples/encoder/value_dial.py @@ -1,6 +1,6 @@ import gc from encoder import Encoder -# from encoder import REVERSED +# from encoder import REVERSED_DIR """ A demonstration of a rotary encoder being used to control a value. @@ -16,13 +16,13 @@ PIN_C = 27 # The common pin enc = Encoder(0, 0, (PIN_A, PIN_B), PIN_C) # Uncomment the below line (and the top import) to reverse the counting direction -# enc.direction(REVERSED) +# enc.direction(REVERSED_DIR) # The min and max value MIN_VALUE = 0 -MAX_VALUE = 11 +MAX_VALUE = 100 -value = 1 +value = 50 # Print out the initial value print("Value =", value)