program keeps locking up/crashing
laser-vector
Posts: 118
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