Go Down

Topic: ATTiny85 PWM frequency selection (Read 12029 times) previous topic - next topic

Bobnova

A bit of background:
I'm looking to control PWM computer cooling fans directly from an ATTiny85, the fans want a ~15-25khz PWM signal.  The currant involved in minimal.

At default settings with Coding Badly's excellent arduino port I got 500hz from pin0 and 1khz from pin1.
If I use " TCCR0B = TCCR0B & 0b11111101 | 0x01;" from the Arduino PWM frequency howto, I can get 1khz from pin0 and 2khz from pin1.

However from reading about AVRs in general it appears that far higher is possible, just not doable through the arduino environment.
Is this correct?  Am I totally out to lunch?

Any help/advice would be greatly appreciated.
(Sidenote:  The 328p's ~32khz output works, but is horrendously inefficient in controlling fans, they don't like it much)

Coding Badly

I'm looking to control PWM computer cooling fans directly from an ATTiny85, the fans want a ~15-25khz PWM signal.


Sounds good.

Quote
The currant involved in minimal.


How minimal?  It's extremely rare to find a motor that can be driven directly from a microprocessor.  Or do the cooling fans have a "control line" separate from the power?

Quote
At default settings with Coding Badly's excellent arduino port


Thanks!   :D

Quote
I got 500hz from pin0 and 1khz from pin1.


Are you running the processor at 16 MHz?

Quote
However from reading about AVRs in general it appears that far higher is possible


The ATtiny85 is capable of generating a 64 MHz PWM signal.  So "far higher" is a good description.

Quote
just not doable through the arduino environment.


The Tiny Core includes a "veneer" that makes changing the timers a bit easier.  Confirm the processor speed and I'll try to help.

MarkT

Quote
If I use " TCCR0B = TCCR0B & 0b11111101 | 0x01;" from the Arduino PWM frequency howto, I can get 1khz from pin0 and 2khz from pin1.


I don't know if the ATTiny85 is similar to the 328, but if so that line needs to be:
TCCR0B = TCCR0B & 0b11111000 | 0b001 ; // set to divide-by-1 prescale
(The 328 timer prescaler fields are 3 bits wide)
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Bobnova

#3
May 13, 2011, 03:54 pm Last Edit: May 13, 2011, 04:14 pm by Bobnova Reason: 1
Minimal currant like <=15ma, the fans are four pin type things: +12v, ground, tach output (you pull it high, it grounds that wire twice per revolution) and PWM input.
The PWM input goes to a controller on the fan circuitboard that figures out when to switch the mosfets to get the fan to run at the speed you selected via PWM.  It's a pretty cool setup, though they cost more than the three pin non-PWM fans.

Processor speed wise I've tried both 1mhz and 8mhz, I don't have any spare 16mhz crystals/resonators.  I should get some.

I'll try that line in my attiny85 and report back in with what happens.

Thanks for the input!


(Sidenote: I got 15.4khz PWM out of a 328p by using the internal oscillator at 8mhz and running the timer at full speed, but attiny85's are cheaper and easier to find)



EDIT:
That worked beautifully!  I now have a pair of 15.6khz PWM outputs from my attiny85.
Thank you very much!

putyn



EDIT:
That worked beautifully!  I now have a pair of 15.6khz PWM outputs from my attiny85.
Thank you very much!


how did you get it to work ? :)

HermannSW

#5
Jan 10, 2017, 05:17 pm Last Edit: Jan 10, 2017, 05:21 pm by HermannSW
Quote
how did you get it to work ? :)
Adding the "TCCR0B = TCCR0B & 0b11111000 | 0b001 ;" line to Setup() results in 32.35kHz on Digispark ATtiny85 module (pin 0 as well as pin 1):


Quote
The ATtiny85 is capable of generating a 64 MHz PWM signal.  So "far higher" is a good description.
How to configure ATtiny85 for MHz PWM frequencies?

HermannSW

Found "Setting High Speed PWM on ATTiny85":
http://stackoverflow.com/questions/21654618/setting-high-speed-pwm-on-attiny85

Adapted for Arduino IDE I measured up to 676.7kHz with "OCR1C = 123;".
Code: [Select]
123*676.7
83234.1
127*648
82296
141*590.8
83302.8
159*524.4
83379.6


This is from comment of sketch below, not sure why I measured 1.3 times as much:
Code: [Select]
    // Set PWM TOP value - counter will count and reset
    //  after reaching this value
    //          OCR1C
    // 400Khz   159     
    // 450khz   141
    // 500khz   127

Code: [Select]
400*159
63600
450*141
63450
127*500
63500


Hermann.
Code: [Select]
//#include <avr/io.h>
//#include <avr/interrupt.h>


void setup()
{
    PORTB = 0;      //Reset values on port B

    // After setting up the timer counter,
    // set the direction of the ports to output
    DDRB |= (1<<PB1) | (1<<PB0); // Set the direction of PB1 to an output

    // PLLCSR - PLL control and status register:
    // PLL is a clock multiplier - multiplies system     8Mhz by 8 to 64Mhz
    // PLL is enabled when:PLLE bit is enabled,
    // CKSEL fuse is programmed to 0001.  This clock is
    //   switched off in sleep modes!
    PLLCSR |= (1<<PLLE);    // PLL enable

    // Wait until the PLOCK bit is enabled
    //  before allowing the PCK to be enabled
    // WaitForPLOCK();
    // unsigned int i = 0;


    while ((PLLCSR & (1<<PLOCK)) == 0x00)
    {
        // Do nothing until plock bit is set
    }

    PLLCSR |= (1<<PCKE); // Enable asynchronous mode, sets PWM clock source


    TCCR1 =
            (1<<CTC1) |  //enable pwm
            (1<<PWM1A) | // set source to pck
            (1<<(CS10)) | // clear the pin when match with ocr1x
            (1<<COM1A1);
    GTCCR =   (1<<PWM1B) | (1<<COM1B1);


    // Set PWM TOP value - counter will count and reset
    //  after reaching this value
    //          OCR1C
    // 400Khz   159     
    // 450khz   141
    // 500khz   127
    OCR1C = 159;


    //enable Timer1 OVF interrupt
    TIMSK = (1<<OCIE1A) | (1<<TOIE1);   

    sei();

    //This should set the duty cycle to about 75%
    OCR1A = 120;
}

void loop() {
}

HermannSW

Some measurements are strange, but I was able to measure 10MHz PWM frequency with these changes:
Code: [Select]
...
    OCR1C = 5;
...
    OCR1A = 3;
...


Nice clean 10MHz PWM signal from 1$ ATtiny85. 10MHz is maximum that I was able to measure with 24Msps logic analyzer. Will try with 400Msps analyzer when back at home.

HermannSW

I had problems determining average frequency for measurement with 400Msps logic analyzer DSView GUI.

Therefore I used 100Msps logic analyzer. Salea Logic 1.2.10 GUI allows to determine average frequency as one of many options for measurements.

Maximal frequency is achieved with
Code: [Select]
...
    OCR1C = 2;
...
    OCR1A = 1;
...


Interestingly maximal PWM frequency is different depending on "board" used in Arduino IDE to program ATtiny85:
  • 22.12MHz for "Digispark (Default - 16.5mhz)"
  • 28.27MHz for "Digispark (16mhz - No USB)"


Hermann.

Go Up