I am unfamiliar with Spins CASE conditional command. Could someone please examine the attached file and left me know if I am going about this correctly.
You obviously didn't try to compile that else you'd seen a massive fail. What is it that you're trying to accomplish? I suggest you start with a compound if-then structure and once that works, convert it to case.
Of course, the code elements can also be other case structures -- though that gets a little unwieldy.
Edit: After staring at your code for a few minutes it seems to be wanting to do this:
case steps
5_000..5_999:
steps //= 100 ' steps bumped down to 0..99
1_000..4_999:
steps //= 1_000 ' steps bumped down to 0..999
Tip: Use PST to run test code to check it -- better to test new code independently before incorporating it into an otherwise working program. My default programming template has the FDS object built in so I can do this easy and, believe me, I do it all the time!
I always stayed away from case statements and used the if conditions in the past. I don't know what I was thinking, I seemed to have remembered it differently. I thought they could be hierarchically ordered. Thanks Jon. I apologize Jon, after making several attempts to get the motor going with your code, I finally settled in to MagIO2's version. But that does not mean that I do not appreciate your effort, because I most certainly do. If it wasn't for the two of you, I would have still been trying to figure it out a month from now.
This is not related to your case question, rather a suggestion about your method that creates pulses. At the moment your code is depending on specific global variables which means you can only use it once. What happens when you decide to add a second motor? As the code stands you have to add a second method.
You can re-use that code by passing the addresses of the variables you want to use instead of referencing them in your program. Your call changes from
By reusing code like this you only have to make one update if you want to change the behavior of the drivesteppin method.
Note: I don't care if you use my code or not -- <EGO> though I think you benefit from at least working through it because I tend write clean, flexible, reusable code (most of the code I write is for public consumption so it has to be).</EGO>. I happen to be working on a motor drive project myself so assisting you with your code helps me help myself.
Thanks for the advice. That thought did cross my mind early in the morning. I will change that because reusable code is a wonderful thing. So what do I do, create a different set of variables for everytime that I know I am going to create a new cog? If so, can I reuse these variables? So what is your motor project?
Your blanking method that backs up from NEGX with frqb=1 is clearly better than my original that played off frqa against frqb=frqa/2N. Better simply because it allows a lax time of nearly 1/2 minute. The computation of the initial phsb is a little tricky. I think this should do it, given a target frequency Fx within the burst and a number Nx of pulses within the burst.
Not sure. I may be over-complicating. I'll try it and report back. How did you settle on the 417 cycle lag? I measured execution time of frqa := longVariable at exactly 400 clock cycles (5 microseconds).
So what do I do, create a different set of variables for everytime that I know I am going to create a new cog?
Yes, because you would, anyway. The difference is that you don't need a separate method for the new set of variables. Call the original with links to the new variables and it will get launched into its own cog (technically, another Spin interpreter is launched and it references the code your specify -- multiple Spin cogs can use the same code because the hub allows only one cog at at time to have access).
If so, can I reuse these variables?
No; you need one set of (global) variables per motor. If you want you could use an array for indexed access to each motor.
So what is your motor project?
Mine is a pan/tilt controller for movie cameras but the PWM code method is identical. In my case, though, I use a fixed frequency (20kHz so the motors don't "whine" and screw up the audio track, and I can control two motors at once in the cog [ctra and ctrb]) and vary the positive side of the pulse; this varies the speed of the DC gear motor (the board uses an H-Bridge).
Okay, here is followup on post 73 that incorporates Kuroneko's comments in post 77.
The attached program uses PST to ask the user for a frequency in Hz and a number of pulses, and then generates the requested burst. This uses the counters as before and is in Spin only, but works from 1 Hz up to 20 MHz with as few or as many pulses as you choose. A monitor routine running in a second cog verifies the number of pulses. An auxiliary pin assists with the monitor and also allows you to visualize the framing pulse on an oscilloscope.
Thanks for the tips. Sorry it took so long to get back, but I definitely had to get some sleep. Cameras, h-bridges, and gear motors, sounds like a cool project to me. Many moons ago, Parallax was selling some ICON H-BRIDGE products from Solutions Cubed for the Basic Stamp. I bought that and all the accessories to go with it. I just haven't got around to messing with it yet. It is all still brand new, packaged and put away for a future project. Too many irons, I must build a larger fire.
I just discovered that my so called solution is not working too well. In the attached code below, the loops account for 20,000 steps, however StepCount registers 51,375 pulses. 'What is going on here? Even if I eliminate the waitcnts, I am still way over on step count and the steppers do not end up where they should be. Is the CycleOffset to narrow?
MagIO2:
With this it should be easy to find the right timing.
StepCount is telling you the truth. Your missunderstanding is: You think the number of loop iterations is equal to the number of steps, but that's not true.
The thing is, that the DriveStepPin and the Ramping are not in sync. The ramping always uses 4_000 for waiting. The DriveStepPin waits for whatever time delta it finds in CycleOffset.
So, when starting with starting speed 8_000 the DriveStepPin will wait 5 times longer than the ramp-loop. But later on, when CycleOffset is going below 4_000 the DriveStepPin will wait for a shorter while than the ramping-loop.
That's why the number of loop cycles does not match with the number of steps. That's what I meant with "find the right timing".
But as the propeller is fully deterministic, there is a formula with which the number of steps can be calculated or a formula with which the waittime between the ramps could be calculated for the given ramp-parameters. But to find those formulas is work that still has to be done.
Let me know if you need some help there. (But not today ... my local time is midnight ;o)
Ok ... now you changed the waitcnt, BUT:
1. with this change the speed increase is no longer linear. The faster the stepper runs, the faster the speed will increase.
2. the loops are still not synced correctly (as far as I can interpret your new snippets without seeing the whole change)
To have the COGs in sync both COGs need to wait for the same waitcnt (lets call that timebase) before they start the loops and then each one should maintain it's own copy of timebase + delta*n to stay in sync.
Ok ... now you changed the waitcnt, BUT:
1. with this change the speed increase is no longer linear. The faster the stepper runs, the faster the speed will increase.
The steppers run pretty darn good with that waitcnt.
They are close, but no cigar just yet, but I have a new idea.
It's again to slow for the 2_000. In terms of SPIN-bytecode the array access is like adding runtime, as it needs additional HUB-RAM access. So, I'd suggest to go back to the loop using fixed variables. Those variables are meant to be used only by the CogDriveStepPin anyway. So it makes no sense to use a pointer and the object still can be used for several steppers, as each instance of the object will have it's own copy of those variables.
The step count and pulses are now in sync. There are two remaining problems with this driver, however, besides these two problems, the driver still needs error checking, aborts, etc.... I know you are dying to know what the two main problems are, so here they are.
There is two extra pulses and therefore two extra steps. I looked for the cause of the extra steps and pulses, but I could not find it. I assume I am picking up a step for both the top and bottom REPEAT's within the DriveStepPin method. It could easily be resolved by subtracting 2 from the Steps variable, however, I would like to understand the cause of it.
The DriveStepPin and CogDriveStepPin run in sync with each other. Of course that is not a problem, it is a good thing. The problem is that sometimes the clock rolls around before these functions continue. I sure could use some advice on fixing this problem.
In the future, I will be adding the CoglessStepperDriver code to the same file. The file will contain conditions on which method to execute based upon the number of the steps. With the current values of the parameters in StartingSpeed and RunningSpeed, the parameter Steps would be required to be at least 34,000. The current number of steps is 1,000,000, you may want to change this when testing. Just remember to keep it above 34,000 and it takes a while to get started.
Check it out, you don't need a stepper motor, I have FullDuplexSerial all ready to go, IO output is on PIN 3.
It is not finished yet, but a good stepper driver is on the way!
The waitcnt is wrong. If you want to access the Counter it has to be
LONG[ CounterPntr ]+=LONG[ CycleOffsetPntr ]
But that again adds runtime to the loop AND only one COG should really update the Counter. If both update the counter chance is high to have Counter += 2*CycleOffset there in the end.
You seem to ignore my last post from yesterday (loop is to slow for 2_000).
I thought about the driver and I still believe that PASM would be the better choice. A nice piece of PASM code that's doing the ramp up/down including emergency brake would be more usefull because it would run in one COG. For the current driver you need 2 COGs which can't do anything else. If you want to drive 2 steppers you need 4 COGs ....
So, this driver might be perfect for you learning how to drive a stepper and it's maybe enough for projects where you only have 1 stepper, but it's not good for more, I suppose.
But if you like we could make the SPIN version run perfectly and then convert it to PASM?!
I initially tried that but it threw out an error. I will try it aain.
The 2000 is not very critical, I just wanted my motors to run much faster than they were currently running, In fact, I had to bump it up to 3000 because it misses steps at 2000, probably due to the reasons you state. But the motors still "ZING" and really fly compared to what I had before this thread started. As I mentioned in the previous post, the problem is that it waits way too long to begin execution. What's up with that, and how can that be resolved?
I was not ignoring what you said. My main goal up to this point was to sync the two methods. Since that has now been achieved, it is time for fine tuning it. There is some confusion however, Jon explained one way and you explained another. Considering my lack of experience in programming with Spin, I am truly uncertain which way to go. Both of you are the experts compared to me. I would love for both of you to examine the code, and determine what is the best way to go to turn this into something nice. It was originally your sample that got me this far, as far as I am concerned, you can doctor this code anyway you like to make it better.
But if you like we could make the SPIN version run perfectly and then convert it to PASM?!
That would be excellent. I would really like to figure out how to do this with one cog, or use one cog to monitor several other cogs, but I am not that smart like you guys. Currently, my programming for these CNC's is inline and can only commit to single tasking. However, when I work out all the bugs, I want to start making use of the Propellers 8 cogs to improve production efficiency. The main reason I like Spin is becaise I can read it, PASM is all greek to me. Normally, I only like to use code that I can easily understand and easily alter. 9 times out of 10, if I don't completely understand the code, I don't use it. This is why I use my overly descriptive symbol names, so that I remember, understand, and can easily alter the code. In this particular circumstance, I would probably make an exception to that rule in this case, because my main goal is to finish the machines, and start producing. If there was truly a good stepper driver in the OBEX that pulsed a step pin like this source code, I would definitely use it, irregardless of the language it was written in.
I am sure that you and many others here at the forum could turn this into a real nice driver that has good value, however it turns out, I would still like to continue participating in that endeavor.
I'm not sure whether we tell you different things. I guess you refere to the 'remove hardcodes and use parameters'-kind of suggestion. And now I tell you to change the loop using it's own variables again. That's not directly the opposite.
Ok ... let's start from the beginning:
What you do is prototyping. It's absolutely feasible to use hardcodes and have the code less flexible in this phase. Once the code is running you should think in objects. (Definitely some more experienced people already think in objects from the very beginning.) In your case I think at the time we convert it to PASM is fine to start thinking in objects. When you start to make the code flexible you have to think about how to do that, so that the benefit for the code using your object is maximised. In our case that means the code should be able to drive not only one stepper.
So, you have to find out how to do that. That's why Jonny suggested to use pointers to the variables that control the stepper COG because with using the exactly same variables you could only drive one stepper. Of course this works, but it's not the way you do it when thinking in objects.
When you start using the driver as an object, you can define ONE variable and each instance of this object WILL have it's own private version of this variable. So, working with pointers in the object world only makes sense if you want the user of the object keep control over such memory. Of course there are usecases for this as well, but as far as I see the stepper driver does not need that.
Main.spin
OBJ
stepper1: "MyStepperDriver"
stepper2: "MyStepperDriver"
PUB
stepper1.start( Here you'd give all the really needed parameters for setup for example the max speed, the min speed, the pin ... )
stepper2.start( ... )
stepper1.RupStepRdown( 10_000, additional parameters which might be usefull )
This is an example how we could use the stepper-driver. RupStepRdown would be our current function Ramp Up Step and Ramp Down. Other usefull functions would maybe not Ramp down but slow down do some more steps or Ramp Up Free Run ....
As you now see,from a usage point of view, you are not interested in the internals. And that's why there is no need to let the user of the object manage the internal variables and pass pointers. The function RupStepRdown belongs to the object as well as the stepper-loop.
In a few hours I can spend some time with the driver and then I can show you more.
Here is an updated version with some problems fixed. It now includes a timer for doing time test comparisons. With a StartingSpeed of 20,000 and RunningSpeed of 2,000, the stepper driver is producing 8.65 Revolutions Per Second.
Within a duplicate file, I converted CycleOffset back to a global instead of passing it as a pointer. Upon testing, it took approximately a minute longer to execute 1,000,000 pulses, and additionally, it did not keep an accurate count. As far as the speed test goes, it did not make much sense, because your sample code appears to run faster than my version, but I could be wrong.
..it took approximately a minute longer to execute...
I was a little surprised by that so I whipped up a quick test -- turns out that accessing a global directly versus a pointer to it is significantly faster. At some point you're going to be faced with organizing your code so that it can be used in your project and others, so you may want to live with the slower speed -- or switch to PASM (I wrote a PASM demo for you a few days ago that does the motor drive stuff, it's in this thread).
var
long global
pub main | t, local, pntr
term.start(RX1, TX1, %0000, 115_200)
pause(1)
term.tx(CLS)
term.str(string("Timing Test", CR, CR))
pntr := @global
t := -cnt ' start timing
'local := global ' 320 ticks
local := long[pntr] ' 544 ticks
t += cnt - 544 ' end timing
term.dec(t)
term.str(string(" ticks"))
repeat
waitcnt(0)
Of course accessing globals or local variables is faster. If you do long[ addressVar ], the SPIN compiler has to read the content of addressVar from HUB-RAM and then can read/write the content of the memory location you want to access. By using direct variable names there is no need for the additional HUB-access.
Makes perfect sense; the address of the global is hard-coded into the byte codes hence eliminating the hub read to get the address to retrieve the value from.
Comments
Here is another modified version of MagIO2's original code. This one still runs in a cog like he had it.
Bruce
I am unfamiliar with Spins CASE conditional command. Could someone please examine the attached file and left me know if I am going about this correctly.
Thanks
Bruce
In general a case structure looks like this:
Of course, the code elements can also be other case structures -- though that gets a little unwieldy.
Edit: After staring at your code for a few minutes it seems to be wanting to do this:
Tip: Use PST to run test code to check it -- better to test new code independently before incorporating it into an otherwise working program. My default programming template has the FDS object built in so I can do this easy and, believe me, I do it all the time!
I always stayed away from case statements and used the if conditions in the past. I don't know what I was thinking, I seemed to have remembered it differently. I thought they could be hierarchically ordered. Thanks Jon. I apologize Jon, after making several attempts to get the motor going with your code, I finally settled in to MagIO2's version. But that does not mean that I do not appreciate your effort, because I most certainly do. If it wasn't for the two of you, I would have still been trying to figure it out a month from now.
Thanks Jon
You can re-use that code by passing the addresses of the variables you want to use instead of referencing them in your program. Your call changes from
to:
(this assumes you'll have more than one motor, hence the "1" at the end of variable names.) Now you method looks like this:
And when you add another motor you simply call the same method with a new set of parameters:
By reusing code like this you only have to make one update if you want to change the behavior of the drivesteppin method.
Note: I don't care if you use my code or not -- <EGO> though I think you benefit from at least working through it because I tend write clean, flexible, reusable code (most of the code I write is for public consumption so it has to be).</EGO>. I happen to be working on a motor drive project myself so assisting you with your code helps me help myself.
Thanks for the advice. That thought did cross my mind early in the morning. I will change that because reusable code is a wonderful thing. So what do I do, create a different set of variables for everytime that I know I am going to create a new cog? If so, can I reuse these variables? So what is your motor project?
Bruce
Your blanking method that backs up from NEGX with frqb=1 is clearly better than my original that played off frqa against frqb=frqa/2N. Better simply because it allows a lax time of nearly 1/2 minute. The computation of the initial phsb is a little tricky. I think this should do it, given a target frequency Fx within the burst and a number Nx of pulses within the burst.
Not sure. I may be over-complicating. I'll try it and report back. How did you settle on the 417 cycle lag? I measured execution time of frqa := longVariable at exactly 400 clock cycles (5 microseconds).
Yes, because you would, anyway. The difference is that you don't need a separate method for the new set of variables. Call the original with links to the new variables and it will get launched into its own cog (technically, another Spin interpreter is launched and it references the code your specify -- multiple Spin cogs can use the same code because the hub allows only one cog at at time to have access).
No; you need one set of (global) variables per motor. If you want you could use an array for indexed access to each motor.
Mine is a pan/tilt controller for movie cameras but the PWM code method is identical. In my case, though, I use a fixed frequency (20kHz so the motors don't "whine" and screw up the audio track, and I can control two motors at once in the cog [ctra and ctrb]) and vary the positive side of the pulse; this varies the speed of the DC gear motor (the board uses an H-Bridge).
The attached program uses PST to ask the user for a frequency in Hz and a number of pulses, and then generates the requested burst. This uses the counters as before and is in Spin only, but works from 1 Hz up to 20 MHz with as few or as many pulses as you choose. A monitor routine running in a second cog verifies the number of pulses. An auxiliary pin assists with the monitor and also allows you to visualize the framing pulse on an oscilloscope.
Thanks for the tips. Sorry it took so long to get back, but I definitely had to get some sleep. Cameras, h-bridges, and gear motors, sounds like a cool project to me. Many moons ago, Parallax was selling some ICON H-BRIDGE products from Solutions Cubed for the Basic Stamp. I bought that and all the accessories to go with it. I just haven't got around to messing with it yet. It is all still brand new, packaged and put away for a future project. Too many irons, I must build a larger fire.
Bruce
Yep it's me again with another problem.
I just discovered that my so called solution is not working too well. In the attached code below, the loops account for 20,000 steps, however StepCount registers 51,375 pulses. 'What is going on here? Even if I eliminate the waitcnts, I am still way over on step count and the steppers do not end up where they should be. Is the CycleOffset to narrow?
MagIO2:
Bruce
The thing is, that the DriveStepPin and the Ramping are not in sync. The ramping always uses 4_000 for waiting. The DriveStepPin waits for whatever time delta it finds in CycleOffset.
So, when starting with starting speed 8_000 the DriveStepPin will wait 5 times longer than the ramp-loop. But later on, when CycleOffset is going below 4_000 the DriveStepPin will wait for a shorter while than the ramping-loop.
That's why the number of loop cycles does not match with the number of steps. That's what I meant with "find the right timing".
But as the propeller is fully deterministic, there is a formula with which the number of steps can be calculated or a formula with which the waittime between the ramps could be calculated for the given ramp-parameters. But to find those formulas is work that still has to be done.
Let me know if you need some help there. (But not today ... my local time is midnight ;o)
The waitcnt was the wrong value, the loops were correct. Okay maybe I was wrong, but now I am right.
'Ramp Up
REPEAT CycleOffset FROM StartingSpeed TO RunningSpeed STEP RampMultiplier '6_000 Steps
WAITCNT(Counter += CycleOffset)
'Maintain High Speed
REPEAT StepRemainders
WAITCNT(Counter += CycleOffset) '8_000 Steps
'Ramp Down
REPEAT CycleOffset FROM RunningSpeed TO StartingSpeed STEP RampMultiplier '6_000 Steps
WAITCNT(Counter += CycleOffset)
Bruce
Let me rephrase, " I am almost right, it appears to be picking up some steps.
Bruce
1. with this change the speed increase is no longer linear. The faster the stepper runs, the faster the speed will increase.
2. the loops are still not synced correctly (as far as I can interpret your new snippets without seeing the whole change)
To have the COGs in sync both COGs need to wait for the same waitcnt (lets call that timebase) before they start the loops and then each one should maintain it's own copy of timebase + delta*n to stay in sync.
The steppers run pretty darn good with that waitcnt.
They are close, but no cigar just yet, but I have a new idea.
Bruce
It's again to slow for the 2_000. In terms of SPIN-bytecode the array access is like adding runtime, as it needs additional HUB-RAM access. So, I'd suggest to go back to the loop using fixed variables. Those variables are meant to be used only by the CogDriveStepPin anyway. So it makes no sense to use a pointer and the object still can be used for several steppers, as each instance of the object will have it's own copy of those variables.
Okay I will look into it. Here is how close I am now to sinking with actual steps
1,000,000 steps
StpCnt = 999827 or StpCnt = 1000141
Bruce
The step count and pulses are now in sync. There are two remaining problems with this driver, however, besides these two problems, the driver still needs error checking, aborts, etc.... I know you are dying to know what the two main problems are, so here they are.
- In the future, I will be adding the CoglessStepperDriver code to the same file. The file will contain conditions on which method to execute based upon the number of the steps. With the current values of the parameters in StartingSpeed and RunningSpeed, the parameter Steps would be required to be at least 34,000. The current number of steps is 1,000,000, you may want to change this when testing. Just remember to keep it above 34,000 and it takes a while to get started.
- Check it out, you don't need a stepper motor, I have FullDuplexSerial all ready to go, IO output is on PIN 3.
It is not finished yet, but a good stepper driver is on the way!Bruce
The waitcnt is wrong. If you want to access the Counter it has to be
LONG[ CounterPntr ]+=LONG[ CycleOffsetPntr ]
But that again adds runtime to the loop AND only one COG should really update the Counter. If both update the counter chance is high to have Counter += 2*CycleOffset there in the end.
You seem to ignore my last post from yesterday (loop is to slow for 2_000).
I thought about the driver and I still believe that PASM would be the better choice. A nice piece of PASM code that's doing the ramp up/down including emergency brake would be more usefull because it would run in one COG. For the current driver you need 2 COGs which can't do anything else. If you want to drive 2 steppers you need 4 COGs ....
So, this driver might be perfect for you learning how to drive a stepper and it's maybe enough for projects where you only have 1 stepper, but it's not good for more, I suppose.
But if you like we could make the SPIN version run perfectly and then convert it to PASM?!
The 2000 is not very critical, I just wanted my motors to run much faster than they were currently running, In fact, I had to bump it up to 3000 because it misses steps at 2000, probably due to the reasons you state. But the motors still "ZING" and really fly compared to what I had before this thread started. As I mentioned in the previous post, the problem is that it waits way too long to begin execution. What's up with that, and how can that be resolved?
I was not ignoring what you said. My main goal up to this point was to sync the two methods. Since that has now been achieved, it is time for fine tuning it. There is some confusion however, Jon explained one way and you explained another. Considering my lack of experience in programming with Spin, I am truly uncertain which way to go. Both of you are the experts compared to me. I would love for both of you to examine the code, and determine what is the best way to go to turn this into something nice. It was originally your sample that got me this far, as far as I am concerned, you can doctor this code anyway you like to make it better.
That would be excellent. I would really like to figure out how to do this with one cog, or use one cog to monitor several other cogs, but I am not that smart like you guys. Currently, my programming for these CNC's is inline and can only commit to single tasking. However, when I work out all the bugs, I want to start making use of the Propellers 8 cogs to improve production efficiency. The main reason I like Spin is becaise I can read it, PASM is all greek to me. Normally, I only like to use code that I can easily understand and easily alter. 9 times out of 10, if I don't completely understand the code, I don't use it. This is why I use my overly descriptive symbol names, so that I remember, understand, and can easily alter the code. In this particular circumstance, I would probably make an exception to that rule in this case, because my main goal is to finish the machines, and start producing. If there was truly a good stepper driver in the OBEX that pulsed a step pin like this source code, I would definitely use it, irregardless of the language it was written in.
I am sure that you and many others here at the forum could turn this into a real nice driver that has good value, however it turns out, I would still like to continue participating in that endeavor.
Code Screams:
Bruce
Ok ... let's start from the beginning:
What you do is prototyping. It's absolutely feasible to use hardcodes and have the code less flexible in this phase. Once the code is running you should think in objects. (Definitely some more experienced people already think in objects from the very beginning.) In your case I think at the time we convert it to PASM is fine to start thinking in objects. When you start to make the code flexible you have to think about how to do that, so that the benefit for the code using your object is maximised. In our case that means the code should be able to drive not only one stepper.
So, you have to find out how to do that. That's why Jonny suggested to use pointers to the variables that control the stepper COG because with using the exactly same variables you could only drive one stepper. Of course this works, but it's not the way you do it when thinking in objects.
When you start using the driver as an object, you can define ONE variable and each instance of this object WILL have it's own private version of this variable. So, working with pointers in the object world only makes sense if you want the user of the object keep control over such memory. Of course there are usecases for this as well, but as far as I see the stepper driver does not need that.
Main.spin This is an example how we could use the stepper-driver. RupStepRdown would be our current function Ramp Up Step and Ramp Down. Other usefull functions would maybe not Ramp down but slow down do some more steps or Ramp Up Free Run ....
As you now see,from a usage point of view, you are not interested in the internals. And that's why there is no need to let the user of the object manage the internal variables and pass pointers. The function RupStepRdown belongs to the object as well as the stepper-loop.
In a few hours I can spend some time with the driver and then I can show you more.
That all sounded and looked very good.
Bruce
I just found a major issue, Counter is only initialized as zero.
Bruce
Bruce
Within a duplicate file, I converted CycleOffset back to a global instead of passing it as a pointer. Upon testing, it took approximately a minute longer to execute 1,000,000 pulses, and additionally, it did not keep an accurate count. As far as the speed test goes, it did not make much sense, because your sample code appears to run faster than my version, but I could be wrong.
Bruce
I was a little surprised by that so I whipped up a quick test -- turns out that accessing a global directly versus a pointer to it is significantly faster. At some point you're going to be faced with organizing your code so that it can be used in your project and others, so you may want to live with the slower speed -- or switch to PASM (I wrote a PASM demo for you a few days ago that does the motor drive stuff, it's in this thread).
Of course accessing globals or local variables is faster. If you do long[ addressVar ], the SPIN compiler has to read the content of addressVar from HUB-RAM and then can read/write the content of the memory location you want to access. By using direct variable names there is no need for the additional HUB-access.
I am testing it right now. In this case the ponters are much faster and the count is accurate. Not true with globals.
Bruce