COG and object questions
idbruce
Posts: 6,197
Hello Everyone
Due to a recent question pertaining to my stepper drivers, I have been trying to create a new variable speed stepper driver.
The new driver that I am trying to create is within a seperate object file and it starts a new cog. After initializing several values, it goes into a loop to wait for value changes. This object also has a "set" method for setting the values of which the watchdog loop is waiting for change. The "set" method has several parameters that it receives from the parent object, and I am attempting to assign these parameters to local variables within the child object. Of course this is all experimental and of course the code is not working
So now I wonder is it not functioning due to the fact that the child object is in an endless loop, or is it something else? I am sure there are a lot of mistakes and problems with the following code, but I am still experimenting.
Here is some code from the parent object:
And here is the child object file:
Any input?
Bruce
Due to a recent question pertaining to my stepper drivers, I have been trying to create a new variable speed stepper driver.
The new driver that I am trying to create is within a seperate object file and it starts a new cog. After initializing several values, it goes into a loop to wait for value changes. This object also has a "set" method for setting the values of which the watchdog loop is waiting for change. The "set" method has several parameters that it receives from the parent object, and I am attempting to assign these parameters to local variables within the child object. Of course this is all experimental and of course the code is not working
So now I wonder is it not functioning due to the fact that the child object is in an endless loop, or is it something else? I am sure there are a lot of mistakes and problems with the following code, but I am still experimenting.
Here is some code from the parent object:
OBJ Stepper1 : "VariableStepperDriver" PUB Main Stepper1.Start(3, 4, 5, CLK_FREQ / 1_000_000) WAITCNT(CLKFREQ * 2 + CNT) Stepper1.SetSpeedDir(CLKFREQ / 13_000, CLK_FREQ / 1_600, CLK_FREQ / 3_200_000, 0, FALSE, FALSE)
And here is the child object file:
VAR
LONG lDirectionPin
LONG lStepPin
LONG lDisablePin
LONG lDirection
LONG lNewDirection
LONG lStopMotor
LONG lDisableMotor
'Variable for cog ID
LONG lCog
LONG lUpdateSpeed
LONG lHighPulseWidth
LONG lCounter
LONG lNewMaxExeMotorSpeed
LONG lNewStartStopSpeed
LONG lNewRampIncDec
LONG lNewRampingSteps
LONG lMaxExeMotorSpeed
LONG lStartStopSpeed
LONG lRampIncDec
LONG lRampingSteps
'Stack for running seperate cog
LONG StepperStack[100]
PUB Start(DirectionPin, StepPin, DisablePin, HighPulseWidth) : Success
Stop
Success := (lCog := COGNEW(Initialize(DirectionPin, StepPin, DisablePin, HighPulseWidth), @StepperStack) + 1)
PUB Stop
IF lCog
COGSTOP(lCog~ - 1)
PUB Initialize(DirectionPin, StepPin, DisablePin, HighPulseWidth)
lDirectionPin := DirectionPin
lStepPin := StepPin
lDisablePin := DisablePin
DIRA[lStepPin] := 1
DIRA[lDirectionPin] := 1
DIRA[lDisablePin] := 1
lHighPulseWidth := HighPulseWidth
lUpdateSpeed := FALSE
SetupCounter
MonitorSpeedChange
PUB SetupCounter
'Set up the CTRMODE of Counter A for NCO/PWM single-ended.
CTRA[30..26] := %00100
'Set the output pin for Counter A.
CTRA[5..0] := lStepPin
'Set the value to be added to PHSA with every clock cycle.
FRQA := 1
'Set APIN as an output.
DIRA[lStepPin] := 1
'Get the current System Counter value and initialize the lCounter
'global variable.
lCounter := CNT
PUB RampUpMotorSpeed
OUTA[lDirectionPin] := lDirection
'Ramp up motor speed
REPEAT lRampingSteps
'Send out a high pulse on the step pin for the desired duration.
PHSA := -lHighPulseWidth
'Wait for a specified period of time before send sending another
'high pulse to the step pin.
WAITCNT(lCounter += lStartStopSpeed -= lRampIncDec)
MaintainCurrentMotorSpeed
PUB MaintainCurrentMotorSpeed
'Run the motor at full speed until we get contrary input and then
'stop this iteration.
REPEAT WHILE lUpdateSpeed == FALSE
'Send out a high pulse on the step pin for the desired duration.
PHSA := -lHighPulseWidth
'Wait for a specified period of time before send sending another
'high pulse to the step pin.
WAITCNT(lCounter += lStartStopSpeed)
PUB RampDownMotorSpeed
OUTA[lDirectionPin] := lDirection
'Ramp down the motor.
REPEAT lRampingSteps
'Send out a high pulse on the step pin for the desired duration.
PHSA := -lHighPulseWidth
'Wait for a specified period of time before send sending another
'high pulse to the step pin.
WAITCNT(lCounter += lStartStopSpeed += lRampIncDec)
IF lStopMotor <> TRUE
MaintainCurrentMotorSpeed
ELSE
IF lDisableMotor == TRUE
'Disable the motor.
OUTA[lDisablePin] := 0
MonitorSpeedChange
PUB MonitorSpeedChange
REPEAT WHILE lUpdateSpeed == FALSE
IF lNewStartStopSpeed > lStartStopSpeed
UpdateSpeedChange
OUTA[lDisablePin] := 1
RampDownMotorSpeed
ELSE
UpdateSpeedChange
OUTA[lDisablePin] := 1
RampUpMotorSpeed
PUB SetSpeedDir(MaxExeMotorSpeed, StartStopSpeed, RampIncDec, Direction, StopMotor, DisableMotor) | RampingSteps
RampingSteps := (StartStopSpeed - MaxExeMotorSpeed) / RampIncDec
lNewMaxExeMotorSpeed := MaxExeMotorSpeed
lNewStartStopSpeed := StartStopSpeed
lNewRampIncDec := RampIncDec
lNewDirection := Direction
lNewRampingSteps := RampingSteps
IF StopMotor == TRUE
lStopMotor := TRUE
ELSE
lStopMotor := FALSE
IF DisableMotor == TRUE
lDisableMotor := TRUE
ELSE
lDisableMotor := FALSE
lUpdateSpeed := TRUE
PUB UpdateSpeedChange
lMaxExeMotorSpeed := lNewMaxExeMotorSpeed
lStartStopSpeed := lNewStartStopSpeed
lRampIncDec := lNewRampIncDec
lRampingSteps := lNewRampingSteps
lDirection := lNewDirection
lUpdateSpeed := FALSE
Any input?
Bruce

Comments
I don't see the endless loop in the child object?
Edit: Or was your concern there is an endless loop you didn't intend to occur?
Edit again: I suspect "MoinitorSpeedChange" doesn't have the proper indentation to loop the way you are expecting. My guess is everything after "REPEAT WHILE lUpdateSpeed == FALSE" should be indented (within that method).
Edit: Duane the way he is using repeat in that instance it is a one line instruction.
The final instruction of Initialize is a call to MonitorSpeedChange, and I believe REPEAT WHILE lUpdateSpeed == FALSE is an endless loop, because I don't believe the call to SetSpeedDir from the parent updates the lUpdateSpeed variable. As far as the indentation goes, my intention was to just keep looping there until lUpdateSpeed equaled TRUE and then execute the remainder of the method, so indentation was not desired. The call from the parent to SetSpeedDir is intended to initialize some variables and then change lUpdateSpeed to TRUE, which would then allow MonitorSpeedChange to exit the REPEAT WHILE lUpdateSpeed == FALSE loop and continue on in that method.
@ratronic
Thanks I will try that.
All indentation is as intended.
As long as lUpdateSpeed == FALSE, it will just sit there and loop, but when lUpdateSpeed == TRUE, the remainder of the method should excute.
You are overlooking the obvious
That is what PUB SetSpeedDir(MaxExeMotorSpeed, StartStopSpeed, RampIncDec, Direction, StopMotor, DisableMotor) is intended for.
Why would I need to do that?
In the child object, the SetSpeedDir method needs values for it's parameters. From the parent method I pass that method values to it's parameters. As stated above and shown below.
I understand that... Look at the last instruction of the SetSpeedDir method, this is where that value is updated and it is not running in that cog.
PUB SetSpeedDir(MaxExeMotorSpeed, StartStopSpeed, RampIncDec, Direction, StopMotor, DisableMotor) | RampingSteps RampingSteps := (StartStopSpeed - MaxExeMotorSpeed) / RampIncDec lNewMaxExeMotorSpeed := MaxExeMotorSpeed lNewStartStopSpeed := StartStopSpeed lNewRampIncDec := RampIncDec lNewDirection := Direction lNewRampingSteps := RampingSteps IF StopMotor == TRUE lStopMotor := TRUE ELSE lStopMotor := FALSE IF DisableMotor == TRUE lDisableMotor := TRUE ELSE lDisableMotor := FALSE lUpdateSpeed := TRUEEdit2: but if that variable is to be used in a REPEAT WHILE statement it will have to be changed from another cog to get out of that loop.
You're treating methods as goto statements. You'll soon run out of stack space doing it this way.
hmmmmmm
Con 'parent object _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 Var long one, two, three long a, b, c, d, e, f Obj child : "template" Pub main a := 1 child.start(a, b, c) waitcnt(clkfreq*4+cnt) repeat child.update(d++, e, f) waitcnt(clkfreq/2+cnt)Child objectVar 'child object long a, b, c long stack[50] Obj io : "parallax serial terminal" Pub start(x, y, z) io.start(115200) a := x b := y c := z cognew(loop, @stack) Pub update(one, two, three) a := one b := two c := three Pub loop repeat io.char(1) io.dec(a) waitcnt(clkfreq/100+cnt)I want to thank you guys for your input, so thank you. I will try to modify my code a little later and see what happens.
Bruce