Signed numbers in a PID statement

hippy

Technical Support
Staff member
temp = $FFFF - Result + 1
temp = $FFFF - ELine + 1

Why not ... ?

temp = -Result
temp = -Eline

Your problem is that #Macro replaces its named parameters with the arguments passed in. Your 'word1' and 'word2' are parameters not local variables, not the variables you have defined elsewhere. Your macro call ...

MultiplySigned(ELine,KpELine)

expands to ...

Code:
	sign = positive
	if ELine >= $8000 then
		sign = NOT sign
		ELine = -ELine
	endif
	if KpELine >= $8000 then
		sign = NOT sign
		KpELine = -KpELine
	endif
	Result = ELine * KpELine
	if sign = negative then
		Result = -Result
  endif
You can probably see why your variables are having their signs changed.

Moral is; never give your #Macro parameter names which are used elsewhere in the program. Change them to arg1 and arg2 and that will probably help.
 

Buzby

Senior Member
... I also used the method suggested by @hippy to measure the time of the loop. The worst case scenario (the greatest correction needed) takes about 60us. I checked many times. Can it be that fast? ...
Are you sure you are measuring the time between two pulses, and not the width of just one pulse ?

60uS is in the right ballpark for a HIGH immediately followed by a LOW, but 60mS is more like what your loop might be taking.

( Another timing method is to just toggle an output every time you finish the main loop, something like 'inc c.3' works well. )

Cheers,

Buzby
 

hippy

Technical Support
Staff member
If anything is taking just 60us it's probably not doing anything much. Even at 64MHz.
 

edmunds

Senior Member
Are you sure you are measuring the time between two pulses, and not the width of just one pulse ?

60uS is in the right ballpark for a HIGH immediately followed by a LOW, but 60mS is more like what your loop might be taking.

( Another timing method is to just toggle an output every time you finish the main loop, something like 'inc c.3' works well. )

Cheers,

Buzby

Yes, you are right, it must be much longer. Must be what I saw was the end-of-loop to start-of-loop transition. Will check again tomorrow.

Edmunds
 

edmunds

Senior Member
temp = $FFFF - Result + 1
temp = $FFFF - ELine + 1

Why not ... ?

temp = -Result
temp = -Eline
[/code]
Sorry, old approach, not using it anymore. Direct from a textbook. Possibly wikipedia when I was just figuring out the signed numbers deal.

Moral is; never give your #Macro parameter names which are used elsewhere in the program. Change them to arg1 and arg2 and that will probably help.
Well, I took the basics of the code from code snippets place and this used exactly these parameter names and also defined them as variables. This made me confused, but I tried it out now and it seems to work well and as expected. Thank you :).

Edmunds
 

AllyCat

Senior Member
Hi,

What I do not understand is how do you make stepping 'in the background'.
Since this part of the project is now considered "finished" (it's in the finsihed projects section) I thought I'd hijack the thread for my own similar (perhaps) project. However, my requirements are rather more difficult because I have two steppers used for differential motive drive (not just one for steering) and I must use an M2 (14 or 8 pins). The steppers appear to rotate well with around a 2 ms pulse period, but the wheel gearing (non-negotiable) gives around 100 steps per revolution, so an update rate of around 5 - 10 ms might be sufficient.

But, unlike the X2s, the M2s don't support timer interrupts (do they), so how to proceed? I briefly tried multitasking (multiple starts) but the motor ran much too fast (when using a trivial secondary task). I wonder if one of the alternative tasks could be for "timekeeping" (i.e. introducing a delay until a predetermined "tick" interval has elapsed), but how does one prevent that task being "interrupted" to allow another of the tasks to proceed (until we want it to)?

Therefore, the only solution that I have at the moment is a "main" program which calls a number of "bite-size", interrupt-style subroutines at a predetermined "tick" rate. AFAIK Timer 1 always repeats with a 20 ms (or perhaps 10 ms) period, regardless of the SETFREQ, to support the "time" and "servo" commands. Of course dividing the "foreground" tasks into bite-size chunks might be tricky, but has anybody any better ideas?

Cheers, Alan.
 

hippy

Technical Support
Staff member
Since this part of the project is now considered "finished" (it's in the finsihed projects section) I thought I'd hijack the thread for my own similar (perhaps) project.
If it's got little or nothing to do with "signed numbers in a PID statement" it would be better off in its own thread.

Firstly those not interested in signed numbers or PID statements might not even look at this thread, and those who are might not be best pleased that it has nothing to do with what they were expecting it to be about.


But, unlike the X2s, the M2s don't support timer interrupts (do they), so how to proceed?
No; there are no timer interrupts on the M2. The best there is is the 'time' variable which increments approximately every second.

Probably the only way to get reliable and accurate timed intervals on an M2 is to use an on-chip timer, poll that for an overflow or a bit being set, and not to use multi-tasking to keep control of program flow.
 

stan74

Senior Member
I think something could be rigged to use pwm and pin interrupts to inc a "timer".It should be accurate.
 
Top