Using PID within functions, is it possible?

I have got the PID (with the library) to work quite well to make a motor drive its gearbox to a particular angle which is measured with an absolute 16 bit optical encoder. At the moment the PID is in the main loop.

What I would like to do is read in commands via Ethernet (from telnet or external program) to make two motors perform various sweeps at various speeds. For example, set motor A to sweep between 90 and 180 degrees at speed A, and motor B to sweep between 0 and 90 degrees at speed B. I’d like one function to do this. Then, I would like to have the option to have another function with some other sweep routine.

Can I use the PID controller within functions, and can I pass commands and values received via Ethernet to control the motors in this manner?

If there are examples of similar tasks I’d be grateful for any links to code or hints to get started. I tried Google but get overloaded with info that doesn’t seem relevant. Thank you.

Just a thought, could the PID.Compute() be repeatedly called from inside a while loop until the setpoint is reached?

The easiest way would probably be to define the PID objects outside your function and just pass a reference to them.

i.e.

double Setpoint, Input, Output, P, I, D;
PID myPID(&Input, &Output, &Setpoint,P,I,D, DIRECT);
void setup() {
      Setpoint=blah
      P = blah blah
      .... etc

      myPID.SetMode(AUTOMATIC); 
}
void loop() {
      myFunction(myPID);
}
void myFunction(PID &myPID) {
      ..do stuff here...
      myPID.Compute();
}

And yeah, you can call PID.Compute() within a while loop. That's pretty much what you're doing by calling it in loop(), its just a different kind of loop. Keep in mind you may never reach the exact position you want, there will be some error. I would have PID continuously run with everything else going on, rather than turning it on and off at whim. If there is zero error, the PID output ends up being zero so there's no reason to turn it off

Thanks, I had the definitions and setup outside the function, as I did when calling the PID from the loop. I seem to have got the PID working. The problem seemed to be the PID settings meant that the setpoint was not reached and therefore the function was not followed through to the end. Now it does finish, after changing the PID settings, and I have an Ethernet print statement to indicate this (as a test), but the main loop doesn’t seem to be looping. It is supposed to reconnect the Ethernet and check if another command has been sent. Here is the part of the code that Im working with.

I found the Ethernet part of the code on a tutorial and it works when the Arduino is first reset. I can send the command “go” from Telnet and the function makes the PID control the motor and then after it completes the function, I don’t get the request to enter a command again unless I restart the Arduino. I would like the Ethernet to accept the next command without having to be restarted. It seems like the connection to Ethernet is lost and is not being reconnected, although I don’t know this for sure as I’m new to all this.

I hope there is enough information here to see what the problem might be. Thanks!

void loop() 
{

EthernetClient client = server.available();        //Wait for a new client

if(client){
  if(!alreadyConnected){
    client.flush();
    commandString =  "";                            //Clear commandString variable
    server.println("-->Please type a command and press the Return Key...");
    alreadyConnected = true;
  }

  while(client.available()){
    char newChar = client.read();            //Read the bytes incoming from the client

    if(newChar == 0x0D){
      server.print("Received this command: ");
      server.println(commandString);
      processCommand(commandString);
    }else{
      Serial.println(newChar);
        commandString += newChar;
    }
  }
}

/////////////////////////////////////////////////////////////////////

}

//Functions below

//processCommand() to determine what command has been received
void processCommand(String command)
{
  server.print("Processing Command ");
  server.println(command);

  if(command.indexOf("go")>-1){
    
    angleELsetpointA=50;
    angleELsetpointB=150;
    server.println("setting angle A= " );
    server.println(angleELsetpointA);
    server.println("setting angle B= " );
    server.println(angleELsetpointB);
    
    commandString = "";

for (int x=0; x<2; x++){
  while((int)angleEL != (int)angleELsetpointA)
  {
    readingEL = readPositionEL();                      //Get value from encoder
    angleEL = ((float)readingEL / 65536.0) * 360.0;    //Make that value in range of 0-360 degrees
    ELAPID.Compute();
    md.setM1Speed(speedEL);
    Serial.println(angleEL);
  }
  while((int)angleEL != angleELsetpointB)
  {
    readingEL = readPositionEL();                      //Get value from encoder
    angleEL = ((float)readingEL / 65536.0) * 360.0;    //Make that value in range of 0-360 degrees
    ELBPID.Compute();
    md.setM1Speed(speedEL);
    Serial.println(angleEL);    
  }  
}  
    
  }
   
    server.println("END OF ROUTINE...");    //Indicate that function has complete and will exit to loop.
    commandString = "";                     //Clear CommandString, ready for te next command.
    return;                                 //Return to loop
  
}

Update: I was trying the above using Telnetnet with TeraTerm and had the problem of the program not responding to repeated commands.

I installed and tried to use PUTTY and now it seems to work as expected! So the I type "go" in the PUTTY terminal, the functions runs and then stops until I type "go" and it runs again.

The next problem is to enter commands and parameters via the Telnet terminal...