m_ledo

Hello!

I am quite new in ladder logic - trying to learn something about. However, now I got stuck on implementating of rotary encoder (something like KY-040).

I made this:

schema.png 

Where IN3 and IN4 contacts are connected to DT and CLK pins of encoder, OUT variable is interger type.

If I understood how rotary encoders works correctly, my program should detect change (rising or falling edge) on IN3 or IN4 contacts, then add or substract value 1 depending on which contact detected change first, and immediately block other pin detection until both contacts has the same values again to avoid negating value by opposite contact signal.

 Problem is, that this works only if I turn encoder shaft really slow. When I turn it faster, output value starts to behave messy, substracts value instead of adding and so on. I thought it might be because scanning time is set to 50ms and it is too slow, but problem remains even after changing it to 5ms.

Did anyone successfully tried to implement this device into Open PLC ladder logic program? Or can anyone help me with it?

Thanks.

Quote 0 0
thiagoralves
You cannot read rotary encoders with ladder logic, it is too slow. Even with a low-level C program running on a Raspberry Pi you might skip counts here and there. You need a dedicated hardware to be able to count the pulses correctly, something like a high speed counter. My suggestion: you can implement a high speed counter on a cheap Arduino, and then add the Arduino as an OpenPLC slave device. This way OpenPLC will be able to read the encoder steps from the Arduino board, and you can have the more complex logic of your program written on OpenPLC.
Quote 0 0
m_ledo

Oh, so that is the problem.. Actually, I am using Raspberry with arduino as a slave device. But I dont understand how do you mean to use it?Because when I set arduino as slave device and upload OpenPLC firmware in it, it is not possible to program it native language to read encoder steps. Or am I wrong? Is it possible for arduino to be a slave for openPLC, and run its own program for encoder at the same time?

One thing that comes to my mind is, to have one independent arduino that will count encoder steps and send its value as number via analog output into openPLC device analog input. But that doesnt look very nice to me 🙂 

Quote 0 0
thiagoralves
You will have to modify the OpenPLC firmware on the Arduino to have the code to count the steps. If you look at the firmware for the Arduino, all it does is establish a Modbus connection with OpenPLC (master). The data captured by Arduino pins and analog inputs are made available on registers read by OpenPLC. All you have to do is put the encoder count on one of these registers. Then, on the OpenPLC side, this number will be available on one of the input registers of the Arduino (%IW100.x)
Quote 0 0
m_ledo

Well, now I understand what do you mean, however that´s quite deep programming for me so far. But maybe in some time I will try. 

Thanks a lot!

Quote 0 0
thiagoralves
If you have the code to count the steps on the Arduino already, it shouldn't be that hard. The modification is very trivial:
On OpenPLC_Uno.ino file, line 124, just change this for loop
for (int i = 0; i < NUM_INPUT_REGISTERS; ++i) 
{
    modbus.Ireg(i, (analogRead(pinMask_AIN[i]) * 64));
}

To this:
for (int i = 0; i < NUM_INPUT_REGISTERS; ++i) 
{
    if (i == 0)
        modbus.Ireg(i, encoder_count); //where encoder_count is the variable that has the current count of the encoder
    else
        modbus.Ireg(i, (analogRead(pinMask_AIN[i]) * 64));
}

After doing this, just connect the Arduino board to your OpenPLC host as you normally do, and then the encoder count will be available on %IW100.0
Quote 0 0
m_ledo

I don´t know how, I dont know why, but it works.

Thank you for your support 🙂 

Quote 0 0
xale12
I know that error because I dont defind encoder count but I  can not see where you define your variable 
Quote 0 0
thiagoralves
@xale12 you need to provide the code to read the encoder yourself. Some good resources: https://playground.arduino.cc/Main/RotaryEncoders/

Once you have the code working on the Arduino, you just define encoder_count somewhere in your code and put the encoder reading in there.
Quote 0 0
BenKissBox
Hi m_ledo,

beside the speed issue pointed by Thiago, you have to take care also of another problem : bouncing contacts. In theory, handling rotary encoders is very simple : one bit gives you the direction (0 : CCW, 1 : CW) when the other bit gives you the clock (rising edge -> read status on input A. if low : count up, if high count down)

However, anything with mechanical contacts inside provides "bouncing" signals. That comes from the fact that a switch never closes in one time. When the two contacts touch, they bounce, which makes the switch open and close very quickly for a few milliseconds. That will generate false clock data and false couting.

So, you will also need to add a debouncer in your code. As Thiago says, forget a PLC to do that, a microcontroller is much more adapted (but nothing prevents you to send the rotary encoder data to the PLC code after local processing)

Benoit
Quote 0 0