PDA

View Full Version : Encoder velocity....



thasatelliteguy
- 18th April 2014, 00:42
HI! I have a project I am bringing over to PIC from Arduino that controls a self-aquire satellite dish. There are no limit switches so I am performing a homing procedure using velocity, specifically, a sudden decrease in velocity, to determine the edge of range of motion. ie, "When the motor starts to significantly bog and slow down, STOP, and call this 0. The current code looks something like this..
(Obviously, it's looped in the program. About every 1/4 second or so..)

newposition = encoder0Pos;
newtime = millis();
if(newposition > oldposition)
{
newvel = (newposition-oldposition) * 1000 /(newtime-oldtime);
}
else if(oldposition > newposition)
{
newvel = (oldposition-newposition) * 1000 /(newtime-oldtime);
}
oldposition = newposition;
oldtime = newtime;

My question is the newtime=millis().... How do I get an equivelent in PBP? Since I am not looking to output this in any terms of RPMs or anything, it doesn't have to be absolute. Could be time, clock cycles, or whatever, it really doesn't matter as long as its accurate relative to itself.

Heckler
- 18th April 2014, 02:38
What does the value "mills" represent?

Is it the time between encoder marks?
What PIC are you using?

Does it have internal timers?
If so you could use an interrupt to start the timer at each mark on the encoder and then check the timer on the next interrupt.

or if you don't need your PIC to do something else while waiting for the next mark you could start incrementing a counter variable when you detect the first mark and then stop incrementing on the next mark and see what the value is. Or if the encoder is going to stop dead at the end of travel you could turn off the motor if the count reaches a high enough value to indicate it has stopped or slowed.

Heckler
- 18th April 2014, 02:45
It looks like you are converting from C to BASIC, is that correct?
What is your level of BASIC understanding?

One good way to learn BASIC is to look at and study all the other code examples in the wiki at the top of the forum and also just search the forum. oh yeah and refer to the PBP manual.

Demon
- 18th April 2014, 02:57
Darrel's interrupt routine makes timers easy to use if you decide to go that route (look at elapsed time example to count ticks).

http://www.picbasic.co.uk/forum/showthread.php?t=17547&p=126222#post126222

Robert

thasatelliteguy
- 18th April 2014, 06:06
Thanks for the replies! Let me see if I can answer some questions....

Chip - 20M2 (Right this second... by the time the encoder clicks again who knows? lol)

No, as long as the dish is moving, I don't really need it to do anything else but count. I am using this with a bluetooth serial connection though. There will be a custom handheld device with some buttons and a Nokia 5110 screen running on a Micro?? at this point. Also, I want to be able to link with a cell phone via bluetooth serial commands. (I did this on a custom toy tank I built earlier this week already with great success.) I may need at some point though, to be able to send the current position to the controlling device, so I wouldn't want to do anything that would prevent that later on.

Yes, I'm bringing this over from C to BASIC.

Experience with BASIC? Fairly strong I guess. I installed the IDE on Friday, and it's Thursday, so nearly a week.

thasatelliteguy
- 18th April 2014, 06:26
I haven't decided what I am going to do just yet exactly... These are the chips I have (or are on their way)
1X 14M2
2X 18M2
2X 20M2
5X 16F688
5X 16F877A-I/P
1X 16F628A-I/P

I didn't realize until just now that the PICAXE BASIC seems to be quite different than PBP?? The two IDE's are giving me different syntax's and procedures? Is this correct or am I missing something? As a backup plan for the picaxe chips, it's my understanding that I can use the PIC programmer to wipe the PICAXE bootloader and use them in their native state?

So now that I seem to have hijacked my own thread....lol

thasatelliteguy
- 18th April 2014, 14:30
What does the value "mills" represent?

it's the command(value) of the clock in the atmega.


Is it the time between encoder marks?
No. It is simply the current time. That's why the newtime-oldtime statement,


What PIC are you using?



Does it have internal timers?
If so you could use an interrupt to start the timer at each mark on the encoder and then check the timer on the next interrupt.

This is my question... what is the command for accessing the internal clock? I may be looking in the wrong places but I can't find it anywhere. I see stuff that appears to be timers, and I guess that would work, but can't I just ask the PIC "What time is it now?" Is it not keeping a clock cycle tally from bootup?


or if you don't need your PIC to do something else while waiting for the next mark you could start incrementing a counter variable when you detect the first mark and then stop incrementing on the next mark and see what the value is. Or if the encoder is going to stop dead at the end of travel you could turn off the motor if the count reaches a high enough value to indicate it has stopped or slowed.

If it stops dead it will destroy itself. It has to stop on deceleration before it binds too much.

HenrikOlsson
- 18th April 2014, 18:59
Hi,

This is my question... what is the command for accessing the internal clock?
There is none.


I may be looking in the wrong places but I can't find it anywhere.
No, you're not looking in the wrong place because there is no such command or function call.


I see stuff that appears to be timers, and I guess that would work, but can't I just ask the PIC "What time is it now?"
Yes, timers would work and timers is exactly what those other chips are using (and using up, stopping you from using them the way you wish) to provide you with the millis() function call etc. So no you can't "just" ask the PIC "What time is it now" - if you don't have a PIC with built in RTC obviosuly, in which case you could ask it EXACTLY that.


Is it not keeping a clock cycle tally from bootup?
No it's not. It can most certainly do it but you need to write the code for.
At the very least you set one of the hardware timers up to derive its clock from the main oscillator and there you have your cycle counter. You read the timer as you read any other register in the PIC, no special function calls etc.

For example, TMR1 is a 16 bit wide counter/timer. It's pretty much setup to be a "tick counter" at start up, all you need to do is enable it

T1CON.0 = 1 ' Start TMR1

From now on TMR1 will tick at Fosc/4 but you can scale that down by using the prescaler.

But, instead of calculating the velocity based on BOTH the time delta and the position delta, why not simply make sure you poll the position at a specific interval? That way you know when the velocity is changing without doing a lot of math.

Finally, PBP and PICAXE are both BASIC but they are not the same. They are similar in some ways, different in others.

/Henrik.

thasatelliteguy
- 18th April 2014, 23:12
[QUOTE=HenrikOlsson;126443]Hi,
For example, TMR1 is a 16 bit wide counter/timer. It's pretty much setup to be a "tick counter" at start up, all you need to do is enable it

T1CON.0 = 1 ' Start TMR1

From now on TMR1 will tick at Fosc/4 but you can scale that down by using the prescaler.

OK. So I am starting the clock ticker... How would I pull the current values from it? And then, since I only really need it when the machine is "lost", after my homing process, would it be to my advantage to disable it once finished, or just leave it running?

And I'm not sure what you mean about getting V without doing a lot of math. The math is simple enough... and I don't see how to find V any easier since V is a calculation of time and distance. I would love an easier way if you can show me. This is what I'm doing now...


homeElevation:
serout commout,T4800,"E"
Eencoder0Pos = 0
gosub elUP
pause(250)
if Eencoder0Pos = 0 then gosub moveerror
done = 0
Do
serin commin,T4800,cereal
if cereal = "*" then goto abort
Enewposition = Eencoder0Pos
newtime = millis()
if Enewposition > Eoldposition then Enewvel = (Enewposition-Eoldposition) * 1000 /(newtime-oldtime)
if Eoldposition > Enewposition then Enewvel = (Eoldposition-Enewposition) * 1000 /(newtime-oldtime)
Eoldposition = Enewposition
oldtime = newtime

if Enewvel < .5*Eoldvel then
gosub allSTOP
Eencoder0Pos = 3665
gosub elDN
do
serin commin,T4800,cereal
if cereal = "*" then goto abort
if Eencoder0Pos =< elHOMEpos then
gosub allSTOP
done = 1
exit
endif
pause(250)
loop
endif
if(Enewvel > .5*Eoldvel) then Eoldvel = Enewvel
if done = 1 then exit
loop
return

Demon
- 18th April 2014, 23:32
...OK. So I am starting the clock ticker... How would I pull the current values from it?...

Did you check this?


Darrel's interrupt routine makes timers easy to use if you decide to go that route (look at elapsed time example to count ticks).

http://www.picbasic.co.uk/forum/showthread.php?t=17547&p=126222#post126222

Robert

HenrikOlsson
- 18th April 2014, 23:38
Hi,

OK. So I am starting the clock ticker... How would I pull the current values from it? And then, since I only really need it when the machine is "lost", after my homing process, would it be to my advantage to disable it once finished, or just leave it running?
The timer, since it is 16 bits wide, consits of two 8 bit registers, TMR1H and TMR1L (check the datasheet). You read the registers as you read any other register in the PIC, for example TickCount = TMR1H * 256 + TMR1L. Since it's a hardware timer it'll keep running in the background without any impact to the rest of your software - as long as you don't want to use it for something else of course. Just remember that it's "only" 16 bits wide so it'll overflow "frequenctly".


And I'm not sure what you mean about getting V without doing a lot of math. The math is simple enough...
Well, yes, the math might not be very complicated from a human perspective but none of the devices you list as possible targets for your code does multiplication OR division (no 10, 12, 16 or 18 series PICs does division) in hardware so even though the actual equation/formula in it self (multiply by a thousand, divide by delta time) isn't "complicated" it's going to take the poor little PIC a lot of instruction cycles to get to a result (which MAY or may not matter). What I'm saying is that if you instead see to it that you get a new position update every x ms then all you need is a subtraction (current position - previous position) to get your velocity (in encoder counts per x ms).

If it's not possible to get a consistent interval between position updates then you ARE doing the right thing by calculating velocity based on delta time AND distance.

/Henrik.

thasatelliteguy
- 21st April 2014, 00:33
Thanks for the help guys... I don't think the clock cycles will be much of an issue cuz the only thing it will be doing is keeping track of the encoder at that time. So I don't think changing it would be of much benefit. Hopefully it'll work out. Now I'm having problems with syntax on the serout command that I just ain't getting. It looks EXACTLY like the help file but will not accept it so I'll be back I'm sure cuz the code in C is 997 lines and is only about 50% complete.