Home→Forums→MonoBrick EV3 Firmware→Engine control – move 45°, wait, move 45°, wait
- This topic has 9 replies, 3 voices, and was last updated 9 years, 11 months ago by Anders Søborg.
-
AuthorPosts
-
November 24, 2014 at 20:57 #5004
Auctor137ParticipantHi everybody,
I’m trying to solve a Rubik Cube with the EV3 Set and therefore I have to write a program, which does this routine eight times:
- wait time x (scanning the color, less than 1s) - move 45° degrees counterclockwise
I tried this code for the beginning
using System; using System.Threading; using MonoBrickFirmware; using MonoBrickFirmware.Movement; using MonoBrickFirmware.Display; using MonoBrickFirmware.UserInput; namespace MoveMotorA90° { class Program { static void Main(string[] args) { Motor motorA = new Motor(MotorPort.OutA); motorA.ResetTacho(); motorA.On(); // First 45° motorA.SpeedProfile(-80, 15, 15, 15, true); // move motorA 45° // 80% speed, 15° accerelate, 15° hold speed, 15° break, break at end LcdConsole.WriteLine("Position A: " + motorA.GetTachoCount()); Thread.Sleep(1000); // Second 45° motorA.SpeedProfile(-80, 15, 15, 15, true); // move motorA 45° LcdConsole.WriteLine("Position A: " + motorA.GetTachoCount()); Thread.Sleep(1000); // Third 45° motorA.SpeedProfile(-80, 15, 15, 15, true); // move motorA 45° LcdConsole.WriteLine("Position A: " + motorA.GetTachoCount()); Thread.Sleep(1000); LcdConsole.WriteLine("Program shutdown in 2s"); Thread.Sleep(2000); motorA.Off(); } } }
It doesn’t work.
Sometimes the engine does not even the first 90°, it stops at 89° but the program waits for the 90°. If I turn the engine with my hand a little bit the program continues. Or it does the first 90°, displays his tacho count “90°”, then he starts again but does only 70° or less or more degrees.Another big problem is the time, I programmed 1 second to wait, but the Brick waits longer.
I also tried to delete the time to wait, but the Brick still does wait for about 4-6s. Why is it doing that?I would really appreciate some help or a easy to understand explanation of the function I have to use.
November 24, 2014 at 22:10 #5008
Anders SøborgKeymasterHi there
Great project that you are working on. I moved your topic to the right forum. Anyway to answer your questions
Sometimes the engine does not even the first 90°, it stops at 89° but the program waits for the 90°.
Your program does not use the waithandle that is returned from the speedprofile function. The execution continues but you wait 1000 ms. Please have a look at the motor example found here
/Anders
November 24, 2014 at 22:18 #5009
Anders SøborgKeymasterHi there
Sorry I did not answer your second question.
I also tried to delete the time to wait, but the Brick still does wait for about 4-6s. Why is it doing that?
The program need to JIT compile each function call (only the first time they are called). That is simply the nature of running on the .NET framework, but on a small processor like the one in the LEGO brick this can sometime takes a little bit longer than expected. On a PC you do not notice it while on the LEGO brick you will… One way to avoid this is to AOT (Ahead Of Time) compile the program (using the menu) from the program menu on the firmware. Another way is to call the function that take a long time to execute once to make the program JIT compile it – this way it executes fine the next time.
/Anders
November 24, 2014 at 22:50 #5010
Anders SøborgKeymasterHi there
I just tried you program, and it turns out that what you have observed
…If I turn the engine with my hand a little bit the program continues…
is in fact a error in the firmware that happens when you move a very small amount and the program has not been AOT compiled. I already fixed it and will create a new release tomorrow. A temporary workaround is to make the motor move a big step the first time you create a profile. I modified your program so it looks like this.
using System; using System.Threading; using MonoBrickFirmware; using MonoBrickFirmware.Movement; using MonoBrickFirmware.Display; using MonoBrickFirmware.UserInput; namespace MoveMotorA90 { class Program { static void Main(string[] args) { Motor motorA = new Motor(MotorPort.OutA); ManualResetEvent stop = new ManualResetEvent(false); bool run = true; WaitHandle motorWaitHandle; ButtonEvents press = new ButtonEvents(); press.EnterPressed += delegate { stop.Set(); run = false; }; motorA.SpeedProfile(30, 300, 300, 300, true).WaitOne(); motorA.ResetTacho(); while(run) { LcdConsole.WriteLine("Position A: " + motorA.GetTachoCount()); motorWaitHandle = motorA.SpeedProfile(30, 15, 15, 15, true); WaitHandle.WaitAny(new WaitHandle[]{motorWaitHandle, stop}); } motorA.Off(); LcdConsole.WriteLine("Position A: " + motorA.GetTachoCount()); } } }
Let me know how it goes…
/Anders
November 26, 2014 at 09:53 #5013
Jacek SParticipantHi,
Few days ago I was trying to fix it on my own.
This is my version of pooling mechanism:
private bool started = false; private void PollFunction (Object source, ElapsedEventArgs e) { if (!Monitor.TryEnter (this)) { //cancel has the lock return; } //Do the polling if (IsRunning ()) { start.Set (); started = true; } else { if (started) { stop.Set (); started = false; } } Monitor.Exit(this); } protected void StartPooling() { waitHandle.Reset(); start.Set(); stop.Set(); started = false; stop.Reset(); start.Reset(); timer.Start(); } protected WaitHandle WaitForMotorsToStartAndStop() { //Optimize the poll function to save this exstra thread (new Thread(() => { start.WaitOne(); stop.WaitOne(); timer.Stop(); start.Reset(); stop.Reset(); waitHandle.Set(); })).Start(); return waitHandle; }
And start pooling call in the speedprofile method:
public WaitHandle SpeedProfile(sbyte speed, UInt32 rampUpSteps, UInt32 constantSpeedSteps, UInt32 rampDownSteps, bool brake) { output.SetPower (0); StartPooling(); output.SetStepSpeed (speed, rampUpSteps, constantSpeedSteps, rampDownSteps, brake); return WaitForMotorsToStartAndStop(); }
I also noticed that LcdConsole.WriteLine method is not thread safe. There should be lock block:
static public void WriteLine(string format, params Object[] arg) { if (cw == null) cw = new ConsoleWriter(); lock (cw) { cw.WriteLine(string.Format(format, arg)); } }
Jacek
November 26, 2014 at 12:40 #5014
Anders SøborgKeymasterHi there
I also noticed that LcdConsole.WriteLine method is not thread safe. There should be lock block:
I don’t think this is an issue since the kernel module is thread safe. Have you seen this fail?
And start pooling call in the speedprofile method:
Great I will have a look at it. I actually think by looking at it that your suggestion is better than mine… I will have a look at it tonight.
/Anders
November 26, 2014 at 13:03 #5015
Jacek SParticipantI don’t think this is an issue since the kernel module is thread safe. Have you seen this fail?
Yes I have seen text displayed in the same line many times, when I had a lot of threads.
(I think the problem is with scrollPos variable)
Jacek- This reply was modified 9 years, 11 months ago by Jacek S.
November 26, 2014 at 13:46 #5017
Anders SøborgKeymasterHi again
Ok great – make a pull request on Git – so you can get credit for the improvements… thanks
/Anders
December 3, 2014 at 15:34 #5025
Auctor137ParticipantThanks a lot Anders, your code works great.
I’ve modified it a bit, to do only 8 turns (=360degrees).and I’ve started another Thread about the nxt color sensor.
December 3, 2014 at 18:22 #5027
Anders SøborgKeymasterHi there
I will have this issue solved in the next release – which will be soon…
/Anders
-
AuthorPosts
You must be logged in to reply to this topic.
Follow