Go to Post Please review the rules for posting. - meaubry [more]
Home
Go Back   Chief Delphi > Technical > Control System > Sensors
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Reply
 
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 16-03-2010, 09:01
Alan Anderson's Avatar
Alan Anderson Alan Anderson is offline
Software Architect
FRC #0045 (TechnoKats)
Team Role: Mentor
 
Join Date: Feb 2004
Rookie Year: 2004
Location: Kokomo, Indiana
Posts: 9,113
Alan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond reputeAlan Anderson has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by AustinSchuh View Post
We are using a continuous rotation potentiometer for a similar purpose. We wired it up like you would wire up any other pot, and it works well. And it is a lot cheaper than an absolute encoder or something like that.
A "free" component from the Kit of Parts (e.g. the magnetic encoder) is cheaper than any potentiometer.
Reply With Quote
  #2   Spotlight this post!  
Unread 16-03-2010, 10:21
Mark McLeod's Avatar
Mark McLeod Mark McLeod is online now
Just Itinerant
AKA: Hey dad...Father...MARK
FRC #0358 (Robotic Eagles)
Team Role: Engineer
 
Join Date: Mar 2003
Rookie Year: 2002
Location: Hauppauge, Long Island, NY
Posts: 8,801
Mark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond reputeMark McLeod has a reputation beyond repute
Re: encoder for cam-driven kicker?

We are also using a limit switch on our cam, and it usually works quite well.

One problem we ran into is that our kicker is adjustable and at high energy the whole robot shakes enough that the limit switch vibrates and can give a false reading that has to be programmed around.
__________________
"Rationality is our distinguishing characteristic - it's what sets us apart from the beasts." - Aristotle
Reply With Quote
  #3   Spotlight this post!  
Unread 16-03-2010, 10:34
pfreivald's Avatar
pfreivald pfreivald is offline
Registered User
AKA: Patrick Freivald
FRC #1551 (The Grapes of Wrath)
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2001
Location: Naples, NY
Posts: 2,296
pfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond reputepfreivald has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Mark McLeod View Post
One problem we ran into is that our kicker is adjustable and at high energy the whole robot shakes enough that the limit switch vibrates and can give a false reading that has to be programmed around.
Hmm... We haven't had that problem. Our limit switch triggers off of the kicker itself -- if it's 'ready to fire', the motor stops the cam until the trigger is pulled, and then runs it until the switch is triggered again.

Thus far, it's been super-solid.
__________________
Patrick Freivald -- Mentor
Team 1551
"The Grapes of Wrath"
Bausch & Lomb, PTC Corporation, and Naples High School

I write books, too!
Reply With Quote
  #4   Spotlight this post!  
Unread 17-03-2010, 09:45
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,077
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Mark McLeod View Post
the limit switch vibrates and can give a false reading
You've piqued my curiosity. Would you mind giving a bit more detail how the switch is mounted?

I can't picture how this might happen; certainly no amount of vibration of the switch itself (that could occur on the robot) could cause the switch to give a false reading... unless the vibration is causing the switch lever to bump against something?


~
Reply With Quote
  #5   Spotlight this post!  
Unread 17-03-2010, 10:09
The Lucas's Avatar
Happy Birthday! The Lucas The Lucas is offline
CaMOElot, it is a silly place
AKA: My First Name is really "The" (or Brian)
FRC #0365 (The Miracle Workerz); FRC#1495 (AGR); FRC#4342 (Demon)
Team Role: Mentor
 
Join Date: Mar 2002
Rookie Year: 2001
Location: Dela-Where?
Posts: 1,564
The Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond reputeThe Lucas has a reputation beyond repute
Send a message via AIM to The Lucas
Re: encoder for cam-driven kicker?

We also use a cam driven kicker. We put a simple 1 turn pot on the shaft for the kicker (not the cam where you need continuous turns). This works well for us because we have multiple positions we want the kicker to be in: one position (middle of travel) for ball collection to stop balls from going under the frame, the other to give us clearance (close to kicking) to go over the bump. It is also easier to detect a pot failure than a limit switch failure.
__________________
Electrical & Programming Mentor ---Team #365 "The Miracle Workerz"
Programming Mentor ---Team #4342 "Demon Robotics"
Founding Mentor --- Team #1495 Avon Grove High School
2007 CMP Chairman's Award - Thanks to all MOE members (and others) past and present who made it a reality.
Robot Inspector
"I don't think I'm ever more ''aware'' than I am right after I burn my thumb with a soldering iron"
Reply With Quote
  #6   Spotlight this post!  
Unread 17-03-2010, 10:32
Chris Hibner's Avatar Unsung FIRST Hero
Chris Hibner Chris Hibner is offline
Eschewing Obfuscation Since 1990
AKA: Lars Kamen's Roadie
FRC #0051 (Wings of Fire)
Team Role: Engineer
 
Join Date: May 2001
Rookie Year: 1997
Location: Canton, MI
Posts: 1,488
Chris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond repute
Re: encoder for cam-driven kicker?

Continuous pots work pretty well, but there are two "gotcha's::

1) The pot can shift over time due to shaft slippage. Usually not that big of a deal, but keep an eye on it.

2) (Potentially BIG) There is a gap in the pot at the wrap-around point where the voltage will float. That will give you false position readings in the gap. The gap may seem insignificant at first, but it grows over time as the pot mechanically wears.

There are two ways to cure #2. The first is to wire in a pull-down resistor so the voltage doesn't float. The second method is to put the gap at an angle that you don't need to stop the motor, stop reading the pot near the gap, do a timed motor command to get through the gap, then start reading the pot again. You may consider doing both. We were using a continuous pot at Kettering and we somehow lost the pull-down resistor. We had trouble kicking for a few matches until we figured out what happened.

If you want to use a relative encoder, your cam actually makes that quite easy. Start each match by driving the kicker motor backward with a small enough PWM so you don't damage anything. Montior the rate of the encoder. Once the encoder stops moving, you know you hit the edge of your cam. Reset the encoder position and then start using the kicker as you normally would. By doing this, you will get a very accurate zero point of the encoder every match.
__________________
-
An ounce of perception is worth a pound of obscure.
Reply With Quote
  #7   Spotlight this post!  
Unread 17-03-2010, 13:54
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,077
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Chris Hibner View Post
If you want to use a relative encoder, your cam actually makes that quite easy. Start each match by driving the kicker motor backward with a small enough PWM so you don't damage anything. Montior the rate of the encoder. Once the encoder stops moving, you know you hit the edge of your cam. Reset the encoder position and then start using the kicker as you normally would. By doing this, you will get a very accurate zero point of the encoder every match.
Great suggestion, but may not be robust for our configuration. We'd have to thread the needle between going slow enough not to damage the motor/cam, and going fast enough not to get a penalty for having the end of the kicker outside the frame perimeter for more than two seconds. Also, it would chew up valuable time in autonomous.

What I envisioned doing instead was to pre-configure the cam in the "armed" ready-to-kick position when the robot is placed on the field. Then at the start of autonomous, zero the encoder counter.

What is the data type of the encoder counter in the FPGA? Is it large enough to just let it run free without overflowing during a match ?


~
Reply With Quote
  #8   Spotlight this post!  
Unread 17-03-2010, 14:24
Chris Hibner's Avatar Unsung FIRST Hero
Chris Hibner Chris Hibner is offline
Eschewing Obfuscation Since 1990
AKA: Lars Kamen's Roadie
FRC #0051 (Wings of Fire)
Team Role: Engineer
 
Join Date: May 2001
Rookie Year: 1997
Location: Canton, MI
Posts: 1,488
Chris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Ether View Post
What is the data type of the encoder counter in the FPGA? Is it large enough to just let it run free without overflowing during a match ?


~
The data type is double, at least in LabVIEW.

You can always convert the encoder output into degrees and do:

Code:
if (encoderDeg > 360)
 {
   encoderDeg -= 360;
}
or the LabVIEW equivalent so you don't have to worry about overflow. Then you can always stop the motor at the same angle.
__________________
-
An ounce of perception is worth a pound of obscure.
Reply With Quote
  #9   Spotlight this post!  
Unread 17-03-2010, 15:09
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,077
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Chris Hibner View Post
The data type is double, at least in LabVIEW.
Yeah, but I doubt that the counter in the FPGA is floating-point.

I want to know if the FPGA counter will not overflow during a match.

Quote:
You can always convert the encoder output into degrees and do:

Code:
if (encoderDeg > 360)
 {
   encoderDeg -= 360;
}

Does the above code actually write a new value to the FPGA counter itself? Or just zero the associated RAM variable in cRIO?


~
Reply With Quote
  #10   Spotlight this post!  
Unread 17-03-2010, 15:57
Chris Hibner's Avatar Unsung FIRST Hero
Chris Hibner Chris Hibner is offline
Eschewing Obfuscation Since 1990
AKA: Lars Kamen's Roadie
FRC #0051 (Wings of Fire)
Team Role: Engineer
 
Join Date: May 2001
Rookie Year: 1997
Location: Canton, MI
Posts: 1,488
Chris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Ether View Post
Yeah, but I doubt that the counter in the FPGA is floating-point.

I want to know if the FPGA counter will not overflow during a match.




Does the above code actually write a new value to the FPGA counter itself? Or just zero the associated RAM variable in cRIO?


~

If WPI and NI did things properly, it really doesn't matter if the FPGA counter overflows or not.

Let's assume they did things correctly. One possible implementation is that the FPGA services the encoder interrupts and keeps track of the counter in a signed 16-bit register. Then the WPI interface samples that register at a given time interval. The WPI code would be like the following:

Code:
// variable declarations
s16 encoderCnt = 0;
s16 encoderCntPrev;
s16 encoderDiff;
double encoderOut;

// ...

// in the loop

encoderCntPrev = encoderCnt;
encoderCnt = getFPGAencoderCnt();
encoderDiff = encoderCnt - encoderCntPrev;

encoderOut = encoderOut + encoderDiff*inchesPerCount;

// etc.
(by the way, s16 is a typdef'd variable type for a signed 16 bit integer variable. The actual declaration will depend on your micro)


With the above code, it does not matter if the FPGA encoder counter overflows. If you don't believe me, try the following code:

Code:
s16 counter1, counter2, counter3;

counter1 = 32765;
counter2 = counter1 + 5;

cout << "counter1 = " << counter1 << "\n";
cout << "counter2 = " << counter2 << "\n";

counter3 = counter2 - counter1;

cout << "counter3 = " << counter3 << "\n";
If you don't like C/C++, you can do the same thing in LabVIEW. You'll notice that the two's compliment math handles the wraparound flawlessly and counter3 will equal 5. With the subtraction, you'll never know an overflow occurred - and it doesn't really matter.

This is actually a very slick way of handling angles to avoid having to do a lot of wrap-around math and checking. If you always scale your angles such that 360 degrees is equal to the overflow point, the two's compliment math automatically takes care of all of the wrapping for you.
__________________
-
An ounce of perception is worth a pound of obscure.

Last edited by Chris Hibner : 17-03-2010 at 16:00.
Reply With Quote
  #11   Spotlight this post!  
Unread 17-03-2010, 16:39
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,077
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Chris Hibner View Post
If WPI and NI did things properly, it really doesn't matter if the FPGA counter overflows or not.

Let's assume they did things correctly. One possible implementation is that the FPGA services the encoder interrupts and keeps track of the counter in a signed 16-bit register. Then the WPI interface samples that register at a given time interval. The WPI code would be like the following:

Code:
// variable declarations
s16 encoderCnt = 0;
s16 encoderCntPrev;
s16 encoderDiff;
double encoderOut;

// ...

// in the loop

encoderCntPrev = encoderCnt;
encoderCnt = getFPGAencoderCnt();
encoderDiff = encoderCnt - encoderCntPrev;

encoderOut = encoderOut + encoderDiff*inchesPerCount;

// etc.
(by the way, s16 is a typdef'd variable type for a signed 16 bit integer variable. The actual declaration will depend on your micro)


With the above code, it does not matter if the FPGA encoder counter overflows. If you don't believe me, try the following code:

Code:
s16 counter1, counter2, counter3;

counter1 = 32765;
counter2 = counter1 + 5;

cout << "counter1 = " << counter1 << "\n";
cout << "counter2 = " << counter2 << "\n";

counter3 = counter2 - counter1;

cout << "counter3 = " << counter3 << "\n";
If you don't like C/C++, you can do the same thing in LabVIEW. You'll notice that the two's compliment math handles the wraparound flawlessly and counter3 will equal 5. With the subtraction, you'll never know an overflow occurred - and it doesn't really matter.

This is actually a very slick way of handling angles to avoid having to do a lot of wrap-around math and checking. If you always scale your angles such that 360 degrees is equal to the overflow point, the two's compliment math automatically takes care of all of the wrapping for you.
What you suggest will likely work for this non-critical application whose running time is less than three minutes.

However, for the benefit of those reading this thread who are just learning about realtime control, and who may go on to program other realtime applications, the following caveat should be pointed out:

The 2010 FRC LabVIEW framework is most definitely NOT hard-real-time. Using code running in cRIO to re-set the FPGA counter is not a robust solution if high accuracy is required and you do not want to introduce errors that may accumulate over time.

At the very least, the reading and re-setting of the FPGA counter should probably be protected by a critical section to minimize the occurrence of accumulated errors.


~
Reply With Quote
  #12   Spotlight this post!  
Unread 17-03-2010, 19:00
JGurnow's Avatar
JGurnow JGurnow is offline
Registered User
FRC #0217 (The Thunder Chickens)
Team Role: Programmer
 
Join Date: Mar 2010
Rookie Year: 2008
Location: Sterling Heights
Posts: 20
JGurnow is on a distinguished road
Re: encoder for cam-driven kicker?

On our kicker's cam we don't use an encoder, we use a hall effect sensor.

How it works is you place two magnets on your robot in the cam at a certain point. When you see an edge that means you crossed over a magnet, depending on how you arrange your magnets. At the top of our cam is a flat region where it sits when the sensor reads it. When it goes over the edge you see the edge again and can recock it easily.

We are going to change to an encoder though, they aren't quadrature or magnetic, they are analog encoders. Essentially an infinite potentiometer. Its setup in a 1:1 ratio so the same value is always cocked. You still need to calibrate when replacing the encoder though.
Reply With Quote
  #13   Spotlight this post!  
Unread 17-03-2010, 22:48
Chris Hibner's Avatar Unsung FIRST Hero
Chris Hibner Chris Hibner is offline
Eschewing Obfuscation Since 1990
AKA: Lars Kamen's Roadie
FRC #0051 (Wings of Fire)
Team Role: Engineer
 
Join Date: May 2001
Rookie Year: 1997
Location: Canton, MI
Posts: 1,488
Chris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond reputeChris Hibner has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Ether View Post
What you suggest will likely work for this non-critical application whose running time is less than three minutes.

However, for the benefit of those reading this thread who are just learning about realtime control, and who may go on to program other realtime applications, the following caveat should be pointed out:

The 2010 FRC LabVIEW framework is most definitely NOT hard-real-time. Using code running in cRIO to re-set the FPGA counter is not a robust solution if high accuracy is required and you do not want to introduce errors that may accumulate over time.

At the very least, the reading and re-setting of the FPGA counter should probably be protected by a critical section to minimize the occurrence of accumulated errors.


~
I'm not sure what you're saying here.

As far as I know, there is no cRIO code resetting the FPGA counter. My point was as follows (I didn't state it very clearly):

As long as:

1) the encoders are decoded by an interrupt handler in the FPGA

and

2) the cRIO samples the FPGA counter fast enough such that it cannot do a complete overflow cycle (e.g. the encoder cannot rotate more than 65536 counts (if 16-bit counter is used) in one cRIO sample).

and

3) The WPI code uses the difference between the current FPGA count and the previous FPGA count (instead of the absolute FPGA).

THEN

FPGA overflow does not matter, since the two's compliment math in the subtraction in step 3 above will work even in an overflow situation. You can run the cRIO for three years (not 3 minutes) and you will not see an issue from the FPGA counter. You will, however, eventually overflow the double-precision distance calculation from the WPI code, but that has nothing to do with the FPGA overflowing.
__________________
-
An ounce of perception is worth a pound of obscure.
Reply With Quote
  #14   Spotlight this post!  
Unread 17-03-2010, 23:02
Ether's Avatar
Ether Ether is offline
systems engineer (retired)
no team
 
Join Date: Nov 2009
Rookie Year: 1969
Location: US
Posts: 8,077
Ether has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond reputeEther has a reputation beyond repute
Re: encoder for cam-driven kicker?

Quote:
Originally Posted by Chris Hibner View Post
I'm not sure what you're saying here.

As far as I know, there is no cRIO code resetting the FPGA counter. My point was as follows (I didn't state it very clearly):

As long as:

1) the encoders are decoded by an interrupt handler in the FPGA

and

2) the cRIO samples the FPGA counter fast enough such that it cannot do a complete overflow cycle (e.g. the encoder cannot rotate more than 65536 counts (if 16-bit counter is used) in one cRIO sample).

and

3) The WPI code uses the difference between the current FPGA count and the previous FPGA count (instead of the absolute FPGA).

THEN

FPGA overflow does not matter, since the two's compliment math in the subtraction in step 3 above will work even in an overflow situation. You can run the cRIO for three years (not 3 minutes) and you will not see an issue from the FPGA counter. You will, however, eventually overflow the double-precision distance calculation from the WPI code, but that has nothing to do with the FPGA overflowing.
OK, my bad, in my haste I didn't look at your code carefully enough.

By the way, I love your sig line. Very clever. Is that an original ?


~
Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
pic: 2252 kicker cam EIT2 Extra Discussion 1 16-02-2010 07:51
pic: Winch for Kicker MrForbes Extra Discussion 10 10-02-2010 10:42
pic: KICKER FOR 1322 joeweber Extra Discussion 12 26-01-2010 16:45
Event Driven Development for FRC-Java spartango Java 5 05-01-2010 11:52
Looking for miniDV cam MattK Chit-Chat 3 31-01-2006 20:32


All times are GMT -5. The time now is 21:58.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi