Outils pour utilisateurs

Outils du site


robots:tondobot:tondobot

Ceci est une ancienne révision du document !


HW

SW

div

motor driver

PWM frequency

https://arduino-info.wikispaces.com/Arduino-PWM-Frequency (copy)

On the Arduino Duemilanove/UNO etc., pins 3,5,6, 9, 10, 11 can be configured for PWM output.

The 8-bit PWM value that you set when you call the analogWrite function:

analogWrite(myPWMpin, 128); Outputs a square wave

is compared against the value in an 8-bit counter. When the counter is less than the PWM value, the pin outputs a HIGH; when the counter is greater than the PWM value, the pin outputs a LOW. In the example above, a square wave is generated because the pin is HIGH from counts 0 to 127, and LOW from counts 128 to 255, so it is HIGH for the same amount of time it is LOW.

It follows logically that the frequency of the PWM signal is determined by the speed of the counter. Assuming you are using an Atmega168 with the Arduino Diecimila bootloader burned on it (which is exactly what you are using if you bought an Arduino Diecimila), this counter's clock is equal to the sytem clock divided by a prescaler value. The prescaler is a 3-bit value stored in the three least significant bits of the Timer/Counter register: CS02, CS01, and CS00. There are three such Timer/Counter registers: TCCR0B, TCCR1B, and TCCR2B.

Since there are three different prescalers, the six PWM pins are broken up into three pairs, each pair having its own prescaler. For instance, Arduion pins 6 and 5 are both controlled by TCCR0B, so you can set Arduino pins 6 and 5 to output a PWM signal at one frequency. Arduino pins 9 and 10 are controlled by TCCR1B, so they can be set at a different frequency from pins 6 and 5. Arduino pins 11 and 3 are controlled by TCCR2B, so they may be set at a third frequency. But you can't set different frequencies for pins that are controlled by the same prescaler (e.g. pins 6 and 5 must be at the same frequency).

If you use the default values set by the Arduino Diecimila's bootloader, these are your PWM frequencies:

Arduino Pins 5 and 6: 1kHz Arduino Pins 9, 10, 11, and 3: 500Hz

How do you change the PWM frequency?
In the void setup() part of your Arduino code, set or clear the CS02,CS01, and CS00 bits in the relevant TCCRnB register.
 
// For Arduino Uno, Nano, Micro Magician, Mini Driver, Lilly Pad and any other board using ATmega 8, 168 or 328**
//---------------------------------------------- Set PWM frequency for D5 & D6 -------------------------------
//TCCR0B = TCCR0B & B11111000 | B00000001;    // set timer 0 divisor to     1 for PWM frequency of 62500.00 Hz
//TCCR0B = TCCR0B & B11111000 | B00000010;    // set timer 0 divisor to     8 for PWM frequency of  7812.50 Hz
  TCCR0B = TCCR0B & B11111000 | B00000011;    // set timer 0 divisor to    64 for PWM frequency of   976.56 Hz (The DEFAULT)
//TCCR0B = TCCR0B & B11111000 | B00000100;    // set timer 0 divisor to   256 for PWM frequency of   244.14 Hz
//TCCR0B = TCCR0B & B11111000 | B00000101;    // set timer 0 divisor to  1024 for PWM frequency of    61.04 Hz
 
//---------------------------------------------- Set PWM frequency for D9 & D10 ------------------------------
//TCCR1B = TCCR1B & B11111000 | B00000001;    // set timer 1 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR1B = TCCR1B & B11111000 | B00000010;    // set timer 1 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR1B = TCCR1B & B11111000 | B00000011;    // set timer 1 divisor to    64 for PWM frequency of   490.20 Hz (The DEFAULT)
//TCCR1B = TCCR1B & B11111000 | B00000100;    // set timer 1 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR1B = TCCR1B & B11111000 | B00000101;    // set timer 1 divisor to  1024 for PWM frequency of    30.64 Hz
 
//---------------------------------------------- Set PWM frequency for D3 & D11 ------------------------------
//TCCR2B = TCCR2B & B11111000 | B00000001;    // set timer 2 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR2B = TCCR2B & B11111000 | B00000010;    // set timer 2 divisor to     8 for PWM frequency of  3921.16 Hz
//TCCR2B = TCCR2B & B11111000 | B00000011;    // set timer 2 divisor to    32 for PWM frequency of   980.39 Hz
  TCCR2B = TCCR2B & B11111000 | B00000100;    // set timer 2 divisor to    64 for PWM frequency of   490.20 Hz (The DEFAULT)
//TCCR2B = TCCR2B & B11111000 | B00000101;    // set timer 2 divisor to   128 for PWM frequency of   245.10 Hz
//TCCR2B = TCCR2B & B11111000 | B00000110;    // set timer 2 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR2B = TCCR2B & B11111000 | B00000111;    // set timer 2 divisor to  1024 for PWM frequency of    30.64 Hz
 
//For Arduino Mega1280, Mega2560, MegaADK, Spider or any other board using ATmega1280 or ATmega2560**
//---------------------------------------------- Set PWM frequency for D4 & D13 ------------------------------
//TCCR0B = TCCR0B & B11111000 | B00000001;    // set timer 0 divisor to     1 for PWM frequency of 62500.00 Hz
//TCCR0B = TCCR0B & B11111000 | B00000010;    // set timer 0 divisor to     8 for PWM frequency of  7812.50 Hz
  TCCR0B = TCCR0B & B11111000 | B00000011;    <// set timer 0 divisor to    64 for PWM frequency of   976.56 Hz (Default)
//TCCR0B = TCCR0B & B11111000 | B00000100;    // set timer 0 divisor to   256 for PWM frequency of   244.14 Hz
//TCCR0B = TCCR0B & B11111000 | B00000101;    // set timer 0 divisor to  1024 for PWM frequency of    61.04 Hz
 
//---------------------------------------------- Set PWM frequency for D11 & D12 -----------------------------
//TCCR1B = TCCR1B & B11111000 | B00000001;    // set timer 1 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR1B = TCCR1B & B11111000 | B00000010;    // set timer 1 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR1B = TCCR1B & B11111000 | B00000011;    // set timer 1 divisor to    64 for PWM frequency of   490.20 Hz
//TCCR1B = TCCR1B & B11111000 | B00000100;    // set timer 1 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR1B = TCCR1B & B11111000 | B00000101;    // set timer 1 divisor to  1024 for PWM frequency of    30.64 Hz
 
//---------------------------------------------- Set PWM frequency for D9 & D10 ------------------------------
//TCCR2B = TCCR2B & B11111000 | B00000001;    // set timer 2 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR2B = TCCR2B & B11111000 | B00000010;    // set timer 2 divisor to     8 for PWM frequency of  3921.16 Hz
//TCCR2B = TCCR2B & B11111000 | B00000011;    // set timer 2 divisor to    32 for PWM frequency of   980.39 Hz
  TCCR2B = TCCR2B & B11111000 | B00000100;    // set timer 2 divisor to    64 for PWM frequency of   490.20 Hz
//TCCR2B = TCCR2B & B11111000 | B00000101;    // set timer 2 divisor to   128 for PWM frequency of   245.10 Hz
//TCCR2B = TCCR2B & B11111000 | B00000110;    // set timer 2 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR2B = TCCR2B & B11111000 | B00000111;    // set timer 2 divisor to  1024 for PWM frequency of    30.64 Hz
 
//---------------------------------------------- Set PWM frequency for D2, D3 & D5 ---------------------------
//TCCR3B = TCCR3B & B11111000 | B00000001;    // set timer 3 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR3B = TCCR3B & B11111000 | B00000010;    // set timer 3 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR3B = TCCR3B & B11111000 | B00000011;    // set timer 3 divisor to    64 for PWM frequency of   490.20 Hz
//TCCR3B = TCCR3B & B11111000 | B00000100;    // set timer 3 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR3B = TCCR3B & B11111000 | B00000101;    // set timer 3 divisor to  1024 for PWM frequency of    30.64 Hz
 
//---------------------------------------------- Set PWM frequency for D6, D7 & D8 ---------------------------
//TCCR4B = TCCR4B & B11111000 | B00000001;    // set timer 4 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR4B = TCCR4B & B11111000 | B00000010;    // set timer 4 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR4B = TCCR4B & B11111000 | B00000011;    // set timer 4 divisor to    64 for PWM frequency of   490.20 Hz
//TCCR4B = TCCR4B & B11111000 | B00000100;    // set timer 4 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR4B = TCCR4B & B11111000 | B00000101;    // set timer 4 divisor to  1024 for PWM frequency of    30.64 Hz
 
//---------------------------------------------- Set PWM frequency for D44, D45 & D46 ------------------------
//TCCR5B = TCCR5B & B11111000 | B00000001;    // set timer 5 divisor to     1 for PWM frequency of 31372.55 Hz
//TCCR5B = TCCR5B & B11111000 | B00000010;    // set timer 5 divisor to     8 for PWM frequency of  3921.16 Hz
  TCCR5B = TCCR5B & B11111000 | B00000011;    // set timer 5 divisor to    64 for PWM frequency of   490.20 Hz
//TCCR5B = TCCR5B & B11111000 | B00000100;    // set timer 5 divisor to   256 for PWM frequency of   122.55 Hz
//TCCR5B = TCCR5B & B11111000 | B00000101;    // set timer 5 divisor to  1024 for PWM frequency of    30.64 Hz

PID

/*
 
*/
#define PIN_SERVO_D 2
#define PIN_SERVO_G 3
#define PIN_MOT_D_R_PWM 5
#define PIN_MOT_D_L_PWM 6
#define PIN_MOT_G_R_PWM 9
#define PIN_MOT_G_L_PWM 10
#define PIN_MOT_D_R_IS A7
#define PIN_MOT_D_L_IS A6
#define PIN_MOT_G_R_IS A1
#define PIN_MOT_G_L_IS A0
 
 
volatile boolean SERVO_D_New_pulse_IT,SERVO_G_New_pulse_IT;
volatile unsigned long SERVO_D_Pulse_micros_IT=0,SERVO_G_Pulse_micros_IT=0;
unsigned long SERVO_D_Pulse_micros=0,SERVO_G_Pulse_micros=0;
unsigned long currentMillis;
unsigned long previousMillis = 0;
byte LED_cnt_u8;
int MOT_D_CMD_s16,MOT_G_CMD_s16;
 
void update_MOT_D_PWMs(int cmd)
{
  if (cmd>0)
  {
      analogWrite(PIN_MOT_D_R_PWM, cmd);
      analogWrite(PIN_MOT_D_L_PWM, 0);
  }
  else
  {
      cmd = abs(cmd);
      analogWrite(PIN_MOT_D_R_PWM, 0);
      analogWrite(PIN_MOT_D_L_PWM, cmd);
  }
}
 
void update_MOT_G_PWMs(int cmd)
{
  if (cmd>0)
  {
      analogWrite(PIN_MOT_G_R_PWM, cmd);
      analogWrite(PIN_MOT_G_L_PWM, 0);
  }
  else
  {
      cmd = abs(cmd);
      analogWrite(PIN_MOT_G_R_PWM, 0);
      analogWrite(PIN_MOT_G_L_PWM, cmd);
  }
}
 
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
 
  pinMode(PIN_SERVO_D, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_SERVO_D), SERVO_D_change_CB, CHANGE);
 
  pinMode(PIN_SERVO_G, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_SERVO_G), SERVO_G_change_CB, CHANGE);
 
  pinMode(PIN_MOT_D_R_PWM, OUTPUT);
  pinMode(PIN_MOT_D_L_PWM, OUTPUT);
  pinMode(PIN_MOT_G_R_PWM, OUTPUT);
  pinMode(PIN_MOT_G_L_PWM, OUTPUT);
  update_MOT_D_PWMs(0);
  update_MOT_G_PWMs(0);
 
  pinMode(PIN_MOT_D_R_IS, INPUT);
  pinMode(PIN_MOT_D_L_IS, INPUT);
  pinMode(PIN_MOT_G_R_IS, INPUT);
  pinMode(PIN_MOT_G_L_IS, INPUT);
 
  Serial.begin(115200);
}
 
void SERVO_D_change_CB() {
  static volatile unsigned long D_rise_micros_IT = 0;
    if (digitalRead(PIN_SERVO_D) == HIGH) {
      D_rise_micros_IT = micros();
    }
    else {
      SERVO_D_Pulse_micros_IT = micros();
      if (SERVO_D_Pulse_micros_IT > D_rise_micros_IT) SERVO_D_Pulse_micros_IT -=D_rise_micros_IT;
      else SERVO_D_Pulse_micros_IT += (0xffffffff-D_rise_micros_IT);//overflow of timer
      SERVO_D_New_pulse_IT = true;
    }
}
 
void SERVO_G_change_CB() {
  static volatile unsigned long G_rise_micros_IT = 0;
    if (digitalRead(PIN_SERVO_G) == HIGH) {
      G_rise_micros_IT = micros();
    }
    else {
      SERVO_G_Pulse_micros_IT = micros();
      if (SERVO_G_Pulse_micros_IT > G_rise_micros_IT) SERVO_G_Pulse_micros_IT -=G_rise_micros_IT;
      else SERVO_G_Pulse_micros_IT += (0xffffffff-G_rise_micros_IT);//overflow of timer
      SERVO_G_New_pulse_IT = true;
    }
}
 
void loop() {
  delay(1); //wait 1ms
  currentMillis = millis();
 
  if (currentMillis - previousMillis >= 100) 
  { // 100ms task
    previousMillis = currentMillis;
 
    LED_cnt_u8++;
    if (LED_cnt_u8 % 10) digitalWrite(LED_BUILTIN, LOW);
    else digitalWrite(LED_BUILTIN, HIGH);
 
    //recuperation des dernieres commande servo
    noInterrupts();
      SERVO_D_Pulse_micros=SERVO_D_Pulse_micros_IT;
      SERVO_G_Pulse_micros=SERVO_G_Pulse_micros_IT;
    interrupts();
    //mise en borne et conversion des commande versos
    if (SERVO_D_Pulse_micros < 500) SERVO_D_Pulse_micros = 1500;  // pour traiter le cas ou on a pas de servo connecté
    SERVO_D_Pulse_micros=constrain(SERVO_D_Pulse_micros, 1000, 2000);
    MOT_D_CMD_s16 = map(SERVO_D_Pulse_micros,1000,2000,-255,255);
    update_MOT_D_PWMs(MOT_D_CMD_s16);
 
    if (SERVO_G_Pulse_micros < 500) SERVO_G_Pulse_micros = 1500;  // pour traiter le cas ou on a pas de servo connecté
    SERVO_G_Pulse_micros=constrain(SERVO_G_Pulse_micros, 1000, 2000);
    MOT_G_CMD_s16 = map(SERVO_G_Pulse_micros,1000,2000,-255,255);
    update_MOT_G_PWMs(MOT_G_CMD_s16);
 
    Serial.print("G");
    Serial.print(SERVO_G_Pulse_micros,DEC);
    Serial.print("\t");
    Serial.print(MOT_G_CMD_s16,DEC);
    Serial.print("\t");
    Serial.print(analogRead(PIN_MOT_G_L_IS));
    Serial.print("\t");
    Serial.print(analogRead(PIN_MOT_G_R_IS));
    Serial.print("\t\t\t\tD");
    Serial.print(SERVO_D_Pulse_micros,DEC);
    Serial.print("\t");
    Serial.print(MOT_D_CMD_s16,DEC);
    Serial.print("\t");
    Serial.print(analogRead(PIN_MOT_D_L_IS));
    Serial.print("\t");
    //Serial.println(analogRead(PIN_MOT_D_R_IS));
    Serial.print(analogRead(PIN_MOT_D_R_IS));
    Serial.print("\r");
  } // end of task
 
}
 
}
robots/tondobot/tondobot.1536432348.txt.gz · Dernière modification : 09/2018 de fred