A question for any programmers....

More
09 Nov 2011 16:54 #14718 by Caleb9849
First of all, this is more a programming question than a question about EMC itself; I hope it's not too off-topic. I have posted the question on more appropriate boards for my question, but I'm finding it hard to get any help with it. Anyone who's never done any low-level programming probably might as well quit reading here....unless you're just curious :D

I've written a small C/C++ header file to interface with a parallel port stepper motor controller. I'm using the method of ioperm(0x378, 3, 1) to get access to the three ports that I need for talking directly to the parallel port, and manually writing out with outb() the bytes needed to instruct the motors. As I understand it (I've looked at outb and it's just one assembly-code instruction), I've essentially written a small, customized "driver" for the parallel port, rather than using the typical drivers supplied with the kernel. The purpose of my driver is to be a small part of a much larger astronomy project that my dad and I are working on together. I actually have the software pretty much finished, and it works exactly as I should on the newest release (10.04) of EMC Linux.

However, in every other distribution I've tried, including *older versions of EMC LInux* , as well as Slax, and pure Ubuntu, my code behaves, but the motors operate *VERY* slowly. The impression I get is that the operating system is somehow enforcing a minimum delay between bytes out through the parallel port, thus spacing out the motor pulses too much -- but even if that's the case, I have no idea how it's doing that, how I'd attack the problem, or why the problem doesn't occur in EMC Linux 10.04. The funny thing is, the EMC application works fine for me and my hardware on both old *and* new EMC Linux, controlling the motors at full speed. But my code *only* works properly on the newest version, 10.04. I thought it might be a timing issue, and I use quite a few calls to usleep(). But re-compiling my code on the other systems doesn't change a thing. This totally baffles me, why the EMC application should work perfectly everywhere, and my code should work perfectly in one environment but cause the motors to turn much too slowly in other, very similar environments. This is a big problem for the project I'm doing, because the more full-featured Ubuntu on which the newest EMC Linux is based is too resource-hungry to accommodate the project (it needs to be dedicated to controlling the motors, and as it currently stands, I'm confined to a laptop with sub-par processing power, which causes a disastrous amount of motor jitter at higher speeds).

If anyone can offer any kind of insight on this, I'd greatly appreciate it. Let me know if there's any other information that would be helpful :)

Please Log in or Create an account to join the conversation.

More
09 Nov 2011 17:17 #14719 by andypugh
What is the interface? Are you sending step and direction pulses, or a binary protocol?

Is it possible for you to stick with a realtime Linux, or do you need this to work on unpatched distributions?

If you can use EMC2 then I would look at using HAL and RTAPI, writing a realtime parport driver in HAL, and a userspace interface for your application (your program would sit in the same place that Axis does)

Please Log in or Create an account to join the conversation.

More
09 Nov 2011 17:32 #14720 by Caleb9849
Thanks very much for the quick reply.

andypugh wrote:

What is the interface? Are you sending step and direction pulses, or a binary protocol?


I'm not exactly sure what you're asking, because both types of manipulation are necessary, so I'll just elaborate on the entire process of what I'm doing. I'm using a hardware controller for the stepper motors which connects to the computer's parallel port, just like can be used with EMC. I'm using the low-level function outb() (it's really just a macro with just one line of assembly code) to send a byte of data to the appropriate IO port, 0x378, as defined by the bios. The byte of data I send corresponds exactly to the electrical signals that the motor controller is going to receive. For example: I'm informed by the documentation for the controller that a low-to-high (0 to 1) transition in the least significant bit results in a pulse of the X-axis motor. Therefore, if I want to pulse the X motor, I output the byte xxxxxxx0, and then I output the byte xxxxxxx1, where the "x"'s mean I'm just leaving the rest of the byte alone.

Is it possible for you to stick with a realtime Linux, or do you need this to work on unpatched distributions?


The only requirement for the environment is that it cannot be too resource hungry, since the computer hardware I'm working with is limited. Other than that, I don't care, the only goal is to be able to turn the motors at full speed with no jitter. Currently, I don't believe that real-timiness ( :) ) of the kernel is related to the issue. I could be wrong about that, but the reason I say it is because the problem occurs on the 8.04 release of EMC Linux, even though it doesn't occur on the 10.04 release. 8.04 uses a realtime kernel as well, doesn't it?

If you can use EMC2 then I would look at using HAL and RTAPI, writing a realtime parport driver in HAL, and a userspace interface for your application (your program would sit in the same place that Axis does)


I will do some research into HAL and RTAPI, even though I don't think real-time vs. non-real-time is the problem. As a side note, my application is already all in userspace -- direct access to a range of IO ports, including the parallel port, 0x378 on the BIOS, can be acquired from the kernel to the user, if you have root privileges and know what function to call (ioperm).

Please Log in or Create an account to join the conversation.

More
09 Nov 2011 19:36 #14724 by andypugh
Caleb9849 wrote:

The only requirement for the environment is that it cannot be too resource hungry, since the computer hardware I'm working with is limited. Other than that, I don't care, the only goal is to be able to turn the motors at full speed with no jitter. Currently, I don't believe that real-timiness ( :) ) of the kernel is related to the issue. I could be wrong about that, but the reason I say it is because the problem occurs on the 8.04 release of EMC Linux, even though it doesn't occur on the 10.04 release. 8.04 uses a realtime kernel as well, doesn't it?


I think you should use EMC2, the realtime kernel and the existing stepgen component. It sounds to me like you have an entirely conventional step-direction drive.

I will do some research into HAL and RTAPI, even though I don't think real-time vs. non-real-time is the problem. As a side note, my application is already all in userspace -- direct access to a range of IO ports, including the parallel port, 0x378 on the BIOS, can be acquired from the kernel to the user, if you have root privileges and know what function to call (ioperm).


One of the problems with userspace access to IO ports to create step signals is that the timing can not be guaranteed. To a large extent the whole point of EMC was to bypass this limitation.
It might not matter too much at very low speeds, but it you are pulsing a stepper at 1kHz, then there is a 10mS pause in the pulse stream, the motor will either stall or overshoot a few steps, and you will lose position.

EMC2 has already solved all the problems of providing fast, synchronous, step pulses to stepper drivers (and it does do it all with inb() and outb()). Using HAL components your User-space program can simply send position requests to HAL, and the stepgen component will look after the rest. (If you want velocity control instead, then that is an option too. I imagine that you will want both, so that you can steer to a position, then track?)

Please Log in or Create an account to join the conversation.

More
09 Nov 2011 20:25 - 09 Nov 2011 20:25 #14725 by Caleb9849
andypugh wrote:

It sounds to me like you have an entirely conventional step-direction drive.


Yes, that's right.

One of the problems with userspace access to IO ports to create step signals is that the timing can not be guaranteed. To a large extent the whole point of EMC was to bypass this limitation.
It might not matter too much at very low speeds, but it you are pulsing a stepper at 1kHz, then there is a 10mS pause in the pulse stream, the motor will either stall or overshoot a few steps, and you will lose position.


We have done *very* extensive testing with my programming and the motors (even though the whole project itself is not yet complete) to verify that they move as they should. Position is never inaccurate in the slightest, no matter how much has been done or how long has been spent. The problem I'm experiencing is not an issue with "timing" in the sense that I need it to be timed exactly right, which I don't (in this circumstance). The problem is that unless I'm in EMC Linux 10.04 release, the motors simply turn too damn slowly, when I want them to go fast. :) A 10 ms pause is not a concern, and often, I intentionally pause much longer than that in between pulses, particularly when gradually ramping the speed up and down to alleviate the concern of tossing hardware around. :) Anyways, I'm rambling, my point is that my method is apparently not resulting in any inaccuracies whatsoever.

EMC2 has already solved all the problems of providing fast, synchronous, step pulses to stepper drivers (and it does do it all with inb() and outb()). Using HAL components your User-space program can simply send position requests to HAL, and the stepgen component will look after the rest. (If you want velocity control instead, then that is an option too. I imagine that you will want both, so that you can steer to a position, then track?)


You're correct in guessing that it's a tracking platform; it's actually more than just that, but I won't go into that. Admittedly, I'm not familiar with HAL, and don't really know what all it does, but what you're talking about sounds like what I've already made for myself. I can say "I need to pulse the motor that controls such-and-such part of the platform, because we're moving the platform to such-and-such position," and the interface I've made knows how to pulse the correct motor the correct amount of times, and gradually ramp the speed up and down at the beginning and end of the progression so there are no inertial problems.

I think I'm going to try a very minimalistic install of Debian's latest release, and see if that will run comfortably on the ancient laptop hardware I'm confined to, and if it gives me the results I want in the motor. I've read something about "udev" replacing HAL (although I don't understand precisely what udev is, either) in very recent years, and I'm crossing my fingers that this may be the cause of the problem I'm having, and that a minimalistic stable Debian install will give me the results I need.

Thanks again for the replies :)
Last edit: 09 Nov 2011 20:25 by Caleb9849.

Please Log in or Create an account to join the conversation.

More
09 Nov 2011 20:38 #14726 by cncbasher
emc can ramp steppers quite fast and accurately , without problem , and can move steppers at a high rate too .
but dont forget it's also a question of the type of steppers being matched to the job in hand , given velocity , torq ,power supply arrangments too.

how ancient is the laptop ? , you can always step back a few years and use a real old version of emc

Please Log in or Create an account to join the conversation.

More
09 Nov 2011 20:52 #14727 by Caleb9849
cncbasher wrote:

how ancient is the laptop ? , you can always step back a few years and use a real old version of emc


I don't think that's true. Since 8.04 gives me the problem and 10.04 doesn't, I'd be surprised if an even older version will work correctly.

Please Log in or Create an account to join the conversation.

More
11 Nov 2011 09:23 #14760 by ArcEye
Hi

I've read something about "udev" replacing HAL


I'm afraid you didn't understand what Andy was telling you, the HAL you refer to is what the computer hardware is modelled under, nothing to do with EMC.

If you have EMC running, you already have access to a realtime thread capable of outputting all the pulses you require to move your steppers.
Instead of reinventing the wheel, you could interface with EMCs hal through a realtime component (device driver) and use the existing system to provide the pulses you require to move a given distance or to a given position, instead of making your own through raw access to the parallel port.

It will probably give you a better solution, but involves another 'steep learning curve' to achieve a single object.

I'm sure some people already run EMC to completely control telescopes, with azimuth, elevation, focus etc plotted to psuedo axes?

regards

Please Log in or Create an account to join the conversation.

More
11 Nov 2011 11:00 #14761 by andypugh
ArcEye wrote:

I'm sure some people already run EMC to completely control telescopes, with azimuth, elevation, focus etc plotted to psuedo axes?


It seems like quite a reasonable use. Typing G0 X6.7525 Y-16.7161 to aim where you want, then let a kinematics module take over the conversions to siderial time so that you auto-track.

In practice that would probably lead to EMC2 throwing a minor panic as the axes moved without a G-code command, so it probably makes sense for something else to provide the telescope aiming points, doing all the calculations of time, latitude, longitude etc. but EMC2 HAL seems like the natural place to handle the actual motion. One advantage of stepgen is that it already includes acceleration and velocity limiting, you can pass it a position to go to in units of your choice, and it will go there.
www.linuxcnc.org/docview/html/hal_rtcomps.html#sec:Stepgen

Please Log in or Create an account to join the conversation.

More
11 Nov 2011 17:42 #14772 by Caleb9849
ArcEye wrote:


Instead of reinventing the wheel, you could interface with EMCs hal through a realtime component (device driver) and use the existing system to provide the pulses you require to move a given distance or to a given position, instead of making your own through raw access to the parallel port.

It will probably give you a better solution, but involves another 'steep learning curve' to achieve a single object.


Maybe I could do that. I don't know, I set out on this project with no experience programming hardware, and did things a certain way. I've got things working that way, so I'd like to stick with what I've got done.


I'm sure some people already run EMC to completely control telescopes, with azimuth, elevation, focus etc plotted to psuedo axes?


Probably, but this project is a bit more involved than just a controller. It's to control an automatic tracking platform, and it's actually more than that. I'd rather not go into the details of what it's going to do; suffice it to say that it needs the fairly in-depth programming I've written in order to work properly.

I've confirmed that this issue is not related to the real-time kernel. I now have the motors behaving with my code exactly as I want them to, in a very minimal (command line only) installation of the latest stable release of Debian, which features the standard Linux kernel. I still don't know what causes the motors to turn so slowly in some environments. A cousin of mine suggested that it might have something to do with baud rate -- I don't know, and at the moment I don't care, because what I've got going is a perfect testing environment, which is good enough for now. Thanks again for all the input!

Please Log in or Create an account to join the conversation.

Time to create page: 0.091 seconds
Powered by Kunena Forum