Third party cookies may be stored when visiting this site. Please see the cookie information.

PenguinTutor YouTube Channel

Electronic H-Bridge circuit - DC motor controller

In an earlier article I have explained how you can use a variable resistor (potentiometer) as a voltage divider. This provides a knob that you can turn where the value changes as the dial is turned. This works well for many circumstances, but has some drawbacks. Firstly the potentiometer can only be turned a set distance, often 270° or sometimes several full revolutions. The other issue is when using a potentiometer alongside an alternative method of controlling the value, such as a web interface. The rotary encoder instead provides a way that you can turn the control any number of times in one direction, and any number in the reverse direction and the microcontroller can track the direction and movement.

A typical scenario is a volume control on a modern car entertainment system. There is often a dial that you can turn to adjust the volume, but there are also buttons on the steering wheel making it convenient for the driver to control the volume without needing to take their hand off the steering wheel. If you used a potentiometer then you would not be able to use both together, or you could end up with a situation where the potentiometer says maximum volume, but the buttons have overridden that to minimum volume. With the potentiomeeter at max there would be no way to turn the volume up using the dial.

Electronics circuit rotary encoder for Raspberry Pi Pico

The solution is to use a rotary encoder. With the rotary encoder the value is relative and tells a microcontroller to increase the volume when the encoder is turned in one direction and decrease the value when it is turned in the other direction. The volume is tracked within the microcontroller which can turn the volume up and down based on either the signals from the rotary encoder or from the steering wheel audio controls.

How the rotary encoder works

The rotary encoder has two outputs which alternative between high (or 1) and low (or 0) as the encoder is turned. These may be referred to as signal A and B, or as Clock and Data, but essentially these are the same signal shifted 90 degrees out of phase. Depending upon the direction that the encoder is turned then signal A will transition to a high before or after signal B.

Rotary encoder waveforms for control of a Raspberry Pi Pico

This is shown in the waveform examples above where in the clockwise direction signal A goes high before signal B, and in the anti-clockwise direction signal B goes high before signal A. Note this is a theorectical example, as the waveform will often be inverted (if using pull-up resistors) and may not be as clean as those shown here.

Not all rotary encoders are the same

I tested three different rotary encoders for this video, but only two of them were compatible with the library used for the Raspberry Pi Pico. Fortunately the one that didn't work is an older model and is therefore less commonly available.

The ones that worked are the ALPS EC12E2430804 and the SKU026777.

The one that did NOT work is the ALPS EC16B2410408. Although this did provide discrete signals which would indicate the direction signal A and B have different pulse widths and rely on watching for a particular transition.

Debouncing

The rotary encoders are essentially switches (typically mechanical or magnetic) and as such will often be susceptable to signal bounce during a transition. This can be avoided by use of simple filters in hardware, but because the code uses a state machine it effectively avoids the problem.

Basic python example of rotary encoder program code

Before you can program the rotary encoder in Python you will need to install a rotary encoder module. This is available at: GitHub - rotary encoder module for MicroPython

You will need the files rotary.py and rotary_irq_rp2.py which need to be uploaded to the Raspberry Pi Pico (this can be done through Thonny).

Sample code is then provided in the code below.



import time

from rotary_irq_rp2 import RotaryIRQ



r = RotaryIRQ(pin_num_clk=14,

              pin_num_dt=15,

              min_val=0,

              reverse=True,

              pull_up=True,

              invert=False,

              range_mode=RotaryIRQ.RANGE_UNBOUNDED)



old_value = r.value()



while True:

    new_value = r.value()

    if new_value != old_value:

        old_value = new_value

        print(f'Value = {new_value}')

    time.sleep(0.5)

Previous Voltage divider
Voltage divider
Next Rectifier diode
Rectifier diode