Управление 4pin-вентилятором ШИМ 25 Khz

kovit
Offline
Зарегистрирован: 16.03.2017

Возникла необходимость регулировки оборотов 4-х пинового вентилятора с помощью ардуино.

По даташиту http://www.formfactors.org/developer/specs/4_Wire_PWM_Spec.pdf 

требуется ШИМ с частотой от 21 до 28 кГц.

Нашел пример получения 25 кГц https://forum.arduino.cc/index.php?topic=415167.0

Загрузил скетч :

#include <Wire.h>

word VentPin = 3;

void setup() {
  Wire.begin();
  pinMode(VentPin, OUTPUT);
  pwm25kHzBegin();
}

void loop() {

  pwmDuty(19); // 25% (range = 0-79 = 1.25-100%)
  delay(5000);
  pwmDuty(39); // 50% (range = 0-79 = 1.25-100%)
  delay (5000);
  pwmDuty(59); // 75% (range = 0-79 = 1.25-100%)
  delay (5000);
  pwmDuty(79); // 100% (range = 0-79 = 1.25-100%)
  delay (5000);
}

void pwm25kHzBegin() {
  TCCR2A = 0; // TC2 Control Register A
  TCCR2B = 0; // TC2 Control Register B
  TIMSK2 = 0; // TC2 Interrupt Mask Register
  TIFR2 = 0; // TC2 Interrupt Flag Register
  TCCR2A |= (1 << COM2B1) | (1 << WGM21) | (1 << WGM20); // OC2B cleared/set on match when up/down counting, fast PWM
  TCCR2B |= (1 << WGM22) | (1 << CS21); // prescaler 8
  OCR2A = 79; // TOP overflow value (Hz)
  OCR2B = 0;
}

void pwmDuty(byte ocrb) {
  OCR2B = ocrb; // PWM Width (duty)
}

Работает, но получена ли требуемая частота в реале, проверить не могу -  к сожалению, не имею доступа к соответствующей измерительной аппаратуре.

Если счастливые обладатели осциллографа помогут - буду благодарен.

Волшебник
Offline
Зарегистрирован: 22.12.2016

А кто мешает запустить в том же скетче частотомер? Соедините два пина и экспериментируйте, пока 25к не побежит. 

kovit
Offline
Зарегистрирован: 16.03.2017

Спасибо за идею, Волшебник!

Загрузил на вторую ардуинку скетч, взятый с этого форума, законнектил платки.

На скрине результат - искомые 25 кГц.

volatile unsigned int int_tic=0; 
volatile unsigned long tic; 

void setup(){
Serial.begin(9600);
pinMode (5,INPUT); // вход сигнала T1 (only для atmega328)
TCCR2A=1<<WGM21; //CTC mode
TIMSK2=1<<OCIE2A; OCR2A=124 ;//прерывание каждые 8мс
TCCR2B=(1<<CS22)|(1<<CS21)|(1<<CS20); //делитель 1024
TCCR1A=0; TIMSK1 = 1<<TOIE1; //прерывание по переполнению
TCCR1B = (1<<CS10)|(1<<CS11)|(1<<CS12);//тактировани от входа Т1
}

ISR (TIMER1_OVF_vect){ int_tic++; }

ISR (TIMER2_COMPA_vect){
  static byte n=1;
  if (n==125){
           tic= ((uint32_t)int_tic<<16) | TCNT1; //сложить что натикало
           int_tic=0;
           TCNT1 = 0; n=0;
           }
      n++; 
}

void loop(){
delay(500);
Serial.println(tic);
}

//частотомер от dimax