Go to Post According to a 6 year old I once met at a demo, our FRC machine was not a robot because, "How can it be a robot if it doesn't have a face?" - Jared Russell [more]
Home
Go Back   Chief Delphi > Technical > Programming
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Closed Thread
Thread Tools Rating: Thread Rating: 6 votes, 5.00 average. Display Modes
  #1   Spotlight this post!  
Unread 12-07-2013, 10:52
cad321 cad321 is offline
Jack of all trades, Master of none
AKA: Brian Wagg
FRC #2386 (Trojans)
Team Role: Alumni
 
Join Date: Jan 2013
Rookie Year: 2012
Location: Burlington, Ontario
Posts: 350
cad321 is just really nicecad321 is just really nicecad321 is just really nicecad321 is just really nice
Arduino Mecanum drive using PWM?

I have been trying to program an Arduino Uno to take PWM signals from a spectrum RC receiver and mix those signals to control 4 motors on a mecanum drive bot. Although I don't have the bot built/designed yet I have been trying to get some of the code working. My issue is that when ever I try to use more than one pulseIn command it adds about 1 second of lag per pulseIn command. I am controlling a servo through this setup.

The code:
Code:
#include <Servo.h>

Servo FLS; //front left servo
Servo FRS; //front right servo...
Servo RLS;
Servo RRS;
int Forward = 1; //Inputs from RC receiver
int Strafe = 2;  
int Rotate = 3;  
unsigned long ForwardDuration; //To store the duration of the pulses
unsigned long StrafeDuration;    //coming from the receiver
unsigned long RotateDuration;
unsigned long FL; //Front Left Value
unsigned long FR; //Front Right Value...
unsigned long RL;
unsigned long RR;

void setup()
{
  FLS.attach(10);
  FRS.attach(11);
  RLS.attach(12);
  RRS.attach(13);
  pinMode(Forward, INPUT);
  pinMode(Strafe, INPUT);
  pinMode(Rotate, INPUT);
}

void loop()
{
  ForwardDuration = pulseIn(Forward, HIGH); //read receiver inputs
  StrafeDuration = pulseIn(Strafe, HIGH);
  RotateDuration = pulseIn(Rotate, HIGH);
  FL = ForwardDuration + StrafeDuration + RotateDuration;
  FR = ForwardDuration - StrafeDuration - RotateDuration;
  RL = ForwardDuration - StrafeDuration + RotateDuration;
  RR = ForwardDuration + StrafeDuration - RotateDuration;
  FLS.writeMicroseconds(FL);
  FRS.writeMicroseconds(FR);
  RLS.writeMicroseconds(RL);
  RRS.writeMicroseconds(RR);  
}
My initial thought was to add interrupts but I'm not exactly sure how to do that.

My attempt at using Interrupts:
Code:
#include <Servo.h>

Servo FLS; //front left servo
Servo FRS; //front right servo...
Servo RLS;
Servo RRS;
int Forward = 1; //Inputs from RC receiver
int Strafe = 2;  
int Rotate = 3;  
volatile unsigned long ForwardDuration; //To store the duration of the pulses
volatile unsigned long StrafeDuration;    //coming from the receiver
volatile unsigned long RotateDuration;
volatile unsigned long FL; //Front Left Value
volatile unsigned long FR; //Front Right Value...
volatile unsigned long RL;
volatile unsigned long RR;

void setup()
{
  attachInterrupt(0, reciever, CHANGE);
  FLS.attach(10);
  FRS.attach(11);
  RLS.attach(12);
  RRS.attach(13);
  pinMode(Forward, INPUT);
  pinMode(Strafe, INPUT);
  pinMode(Rotate, INPUT);
}

void loop()
{
  FLS.write(FL);
  FRS.writeMicroseconds(FR);
  RLS.writeMicroseconds(RL);
  RRS.writeMicroseconds(RR);
}
void reciever()
 {
  ForwardDuration = pulseIn(Forward, HIGH); //read receiver inputs
  StrafeDuration = pulseIn(Strafe, HIGH);
  RotateDuration = pulseIn(Rotate, HIGH);

  FL == ForwardDuration + StrafeDuration + RotateDuration;
  FR == ForwardDuration - StrafeDuration - RotateDuration;
  RL == ForwardDuration - StrafeDuration + RotateDuration;
  RR == ForwardDuration + StrafeDuration - RotateDuration;
 }
The reason I am posting here and not on the Arduino forums is that it wont load on my computer right now so I thought I'd try my shot with CD and see if anyone here could help.
  #2   Spotlight this post!  
Unread 12-07-2013, 14:09
tr6scott's Avatar
tr6scott tr6scott is offline
Um, I smell Motor!
AKA: Scott McBride
FRC #2137 (TORC)
Team Role: Mentor
 
Join Date: Dec 2007
Rookie Year: 2005
Location: Oxford, MI
Posts: 535
tr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond reputetr6scott has a reputation beyond repute
Re: Arduino Mecanum drive using PWM?

http://forum.arduino.cc/index.php?PH...p ic=42462.60

Should Help, looks like there is an interrupt library developed for servo.
__________________
The sooner we get behind schedule, the more time we have to catch up.

  #3   Spotlight this post!  
Unread 12-07-2013, 14:45
magnets's Avatar
magnets magnets is offline
Registered User
no team
 
Join Date: Jun 2013
Rookie Year: 2012
Location: United States
Posts: 748
magnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond repute
Re: Arduino Mecanum drive using PWM?

I don't think that you'll be needing interrupts. The arduino is fast enough to control 4 PWM's. Also, don't use the unsigned longs. If forwardDuration is 10, strafeDuration is 100, and rotateDuration is 100, you will have a negative value for FR, which is unsigned. I don't know what happens on the arduino, but it may wrap around to some massive number.

EDIT: Depending on what you're using to control your motors, you may have better sucsess with analogWrite. Also, how are you testing to see the lag?

Last edited by magnets : 12-07-2013 at 15:16.
  #4   Spotlight this post!  
Unread 12-07-2013, 15:25
cad321 cad321 is offline
Jack of all trades, Master of none
AKA: Brian Wagg
FRC #2386 (Trojans)
Team Role: Alumni
 
Join Date: Jan 2013
Rookie Year: 2012
Location: Burlington, Ontario
Posts: 350
cad321 is just really nicecad321 is just really nicecad321 is just really nicecad321 is just really nice
Re: Arduino Mecanum drive using PWM?

Thanks for the help. I finally was able to load the arduino forums and now have my servos responding virtually instantly. I just needed to increase the timeout in the pulseIn function (the amount of time the arduino searched for a pulse coming in before moving on in the code).
  #5   Spotlight this post!  
Unread 12-07-2013, 16:05
Tungrus Tungrus is offline
Registered User
no team
 
Join Date: Mar 2013
Location: Somewhere
Posts: 375
Tungrus is a jewel in the roughTungrus is a jewel in the roughTungrus is a jewel in the roughTungrus is a jewel in the rough
Re: Arduino Mecanum drive using PWM?

Care to share your implementation? It may help other expri-mentors. Thanks.
  #6   Spotlight this post!  
Unread 12-07-2013, 18:44
cad321 cad321 is offline
Jack of all trades, Master of none
AKA: Brian Wagg
FRC #2386 (Trojans)
Team Role: Alumni
 
Join Date: Jan 2013
Rookie Year: 2012
Location: Burlington, Ontario
Posts: 350
cad321 is just really nicecad321 is just really nicecad321 is just really nicecad321 is just really nice
Re: Arduino Mecanum drive using PWM?

I am planning on taking the pwm signals from my spectrum ar6210 and mixing them with the arduino using the following code to create a robot with a mecanum drive. For the motors I plan on using some continuous rotation servos and I am planning on buying some small mecanum wheels such as the 4in vex wheels.

Code:
#include <Servo.h>

Servo FLS; //front left servo
Servo FRS; //front right servo...
Servo RLS;
Servo RRS;
int Forward = 1; //Inputs from RC receiver
int Strafe = 2;  
int Rotate = 3;  
unsigned long ForwardDuration; //To store the duration of the pulses
unsigned long StrafeDuration;    //coming from the receiver
unsigned long RotateDuration;
unsigned long FL; //Front Left Value
unsigned long FR; //Front Right Value...
unsigned long RL;
unsigned long RR;
unsigned long timeout = 20000;

void setup()
{
  FLS.attach(10);
  FRS.attach(11);
  RLS.attach(12);
  RRS.attach(13);
  pinMode(Forward, INPUT);
  pinMode(Strafe, INPUT);
  pinMode(Rotate, INPUT);
}

void loop()
{
  ForwardDuration = pulseIn(Forward, HIGH, timeout); //read receiver inputs
  StrafeDuration = pulseIn(Strafe, HIGH, timeout);
  RotateDuration = pulseIn(Rotate, HIGH, timeout);
  FL = ForwardDuration + StrafeDuration + RotateDuration;
  FR = ForwardDuration - StrafeDuration - RotateDuration;
  RL = ForwardDuration - StrafeDuration + RotateDuration;
  RR = ForwardDuration + StrafeDuration - RotateDuration;
  if(FL < 1000){
    FL = 1000;
  }else if(FL > 2000){
    FL = 2000;
  }if(FR < 1000){
    FR = 1000;
  }else if(FR > 2000){
    FR = 2000;
  }if(RL < 1000){
    RL = 1000;
  }else if(RL > 2000){
    RL = 2000;
  }if(RR < 1000){
    RR = 1000;
  }else if(RR > 2000){
    RR = 2000;
  }
  FLS.writeMicroseconds(FL);
  FRS.writeMicroseconds(FR);
  RLS.writeMicroseconds(RL);
  RRS.writeMicroseconds(RR);  
}
I am unsure at the moment if this code will work yet as I do not have a bot to test with at the moment, but hopefully I will be able to collect all of the resources I need this summer.
  #7   Spotlight this post!  
Unread 14-07-2013, 15:49
Mike Bortfeldt Mike Bortfeldt is offline
Registered User
FRC #1126 (& 1511)
Team Role: Mentor
 
Join Date: Oct 2004
Rookie Year: 2004
Location: Rochester, NY
Posts: 119
Mike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud ofMike Bortfeldt has much to be proud of
Re: Arduino Mecanum drive using PWM?

cad321,

A couple of observations regarding the I/O. The pulseIn code (source) looks like it will return a zero (0) when it does not find the pulse within the timeout period. You may want to put in some code to check for this, otherwise your outputs may not be what you would like. Also, be aware that your "loop" execution time will be variable depending on how long it takes to obtain the three pulse values and output to your four servos. Assuming a standard 20 millisecond interval for the incoming servo PWM value, you will probably have a range between 8 to 65 milliseconds. This may not be a problem.

My knowledge of the hardware you are using is limited, but You may also want to review your mixing algorithm as well. Again, assuming a standard servo input (1-2 ms pulse), the pulseIn should return values between 1000 and 2000 (usec). Adding all three together for FL (for example) would yield 3000 to 6000, or basically your maximum all the time. This could be correct if the inputs are not what I assumed, but it doesn't look right for a standard servo input/output signal. My guess, based on your original post of the 1 second delays, indicate that you are probably not reading at least two of the signals (Strafe & Rotate perhaps?), so you are adding zero (0) to your forward value and the calculations are doing what you expect. The 1 second delay is approximately the timeout for the default pulseIn when it doesn't see a pulse and no explicit timeout is passed.

Mike
  #8   Spotlight this post!  
Unread 14-07-2013, 16:24
cad321 cad321 is offline
Jack of all trades, Master of none
AKA: Brian Wagg
FRC #2386 (Trojans)
Team Role: Alumni
 
Join Date: Jan 2013
Rookie Year: 2012
Location: Burlington, Ontario
Posts: 350
cad321 is just really nicecad321 is just really nicecad321 is just really nicecad321 is just really nice
Re: Arduino Mecanum drive using PWM?

Quote:
Originally Posted by Mike Bortfeldt View Post
My knowledge of the hardware you are using is limited, but You may also want to review your mixing algorithm as well. Again, assuming a standard servo input (1-2 ms pulse), the pulseIn should return values between 1000 and 2000 (usec). Adding all three together for FL (for example) would yield 3000 to 6000, or basically your maximum all the time.
I to realized this and based on mecanum drive code i have found and tried using Java for my team and through research for this, I am now taking all of the values and dividing by the highest or lowest absolute value if one of them is either above 2000ms or below 1000ms. I am learning this as I go and so am having my ups and downs. I have however just realized I can map my 1000 - 2000ms inputs to an equal negative - positive range such as (-255) - (255). This has helped me a great deal.

Quote:
Originally Posted by Mike Bortfeldt View Post
My guess, based on your original post of the 1 second delays, indicate that you are probably not reading at least two of the signals (Strafe & Rotate perhaps?), so you are adding zero (0) to your forward value and the calculations are doing what you expect. The 1 second delay is approximately the timeout for the default pulseIn when it doesn't see a pulse and no explicit timeout is passed.

Mike
This is exactly what was happening so I lowered the timeout value to be 30ms and it was responding virtually instantly (give or take the lag of the 30ms per input if I wasn't receiving a pulse).
Closed Thread


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


All times are GMT -5. The time now is 03:20.

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