pwm arduino uno

possible to obtain say four different pwm frequencies from an uno? if so how? max freq is 20 khz

possible to obtain say four different pwm frequencies from an uno? if so how? max freq is 20 khz

No. Pairs of pins use the same frequency. Since there are only 6 PWM pins, the limit is three different frequencies.

Why do you want to diddle with the frequency?

need to use them as pulses for steppers. if only 3 freq can be generated how to go about doing that?

I drive stepper motors using a driver shield. I tell the driver when the step. I don't use PWM to drive them.

How are you doing that?

i use these from sparkfun

so need to send pulses

i use these from sparkfun

What a coincidence. So do I. They are NOT driven using PWM.

PWM has no role in driving stepper motors.

You can generate a step pulse with

digitalWrite(stepPin, HIGH);
digitalWrite(stepPin, LOW);

and then the interval between those pulses controls the speed.

...R

You can generate a step pulse with

Or use the Stepper (or AccelStepper) library, and simply call step().

I have comms setup which is looking for commands in the main loop and based on the command it needs to step each motor at the told speed.
void loop()
{
//look for serial data
//parse data
//see what command
//if(command = motorA & 600revl)
{
digitalwrite(pin,high)
delay(xx);
digtialwrite(pin,low)
delay(xx);
}
//for motor b
etc

but motor is not going at the correct rpm based on freq calc. the program is running through the comms and getting delayed before it can send pulses out. any work around this?

blueknight:
I have comms setup which is looking for commands in the main loop and based on the command it needs to step each motor at

As you haven't posted all your code I have no idea what the problem is. It can certainly be done without difficulty.

You don't need the first delay in this code - or if you do it should be a fixed delay of a few microseconds. Use the second delay - the interval between steps - to manage the speed of the motor.

{
digitalwrite(pin,high)
delay(xx);
digtialwrite(pin,low)
delay(xx);
}

...R

void loop()
{
while(Serial.available())
{
char inChar = (char)Serial.read();
dataRecv += inChar; //string
}
if(dataRecv.length > 1)
{

if(dataRecv[1] == 'A' && dataRecv[2] == '6' && dataRecv[3] == '0' && dataRecv[4] == '0')
{
state = MTR1;
removeCommand();//delete chars from dataRecv
}

switch(state)
{
case MTR1: digitalwrite(pin,high);
digitalwrite(pin,low);
delay(xx);
break;
}

}
}

    if(dataRecv.length > 1)
    {

               if(dataRecv[1] == 'A' && dataRecv[2] == '6' && dataRecv[3] == '0' && dataRecv[4] == '0')

Suppose dataRecv.length is 2. What it this going to do?

Wouldn't

    if(dataRecv == "A630")

be simpler?

blueknight:
void loop()
{

If YOU want help why is is necessary for ME to ask twice for you to post all of your code?

And please read the How to use the forum and post your code in code tags as I did. It makes it so much easier to read.

...R

Here you go sorry abt that

String dataRecv = "";

int clk1=3;
int clk2 =4;
int clk3 = 5;
int clk4 = 6;

enum _states
{
  state1,state2,state3,state4
};

void setup()
{
pinMode(clk1, OUTPUT);
  pinMode(clk2, OUTPUT);
 pinMode(clk3, OUTPUT);
  pinMode(clk4, OUTPUT);
 dataRecv.reserve(4000);
Serial.begin(9600);
}
void checkData()
{
    while(Serial.available())
    {
          char inChar = (char)Serial.read();
          dataRecv += inChar;   //string
     }
}
void loop()
{ 
     
     if(dataRecv.length() >= 1)
    {

               if(dataRecv[1] == 'A' && dataRecv[2] == '6' && dataRecv[3] == '0' && dataRecv[4] == '0')
                {
                        state = state1;
                        Serial.println("1");
                        removeCommand();//delete chars from dataRecv
                 }
                 else if(dataRecv[1] == 'B' && dataRecv[2] == '4' && dataRecv[3] == '4' && dataRecv[4] == '0')
                {
                        state = state2;
                        Serial.println("2");
                        removeCommand();//delete chars from dataRecv
                 }
                 else if(dataRecv[1] == 'C' && dataRecv[2] == '1' && dataRecv[3] == '0' && dataRecv[4] == '0')
                {
                        state = state3;
                        Serial.println("3");
                        removeCommand();//delete chars from dataRecv
                 }
                 else if(dataRecv[1] == 'D' && dataRecv[2] == '0' && dataRecv[3] == '7' && dataRecv[4] == '0')
                {
                        state = state4;
                        Serial.println("4");
                        removeCommand();//delete chars from dataRecv
                 }
   }
   switch(state)
   {
                       case state1: digitalWrite(clk1,HIGH);
                                        digitalWrite(clk1,LOW);
                                        delayMicroseconds(58);
                                        break;
                        case state2: digitalWrite(clk2,HIGH);
                                        digitalWrite(clk2,LOW);
                                        delayMicroseconds(100);
                                        break;
                        case state2: digitalWrite(clk3,HIGH);
                                        digitalWrite(clk3,LOW);
                                        delayMicroseconds(40);
                                        break;
                        case state2: digitalWrite(clk4,HIGH);
                                        digitalWrite(clk4,LOW);
                                        delayMicroseconds(20);
                                        break;
     }
}

void removeCommand()
{
  for(int i=0;i<5;i++)
  {
    removeString();
  }
}

It is constantly looking at the serial port for data and parses the command. so the command can be "A660B440..." etc

if i do the foll code

void loop()
{
digitalWrite(clk1,HIGH);
digitalWrite(clk1,LOW);
delayMicroseconds(58);
}

This turns the motor at the reqd speed. but the other one does not. i believe this is because of the serial port parsing and data handling there is a certain delay introduced. So is there a better way to do this?

It would be easier to read your code if you used the auto format option of the Arduni IDE to tidy it up - but that's a minor point.

I don't understand all the case statements. Are they intended to change the speed of the steps? If so it seem a very long winded way to change the value of intervalbetweenSteps in code like this

digitalWrite(clk1,HIGH);
digitalWrite(clk1,LOW);
delayMicroseconds(intervalBetweenSteps);

If you want to do other things (such as receive data) you need to stop using delay() and delayMicroseconds() and replace them with the technique in the Blink Without Delay example sketch. It uses millis() but the same technique can be used with micros()

It would be a good idea to shorten the incoming data as much as possible. A single byte can be used to convey any of 256 speeds and 2 bytes can convey up to 2^16 speeds. If you want to use only printable characters then you can get 75 different options with a single character from '0' to 'z'

...R

     if(dataRecv.length() >= 1)
    {

               if(dataRecv[1] == 'A' && dataRecv[2] == '6' && dataRecv[3] == '0' && dataRecv[4] == '0')

Checking 4 of the 2 characters in the String does not make sense. Checking each character in a String does not make sense.

It is constantly looking at the serial port for data and parses the command. so the command can be "A660B440..." etc

If the "commands" are always 4 characters, quit pissing away resources using the String class. Wait until there are 4 characters to read. Read all 4 of them, and act on THE command. Then, there is no stupid need to "remove the command from the string".