01-21-2019 05:47 PM
I need to control a stepper motor and two servo motors using a cDAQ-9174 and two 9401 DIO Modules. The stepper motor has a built in controller and I am trying to control it open loop with a finite pulse train (one pulse causes the motor controller to move one step) and a digital output for direction of rotation. I am sending the finite pulse train by first reserving the counter output, setting up a "Finite Samples" output with the desired number of pulses, starting the task, then using "is task done?" and when it is stopping and re-reserving the hardware. Additionally there is a separate digital output task that controls the direction the motor spins. When I tried to run just this it seemed to work, until I tried to change the number of pulses to send at which point I would get error -201133 (see attached image). If I moved the digital output to a separate 9401 (Which I needed as I also have to add up to two servo commands to this VI) this error didn't appear.
I figured this meant I could just put the two servo commands (running as continuous samples) and the stepper motor command one one 9401 (I read that the finite sample would require two timers hence why I added a second 9401) and the digital output on the second 9401 but damn it if I don't get the same error-201133 the second I try and change the number of pulses to send.
Any help would be greatly appreciated, I'm finding this problem quite vexing.
01-21-2019
06:23 PM
- last edited on
12-18-2024
06:00 PM
by
Content Cleaner
A few things- first, please post your code, as we can't debug images 🙂
Second- according to this article the 9401 can access the counter output directly, so you don't need to create a digital output task to use the CO Pulse Frequency task. You should just be able to configure the counter output to use the digital module's output directly.
Third, your first "reserve" function isn't needed, and your second one isn't doing anything in your code, as you do a task cleanup right after it. What are you trying to do by keeping it in there?
Next, I think you're using the CO incorrectly. I don't think the Pulse Frequency output can control the number of pulses (at least I don't know how to...). It generates a continuous train of pulses at a specific frequency. In your code, I don't see you doing a Write anywhere, so I think that task is just spinning its wheels and not really doing anything. The DO task isn't using it for a clock source, and since you don't write any values it just goes until the time it takes to "not" write anything to the port. The values you write to that task should be Frequencies- not number of pulses. For this reason, I don't think you need this type of Counter task at all. You will need a second counter to act as a "gating" counter- see this article for more information. The first counter will act as a pulse train and the second will act as an "enable" on the train.
Further still, you should be able to do this using your hardware, but beware you can only have one hardware DO task running on the whole chassis (see this article for more info). I do not know if you can have a DO and a CO task running on the same DO module simultaneously, but I somewhat doubt it. For simplicity, I'd suggest writing the DO as a single, software timed point before starting your pulse train. That way nothing gets crossed up.
You should be able to do your stepper control with a single DO module, 2 counter tasks, and a software-timed DO task that you start, write, and finish before starting your CO tasks.
I hope that helps!
The way I'd recommend doing this is to set your
01-22-2019 06:40 AM
And here's yet another article that addresses the -201133 error on a 9401 module. It seems that whenever you resolve the error with the stepper alone, you'll also need to be careful about sequencing the "reserve" and start of the servo tasks.
Other notes: given the code you posted, it seems very odd to me that the resource-related error you get depends on the # of pulses you request. Are you sure you can turn the error on and off solely by change the # pulses? What's the highest # of pulses that doesn't produce the error?
-Kevin P
01-22-2019 11:23 AM - edited 01-22-2019 11:33 AM
As requested I have uploaded my code, it's in LabVIEW 2017.
The pulse generation as shown, without a write command, works just fine. I've verified it with an O-scope and it gives the requested number of pulses at the requested frequency without issue. I have to have the Reserve Control Task in the stepper counter task otherwise I will get the error -201133 error as when I try and start the task. With the reserve I do not get the error when starting the task, it will send the pulse train as requested with the correct number of pulses, but if I then change the number of pulses requested the error occurs again. This is why I added the Reserve Control Task after the stop command in an attempt to trouble shoot the issue though it made no difference so I will be removing it.
To sum up so long as I keep the three counter outputs on one 9401 and the digital output task on the second 9401 I can generate my finite pulse train as desired and it will work every time I press the button to send the pulse train so long as I make no changes. As soon as I change the number of pulses to send I get a error -201133. I'm am at a complete loss as to why this is causing the issue.
Edit: Reply to Kevin_Price
It doesn't matter what the number of pulses I request is. Whatever I start the program with will work and will continue to work. If I deviate the number of pulses by even one in either direction I get the error.
01-22-2019
12:33 PM
- last edited on
12-18-2024
06:01 PM
by
Content Cleaner
I misunderstood what you meant about changing the # of pulses to generate. I thought that you stopped the whole app, *then* changed the #, then restarted the whole app. Now I understand that you were trying to change while the app continued running, and that makes more sense.
I can only look at your original screencap pic b/c I'm on LV 2016 and can't open your latest code. With a closer look, it appears that the main problem is the order of DAQmx calls inside the loop. You ought to be stopping the task *before* reconfiguring it for a different # of pulses. It appears you're trying to reconfigure before stopping.
After fixing that part of the problem, it's possible you might then *also* run into a subtle side-effect of the DAQmx task state model. But don't concern yourself with the stuff below yet, unless the sequencing fix isn't enough on its own.
*(DAQmx task state model stuff:
Because you have "reserved" the task before starting it, a subsequent Stop will make the task revert back to "reserved" state. I don't know for certain, but it's possible you aren't allowed to call DAQmx Timing to reconfigure your finite pulse train while the task is "reserved". You may need to explicitly revert back to "verified" or "unverified" first.
After reconfiguring, it's possibly you'll also need to stop the DO task, explicitly "reserve" the finite pulse train task again, and then restart the DO task. Much as you found you needed to do during the pre-loop initialization of tasks.)
-Kevin P
01-22-2019 01:18 PM
There is a "Is task done?" that will look for the when the task is compete. If it's not complete it will do nothing, if it is complete it will stop the task, reserve the hardware again. I thought the ordering was important so I attempted to recreate the order of reservation that I had to do prior to the loop. I added a stop task to the Do and then started it again using the error wires to ensure the same reservation order as earlier. This did not fix the problem.
I think I have a workaround for this issue though I am not very happy about it. It would appear if I simply clear the -201133 then run the timer and start the task immediately after it works. I removed the reserve function form inside the loop. This is a rather crude and ugly solution. I don't honestly understand why it works but work it does.
01-22-2019 04:49 PM - edited 01-22-2019 04:51 PM
Yeah, I agree, that doesn't seem like the kind of workaround to be happy about. So I looked a little closer and thought a little harder and came up with the following:
- based on the linked article and some things you've reported, it sounds like you can get rid of the explicit "reserve" action on your step pulse task *IF* you configure your DO task for a different module than the 3 CO tasks
- presumably the DO task is just to set the stepper direction. I wouldn't start it before the loop. Instead I'd put both the start and the write inside the "OK Button" case structure, sequenced so that the DO start and DO write happen *before* starting the finite step pulse task.
- similarly, I'd stop the DO task right after stopping the step pulse task.
- if you even want or need to run the DO off the same module and you need to do the explicit "reserve" action again, putting the DO start/stop inside the case structures gives you a head start in the right direction.
-Kevin P
01-23-2019 09:29 AM
I believe I set things up as you prescribed.
-When I removed the hardware reserve outside of the loop I would get the error every loop iteration though clearing it and restarting the task still worked. If I reserved the hardware outside of the loop I wouldn't get the error on the first loop iteration nor in following commands until I changed the number of pulses and then the error would re-appear. Again clearing the error and restarting still worked.
-I attached an image of the front panel to illustrate that I have all three counter tasks on the 9401 in slot 3 while the digital out task is on the 9401 in slot 4.
I'm just going to have to run with the program as is because I'm about to become the bottleneck on this test setup but lord knows this is a frustrating solution.
Thanks for all the help though Kevin! I appreciate it
01-23-2019 10:39 AM
Vexing. For now, I'll go with the plan to reserve the CO task before starting DO. The linked article didn't *sound* like that should be necessary when DO is on a different module, but let's just go with it.
I have a theory that I don't have time to explain thoroughly. Summarizing:
1. Doing the "reserve" action for CO before calling DAQmx Timing might be a mistake.
2. Let's try bringing the "reserve" action inside the "OK Button" case structure.
3. Sequence those calls in this order: DAQmx Timing for CO, "reserve" for CO, DAQmx Start for DO, DAQmx Write for DO, DAQmx Start for CO.
4. Use a probe or error dialog to make yourself aware of any errors after the first call to DAQmx Start for CO. Delete or bypass the inner case structure with the 2nd attempt.
4. For the loop's 2nd case structure, after stopping CO the DAQmx task state model will revert back to the pre-Start state, i.e., "reserved". This might be why the 1st call to DAQmx Timing & Start gives you an error but the 2nd doesn't. The error state will have knocked the task out of the "reserved" state, allowing the 2nd attempt to work.
5. Thus, in that 2nd case structure, make an explicit call to set the CO task to "unverified" right after stopping CO. It shouldn't matter whether you do it before or after stopping DO.
I'm fairly hopeful this might work. I suspect there's a cleaner approach, but this one should at least be quick to try.
-Kevin P
01-23-2019 01:28 PM
Tried arranging things as you specified. I'm not sure what you meant by "Unverified" so I assumed you meant "Unreserve". I attached an image of the modified program. I left the second timing and start function but just disabled it for the first attempt.
-The same -201133 error occurred when triggering the pulse train. Again if I re-enabled the error clear, and ran the timing and start again it worked.