program keeps locking up/crashing
hi all,
im having a little issue where i have started 3 cogs,
two of them drive a stepper motor and are constantly reading their speed variable which is pumped into waitcnt(clkfreq/speed + cnt)
at the same time there is a serial interface (PreambleCommandIndex) that can update these variables via command input and read them back as a status screen (status command "?").
im not sure if im sharing the variables correctly as the two motor driver processes are very high priority and the serial interface is very low.
if im running the motors fast (over 500 steps per second) and i type in the command to read out the variables sometimes it will lock up and do funny things.
the code i have is kind of long, its something i just threw together in the last couple of days so its not very well commented (some comments are incomplete/false) ill fix these soon!, i can explain anything if needed:
Thanks for any ideas or help!!!!!
im having a little issue where i have started 3 cogs,
two of them drive a stepper motor and are constantly reading their speed variable which is pumped into waitcnt(clkfreq/speed + cnt)
at the same time there is a serial interface (PreambleCommandIndex) that can update these variables via command input and read them back as a status screen (status command "?").
im not sure if im sharing the variables correctly as the two motor driver processes are very high priority and the serial interface is very low.
if im running the motors fast (over 500 steps per second) and i type in the command to read out the variables sometimes it will lock up and do funny things.
the code i have is kind of long, its something i just threw together in the last couple of days so its not very well commented (some comments are incomplete/false) ill fix these soon!, i can explain anything if needed:
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
highpinX = 19
lowpinX = 16
highpinY = 23
lowpinY = 20
OBJ
NUM : "numbers"
Debug : "fullduplexserial"
VAR
Long DirX, DirY
Long idx, stpIdxX, stpIdxY, stpDelay, stepspeedX, stepspeedY, stepcnt
Long RXbyte, Data
Long stack0[70], Stack1[50], Stack2[50]
Long LimitMaxX, LimitMaxY
byte Estop
Long AsciiNumbers
Long PositionX, PositionY
Long INDSpeedX, INDSpeedY, INDLimitX, INDLimitY, INDDirectionX, INDDirectionY, INDPosX, INDPosY
PUB main | c
Num.Init ' initilize numbers
Debug.Start(31, 30, 0, 9600) ' configure serial communication
LimitMaxX := INDLimitX := 500
LimitMaxY := INDLimitY := 500
DirX := INDDirectionX := 1
DirY := INDDirectionY := 1
StepSpeedX := INDSpeedX := -1
StepSpeedY := INDSpeedY := -1
PositionX := INDPosX := 0
PositionY := INDPosY := 0
cognew(PreambleCommandIndex, @Stack0) ' main loop to compile and distribute value of DataLong
cognew(StepDriverX, @stack1)
cognew(StepDriverY, @stack2)
PUB StepDriverX|T
dira[highpinX..lowpinX]~~
repeat
repeat while EStop == False and StepSpeedX => 0
repeat while StepSpeedX == 0
if DirX == 1
StepFwdWaveX
waitcnt(clkfreq/StepSpeedX + cnt)
if DirX == 0
StepRevwaveX
waitcnt(clkfreq/StepSpeedX + cnt)
if stepspeedX == -1
outa[highpinX..lowpinX]~
PUB StepDriverY|T
dira[highpinY..lowpinY]~~
repeat
repeat while EStop == False and StepSpeedY => 0
repeat while StepSpeedY == 0
if DirY == 1
StepFwdWaveY
waitcnt(clkfreq/StepSpeedY + cnt)
if DirY == 0
StepRevwaveY
waitcnt(clkfreq/StepSpeedY + cnt)
if stepspeedY == -1
outa[highpinY..lowpinY]~
PUB PreambleCommandIndex | c '"c" is to index through the data array, "t" is the loop true/false flag
Repeat
DEBUG.RXFLUSH
WAITCNT(CLKFREQ/1000 + CNT) ' start Main data acqusition loop, execution is now localized within this loop only
RXbyte := Debug.RXcheck ' setting rxbyte to the value in rxcheck's serial buffer
Case RXbyte
"O" :
Debug.Str(String("O"))
"?" :
debug.tx($00)
debug.tx($0d)
Debug.Str(String("************SYSTEM INFORMATION************"))
debug.tx($0d)
debug.tx($0d)
Debug.Str(String("GLOBAL SETTINGS"))
debug.tx($0d)
Debug.Str(String("E Stop Status: "))
If Estop == 0
Debug.Str(String("FALSE"))
ELSE
Debug.Str(String("TRUE"))
debug.tx($0d)
debug.tx($0d)
Debug.Str(String("CHANNEL X SETTINGS"))
debug.tx($0d)
Debug.Str(String("Position: "))
'Debug.str(num.tostr(INDPosX, num#dec))
debug.tx($0d)
Debug.Str(String("Maximum Speed Limit: "))
WAITCNT(CLKFREQ/10 + CNT)
Debug.str(num.tostr(INDLimitX, num#dec))
Debug.Str(String(" Steps/Second"))
debug.tx($0d)
Debug.Str(String("Current Speed Setting:"))
IF StepSpeedX == -1
Debug.Str(String(" DEACTIVATED!"))
ELSE
WAITCNT(CLKFREQ/10 + CNT)
Debug.str(num.tostr(INDSpeedX, num#dec))
Debug.Str(String(" Steps/Second"))
debug.tx($0d)
Debug.Str(String("Travel Direaction: "))
Case DirX
1 :
Debug.Str(String("Positive"))
0 :
Debug.Str(String("Negitive"))
other :
Debug.Str(String("N/A"))
debug.tx($0d)
debug.tx($0d)
Debug.Str(String("CHANNEL Y SETTINGS"))
debug.tx($0d)
Debug.Str(String("Position: "))
'Debug.str(num.tostr(INDPosY, num#dec))
debug.tx($0d)
Debug.Str(String("Maximum Speed Limit: "))
WAITCNT(CLKFREQ/10 + CNT)
Debug.str(num.tostr(INDLimitY, num#dec))
Debug.Str(String(" Steps/Second"))
debug.tx($0d)
Debug.Str(String("Current Speed Setting:"))
IF StepSpeedY == -1
Debug.Str(String(" DEACTIVATED!"))
ELSE
WAITCNT(CLKFREQ/10 + CNT)
Debug.str(num.tostr(INDSpeedY, num#dec))
Debug.Str(String(" Steps/Second"))
debug.tx($0d)
Debug.Str(String("Travel Direaction: "))
Case DirY
1 :
Debug.Str(String("Positive"))
0 :
Debug.Str(String("Negitive"))
other :
Debug.Str(String("N/A"))
repeat 5
debug.tx($0d)
PreambleCommandIndex
"D" :
Debug.Str(String("D"))
Repeat
RXbyte := Debug.RXcheck ' setting rxbyte to the value in rxcheck's serial buffer
If RXbyte => 0
Case RXbyte
"X" :
Debug.Str(String("X"))
ASCIIToNum(1)
INDDirectionX := AsciiNumbers <# 1
DirX := AsciiNumbers <# 1
"Y" :
Debug.Str(String("Y"))
ASCIIToNum(1)
INDDirectionY := AsciiNumbers <# 1
DirY := AsciiNumbers <# 1
"Q" :
PreambleCommandIndex
OTHER :
Debug.Str(String("!"))
PreambleCommandIndex
PreambleCommandIndex
"L" :
Debug.Str(String("L"))
Repeat
RXbyte := Debug.RXcheck ' setting rxbyte to the value in rxcheck's serial buffer
If RXbyte => 0
Case RXbyte
"X" :
Debug.Str(String("X"))
ASCIIToNum(4)
INDLimitX := AsciiNumbers
LimitMaxX := AsciiNumbers
"Y" :
Debug.Str(String("Y"))
ASCIIToNum(4)
INDLimitY := AsciiNumbers
LimitMaxY := AsciiNumbers
"Q" :
PreambleCommandIndex
OTHER :
Debug.Str(String("!"))
PreambleCommandIndex
PreambleCommandIndex
"G" :
Debug.Str(String("G"))
Repeat
RXbyte := Debug.RXcheck
If RXbyte => 0
Case RXbyte
"X" :
Debug.Str(String("X"))
ASCIIToNum(10)
INDSpeedX := AsciiNumbers <# LimitMaxX
StepSpeedX := AsciiNumbers <# LimitMaxX
"Y" :
Debug.Str(String("Y"))
ASCIIToNum(10)
INDSpeedY := AsciiNumbers <# LimitMaxY
StepSpeedY := AsciiNumbers <# LimitMaxY
"Q" :
PreambleCommandIndex
OTHER :
Debug.Str(String("!"))
PreambleCommandIndex
PreambleCommandIndex
"S" :
Debug.Str(String("S"))
Repeat
RXbyte := Debug.RXcheck
If RXbyte => 0
Case RXbyte
"X" :
Debug.Str(String("X"))
INDSpeedX := -1
StepSpeedX := -1
"Y" :
Debug.Str(String("Y"))
INDSpeedY := -1
StepSpeedY := -1
"Q" :
PreambleCommandIndex
OTHER :
Debug.Str(String("!"))
PreambleCommandIndex
PreambleCommandIndex
"!" :
Debug.Str(String("!"))
EStop := True
INDSpeedX := -1
StepSpeedX := -1
INDSpeedY := -1
StepSpeedY := -1
PreambleCommandIndex
"I" :
Debug.Str(String("I"))
EStop := False
PreambleCommandIndex
PUB ASCIIToNum(DecimalCount) | C, N
AsciiNumbers := 0
C := 0
data := 0
Repeat
RXbyte := Debug.RXcheck
If RXbyte => 0
case RXbyte
"0".."9" :
AsciiNumbers := AsciiNumbers * 10 + (RXbyte - "0") <# 1_000_000_000
$0D :
c := (DecimalCount - 1)
"Q" :
PreambleCommandIndex
other :
Debug.Str(String("!"))
return
if c => (DecimalCount - 1)
return
C++
PUB FormLong(bytecnt) | C ' constructs an array from incoming serial data
data := FALSE
C := 0 ' setup, counter reset = 0
Repeat ' then repeat this part while T flag is true
RXbyte := Debug.RXcheck ' retreive byte from serial buffer
If RXbyte => 0 ' if rxbyte is true there is a byte from the buffer in it, Go Get It!!
If RXbyte == $0D ' if a carriage return was sent
Repeat C From 0 To (bytecnt - 1) <# 3 ' loop while looking for false bytes in the array
If Data.byte[C] == -1 ' if fase byte exsists
Data.byte[C] := 0
Return ' --> Return to caller
Data.byte[C] := RXbyte ' then data[array#] = serial data byte (next pass array# "c" will = + 1 )
RXbyte := -1 ' reset rxbyte to false, go back and loop until rxcheck's buffer passes byte to rxbyte, OR>
If c == (bytecnt - 1) ' if the last long in Data[last-array#] is not false
Return ' incriment the byte position indxer/counter
C ++
{--------------------------CHANNEL Y--------------------------}
PRI stepFwdX
PositionX ++
INDPosX := PositionX
stpIdxX := ++stpIdxX // 4 ' point to next step
outa[highpinX..lowpinX] := XSteps[stpIdxX] ' update outputs
PRI stepRevX
PositionX --
INDPosX := PositionX
stpIdxX := (stpIdxX + 3) // 4 ' point to previous step
outa[highpinX..lowpinX] := XSteps[stpIdxX] ' update outputs
PRI stepFwdWaveX
PositionX ++
INDPosX := PositionX
stpIdxX := ++stpIdxX // 4
outa[highpinX..lowpinX] := XStepsW[stpIdxX]
PRI stepRevWaveX
PositionX --
INDPosX := PositionX
stpIdxX := (stpIdxX + 3) // 4
outa[highpinX..lowpinX] := XStepsW[stpIdxX]
PRI HalfStepFwdX
PositionX ++
INDPosX := PositionX
stpIdxX := ++stpIdxX // 8
outa[highpinX..lowpinX] := XStepsH[stpIdxX]
PRI HalfStepRevX
PositionX --
INDPosX := PositionX
stpIdxX := (stpIdxX + 7) // 8
outa[highpinX..lowpinX] := XStepsH[stpIdxX]
PRI pauseX(ms) | c
c := cnt ' sync with system counter
repeat until (ms-- == 0) ' repeat while time left
waitcnt(c += clkfreq / 1000) ' wait 1 ms
{--------------------------CHANNEL Y--------------------------}
PRI stepFwdY
PositionY ++
INDPosY := PositionY
stpIdxY := ++stpIdxY // 4 ' point to next step
outa[highpinY..lowpinY] := YSteps[stpIdxY] ' update outputs
PRI stepRevY
PositionY --
INDPosY := PositionY
stpIdxY := (stpIdxY + 3) // 4 ' point to previous step
outa[highpinY..lowpinY] := YSteps[stpIdxY] ' update outputs
PRI stepFwdWaveY
PositionY ++
INDPosY := PositionY
stpIdxY := ++stpIdxY // 4
outa[highpinY..lowpinY] := YStepsW[stpIdxY]
PRI stepRevWaveY
PositionY --
INDPosY := PositionY
stpIdxY := (stpIdxY + 3) // 4
outa[highpinY..lowpinY] := YStepsW[stpIdxY]
PRI HalfStepFwdY
PositionY ++
INDPosY := PositionY
stpIdxY := ++stpIdxY // 8
outa[highpinY..lowpinY] := YStepsH[stpIdxY]
PRI HalfStepRevY
PositionY --
INDPosY := PositionY
stpIdxY := (stpIdxY + 7) // 8
outa[highpinY..lowpinY] := YStepsH[stpIdxY]
PRI pauseY(ms) | c
c := cnt ' sync with system counter
repeat until (ms-- == 0) ' repeat while time left
waitcnt(c += clkfreq / 1000) ' wait 1 ms
DAT
XSteps byte %0011, %0110, %1100, %1001 ' full step
XStepsW byte %0001, %0010, %0100, %1000 ' Wave
XStepsH byte %0001, %0011, %0010, %0110, %0100, %1100, %1000, %1001 ' Half step
YSteps byte %0011, %0110, %1100, %1001 ' full step
YStepsW byte %0001, %0010, %0100, %1000 ' Wave
YStepsH byte %0001, %0011, %0010, %0110, %0100, %1100, %1000, %1001 ' Half step
Thanks for any ideas or help!!!!!

Comments
My intuition makes me think that the Stack space allocated for PreambleCommandIndex is not large enough.
i made Long stack0[250], Stack1[100], Stack2[100]
and it still crashes but its after like 30 updates!
thanks for the help so far!!
is there something im forgetting to clear after a status update?
Maybe, maybe not. But the reason for these lockups is primarily due to recursion. Worst example is PreambleCommandIndex. From within the case statement you keep calling yourself in a number of locations. That will eventually eat up your stack. You'll have to find a better way of returning to the top of the method.
Making use of QUIT within the PreambleCommandIndex PUB instead of calling PreambleCommandIndex again will help, but it won't solve the case where the ASCIIToNum(DecimalCount) PUB calls PreambleCommandIndex