Pages: 1 [2]   Go Down
Author Topic: How to get 20khz PWM on pin D9  (Read 3576 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 206
Posts: 12852
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Channel A output...
Code:
void analogWriteSAHA( uint16_t value )
{
  if ( (value >= 0) && (value < 800) )
  {
    OCR1A = value;
  }
}

Channel B output...
Code:
void analogWriteSAHB( uint16_t value )
{
  if ( (value >= 0) && (value < 800) )
  {
    OCR1B = value;
  }
}
Logged

Marseille - FRANCE
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Coding Badly for your quick reply! and commented code  smiley-cool

Wonderful!
It seems that because the 2 pins are sharing the same timer (PWM T1), it's quite short to implement: excellent! I woudn't have dared to mess with the code: registry frighten me!

I'll have a try now with my Nano ATMega 328

To be compliant with the rest of my code, can I use this (map and constrain) without decreasing the overall performance?

Code:
void analogWriteSAHA( uint8_t value )
{
  //  My variable value varies from 0 to 255
  //  but awaited range in OCR1A is from 0 to 799 and nothing else!
    OCR1A = constrain(map(value, 0, 255, 0, 799), 0, 799);
}

Thks  smiley
Logged

Marseille - FRANCE
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is my test: it compiles perfectly, upload ok, but no moves...

The direction leds (green/red) are less bright... than usual.
When a motor is connected, the leds don't light at all...

it must be kryptonite somewhere close...  smiley-mr-green

After that, I modified ICR1 to 1599 to get 10kHz (and OCR1A max in the function)
but the behaviour is the same ;-(


* pwm ultrasonic test 1.JPG (696.5 KB, 2304x1728 - viewed 29 times.)
« Last Edit: May 01, 2014, 01:14:22 am by Mat13 » Logged

Marseille - FRANCE
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

... I'll have to buy an oscilloscope  $$
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 206
Posts: 12852
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
This website has been reported as unsafe
Phishing threat:
This site might try to trick you into disclosing your login, password or other sensitive information by disguising itself as another website you may trust.

Instead of hosting images off-site please attach them to your post.  Click Modify to change your post, click Addition Options, click Browse to select the file, then click Save.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 206
Posts: 12852
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The direction leds (green/red) are less bright... than usual.
When a motor is connected, the leds don't light at all...

Test with two LEDs (and series resistors) using the Fade example.  If the LEDs get dimmer / brighter then at least you know the pulse width modulation is working.
Logged

Marseille - FRANCE
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, good idea!  smiley-lol

I didn't succeeded in fading the LED.
With the Analogwrite, it is Ok: LED is fading
With analogWriteSAHA, the LED stays off

Maybe my Arduino Nano V3.0 funduino is not working...

Thanks for any hint!
yours
Mat
Code:
int led = 9;           // the pin that the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

void analogWriteSAH_Init( void )
{
  TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10);
  TCCR1A =
    (1 << COM1A1) | (0 << COM1A0) |   // COM1A1, COM1A0 = 1, 0
  (1 << COM1B1) | (0 << COM1B0) |
    (1 << WGM11) | (0 << WGM10);      // WGM11, WGM10 = 1, 0
 
  ICR1 = 799;
  TCNT1 = 0;

  OCR1A = 0;
  OCR1B = 0;
  TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (0 << TOIE1);

  DDRB |= (1 << DDB1);
  DDRB |= (1 << DDB2);

  TCCR1B =
    (0 << ICNC1) | (0 << ICES1) |
    (1 << WGM13) | (1 << WGM12) |              // WGM13, WGM12 = 1, 1
  (0 << CS12) | (0 << CS11) | (1 << CS10);
}

void analogWriteSAHA( uint16_t value )
{
  if ( (value >= 0) && (value < 800) )
  {
    OCR1A = value;
  }
}
// the setup routine runs once when you press reset:
void setup()  {
  analogWriteSAH_Init;
  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop()  {
  // set the brightness of pin 9:
 analogWriteSAHA(brightness); 
// analogWrite(led, brightness); 
  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness == 0 || brightness == 795) {
    fadeAmount = -fadeAmount ;
  }   
  // wait for 30 milliseconds to see the dimming effect   
  delay(30);                           
}
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 206
Posts: 12852
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


You forgot something...

Code:
void setup()  {
  analogWriteSAH_Init();
...
Logged

Marseille - FRANCE
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks but unfortunatly, it was already in the code... there must be something else somewhere else smiley-confuse

maybe in the wiring.c or .h files? or a previous tweak i may have done in serial file...
I'll do a reinstall!
and meanwhile I'll ask a friend to do the same ;-)

Code:
// the setup routine runs once when you press reset:
void setup()  {
  analogWriteSAH_Init;
  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);
}
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 206
Posts: 12852
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks but unfortunatly, it was already in the code... there must be something else somewhere else smiley-confuse

Reread my previous post.  More carefully this time.  I promise you forgot something.  Just not what you think.
Logged

Marseille - FRANCE
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh myGod! I forgot the brackets!
Thanks for having spotted that Coding Badly! smiley-cool

Ultrasonic fading led is now working!
Tomorrow a video with the Hbridge hopefully!!
Logged

Marseille - FRANCE
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello!

Thansk to Coding Badly's help,
here is the video demonstrating that the ultrasonic PWM eliminates the buzzing sound of the driven DCmotor!  smiley-razz
http://youtu.be/FzhUga64fJs

The codes I used are the following:
non ultrasonic code:

Code:
////////////////////////////////////////////////////////////////////////////////
//  DECLARATIONS
////////////////////////////////////////////////////////////////////////////////
/*  VNH2SP30 pin definitions*/
// to have the wiring compliant with 20kHz pinout, you CANNOT stack the motomonster anymore!
/*  Arduino /..Motomonster1
 ......GND <-> GND pin
 ........5V <-> 5V
 .....pin 7 <-> pin 4 inA motor1
 .....pin 8 <-> pin 8 inB motor1
 .....pin 9 <-> pin 5 pwm motor1
 */
int inApin = 7;  // INA: Clockwise input
int inBpin = 8; // INB: Counter-clockwise input
int pwmpin = 9; // PWM input

#define potR A5
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void setup()
{ // initialization of Arduino's pins
  pinMode(inApin, OUTPUT);
  pinMode(inBpin, OUTPUT);
  pinMode(pwmpin, OUTPUT);

  digitalWrite(inApin, HIGH);
  digitalWrite(inBpin, LOW);
}
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Main Loop ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void loop()
{
  int sensor;
  sensor = analogRead(potR);  // range 0-1024

  analogWrite(pwmpin, (sensor/4));
}

and then ultrasonic code:

Code:
////////////////////////////////////////////////////////////////////////////////
//  DECLARATIONS
////////////////////////////////////////////////////////////////////////////////
/*  VNH2SP30 pin definitions
 // with 20kHz PWM pinout is changed, you CANNOT stack the motomonster anymore!
 Arduino /..Motomonster1
 ......GND <-> GND pin
 ........5V <-> 5V
 .....pin 7 <-> pin 4 inA motor1
 .....pin 8 <-> pin 8 inB motor1
 .....pin 9 <-> pin 5 pwm motor1
 */

int inApin = 7;  // INA: Clockwise input
int inBpin = 8; // INB: Counter-clockwise input
int pwmpin = 9; // PWM input

#define potR A5
////////////////////////////////////////////////////////////////////////////////
// INITIALIZATION
////////////////////////////////////////////////////////////////////////////////
void analogWriteSAH_Init( void )
{
  // Stop the timer while we muck with it

  TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10);

  // Set the timer to mode 14...
  //
  // Mode  WGM13  WGM12  WGM11  WGM10  Timer/Counter Mode of Operation  TOP   Update of OCR1x at TOV1  Flag Set on
  //              CTC1   PWM11  PWM10
  // ----  -----  -----  -----  -----  -------------------------------  ----  -----------------------  -----------
  // 14    1      1      1      0      Fast PWM                         ICR1  BOTTOM                   TOP

  // Set output on Channel A and B to...
  //
  // COM1z1  COM1z0  Description
  // ------  ------  -----------------------------------------------------------
  // 1       0       Clear OC1A/OC1B on Compare Match (Set output to low level).

  TCCR1A =
    (1 << COM1A1) | (0 << COM1A0) |   // COM1A1, COM1A0 = 1, 0
  (1 << COM1B1) | (0 << COM1B0) |
    (1 << WGM11) | (0 << WGM10);      // WGM11, WGM10 = 1, 0

    // Set TOP to...
  //
  // fclk_I/O = 16000000
  // N        = 1
  // TOP      = 799
  //
  // fOCnxPWM = fclk_I/O / (N * (1 + TOP))
  // fOCnxPWM = 16000000 / (1 * (1 + 799))
  // fOCnxPWM = 16000000 / 800
  // fOCnxPWM = 20000

    ICR1 = 799;

  // Ensure the first slope is complete

  TCNT1 = 0;

  // Ensure Channel A and B start at zero / off

  OCR1A = 0;
  OCR1B = 0;

  // We don't need no stinkin interrupts

  TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (0 << TOIE1);

  // Ensure the Channel A and B pins are configured for output
  DDRB |= (1 << DDB1);
  DDRB |= (1 << DDB2);

  // Start the timer...
  //
  // CS12  CS11  CS10  Description
  // ----  ----  ----  ------------------------
  // 0     0     1     clkI/O/1 (No prescaling)

  TCCR1B =
    (0 << ICNC1) | (0 << ICES1) |
    (1 << WGM13) | (1 << WGM12) |              // WGM13, WGM12 = 1, 1
  (0 << CS12) | (0 << CS11) | (1 << CS10);
}

void analogWriteD9( uint16_t value )

  //  My variable value varies from 0 to 1024
  //  but awaited range in OCR1A is from 0 to 799 and nothing else!
  OCR1A = constrain(map(value, 0, 1024, 0, 799), 0, 799);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void setup()
{
  analogWriteSAH_Init();
  // initialization of Arduino's pins
  pinMode(inApin, OUTPUT);
  pinMode(inBpin, OUTPUT);
  pinMode(pwmpin, OUTPUT);

  digitalWrite(inApin, HIGH);
  digitalWrite(inBpin, LOW);
}
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Main Loop ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void loop()
{
  int sensor;

  sensor = analogRead(potR);  // range 0-1024
  analogWriteD9(sensor);

}

Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 206
Posts: 12852
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thansk to Coding Badly's help,
here is the video demonstrating that the ultrasonic PWM eliminates the buzzing sound of the driven DCmotor!

You are welcome.  Thank you for the video.  It illustrates the problem beautifully.

For the record, that is actually a good way to ensure PWM is working correctly for a new core (a piezoelectric buzzer is a less expensive tool than a motor+driver).  Just listen for the distinctive frequency and all is good.
Logged

Pages: 1 [2]   Go Up
Jump to: