Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- 18 May 2018
- This sketch is to monitor a gray-code incremental rotary encoder with an Arduino board.
- This sketch does not use interrupts; instead it lets you set a time interval in milliseconds to check the encoder.
- It also does not use significant delay() statements, so that it allows other code to run in the time it is not active.
- Every time that the encoder state changes, a message giving the new encoder value is printed to the serial monitor window.
- For this example, the encoder used is gray code (incremental) 400 pulses-per-turn generic Chinese optical type.
- The sketch is set to count from zero to 399, and to roll over both directions (above 399 goes back to zero, and less-than-zero goes to 399).
- The sketch will also work with HID (control panel) knob-type encoders as well. HID-type encoders are usually just mechanical switches.
- Since HID encoders don't have nearly as many pulses per turn (maybe 36) and they are rotated by hand,
- the monitoring interval can be set much longer than for a motor-style encoder.
- Setting the monitoring interval to only 10 times a second is good enough.
- */
- int phaseA_pin = A2;
- int phaseB_pin = A3;
- // Incremental encoders have two output pins.
- bool encoder_enable = true; // This is a flag that allows disabling the encoder checking when you don't need it to work.
- int encoder_minimum_value = 0; // This is the minimum value that you want the encoder to read.
- int encoder_maximum_value = 12; // This is the maximum value that you want the encoder to produce.
- // The optical / motor encoder that I used for the initial sketch was a 400-pulse-per-turn model, so I used 399 as the maximum.
- // You can set the maximum value to whatever you want though; it doesn't need to match the actual encoder's specs.
- // Since an incremental incoder only generates positive and negative pulses, it can count up or down to any value.
- bool allow_high_rollover = true; // This is to control if the encoder is allowed to roll over from the maximum value back to the minimum value or not.
- bool allow_low_rollover = true; // This is to control if the encoder is allowed to roll over from less-than-minimum value back to the maximum value or not.
- // Note: this sketch uses the int type for the encoder value, that is limited to ~32K.
- bool flip_encoder_directon = false; // This is a vairable that allows you to flip the direction (rotation) of the encoder values in code,
- // without needing to change around the actual input pins.
- int encoder_current_value = 0; // This is where the encoder value is stored. You can re-set this to any value you want, at any time.
- int encoder_monitor_interval = 50; // This is the time in milliseconds to check the encoder pins.
- // For a HID-style (control panel) knob encoder you could set this to ~10 - 20 times a second and it would work perfectly fine.
- // ,,,,,,
- // For a motor-style encoder the sampling speed depends on the encoder resolution
- // and the maximum speed that the encoder is expected to be turning when you want to get its position.
- // For higher-speed sampling you would need to switch the millisecond timing to microsecond values,
- // and also get rid of the serial.print() statements on every value change,
- // since the serial messages would take long enough for the encoder to miss values.
- unsigned long encoderCheck_previous_time = 0; // These two variables are for timing when to re-check the encoder pins.
- unsigned long encoderCheck_current_time = 0;
- int phaseA_value = 0; // used for saving the pin states into.
- int phaseB_value = 0;
- int encoder_previous_state = 1; // This is a number 1 to 4, indicating the condition of both pins.
- int encoder_current_state = 1;// This is a number 1 to 4, indicating the condition of both pins.
- // state #1: (A = low, B = low)
- // state #2: (A = high, B = low)
- // state #3: (A = high, B = high)
- // state #4: (A = low, B = high)
- // Function prototypes:
- int check_for_rollover(int); // This (optionally) re-sets the encoder value if it rolls over the top or bottom value.
- void display_encoder_value(); // This prints the encoder value to the serial monitor.
- void setup() {
- Serial.begin(57600); // Since the encoder value can change fast, it is advised to use a faster serial baud rate...
- pinMode(phaseA_pin, INPUT_PULLUP);
- pinMode(phaseB_pin, INPUT_PULLUP);
- /*
- For the optical motor encoders that use open-collector output lines,
- you can either use a separate voltage source with a 50K - 200K resistor to pull them up to the pin voltage,
- or you can use the Arduino's INPUT_PULLUP pinmode.
- */
- Serial.println("[OK] exiting setup.");
- }
- void loop() {
- if (encoder_enable) {
- // The encoder is only checked if it is enabled.
- encoderCheck_current_time = millis();
- if (encoderCheck_current_time > encoderCheck_previous_time) {
- // The encoder is only checked at the specified time interval.
- if (encoderCheck_current_time >= (encoderCheck_previous_time + encoder_monitor_interval)) {
- encoder_current_state = get_phase_state();
- if (encoder_current_state != encoder_previous_state) {
- // The encoder is only updated if the current state is different than the last known state.
- if (encoder_current_state == 4) {
- if (encoder_previous_state == 3) {
- // encoder turning foward
- if (flip_encoder_directon) {
- encoder_current_value--;
- }
- else {
- encoder_current_value++;
- }
- encoder_current_value = check_for_rollover(encoder_current_value);
- encoder_previous_state = encoder_current_state;
- }
- else if (encoder_previous_state == 1) {
- // encoder turning backward
- if (flip_encoder_directon) {
- encoder_current_value++;
- }
- else {
- encoder_current_value--;
- }
- encoder_current_value = check_for_rollover(encoder_current_value);
- encoder_previous_state = encoder_current_state;
- }
- }
- else if (encoder_current_state == 1) {
- if (encoder_previous_state == 4) {
- // encoder turning foward
- if (flip_encoder_directon) {
- encoder_current_value--;
- }
- else {
- encoder_current_value++;
- }
- encoder_current_value = check_for_rollover(encoder_current_value);
- encoder_previous_state = encoder_current_state;
- }
- else if (encoder_previous_state == 2) {
- // encoder turning backward
- if (flip_encoder_directon) {
- encoder_current_value++;
- }
- else {
- encoder_current_value--;
- }
- encoder_current_value = check_for_rollover(encoder_current_value);
- encoder_previous_state = encoder_current_state;
- }
- }
- else {
- if (encoder_current_state > encoder_previous_state) {
- // encoder turning forward
- if (flip_encoder_directon) {
- encoder_current_value--;
- }
- else {
- encoder_current_value++;
- }
- encoder_current_value = check_for_rollover(encoder_current_value);
- encoder_previous_state = encoder_current_state;
- }
- else {
- // encoder turning backward
- if (flip_encoder_directon) {
- encoder_current_value++;
- }
- else {
- encoder_current_value--;
- }
- encoder_current_value = check_for_rollover(encoder_current_value);
- encoder_previous_state = encoder_current_state;
- }
- }
- display_encoder_value();
- }
- encoderCheck_previous_time = millis(); // reset the timer to check again.
- }
- }
- else {
- // If the millis() clock has rolled over, this line is to make sure that it will keep working normally
- // by re-setting the encoderCheck_previous_time() again.
- encoderCheck_previous_time = millis(); // millis() rollover condition.
- }
- }
- } // end of main program loop()
- int get_phase_state() {
- phaseA_value = digitalRead(phaseA_pin);
- delayMicroseconds(100);
- phaseA_value = digitalRead(phaseA_pin);
- phaseB_value = digitalRead(phaseB_pin);
- delayMicroseconds(100);
- phaseB_value = digitalRead(phaseB_pin);
- if (phaseA_value) {
- if (phaseB_value) {
- return 3;
- }
- else {
- return 2;
- }
- }
- else {
- if (phaseB_value) {
- return 4;
- }
- else {
- return 1;
- }
- }
- }
- int check_for_rollover(int currentValue) {
- // This function checks for rollover values and resets the encoder value as needed.
- int checkedValue = 0;
- if (currentValue == (encoder_minimum_value - 1)) {
- // if the encoder value is {less than the minimum value}:
- if (allow_low_rollover == true) {
- // and you want it to reset to the maximum value:
- checkedValue = encoder_maximum_value;
- }
- else {
- // If you dont want it to reset, then leave it as it is (this will allow values below the stated minimum).
- checkedValue = currentValue;
- }
- }
- else if (currentValue == (encoder_maximum_value + 1)) {
- // If the encoder value is {over the maximum value}:
- if (allow_high_rollover == true) {
- // and you want it to reset to the minimum value:
- checkedValue = encoder_minimum_value;
- }
- else {
- // If you dont want it to reset, then leave it as it is (this will allow values above the stated maximum).
- checkedValue = currentValue;
- }
- }
- else {
- // If the current encoder value is not over the maximum or under the minimum,
- // then leave it as the same value because there is no reason to change it:
- checkedValue = currentValue;
- }
- return checkedValue;
- }
- void display_encoder_value() {
- Serial.print("end value = ");
- Serial.println(encoder_current_value);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement