Quadrature Encoder

I made a Quadrature Encoder using optical gate sensors take from a printer with 20 state changes per rotation.

Using an ESP32 I am having issues reading the gates states when turning faster than 1 rotation per second, and so am loosing steps (probably due to outputting values on two displays).

I've thought of using a dedicated core in the ESP to do the reading, but are there any other methods such as dedicated chips made for this purpose, since I wanted to use the second core for something else.

what software did you use as the QEI decoder?
how fast is it rotating?
I have used QEI decoder using interupt on change to detect changes in the A and B levels

works Ok at low speeds, e.g. for menu selection etc. For higher speeds I would use a microcontroller with QEI decoder hardware such as the Arduino Due

Small Arduinos are well suited for encoder handling, by interrupt or polling as required. I don't know how the ESP32 firmware would handle an encoder task, but I don't think that this is a mission impossible for such a powerful controller.

Using an ESP32 I am having issues reading the gates states when turning faster than 1 rotation per second, and so am loosing steps (probably due to outputting values on two displays).

What is the encoder connected to? How are the optical gate sensors wired?

You will have to post your code, and explain what else is going on in the sketch as well as the encoder reading. What are you trying to do with the encoder readings?

I would expect that an interrupt based routine on an esp32 would have no problem reading the encoder at significantly higher speeds.

Hi,
Can you please post a circuit diagram of your project?

Thanks.. Tom... :slight_smile:

The current code That I wrote for the encoding is as follows

   if (lastRead != digitalRead(Encoder_PinA))
      lastRead ^= 1;
    if (lastRead2 != digitalRead(Encoder_PinB))
      lastRead2 ^= 1;

    //ESP32 doesn't like this
    //lastRead == (int)digitalRead(Encoder_PinA);
    //lastRead2 == (int)digitalRead(Encoder_PinB);

    if (lastState != lastRead || lastState2 != lastRead2)
    {      
      if ((lastState > lastRead && lastState2 == 1) || (lastState < lastRead && lastState2 == 0))
        Counter++;
      else if ((lastState > lastRead && lastState2 == 0) || (lastState < lastRead && lastState2 == 1))
        Counter--;

      lastState = lastRead;
      lastState2 = lastRead2;
    }

Which runs fast enough on its own, but I need three of them, and I need to write data into one of three I2C displays two of which are soft I2C due to address constraints. This requires quite a bit of processing and slows the read cycle down too much.

As to a wiring diagram, there really isn’t much to say… two data pins, one for each optical gate.

Hi,
Can you please put component and voltage values as well as pin numbers on your schematic please?

Have you looked for a library to read a quad encoder with ESP32?

Google
quad encoder library esp32

Thanks.. Tom... :slight_smile:

if you have a problems with conflicting I2C addresses use an I2C multiplexor

you can run 8 devices with the same address of a single hardware I2C interface rather than using software I2C

horace:
if you have a problems with conflicting I2C addresses use an I2C multiplexor
Overview | Adafruit TCA9548A 1-to-8 I2C Multiplexer Breakout | Adafruit Learning System
you can run 8 devices with the same address of a single hardware I2C interface rather than using software I2C

Horace, did you post that on the wrong topic?

The current code That I wrote for the encoding is as follows

I think the problem must be elsewhere. The code you posted, running on a 160MHz esp32 core, would probably take much less than a microsecond.

PaulRB:
Horace, did you post that on the wrong topic?

if post #5 there was mention of soft I2C due to address constraints - hence the I2C multiplexor

horace:
if post #5 there was mention of soft I2C due to address constraints - hence the I2C multiplexor

Yes, you are correct. Apologies, I missed that.

But on esp32, is all i2c done in software, like on esp8266? If so, the multiplexer would not help.

PaulRB:
But on esp32, is all i2c done in software, like on esp8266? If so, the multiplexer would not help.

the esp32_datasheet section 1.4.3 Advanced Peripheral Interfaces lists 2 × I²C interfaces so I would asume hardware I2C is used

horace:
if you have a problems with conflicting I2C addresses use an I2C multiplexor
Overview | Adafruit TCA9548A 1-to-8 I2C Multiplexer Breakout | Adafruit Learning System
you can run 8 devices with the same address of a single hardware I2C interface rather than using software I2C

Thanks, I did not know this was a thing.

PaulRB:
I think the problem must be elsewhere. The code you posted, running on a 160MHz esp32 core, would probably take much less than a microsecond.

Yes, as I wrote before the issue is most likely that I am updating three displays (2 via soft I2C, one Hardware I2C) on the same core, which causes the core to not check the pins for the duration of time necessary to do this. This is also why I figured I would need a hardware solution to keep track of the encoder until I was ready to pick up the change.

Yes, I see. It would be good to use both cores if possible. One core for time-critical operations like reading the encoders, the other for WiFi stuff and updating displays. Unfortunately I've never used esp32, only esp8266.

Could you swap to SPI interface displays? Much faster and no problems getting them to share the same bus.

Could you use tiny84/85 as slaves to monitor encoders and communicate with esp32 over i2c/spi/serial?

Hi,
If you google

esp32 using both cores

You will find quite a bit of info and examples of using both cores at once.

Tom.. :slight_smile:

PaulRB:
Yes, I see. It would be good to use both cores if possible. One core for time-critical operations like reading the encoders, the other for WiFi stuff and updating displays. Unfortunately I've never used esp32, only esp8266.

Did not want to do this as I am using the other core for communications and web.

PaulRB:
Could you swap to SPI interface displays? Much faster and no problems getting them to share the same bus.

Happen to have 6 IC2 displays lying around... also dont know how much faster SPI would be.

PaulRB:
Could you use tiny84/85 as slaves to monitor encoders and communicate with esp32 over i2c/spi/serial?

Was considering this, but I doubt an attiny would be fast enough, If anyone could confirm this it would be helpful. I honestly cant believe there is no dedicated counting IC for encoders, even though I couldn't find any.

I2c is normally 100KHz, by default. Many i2c devices can run at faster speed of 400KHz, some even faster, but check your displays and esp32 specs. If you are not using the best speed available, you should try that as first step. SPI can run up to 8MHz on standard arduino, probably much faster on esp32, but again check the specs. So SPI could potentially be 20 to 80 times faster than i2c.

EDIT: checking the data sheet for SSD1306, commonly used in OLED displays, the minimum clock cycle for i2c interface is 2.5us which corresponds to 400KHz. With SPI interface, minimum clock time is 100ns corresponding to 10MHz, so 25 x faster, if I'm reading the sheet correctly.

Yes, attiny would be fast enough.

Clock speed determines only part of a serial channel throughput. The higher the frequency the more efforts have to be put into the hardware (cables, line drivers...). In case of trouble a scope can reveal horrible signal shapes on the wires. What works fine on the work bench may fail badly in the field.