Solved: Error with EV3 Motors using BricxCC
Re: Error with EV3 Motors using BricxCC
I tested the same thing with RotateMotorNoWaitEx, and again, it works with OUT_AB but doesn't with OUT_A.
RobotcxCC only bundles the tools for communicating with the ev3, right?
Because than codesourcery just compiles to native linux opcode which runs on the brick's OS - I boot it with the standard firmware on it and I can start the program directly from the brick's interface.
(Well, I am a Noob on low-level stuff like that, but I'm willing to learn more if necessary)
RobotcxCC only bundles the tools for communicating with the ev3, right?
Because than codesourcery just compiles to native linux opcode which runs on the brick's OS - I boot it with the standard firmware on it and I can start the program directly from the brick's interface.
(Well, I am a Noob on low-level stuff like that, but I'm willing to learn more if necessary)
Re: Error with EV3 Motors using BricxCC
// currently no way to turn off syncronization (Sync parameter is ignored)
So sayeth ev3_output.c. Looks like 1-motor isn't implemented yet. It waits for the second motor to sync, indefinitely, then the counter probably overflows and crashes the kernel, if I had to guess.
So sayeth ev3_output.c. Looks like 1-motor isn't implemented yet. It waits for the second motor to sync, indefinitely, then the counter probably overflows and crashes the kernel, if I had to guess.
Re: Error with EV3 Motors using BricxCC
So I am very curious how RotateMotorNoWait works or does not work. It does not wait until the motors finish their rotation so an additional wait after the call would be appropriate.
Here's the very simple code for RotateMotor:
I think the usleep(2) is probably bad. It should sleep more than 2 microseconds (and the comment is clearly wrong). Replacing that with Wait(2) might be worth trying.
Here's the code for OutputTest:
This is essentially identical to the OUTPUT_TEST opcode implementation in the LMS firmware. The code for OutputStepSyncEx is here:
If RotateMotorNoWait works then it must be a bug in the API layer.
John Hansen
Here's the very simple code for RotateMotor:
Code: Select all
void RotateMotorEx(byte Outputs, char Speed, int Angle, short Turn, bool Sync, bool Stop)
{
// currently no way to turn off syncronization (Sync parameter is ignored)
OutputStepSyncEx(Outputs, Speed, Turn, Angle, Stop, OWNER_NONE);
bool busy;
while (true)
{
usleep(2); // 2ms between checks
busy = false;
OutputTest(Outputs, &busy);
if (!busy) break;
}
}
Here's the code for OutputTest:
Code: Select all
bool OutputTest(byte Outputs, bool * isBusy)
{
if (!OutputInitialized())
return false;
byte Layer;
int test;
int test2;
char busyReturn[20]; // Busy mask
bool result = false;
*isBusy = false;
test2 = 0;
DecodeOutputs(&Outputs, &Layer);
if (Layer == LAYER_MASTER)
{
if (OutputInstance.PwmFile >= 0)
{
size_t bytes_read = read(OutputInstance.PwmFile, busyReturn, 10);
result = bytes_read > 0;
sscanf(busyReturn, "%u %u", &test, &test2);
*isBusy = ((Outputs & (byte)test2) != 0);
}
}
else
{
// if cDaisyCheckBusyBit(Layer, Outputs) )
*isBusy = false;
}
return result;
}
Code: Select all
bool OutputStepSyncEx(byte Outputs, char Speed, short Turn, int Step, bool useBrake, byte Owner)
{
if (!OutputInitialized())
return false;
int cmdLen = sizeof(StepOrTimeSync);
byte Layer;
StepOrTimeSync cmd;
// opOutputStepSync (outputs, speed, turn, step, brake?)
DecodeOutputs(&Outputs, &Layer);
cmd.Cmd = opOutputStepSync;
cmd.Outputs = Outputs;
cmd.Speed = Speed;
cmd.Turn = Turn;
cmd.StepOrTime = Step;
cmd.Brake = (byte)useBrake;
if (Layer == LAYER_MASTER)
{
bool result = WriteToPWMDevice((char*)&(cmd.Cmd), cmdLen) == cmdLen;
if (result)
{
int i;
for (i = 0; i < NUM_OUTPUTS; i++)
{
if (Outputs & (0x01 << i))
OutputInstance.Owners[i] = Owner;
}
}
return result;
}
else
{
return false;
/*
if (cDaisyReady() != BUSY)
{
DaisyBuf[Len++] = 0;
DaisyBuf[Len++] = 0;
DaisyBuf[Len++] = opOUTPUT_STEP_SYNC;
Len += cOutputPackParam((DATA32)0, &(DaisyBuf[Len]));
Len += cOutputPackParam((DATA32)StepSync.Nos, &(DaisyBuf[Len]));
Len += cOutputPackParam((DATA32)StepSync.Speed, &(DaisyBuf[Len]));
Len += cOutputPackParam((DATA32)StepSync.Turn, &(DaisyBuf[Len]));
Len += cOutputPackParam((DATA32)StepSync.Step, &(DaisyBuf[Len]));
Len += cOutputPackParam((DATA32)StepSync.Brake, &(DaisyBuf[Len]));
if(OK != cDaisyMotorDownStream(DaisyBuf, Len, Layer, StepSync.Nos))
{
SetObjectIp(TmpIp - 1);
DspStat = BUSYBREAK;
}
//cDaisyMotorDownStream(DaisyBuf, Len, Layer, StepSync.Nos);
}
else
{
SetObjectIp(TmpIp - 1);
DspStat = BUSYBREAK;
}
*/
}
}
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: Error with EV3 Motors using BricxCC
I assume you are talking about BricxCC. I am not sure what RobotcxCC is.endojo wrote:I tested the same thing with RotateMotorNoWaitEx, and again, it works with OUT_AB but doesn't with OUT_A.
RobotcxCC only bundles the tools for communicating with the ev3, right?
Because than codesourcery just compiles to native linux opcode which runs on the brick's OS - I boot it with the standard firmware on it and I can start the program directly from the brick's interface.
(Well, I am a Noob on low-level stuff like that, but I'm willing to learn more if necessary)
It is definitely not possible to execute a native arm-linux executable from the EV3's on-brick user interface. They do not even show up as files with the on-brick interface. The only way to execute a native-arm linux executable is via the BricxCC IDE with the Explorer tool or with the Run button on the compile toolbar. Or you can run it from a command prompt if you have shut down the VM or connected to it via telnet or SSH while the VM is still running.
If you have a native arm-linux executable running from a command prompt then I think it is likely that it could be killed with Ctrl+Break or Ctrl+C but perhaps not. I'm not in a position to test that right now.
Perhaps it would be preferable for BricxCC to launch executables as a background process by sticking " &" on the end of the command. That way the process could be killed if it hangs without completely hanging the VM executable. But if it is actually crashing a kernel module then it is a much more serious problem.
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: Error with EV3 Motors using BricxCC
Code: Select all
* opOUTPUT_STEP_SYNC: Runs two motors regulated and syncronized, duration as specified by tacho cnts
* opOUTPUT_TIME_SYNC: Runs two motors regulated and syncronized, duration as specified by time
Code: Select all
* opOUTPUT_POSITION: Runs the motor to the absolute tacho positon - Starts the motor
Code: Select all
case opOUTPUT_POSITION:
{
}
break;
Code: Select all
* opOUTPUT_STEP_POWER: Runs the motor un-regulated with ramp up const and down according to the tacho
* opOUTPUT_STEP_SPEED: Runs the motor regulated with ramp up const and down according to the tacho
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: Error with EV3 Motors using BricxCC
Sorry for the misinformation, in my haste to figure out the problem I should've mentioned I didn't have an EV3 in front of me to check everything! Seems like it's figured out now though.
Re: Error with EV3 Motors using BricxCC
Try these changes:
And in that same file insert this code after DecodeOutputs in OutputStepSyncEx (line 866) and OutputTimeSyncEx (line 932):
Please test this and let me know how it works (or does not work). This line
is, in theory, setting a 10% ramp up, 80% steady state, and 10% ramp down to the originally specified tachometer limit. I have not tested the 3 step API functions at all so I am not 100% sure how they are supposed to work. In theory, 0, Angle, 0 would work without any ramp up or ramp down.
John Hansen
Code: Select all
void RotateMotorNoWaitEx(byte Outputs, char Speed, int Angle, short Turn, bool Sync, bool Stop)
{
if (Sync)
{
byte Layer, tmpOuts;
tmpOuts = Outputs;
DecodeOutputs(&tmpOuts, &Layer);
if (tmpOuts == OUT_AB || tmpOuts == OUT_AC || tmpOuts == OUT_AD ||
tmpOuts == OUT_BC || tmpOuts == OUT_BD || tmpOuts == OUT_CD)
{
OutputStepSyncEx(Outputs, Speed, Turn, Angle, Stop, OWNER_NONE);
return;
}
}
// otherwise use a non-synchronized API call
int s1 = Angle / 10, s2 = Angle - (2*s1), s3 = s1;
OutputStepSpeedEx(Outputs, Speed, s1, s2, s3, Stop, OWNER_NONE);
}
void RotateMotorEx(byte Outputs, char Speed, int Angle, short Turn, bool Sync, bool Stop)
{
RotateMotorNoWaitEx(Outputs, Speed, Turn, Angle, Stop, OWNER_NONE);
bool busy;
while (true)
{
Wait(MS_2); // 2ms between checks
busy = false;
OutputTest(Outputs, &busy);
if (!busy) break;
}
}
Code: Select all
// it is invalid to call this function with anything other than 2 motors:
// i.e., OUT_AB, OUT_AC, OUT_AD, OUT_BC, OUT_BD, or OUT_CD
if (!(Outputs == OUT_AB || Outputs == OUT_AC || Outputs == OUT_AD ||
Outputs == OUT_BC || Outputs == OUT_BD || Outputs == OUT_CD))
return false;
Code: Select all
int s1 = Angle / 10, s2 = Angle - (2*s1), s3 = s1;
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: Error with EV3 Motors using BricxCC
I'm afraid that didn't fix it.
Trying to rotate only one motor does nothing, and two motors now crash. First it's rotating for a short amount of time fast, then it crashes and the motor continues rotating really slow.
Wait... doesn't there belong an "else" after the "if(Sync)"?
-> I tried it out, it only solved that the motor doesn't continue moving after the crash - it stops after the stuttering
Trying to rotate only one motor does nothing, and two motors now crash. First it's rotating for a short amount of time fast, then it crashes and the motor continues rotating really slow.
Wait... doesn't there belong an "else" after the "if(Sync)"?
-> I tried it out, it only solved that the motor doesn't continue moving after the crash - it stops after the stuttering
Re: Error with EV3 Motors using BricxCC
It is not clear to me which API function you are testing, RotateMotor or RotateMotorNoWait. The best thing to do is try to get the low level routines working. Try OutputStepSyncEx with one motor. It should return false now, no motors turning, no crashing. Try OutputStepSyncEx with three or more motors. It should do the same. Try it with OUT_AB, OUT_AC, OUT_AD, OUT_BC, OUT_BD, and OUT_CD and verify whether it works correctly in all of these cases. This function did not change aside from an if statement to return false if the Outputs passed into the routine were not one of the 2 motor combinations I just listed. So it should still work correctly.
There is no need for an else clause in RotateMotorNoWaitEx because if the code calls OutputStepSyncEx it exits the routine immediately thereafter. The lack of an else is so that if you pass in TRUE for the Sync parameter but you pass in a set of invalid Outputs then it will fall through in either case to the unsynchronized motor movement function call, i.e., OutputStepSpeedEx.
I just now have noticed a bug. I scewed up on the parameters being passed from RotateMotorEx to RotateMotorNoWaitEx. It used to call OutputStepSyncEx there which has a different set of parameters (the same number, though) so it compiled but the values are wrong in a few places.
Try this for RotateMotorEx:
John Hansen
There is no need for an else clause in RotateMotorNoWaitEx because if the code calls OutputStepSyncEx it exits the routine immediately thereafter. The lack of an else is so that if you pass in TRUE for the Sync parameter but you pass in a set of invalid Outputs then it will fall through in either case to the unsynchronized motor movement function call, i.e., OutputStepSpeedEx.
I just now have noticed a bug. I scewed up on the parameters being passed from RotateMotorEx to RotateMotorNoWaitEx. It used to call OutputStepSyncEx there which has a different set of parameters (the same number, though) so it compiled but the values are wrong in a few places.
Try this for RotateMotorEx:
Code: Select all
void RotateMotorEx(byte Outputs, char Speed, int Angle, short Turn, bool Sync, bool Stop)
{
RotateMotorNoWaitEx(Outputs, Speed, Angle, Turn, Sync, Stop);
bool busy;
while (true)
{
Wait(MS_2); // 2ms between checks
busy = false;
OutputTest(Outputs, &busy);
if (!busy) break;
}
}
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: Error with EV3 Motors using BricxCC
I'm sorry that I were not precise.
So right now I tried out "OutputStepSyncEx(OUT_XX, 50, 0, 360, true, OWNER_NONE);"
If i use something else than two motors, it returns false. (Which was obvious)
I have a setup of one medium motor at port A and two large ones at Port B and C.
OUT_AB: Only B makes a little stuttering.
OUT_AC: Only C makes a little stuttering.
OUT_AD: Nothing happens.
OUT_BC: Both motors do a full 360° like they're supposed to do.
OUT_BD: B makes a little stuttering.
OUT_CD: C makes a little stuttering.
(If I only tried it earlyer, I'd propably saved you some time)
Conclusion:
The medium motor doesn't get dedected; And if a big one gets paired with "nothing", a bug or whatever appears.
I really appreciate your effords and I'll keep my fingers crossed for you to get this nasty bug fixed!
So right now I tried out "OutputStepSyncEx(OUT_XX, 50, 0, 360, true, OWNER_NONE);"
If i use something else than two motors, it returns false. (Which was obvious)
I have a setup of one medium motor at port A and two large ones at Port B and C.
OUT_AB: Only B makes a little stuttering.
OUT_AC: Only C makes a little stuttering.
OUT_AD: Nothing happens.
OUT_BC: Both motors do a full 360° like they're supposed to do.
OUT_BD: B makes a little stuttering.
OUT_CD: C makes a little stuttering.
(If I only tried it earlyer, I'd propably saved you some time)
Conclusion:
The medium motor doesn't get dedected; And if a big one gets paired with "nothing", a bug or whatever appears.
I really appreciate your effords and I'll keep my fingers crossed for you to get this nasty bug fixed!
Who is online
Users browsing this forum: No registered users and 2 guests