PID and encoder problem for arduino uno

Hello dear partners
i am working for the making of PID with DC motor with encoder, i have tried so many ways, and in all of them i have failed, i havebeen looking in other post but they usually do different things and that confuses me more i gues maybe the problem is the setpoint variable, because the program works good until the readin of the encoder or maybe the way i put te output. i have used this gear motor http://g01.a.alicdn.com/kf/HTB1aiI.HVXXXXc1XXXXq6xXFXXXe/ESCAP-16-Coreless-DC-12V-540RPM-font-b-Gear-b-font-font-b-Motor-b-font.jpg and the arduino uno. If you ca help i will be so happy because i have spend so many hours in this without much progress. Thnaks for your attention

Esclavo_Scara.ino (1.47 KB)

What, exactly, are you measuring? What, exactly, are you trying to influence? Without that information, there is no chance of helping you.

sorry i am really new on this, i want that the reading of the encoder give me the position of the motor, if the encoder increments the motor turns clockwise. Sorry if my grammar is really bad, i have been working on this since yesterday

That doesn't explain why you think you need to use PID. PID is useful when you are trying to control temperature, or pressure, or anything where there is not a direct link between the measure attribute and the controlled attribute.

Motor position and encoder reading HAVE a direct relationship. Motor speed and motor direction have only an indirect relationship.

What does the code do that you don't want? What does it not do that you want?

PaulS:
PID is useful when you are trying to control temperature, or pressure, or anything where there is not a direct link between the measure attribute and the controlled attribute.

Well, to quote yourself: That is PURE BS! PIDs are VERY commonly used to control motor position. Virtually every precision CNC machine uses PID to control the servo motors. In fact, they typically use multiple, nested PIDs on each axis. It makes it possible to position very precisely, and very quickly. Abd there is a very direct relationship between the measured attribute (encoder position) and the controlled attribute (motor current). There are very few better ways to control a motor, and all are far more complex and expensive.

Regards,
Ray L.

jeje sorry for been to general, well the motor is going to be moving the link of a Scara robot, and i want that this arm moves fast when it´s far of the desired position, slowing while it approaches to this place, the thing that is bothering me in the program is that while i am reading the serial of the encoder it does not stop incrementing or decreasing, even if i change the setpoint, and with that i do not have PID, just a motor that is always acive. if i am able to fix this i will read a vector from matlab to change the setpoint and control this little arm. Once again sorry for not saying that in the first lines, i have not sleep for an entire day and i am kind of distracted

Every time doEncoder() is called, counter is incremented, regardless of which way the encoder is turning. What, exactly, is counter supposed to be counting?

It seems to be that if the encoder is moving one way, counter should increase. If the encoder is moving the other way, counter should decrease.

There is no reason to attach the interrupt handler again.

What is sending data to the serial port? Is it sending ASCII data or binary data?

How is the data from the serial port related to the encoder position?

Having a global variable named Input and a function argument with the same name is not a good idea.

The compute function removes the sign of the discrepancy between the measured value and the desired value. It then computes a correction factor. The sign information is never restored. So, the correction factor will not have the correct sign, and will not serve to stabilize the system.

you have a lot of reason there, i left some variables that i am not using like counter and encoder0dir, in this moment i am not sending anything in the serial port yet, i will be reading int in that part, but i stop with that because i get really confused in this part.

the serial port will be the way i change the setpoint of the arduino(still figuring out how to send it through matlab)

so making input as a global variable its a bad idea, how should i fix it?

sorry for saying this but i did not understand the whole thing of compute, are you saying that if i do not have compute the system will not be stabilized

so making input as a global variable its a bad idea, how should i fix it?

The myPID.compute() function id going to use the value in Input as one of the three needed value (Output and Setpoint are the others). You assign a value to Input, the function argument, but not to Input, the global variable. Which one does the compute() method use? The global one.

Having Input as a global argument is fine. Having Input as the function argument is NOT. Not assigning a value to Input is not.

are you saying that if i do not have compute the system will not be stabilized

No, I am not. You need to understand the relationship between the input (where you actually are), the setpoint (where you want to be), and the output (how to get from where you are to where you want to be).

Lets use a compass as the input device. You want to be heading north (0). You are heading east of north, say 30 degrees. So, you compute that you are off course, and need a correction. Just understanding that a correction of 30 degrees is needed is NOT enough. Do you turn clockwise 30 degrees or do you turn counterclockwise 30 degrees?

What you are doing now is not getting good data from the encoder, so you don't know where you are. You are not getting good data from the serial port, so you don't know where you want to be. You are computing a correction amount, based on the absolute value of the difference between two pieces of bad data. You then apply that correction in a positive direction, even if a negative correction is needed. You will never get where you want to be unless you have good data for where you are and where you want to be, AND you consider the sign of the discrepancy between where you are and where you want to be.

wow, now i know i have made some really big mistakes, i tried to fix some of them could you please tell me if what i did have sense? i deleted the variables i am not using anymore and some other things, i tried to put some marks for you to easily spot the changes i made

Esclavo_Scara.ino (1.68 KB)

You're not USING the PID! You call PID.Compute, then ignore it's Output value, and use your own logic to force the motor outputs based purely on the sign of the error. You could completely remove the PID and it would make not difference whatsoever. I suggest you spend some time with Google, and understand HOW a PID works, before you try to use one. Without understanding HOW it works, you'll never get it to work properly, as you must be capable of tuning the coefficients (and yours are certainly wrong....).

Regards,
Ray L.

i wish i could understand you, i have made like 3 o 4 programs of this (none of them worked) i tried different libraries, and even putting all the values manually, and yes the tunesettings are incorrect, i am testing the software before solving the transfer function of the engines. maybe it is too much asking but could you give a handle book of how the PID works on arduino, i really do not understand how does the commands work here and the arduino examples and instructions are not so clear for me. thanks for your attention

You need to take this one step at a time. The first step is reading the encoder correctly, for every movement the encoder makes. Can you do this?

The PID functionality assumes that you are measuring something, like the temperature of a container of water, and varying the output of a heater, with the goal of maintaining a steady temperature. If the actual temperature is above the set point, you turn the heater down. If the actual temperature is below the set point, you turn the heater up. There is no DIRECT link between the temperature of the water and the amount of current flowing through the heater.

Given this, what EXACTLY is your set point? Dump that crap, for now, of reading set point from the serial port. That is NOT working. Hardcode some value, and explain how that relates to the information you get from the encoder. If the value you assign is 787, how does that relate to the position data from the encoder? If you can't answer that, you have no way of making the encoder reading match the setpoint except be accident.

ok i have read some different things in google and arduino, i hope (really hope) i am not making another childs mistake on this code i made.

Esclavo_Scara.ino (1.35 KB)