Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Electrical (http://www.chiefdelphi.com/forums/forumdisplay.php?f=53)
-   -   Arduino PWM output (http://www.chiefdelphi.com/forums/showthread.php?t=106665)

sand500 26-05-2012 14:04

Arduino PWM output
 
I just got my Arduino Uno and I'm trying to learn how to use it so couple of questions. Can the Arduino support reverse PWM or can it only output values from 0-255 so only one direction? Would the PWM output be compatible with Jaguars, Victors and the VEX motor controllers? Would this be only in one direction?

I know that the RobotOpen shield gives ability to use the digital side car but is it worth the price?

sjspry 26-05-2012 14:38

Re: Arduino PWM output
 
To figure out if the analogWrite() function's default frequency and range of duty cycles is compatible with the Jaguars or Victors, you will need to read the data sheet and compare to what the Arduino documentation says. There's also the robotopen project, which seems to have done work with this.

If I had to guess, I would say no, the analogWrite() function will not be compatible with the Jaguars. Why? The code I've seen to control a hobby servo from the same port you can control a Jaguar from sets up the port the same way, and hobby servos do not actually use "PWM". They use pulse-position modulation, which is different.

So what I can suggest, if you need something to happen quickly, is looking for the Arduino Servo library and using that to generate the signal to feed the Jaguar.

For future reference, please know that "PWM" is often used to (some would say incorrectly) refer to about three different things:

1) pulse-width modulation (PWM), where the duty cycle of a fixed frequency signal is varied (what the analogWrite() function does);
2) pulse-position modulation (PPM), which has a fixed-time pulse separated by variable time pulses for the values (750µs to 2400µs, used in the VEX controllers and by hobby servos, and other various motor controllers);
3) pulse-length modulation (PLM, other), used in simple IR remote controls and usually proprietary thingies. Not very common. Usually a dead time of 600µs followed by a 1 (1200µs) or 0 (600µs), repeat as necessary.

NickE 26-05-2012 15:56

Re: Arduino PWM output
 
The standard Arduino PWM will likely not work with Victors. Check out the myservo.write() function in the Arduino Servo Library. The Arduino software should have a servo example which should work with the Victors.

Dad1279 26-05-2012 16:18

Re: Arduino PWM output
 
The same PWM code that controls a servo for Arduino will work to drive a speed controller. Disconnect the power (red) lead of a std pwm cable, just connect the white (signal) and ground.

Motor is off when servo receives the same signal as 'centering' a servo (90 degrees) 'Zero degrees' is full reverse to the motor, 180 degrees full forward. Signal should look like this:


Another very good explanation is here:http://team358.org/files/electrical/PWMGenerator.pdf

sand500 26-05-2012 17:20

Re: Arduino PWM output
 
Quote:

Originally Posted by sjspry (Post 1171624)
To figure out if the analogWrite() function's default frequency and range of duty cycles is compatible with the Jaguars or Victors, you will need to read the data sheet and compare to what the Arduino documentation says. There's also the robotopen project, which seems to have done work with this.

If I had to guess, I would say no, the analogWrite() function will not be compatible with the Jaguars. Why? The code I've seen to control a hobby servo from the same port you can control a Jaguar from sets up the port the same way, and hobby servos do not actually use "PWM". They use pulse-position modulation, which is different.

So what I can suggest, if you need something to happen quickly, is looking for the Arduino Servo library and using that to generate the signal to feed the Jaguar.

For future reference, please know that "PWM" is often used to (some would say incorrectly) refer to about three different things:

1) pulse-width modulation (PWM), where the duty cycle of a fixed frequency signal is varied (what the analogWrite() function does);
2) pulse-position modulation (PPM), which has a fixed-time pulse separated by variable time pulses for the values (750µs to 2400µs, used in the VEX controllers and by hobby servos, and other various motor controllers);
3) pulse-length modulation (PLM, other), used in simple IR remote controls and usually proprietary thingies. Not very common. Usually a dead time of 600µs followed by a 1 (1200µs) or 0 (600µs), repeat as necessary.

Yea I understand that PWM controls the speed of the motors, but I dont know if the duty cycle of the arduinos are the same as what a jag and victor takes.

WizenedEE 26-05-2012 18:19

Re: Arduino PWM output
 
Quote:

Originally Posted by sand500 (Post 1171634)
Yea I understand that PWM controls the speed of the motors, but I dont know if the duty cycle of the arduinos are the same as what a jag and victor takes.

Check out the writeMicroseconds function. Snippet from my code that controls a jaguar (working and controls a robot and stuff):
Code:

Servo jag;
    jag.attach(9);
    int8_t jagspeed

    // ... set jagspeed to a value from -100 to 100

    // Jag datasheet says it wants a puse between .67ms and 2.33ms
    jag.writeMicroseconds(map(jagspeed, -100, 100, 670, 2330));


slijin 26-05-2012 18:25

Re: Arduino PWM output
 
Quote:

Originally Posted by sand500 (Post 1171620)
Can the Arduino support reverse PWM or can it only output values from 0-255 so only one direction?

Although this has been implied, there is no such thing as reverse PWM. Duty cycles can be anywhere between 0 and 255, with 0 being full reverse, 255 being forward, and a deadband in the middle for neutral.

Quote:

Originally Posted by sand500 (Post 1171620)
Would the PWM output be compatible with Jaguars, Victors and the VEX motor controllers?

The Arduino PWM library will not. The Servo library will. See above for the reasons why.
Using the Servo library will give you the full range of control over a Victor. We have developed testing platforms which feed Arduinos an analog input to drive a Victor; no recalibration was necessary, but the code had to be tweaked a little.
You will have to either recalibrate the Jaguar or adjust the methods found in the Servo library to achieve a full range of control.

Quote:

Originally Posted by sand500 (Post 1171620)
I know that the RobotOpen shield gives ability to use the digital side car but is it worth the price?

You don't need RobotOpen for a task like this. RobotOpen is designed to replace a cRIO, allowing teams to work with a larger budget and replace the core of their control systems with little hassle.

RyanCahoon 26-05-2012 22:37

Re: Arduino PWM output
 
At least for running Victors, you'll need a Signal Driver or create equivalent functionality, using a FET or similar. Not sure if Jaguars have the same requirement.

ajlapp 27-05-2012 00:28

Re: Arduino PWM output
 
As stated above, a RobotOpen Shield is all about building a more complete control system that uses wifi to send wireless commands.

You can definitely control both Victors and Jaguars using an Arduino straight out of the box. This robot and this robot were created before we invented RobotOpen. They both use Arduino as the basis for their control system.

The complete code used can be downloaded here.

sand500 27-05-2012 00:51

Re: Arduino PWM output
 
Quote:

Originally Posted by ajlapp (Post 1171660)
As stated above, a RobotOpen Shield is all about building a more complete control system that uses wifi to send wireless commands.

You can definitely control both Victors and Jaguars using an Arduino straight out of the box. This robot and this robot were created before we invented RobotOpen. They both use Arduino as the basis for their control system.

The complete code used can be downloaded here.

are there any built in ways to communicate to a java program running on a computer via ethernet and ip? java has sockets but can arduino support that? Also, can I2C be used to communicate a arduino to crio

slijin 27-05-2012 08:55

Re: Arduino PWM output
 
Quote:

Originally Posted by sand500 (Post 1171663)
are there any built in ways to communicate to a java program running on a computer via ethernet and ip? java has sockets but can arduino support that? Also, can I2C be used to communicate a arduino to crio

No, you also need the Ethernet Arduino if you plan to use RobotOpen with ethernet. The Arduino will then support networked connections.

Yes, I2C can be used with a an Arduino. The cRIO has no direct I2C output, but there are I2C ports on the DSC.

JoshSmith 27-05-2012 11:49

Re: Arduino PWM output
 
Quote:

Originally Posted by sand500 (Post 1171663)
are there any built in ways to communicate to a java program running on a computer via ethernet and ip? java has sockets but can arduino support that? Also, can I2C be used to communicate a arduino to crio

Quick note one this, it will take some modifications to get it to work (a "stock" Arduino Wire library will not work). And you can use an ethernet shield for your Arduino Uno if you want to get communications over ethernet working (this will still work with a RobotOpen shield if you ever want to add that).

Here is the relevant shield on sparkfun: http://www.sparkfun.com/products/9026

WizenedEE 27-05-2012 14:23

Re: Arduino PWM output
 
1 Attachment(s)
Quote:

Originally Posted by JoshSmith (Post 1171693)
Quick note one this, it will take some modifications to get it to work (a "stock" Arduino Wire library will not work). And you can use an ethernet shield for your Arduino Uno if you want to get communications over ethernet working (this will still work with a RobotOpen shield if you ever want to add that).

Here is the relevant shield on sparkfun: http://www.sparkfun.com/products/9026

AFAIK we used the "stock" Arduino Wire library on this year's competition robot to communicate the shooter angular velocity with the cRIO.

We just had to use the transaction method of the I2C class.

relevant part of our code:
Code:

UINT8 valuesGotten[2] = {0, 0};
I2CArduino->Transaction(NULL, 0, valuesGotten, 2);
UINT16 fullNumber = (valuesGotten[1] << 8) | valuesGotten[0];

Full code for reading our sensor is attached. I don't currently have access to the arduino side, though.

sand500 27-05-2012 21:06

Re: Arduino PWM output
 
Quote:

Originally Posted by JoshSmith (Post 1171693)
Quick note one this, it will take some modifications to get it to work (a "stock" Arduino Wire library will not work). And you can use an ethernet shield for your Arduino Uno if you want to get communications over ethernet working (this will still work with a RobotOpen shield if you ever want to add that).

Here is the relevant shield on sparkfun: http://www.sparkfun.com/products/9026


Both RobotOpen and the Ethernet Shield are a little bit expensive for personal use. If our team needs it next year, I guess we could use them. But using just the Ethernet Shield might be another possibility because we have our custom java dashboard so if we want, we might decide to ditch the CRIO and FRC system for our practice bots.

Michael Hill 27-05-2012 22:16

Re: Arduino PWM output
 
If you read the datasheet for Victors, you'll notice that they accept a "servo" PWM signal. Hence why you must use the servo library for Arduino.

JoshSmith 28-05-2012 00:47

Re: Arduino PWM output
 
Quote:

Originally Posted by WizenedEE (Post 1171699)
AFAIK we used the "stock" Arduino Wire library on this year's competition robot to communicate the shooter angular velocity with the cRIO.

We just had to use the transaction method of the I2C class.

relevant part of our code:
Code:

UINT8 valuesGotten[2] = {0, 0};
I2CArduino->Transaction(NULL, 0, valuesGotten, 2);
UINT16 fullNumber = (valuesGotten[1] << 8) | valuesGotten[0];

Full code for reading our sensor is attached. I don't currently have access to the arduino side, though.

Interesting. I know for this year I changed the Wire library to run at 38.4khz (what I was told was the digital sidecar's operating frequency for I2C) and just set the Arduino up as a slave device and it worked nicely. But anyways, I will stop myself now before I get too far off-topic. My recommendation on the shields is that if you plan on making more robots than cRIOs, then you should look at a shield as they will be cheaper than spending credits or money on an extra cRIO. Otherwise, if you have a cRIO lying around, just use that (providing you have a backup for your competition bot).

sand500 05-06-2012 19:24

Re: Arduino PWM output
 
I have a VEX Motor Module(3-wires) that our teacher had from a Vex Kit. I have the Arduino to slowly rise the PWM from 0-255 and then lower it down. What I have found is that the motor starts moving when the PWM is at around 40. I know that around 120, the motor starts slowing down and at 170, it stops completely. Once it is at 200, the motor starts again but in the opposite direction, slow at first but gets faster around 250. At 255, the motor stops completely and at 254, it starts again. Again the motor doesnt move when the PWM is between 200 and 170 and after that, it turns again in the original direction and stops at 40.

I dont know why this is happening but the duty cycle frequency was wrong, then why does it stop completely at 255? When I hook up the pwm and ground on the arduino to a regular dc motor that you would find in an electronics kit, the motor works just like how pwm should.


Here is the code I ran:
Code:

boolean increasing;
int x;
void setup() {
  x=0;
  Serial.begin(9600); 
increasing = true;
}

void loop()
{
 
 
  Serial.println(x);
  analogWrite(9,x);
 
  if (increasing)
{
  x++;
}
else
{
  x--;
}
  if(x==255)
  {
    increasing = false;
  }
  if (x==0)
  {
    increasing = true;
  }
  delay(500);
 
 
}


slijin 05-06-2012 22:56

Re: Arduino PWM output
 
Quote:

Originally Posted by sand500 (Post 1172812)
I have a VEX Motor Module(3-wires) that our teacher had from a Vex Kit. I have the Arduino to slowly rise the PWM from 0-255 and then lower it down. What I have found is that the motor starts moving when the PWM is at around 40. I know that around 120, the motor starts slowing down and at 170, it stops completely. Once it is at 200, the motor starts again but in the opposite direction, slow at first but gets faster around 250. At 255, the motor stops completely and at 254, it starts again. Again the motor doesnt move when the PWM is between 200 and 170 and after that, it turns again in the original direction and stops at 40.

I dont know why this is happening but the duty cycle frequency was wrong, then why does it stop completely at 255? When I hook up the pwm and ground on the arduino to a regular dc motor that you would find in an electronics kit, the motor works just like how pwm should.

I'm not too familiar with the VEX system, so take what I say with a grain of salt, but here's what I see happening:

The VEX motor module has built-in deadbands at 1) the neutral, which allows a user to feed a noisy joystick signal straight to the motor and 2) the ends, which either acts as a safety, to facilitate interfacing with the VEX system (due to hardware/programming constraints etc), or it was a design decision.

Hooking up this signal to a regular DC motor produces exactly that kind of behavior, not because it's how your signal "should" behave, but because it's how motors are expected to behave in response to such signals.

sand500 05-06-2012 23:16

Re: Arduino PWM output
 
Quote:

Originally Posted by slijin (Post 1172835)
I'm not too familiar with the VEX system, so take what I say with a grain of salt, but here's what I see happening:

The VEX motor module has built-in deadbands at 1) the neutral, which allows a user to feed a noisy joystick signal straight to the motor and 2) the ends, which either acts as a safety, to facilitate interfacing with the VEX system (due to hardware/programming constraints etc), or it was a design decision.

Hooking up this signal to a regular DC motor produces exactly that kind of behavior, not because it's how your signal "should" behave, but because it's how motors are expected to behave in response to such signals.

Why does the higher end of the pwm, have a smaller range, 200-255, while the lower end of the pwm has a bigger range, 40-170. When I was running the motor, I could see the motor hit a higher speed in the 40-170 range than in the 200-255. So why would a motor rotate faster in one direction than in another direction?

Gdeaver 05-06-2012 23:42

Re: Arduino PWM output
 
Use the servo library.

slijin 06-06-2012 00:02

Re: Arduino PWM output
 
Quote:

Originally Posted by sand500 (Post 1172839)
Why does the higher end of the pwm, have a smaller range, 200-255, while the lower end of the pwm has a bigger range, 40-170. When I was running the motor, I could see the motor hit a higher speed in the 40-170 range than in the 200-255. So why would a motor rotate faster in one direction than in another direction?

Again, purely hypothetical here:

There are multiple reasons that this could happen, both electrical and mechanical.

On the electrical side, it could be an intentional design point (unlikely). It could also be that it's designed to take a different type of pulse (also unlikely). The most probable reason is an amalgam of 1) manufacturing inconsistencies and 2) a design "flaw" stemming from the circuit design (see the discussions about Victor and Jaguar signal driving; I can't do an explanation of these mechanisms justice, nor will I attempt to).

On the mechanical side, it could be a damaged bearing/bushing or shaft that gunks up in one direction and offers no resistance in the other (almost like a ratchet).

Greg McCoy 06-06-2012 00:09

Re: Arduino PWM output
 
Quote:

Originally Posted by sand500 (Post 1172812)
I dont know why this is happening but the duty cycle frequency was wrong, then why does it stop completely at 255?

The motor controller is behaving erratically because the PWM frequency and the duty cycle are wrong. The analogWrite() function is generating this PWM signal:


(from Arduino.cc)

...but your motor controller is expecting this:




The frequency of the signal in Hz is the number of pulses per second. The reciprocal of the frequency is the period, which is the time between the rising edges of the PWM signal. For your motor controller, this should be 50 Hz, or a 20 ms (millisecond) period. According to the Arduino documentation, the analogWrite() function produces a 490 Hz PWM signal, or a 2 ms period.


The duty cycle of the signal is the ratio between the pulse width and the period. For your motor controller, the pulse width is "mapped" as follows:

Full Forward: 2 ms pulse / 20 ms period = 10% duty cycle.
Neutral: 1.5 ms pulse / 20 ms period = 7.5% duty cycle.
Full Reverse: 1 ms pulse width / 20 ms period = 5% duty cycle.


As others have suggested, the Arduino servo library should be able to produce the correct signal. 180 degrees on a servo is the equivalent of "full forward" on a motor attached to the motor controller (0 degrees is full reverse, 90 is neutral, etc.)

Quote:

Originally Posted by sand500 (Post 1172812)
When I hook up the pwm and ground on the arduino to a regular dc motor that you would find in an electronics kit, the motor works just like how pwm should.

The motor controller does just this - it generates a 0-100% duty cycle PWM signal to the motor, using a circuit called an "H-bridge" to reverse the voltage when changing directions.

Hope this helps...

slijin 06-06-2012 00:15

Re: Arduino PWM output
 
Quote:

Originally Posted by Greg McCoy (Post 1172851)
The motor controller is behaving erratically because the PWM frequency and the duty cycle are wrong

Can't believe I overlooked that. Should've been the first thing I realized.

Greg Needel 06-06-2012 04:41

Re: Arduino PWM output
 
1 Attachment(s)
I have a custom victor library for the arduino that was written for one of my projects. This takes care of the timing issues, and duty cycle issues. While the the stock servo library will work, there are things that will cause hiccups.

Edit, I have attached the files.


Attachment 12807

Greg

sand500 08-06-2012 16:59

Re: Arduino PWM output
 
Quote:

Originally Posted by Greg McCoy (Post 1172851)
The motor controller is behaving erratically because the PWM frequency and the duty cycle are wrong. The analogWrite() function is generating this PWM signal:


(from Arduino.cc)

...but your motor controller is expecting this:




The frequency of the signal in Hz is the number of pulses per second. The reciprocal of the frequency is the period, which is the time between the rising edges of the PWM signal. For your motor controller, this should be 50 Hz, or a 20 ms (millisecond) period. According to the Arduino documentation, the analogWrite() function produces a 490 Hz PWM signal, or a 2 ms period.


The duty cycle of the signal is the ratio between the pulse width and the period. For your motor controller, the pulse width is "mapped" as follows:

Full Forward: 2 ms pulse / 20 ms period = 10% duty cycle.
Neutral: 1.5 ms pulse / 20 ms period = 7.5% duty cycle.
Full Reverse: 1 ms pulse width / 20 ms period = 5% duty cycle.


As others have suggested, the Arduino servo library should be able to produce the correct signal. 180 degrees on a servo is the equivalent of "full forward" on a motor attached to the motor controller (0 degrees is full reverse, 90 is neutral, etc.)



The motor controller does just this - it generates a 0-100% duty cycle PWM signal to the motor, using a circuit called an "H-bridge" to reverse the voltage when changing directions.

Hope this helps...

Thanks a lot, its a lot clearer to me now. I'll try Greg Needel's library and the servo library.

markgryzwa 26-07-2012 13:48

Re: Arduino PWM output
 
Here is some servo code that I put together to try to run some basic robot functions. I've not tested in out for polarity yet but the ideas are correct.

#include <Servo.h>

// global variables

// ------------- Servo setup ------------------------------
Servo myservo_left;
Servo myservo_right;

int left_pwm = 10; // set up the servo connections for the Jaguar controllers
int right_pwm = 9;
int rate = 0;


// ------- Spike relay control signals -------------------
int FWD = 1;
int REV = 2;
int OFF = 0;
int spike_white = 0; // pin 0 for spike signal wire
int spike_red = 1; // pin 1 for spike red wire


void setup() {
// put your setup code here, to run once:

myservo_left.attach(left_pwm);
myservo_right.attach(right_pwm);

pinMode(spike_white, OUTPUT);
pinMode(spike_red, OUTPUT);

}

void loop() {

// Set up the default
Spike(OFF);


// Make stuff happen
Forward(100, 1000); // move forward as a % of full speed for ms Foward(%*full speed,ms)
delay(1000);

Spike(FWD);
Reverse(100, 1000);
delay(1000);

Spike(REV);
Right(50, 100);
delay(1000);

Left(50,200);
delay(1000);

Spike(OFF);
Right(50, 100);
delay(6000);


}



//------------------ Subroutines ---------------------------

//-----------------------------------------------------------
void Forward(int rate, int duration) {

int spd = rate * 500; // set speed as a % of rate

myservo_left.writeMicroseconds(1500+spd);
myservo_right.writeMicroseconds(1500-spd);
delay(duration);
myservo_left.writeMicroseconds(1500);
myservo_right.writeMicroseconds(1500);
}

//-----------------------------------------------------------
void Reverse(int rate, int duration) {

int spd = rate * 500; // set speed as a % of rate

myservo_left.writeMicroseconds(1500-spd);
myservo_right.writeMicroseconds(1500+spd);
delay(duration);
myservo_left.writeMicroseconds(1500);
myservo_right.writeMicroseconds(1500);

}

//------------------------------------------------------------
void Left(int rate, int duration) {

int spd = rate * 500; // set speed as a % of rate

myservo_left.writeMicroseconds(1500+spd);
myservo_right.writeMicroseconds(1500+spd);
delay(duration);
myservo_left.writeMicroseconds(1500);
myservo_right.writeMicroseconds(1500);

}


//------------------------------------------------------------
void Right(int rate, int duration) {

int spd = rate * 500; // set speed as a % of rate

myservo_left.writeMicroseconds(1500-spd);
myservo_right.writeMicroseconds(1500-spd);
delay(duration);
myservo_left.writeMicroseconds(1500);
myservo_right.writeMicroseconds(1500);

}



//---------------------------------------------------------------
void Spike(int state) { //states can be 0=Off, 1 = FWD, 2=REV

switch (state) {
case 0:
digitalWrite(spike_red, LOW);
digitalWrite(spike_white, LOW);
break;

case 1:
digitalWrite(spike_red, HIGH);
digitalWrite(spike_white, LOW);
break;

case 2:
digitalWrite(spike_red, LOW);
digitalWrite(spike_white, HIGH);
break;

default:
digitalWrite(spike_red, LOW);
digitalWrite(spike_white, LOW);
break;
}

}

AlexH 26-07-2012 17:50

Re: Arduino PWM output
 
to run a victor with anything besides the current FIRST robot control system or the old IFI system you need a "signal driver cable" instead of a normal PWM cable.

Ether 26-07-2012 18:07

Re: Arduino PWM output
 
Quote:

Originally Posted by AlexH (Post 1179409)
to run a victor with anything besides the current FIRST robot control system or the old IFI system you need a "signal driver cable" instead of a normal PWM cable.

"Anything" covers a lot of ground. I'm not sure that's true.



Cuog 26-07-2012 22:47

Re: Arduino PWM output
 
Quote:

Originally Posted by AlexH (Post 1179409)
to run a victor with anything besides the current FIRST robot control system or the old IFI system you need a "signal driver cable" instead of a normal PWM cable.



I keep reading this on here but I have personally run an old blue label victor 883 directly from a 5v arduino(pro SMD version from sparkfun). Your mileage may vary of course.

Mark McLeod 26-07-2012 22:54

Re: Arduino PWM output
 
That signal driver cable is only required to boost a standard RC receiver PWM signal to the level required by a Victor. An RC receiver normally drives servos and RC motor controllers that get by on a lower power signal.

AlexH 27-07-2012 09:21

Re: Arduino PWM output
 
Quote:

Originally Posted by Mark McLeod (Post 1179474)
That signal driver cable is only required to boost a standard RC receiver PWM signal to the level required by a Victor. An RC receiver normal drives servos and RC motor controllers that get by on a lower power signal.

my mistake, sorry for causing any confusion.


All times are GMT -5. The time now is 19:13.

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