I am a final year student working on my final paper and a newbie with Codesys. I plan to drive a stepper motor with a Moeller/Eaton XC201, but for now I am trying to generate a pulse train at one of the outputs. There are 10 pulses per second, 50% duty cycle, followed by a 1s pause, then repeated. So, for 10 pulses per second, you must have a pulse length of 50ms (1s divided by 10 and by 2). I have implemented this using SFC and a delay function same as in the trafficlights tutorial.
The only problem is that, when I see the output on the oscilloscope, the pulse length is 58 to 60ms (it depends), which is 8-10ms longer than it should be. I also tried (for testing purposes) to increase the pulse length to 100, 500, 1000ms. The result on the oscilloscope is the same, an extra 10ms (approx.).
Of course, I have read that this may be influenced by the cycle time and processing time, but, for the Moeller XC201, these are under 0.05ms.
What do you think may be the problem?
Thank you in advance.
Lucian
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
wrong use of the timers.
and the cycle time is about 5 to 10 ms.
when a timer is expired it is only checked when the program is on that line. (interupt is better on this.
nd when you start it again it will have a delay,
As most systems do have an RTC (which runs independent from process, you can take this time.
say if time >100 ms as last time do your thing.
another way is to do it in timed events in the task list.
however you will always have an unstable shape.
this is because you did not make a realtime process and the PLC is interuted for other tasks like visualisation and communication.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you very much for your quick reply. You made me look more thoroughly into the libraries. I have solved my problem using a predefined function block called BLINK, from Util.lib, available in the Eaton EasySoft Codesys.
I come now with another question. Suppose I have a function block that generates N pulses and I want to call it M times from another PRG, with certain arguments. THis function block return a signal called PULSE (containing the pulse train) and a flag OK when it finishes.
How do I implement this?
Because, if I use a FOR, it doesn't work when I call it inside the loop like FUNCTION(EN:=TRUE, PULSE_NO:=N). How can I make it wait for the OK, then go to the next instruction? I'm sorry I may look stupid, but this really works in classical programming like C. How do I implement this for a PLC in Codesys?
Also, how do I save the FUNCTION.PULSE variable in another global variable real-time, for output, when calling the function?
Thank you in advance and sorry for my limited knowlegde of this.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
ave a look in w www.oscat.de w and use the txt version, this way you will learn ST very quick.
the txt version is fully in ST, however you can also use the function blocks in a self made block or in a POU.
Blink works with internal timeinterupt, so it will work even if you do not call the function.
In your case make a function block and you can give it all the parameters in one line, and you can make global vars for anything you need.
In your main program you will have to make something that asks for the time elapsed and then set a flag.
you can also use a timed program look in tasks for this.
now the blinker will inetrupt your running program to set the flag, have this running free to have the highest speed.
your runners should be timed also but a lot slower like T#200ms. to avoid the processor to busy.
for your pulse train
readypuls=false
FOR number of repeats
for number of pulses
set puls on
wait
set puls off
wait
next
next
readypuls=true
In another program you can ask for this readypuls
the wait has the disadvantage that processor stops until wait is over.
to avoid this use elapsed time
wait:
if time not running then
set time = now()
else
if time+waittime < now()
then time is elapsed
endif
endif
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This extra time is used by the controller to get the info from the inputs, and set outputs, also for communication etc.
This is done before every loop.
If you stop inside a program this is also delayed, so no good.
better to look for an event or skip your program when timer is not finished.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you very much for you quick reply. I didn't check the forum for an answer until now.
I will look into what you have said one of the following days, because I don't really have enough time now.
But, again, thank you. This is very helpful.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello.
I am a final year student working on my final paper and a newbie with Codesys. I plan to drive a stepper motor with a Moeller/Eaton XC201, but for now I am trying to generate a pulse train at one of the outputs. There are 10 pulses per second, 50% duty cycle, followed by a 1s pause, then repeated. So, for 10 pulses per second, you must have a pulse length of 50ms (1s divided by 10 and by 2). I have implemented this using SFC and a delay function same as in the trafficlights tutorial.
The only problem is that, when I see the output on the oscilloscope, the pulse length is 58 to 60ms (it depends), which is 8-10ms longer than it should be. I also tried (for testing purposes) to increase the pulse length to 100, 500, 1000ms. The result on the oscilloscope is the same, an extra 10ms (approx.).
Of course, I have read that this may be influenced by the cycle time and processing time, but, for the Moeller XC201, these are under 0.05ms.
What do you think may be the problem?
Thank you in advance.
Lucian
wrong use of the timers.
and the cycle time is about 5 to 10 ms.
when a timer is expired it is only checked when the program is on that line. (interupt is better on this.
nd when you start it again it will have a delay,
As most systems do have an RTC (which runs independent from process, you can take this time.
say if time >100 ms as last time do your thing.
another way is to do it in timed events in the task list.
however you will always have an unstable shape.
this is because you did not make a realtime process and the PLC is interuted for other tasks like visualisation and communication.
Thank you very much for your quick reply. You made me look more thoroughly into the libraries. I have solved my problem using a predefined function block called BLINK, from Util.lib, available in the Eaton EasySoft Codesys.
I come now with another question. Suppose I have a function block that generates N pulses and I want to call it M times from another PRG, with certain arguments. THis function block return a signal called PULSE (containing the pulse train) and a flag OK when it finishes.
How do I implement this?
Because, if I use a FOR, it doesn't work when I call it inside the loop like FUNCTION(EN:=TRUE, PULSE_NO:=N). How can I make it wait for the OK, then go to the next instruction? I'm sorry I may look stupid, but this really works in classical programming like C. How do I implement this for a PLC in Codesys?
Also, how do I save the FUNCTION.PULSE variable in another global variable real-time, for output, when calling the function?
Thank you in advance and sorry for my limited knowlegde of this.
Of course, I know I can implement this using SFC and, finally, so I did. But, I am curious, can I do it in ST?
Thanks.
ave a look in w www.oscat.de w and use the txt version, this way you will learn ST very quick.
the txt version is fully in ST, however you can also use the function blocks in a self made block or in a POU.
Blink works with internal timeinterupt, so it will work even if you do not call the function.
In your case make a function block and you can give it all the parameters in one line, and you can make global vars for anything you need.
In your main program you will have to make something that asks for the time elapsed and then set a flag.
you can also use a timed program look in tasks for this.
now the blinker will inetrupt your running program to set the flag, have this running free to have the highest speed.
your runners should be timed also but a lot slower like T#200ms. to avoid the processor to busy.
for your pulse train
readypuls=false
FOR number of repeats
for number of pulses
set puls on
wait
set puls off
wait
next
next
readypuls=true
In another program you can ask for this readypuls
the wait has the disadvantage that processor stops until wait is over.
to avoid this use elapsed time
wait:
if time not running then
set time = now()
else
if time+waittime < now()
then time is elapsed
endif
endif
This extra time is used by the controller to get the info from the inputs, and set outputs, also for communication etc.
This is done before every loop.
If you stop inside a program this is also delayed, so no good.
better to look for an event or skip your program when timer is not finished.
Thank you very much for you quick reply. I didn't check the forum for an answer until now.
I will look into what you have said one of the following days, because I don't really have enough time now.
But, again, thank you. This is very helpful.