PID controller with Teensy 3.1

Status
Not open for further replies.

kpap

New member
Hi all, first post here. My congratulations to Paul for his excellent products!

Have made some Teensy projects in the past, but this is the first time that I think I might have to dig deep in some hardware specifics. I'm planning on using Teensy 3.1 on a small PID controller for 3 servo motors. I have made the first tests with a Teensy 3 I have and they are very promising, although I think I already have some issues with needed interrupt priorities.

So, here are the project details as well as the first questions.

This is a project for driving servos for cnc machines. I'm going to get 3 step and 3 direction signals from a PC's parallel port or from any other source (fpga cards that generate step and direction signals are common place in cnc projects). Teensy will count the step signals and together with the direction signals will know the target position of the motor's encoder. Teensy will also read the servos' quadrature encoders A and B signals (another total of 6 signals) and calculate the PID output for the motors for 3 PWMs.

I have succesfully made a simple PID loop that runs every 1 ms using IntervalTimer and checked on my oscilloscope for the function's timing which i see is excellent. I have also tied the encoder signals to an Encoder object and saw that it counts correctly. I'm also driving one motor using a PWM output. So far so good, except that I think I'm having trouble when I attach an interrupt to a pin so that I can count the step pulses. I run some tests this morning and I get a very strange behaviour from the PID output which I *think* is caused by a delay that the PID function does to the step counting function. I read in another post that all interrupts get the same default priority at first. Is this correct?

My first question will be if you think it will be feasible to have this kind of timing that I need for everything to run smooth with 3 motors in some relatively high step frequencies (say 200KHz, I don't know how far I can get and what level of programming I will need). Maybe I should use external counter ICs for this job? Second question is how I change the priority for an interrupt I defined with attachInterrupt, or the IntervalTimer priority.

Thanks in advance,
Kostas
 
Second question is how I change the priority for an interrupt I defined with attachInterrupt, or the IntervalTimer priority.

I haven't tried changing these yet myself, but there are some macros defined in mk20dx128.h:
Code:
// 0 = highest priority
// Cortex-M4: 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240
// Cortex-M0: 0,64,128,192
#define NVIC_SET_PRIORITY(irqnum, priority)  (*((volatile uint8_t *)0xE000E400 + (irqnum)) = (uint8_t)(priority))
#define NVIC_GET_PRIORITY(irqnum) (*((uint8_t *)0xE000E400 + (irqnum)))

One thing that I have used to prevent a higher priority interrupt from starting in the middle of one of my IRQ handlers is to add these lines in. I've found that it can make a big difference without having to reassign priorities:
Code:
void my_irq_handler(void)
{
    __disable_irq();
    ...
    ...
    __enable_irq();
}

Another technique I've used before when working with PWM outputs, is to let the PWM use the interrupt for its timing, but actually control the PWM settings from the main loop (not inside an interrupt), using flags set from the PWM IRQ to indicate when to do things in the main loop. This eliminates conflicting timing between two async interrupts so there is no issue of them blocking each other.
 
Thanks. I read about NVIC_SET_PRIORITY in another thread today, but don't know how I can find the interrupt number for the input pin.
Also, is it wrong setting the PWM value inside an interrupt? Will there be a conflict somewhere?
 
Thanks. I read about NVIC_SET_PRIORITY in another thread today, but don't know how I can find the interrupt number for the input pin.
They are given in the mk20dx128.h file, the path is (alter prefix as needed):
<arduinoPath>/hardware/teensy/cores/teensy3/mk20dx128.h
Start at the bottom of the file and go backwards, you will see the interrupt number definitions, along with the NVIC defines.

Also, is it wrong setting the PWM value inside an interrupt? Will there be a conflict somewhere?
The PWM is designed to put out a full cycle before updating, so it shouldn't matter if it gets updated in say the middle of a cycle. The problem with doing things inside a PWM interrupt is that if the PWM is high speed, you just run out of clock cycles.

Going back to your earlier post, you mention attaching an interrupt. I can tell you one thing that I found out recently is that the interrupt attach is not exactly a low-latency method. In being generic it incurs a processing cost, which could be screwing up your sampling. It was too high latency in my project, which was 400kHz clocked, and at 200kHz I can't see it working well either. To get higher speed interrupt response you basically need to override some core functions, specifically the portX_isr() functions in the pins_teensy.c file (same path as above). What I do is comment out those functions in there and write my own in my project using the same name. It requires experimentation to figure out what you can achieve.
 
Hi kpap,
I am very interested in your project and eager to know or you are making any progress. I'm a mechanical engineering student myself and currently looking into making a linear motor with the teensy3.1 to later become a basis for a cnc lasercutter.
The motor will also have a set of three coils to drive from a Pid controller.
My realtime/low-level programming skills are not good as I would like. And I would therefore be very interested in looking at you setup. Maybe in exchange I could help with knowledge on the control side of things. Hope to hear from you.
Kind regards
 
Hi kpap,
I am very interested in your project and eager to know or you are making any progress. I'm a mechanical engineering student myself and currently looking into making a linear motor with the teensy3.1 to later become a basis for a cnc lasercutter.
The motor will also have a set of three coils to drive from a Pid controller.
My realtime/low-level programming skills are not good as I would like. And I would therefore be very interested in looking at you setup. Maybe in exchange I could help with knowledge on the control side of things. Hope to hear from you.
Kind regards

Hi Tobias, I have paused the project for about a month now due to other reasons, but I will certainly come back to this and post here. I would love to exchange knowledge.
 
Hi Tobias, I have paused the project for about a month now due to other reasons, but I will certainly come back to this and post here. I would love to exchange knowledge.

Hi Kpap, To bad you have had to pause the project for now. I would be very interested in seeing how you got the initial PID working in realtime and how you generate to three pwm signals for the servo. I take it the pwm signals from the teensy go to a three phase bridge converter?

kind regards
 
I'm driving only one DC servo for now, so one PWM signal only. The PID calculations are made every 1 ms using IntervalTimer, it's a very simple program till now.
 
Hello everyone.

I just started reading about PID control.

I am using a linear actuator with brushless DC motor that has 3 internal hall sensors through which i can count steps and ultimately calculate position information.

Via serial communication i am planning to update the position of the motor as often as possible. I am very familiar with writing code for arduino and teensy.
But I have a bit or a problem understand what the best way is to tell a motor to go to a specific position without it over shooting and finding the right speed and timing etc.
I am correct to assume that PID control helps working out the right mix between input position, actual position and desired target position?

I found this link to a PID control library: http://www.interaxllc.com/GettingStarted/pid.zip from this page: http://www.interaxllc.com/GettingStarted/programming-the-teensy-30.html

My setup is working right now. But if new position data arrives too late the motor pauses and waits, which creates a stutter motion.
If new position info arrives before previous target position has been reach things also get messed up.

Do you guys have some general pointers?

thanks, stephan
 
Hello everyone.

I just started reading about PID control.

I am using a linear actuator with brushless DC motor that has 3 internal hall sensors through which i can count steps and ultimately calculate position information.

Via serial communication i am planning to update the position of the motor as often as possible. I am very familiar with writing code for arduino and teensy.
But I have a bit or a problem understand what the best way is to tell a motor to go to a specific position without it over shooting and finding the right speed and timing etc.
I am correct to assume that PID control helps working out the right mix between input position, actual position and desired target position?

I found this link to a PID control library: http://www.interaxllc.com/GettingStarted/pid.zip from this page: http://www.interaxllc.com/GettingStarted/programming-the-teensy-30.html

My setup is working right now. But if new position data arrives too late the motor pauses and waits, which creates a stutter motion.
If new position info arrives before previous target position has been reach things also get messed up.

Do you guys have some general pointers?

thanks, stephan

I'm definitely a novice regarding PID but I successfully implemented PID control for 8 motorfaders, see Teensy 3.6 controlled motorfader panel.
Are you implementing the control loop over a serial connection? What is the speed?
How accurate is the timing of your control loop? To calculate the derivative it is very important that the loop interval is constant,how constant it needs to be depends on your requirements.


Kind regards,

Gerrit
 
Hello Gerrit.

My communication will be with the teensy over OSC via the wiz ethernet shield.
I can alter the speed but was hoping for constant control that allows for smooth - non-stutter motion.
I hope the OSC network timing is accurate enough, but i guess i will only see once i test the PID code.

I will check your link and trying to find some code examples too.

thanks for your reply.
 
Hello Gerrit.

My communication will be with the teensy over OSC via the wiz ethernet shield.
I can alter the speed but was hoping for constant control that allows for smooth - non-stutter motion.
I hope the OSC network timing is accurate enough, but i guess i will only see once i test the PID code.

I will check your link and trying to find some code examples too.

thanks for your reply.

OSC as in Open Sound Control? I'm very interested in that and would appreciate any links you can provide on working with OSC and Teensy.

I guess my question was not formulated clearly enough. I was referring to the PID control loop, does the Teensy read the position directly or does the position have to be acquired over a serial connection?
Also, the timing is about the PID control loop running on the Teensy. Does the Teensy need to do other stuff that could interfere wit the timing?

King regards,

Gerrit
 
for OSC we pretty much followed these instructions: https://www.pjrc.com/store/wiz820_sd_adaptor.html

the teensy reads the hall sensors directly via out custom BLDC driver. the driver has the 6 MOSFETs on it IR2136 IC + etc.
via interrupts we read the hall sensors and do the usual BLDC stepping.

other than OSC, reading Hall sensors and setting the BLDC phases nothing happens on the teensy.

i found this page about PID and linear actuators http://www.phidgets.com/docs/Linear_Actuator_-_PID_Control but the code is in visual c.
i am basically re-designing the micro controller side (now with teensy) for this installation http://lozano-hemmer.com/wavefunction.php
 
Status
Not open for further replies.
Back
Top