Arduino timer kodlama

Muhendsi

Üye
Katılım
9 Eki 2021
Mesajlar
13
Puanları
1
Yaş
28
Öncelikle herkese iyi günler. Bidirectional converter tasarlıyorum resimde de görüleceği üzere fakat arduino üzerinde timer kullanarak 30 KHz civarında 2 adet mosfeti anahtarlama yapmam gerekiyor. Kod yazma konusunda iyi değilim yardımcı olabilecek varmı acaba?

Edit: örnek kod kodla boost converter yaptım. Bu şekilde 2 ayrı mosfeti anahtarlamam gerekiyor. Gücü ölçerek anahtarlara farklı Duty oranları vereceğim. Panel ve bataryadan oluşan sistemde fazla enerjiyi depolama veya panelden yetersiz güç geldiğinde bataryadan yüke enerji akışı sağlayacağım
 

Ekli dosyalar

  • Schematic-of-the-bidirectional-DC-DC-converter.png
    Schematic-of-the-bidirectional-DC-DC-converter.png
    15.3 KB · Görüntüleme: 26
  • pwm kodu.png
    pwm kodu.png
    14.2 KB · Görüntüleme: 28
Örnekte timer0 fast pwm kullanılmış ve datasheete göre frekans hesabı
fPWM = fOSC(prescalar*256)
ve değiştirebileceğin iki seçenek var ya devrenin kristalini değiştireceksin yada prescalar faktörünü değiştireceksin. Örnekte 16Mhz kristal kullnılmış ve TCCR0B |=0x05 yapılmış yani


TCCR0B.png


registerinin prescalar bitlerinden CS02 ve CS00 biti set edilmiş bu aşağıdaki tabloya göre

prescalar.png


1024 presclar değeri girilmiş yani en üst değer. Formülden gidersek

fPWM = 16000000/(1024*256) =>fPWM = 61.03515625Hz

Eğer prescalar değerini değerini 1 yaparsak yani CS00 bitini 1 yaparsak

TCCR0B |= (1<<CS00);

formüle göre

fPWM = 16000000(1*256) => fPWM = 62500Hz
olacaktır yani en yüksek 62.5Khz değere çıkabilirsin.

Aşağıdaki kod 62500Hz lik bir pwm üretecektir (pin5).

C++:
void pwm_ayarla(uint8_t);
void setup(){
  // WGM02/WGM01/WGM00 all set -> Mode 7, fast PWM
  TCCR0A = (1<<COM0B1) + (1<<WGM01) + (1<<WGM00); // Set OC2B at bottom, clear OC2B at compare match
  TCCR0B = (1<<CS00) + (1<<WGM02); // prescaler = 1;
  OCR0A = 255;
  OCR0B = 0;
  DDRD |= (1<<PD5);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri);
}

void pwm_ayarla(uint8_t duty){
  OCR0B = duty;
}

mosfetin birisini bu çıkışa diğerini ise aşağıdaki kodla timer2 ile üreteceğin çıkışa bağlayabilirsin (pin3).

C++:
void pwm_ayarla(uint8_t);
void setup(){
  TCCR2A = (1<<COM2B1) + (1<<WGM21) + (1<<WGM20); // Set OC2B at bottom, clear OC2B at compare match
  TCCR2B = (1<<CS20) + (1<<WGM22); // prescaler = 1;
  OCR2A = 255;
  OCR2B = 0;
  DDRD |= (1<<PD3);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri);
}

void pwm_ayarla(uint8_t duty){
  OCR2B = duty;
}

yani toparlarsak

C++:
void pwm_ayarla(uint8_t,uint8_t);
void setup(){
    // WGM02/WGM01/WGM00 all set -> Mode 7, fast PWM
  TCCR0A = (1<<COM0B1) + (1<<WGM01) + (1<<WGM00); // Set OC2B at bottom, clear OC2B at compare match
  TCCR0B = (1<<CS00) + (1<<WGM02); // prescaler = 1;
  OCR0A = 255;
  OCR0B = 0;
  TCCR2A = (1<<COM2B1) + (1<<WGM21) + (1<<WGM20); // Set OC2B at bottom, clear OC2B at compare match
  TCCR2B = (1<<CS20) + (1<<WGM22); // prescaler = 1;
  OCR2A = 255;
  OCR2B = 0;

  DDRD |= (1<<PD3);
  DDRD |= (1<<PD5);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri,255-duty_degeri);
}

void pwm_ayarla(uint8_t duty0,uint8_t duty2){
  OCR0B = duty0;
  OCR2B = duty2;
}


Test etmedim ama teorik olarak çalışması gerekiyor. A0 daki potun değerine göre bir çıkış artarken diğeri azalacaktır. Kaynağı aşağıya bırakıyorum tüm modları inceleyip kendin istediğini yapabilirsin

https://wolles-elektronikkiste.de/en/timer-and-pwm-part-1-8-bit-timer0-2
 
Son düzenleme:
çok teşekkür ederim deneyince haber verecegim. ben güneş panelinden gelen gücü ölçecegin ve yükün harcagidi güc örnegin 10watt ise fazlasini bataryaya depo etmesi icin ona gore ayarlayacagim if blokları içerisinde örnegin fazladan 5watt enerji varsa pwm'i %10 yap, 6watt fazla varsa %12 yap gibi kod yazmayi dusundum. panelden gelen enerji yetersiz ise bataryadan destek verecegim. baska bir tavsiyen varsa fikrini almak isterim
Örnekte timer0 fast pwm kullanılmış ve datasheete göre frekans hesabı

ve değiştirebileceğin iki seçenek var ya devrenin kristalini değiştireceksin yada prescalar faktörünü değiştireceksin. Örnekte 16Mhz kristal kullnılmış ve TCCR0B |=0x05 yapılmış yani


Ekli dosyayı görüntüle 82742

registerinin prescalar bitlerinden CS02 ve CS00 biti set edilmiş bu aşağıdaki tabloya göre

Ekli dosyayı görüntüle 82743

1024 presclar değeri girilmiş yani en üst değer. Formülden gidersek



Eğer prescalar değerini değerini 1 yaparsak yani CS00 bitini 1 yaparsak



formüle göre


olacaktır yani en yüksek 62.5Khz değere çıkabilirsin.

Aşağıdaki kod 62500Hz lik bir pwm üretecektir (pin5).

C++:
void pwm_ayarla(uint8_t);
void setup(){
  // WGM02/WGM01/WGM00 all set -> Mode 7, fast PWM
  TCCR0A = (1<<COM0B1) + (1<<WGM01) + (1<<WGM00); // Set OC2B at bottom, clear OC2B at compare match
  TCCR0B = (1<<CS00) + (1<<WGM02); // prescaler = 1;
  OCR0A = 255;
  OCR0B = 0;
  DDRD |= (1<<PD5);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri);
}

void pwm_ayarla(uint8_t duty){
  OCR0B = duty;
}

mosfetin birisini bu çıkışa diğerini ise aşağıdaki kodla timer2 ile üreteceğin çıkışa bağlayabilirsin (pin3).

C++:
void pwm_ayarla(uint8_t);
void setup(){
  TCCR2A = (1<<COM2B1) + (1<<WGM21) + (1<<WGM20); // Set OC2B at bottom, clear OC2B at compare match
  TCCR2B = (1<<CS20) + (1<<WGM22); // prescaler = 1;
  OCR2A = 255;
  OCR2B = 0;
  DDRD |= (1<<PD3);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri);
}

void pwm_ayarla(uint8_t duty){
  OCR2B = duty;
}

yani toparlarsak

C++:
void pwm_ayarla(uint8_t,uint8_t);
void setup(){
    // WGM02/WGM01/WGM00 all set -> Mode 7, fast PWM
  TCCR0A = (1<<COM0B1) + (1<<WGM01) + (1<<WGM00); // Set OC2B at bottom, clear OC2B at compare match
  TCCR0B = (1<<CS00) + (1<<WGM02); // prescaler = 1;
  OCR0A = 255;
  OCR0B = 0;
  TCCR2A = (1<<COM2B1) + (1<<WGM21) + (1<<WGM20); // Set OC2B at bottom, clear OC2B at compare match
  TCCR2B = (1<<CS20) + (1<<WGM22); // prescaler = 1;
  OCR2A = 255;
  OCR2B = 0;

  DDRD |= (1<<PD3);
  DDRD |= (1<<PD5);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri,255-duty_degeri);
}

void pwm_ayarla(uint8_t duty0,uint8_t duty2){
  OCR0B = duty0;
  OCR2B = duty2;
}


Test etmedim ama teorik olarak çalışması gerekiyor. A0 daki potun değerine göre bir çıkış artarken diğeri azalacaktır. Kaynağı aşağıya bırakıyorum tüm modları inceleyip kendin istediğini yapabilirsin

https://wolles-elektronikkiste.de/en/timer-and-pwm-part-1-8-bit-timer0-2
 
Örnekte timer0 fast pwm kullanılmış ve datasheete göre frekans hesabı

ve değiştirebileceğin iki seçenek var ya devrenin kristalini değiştireceksin yada prescalar faktörünü değiştireceksin. Örnekte 16Mhz kristal kullnılmış ve TCCR0B |=0x05 yapılmış yani


Ekli dosyayı görüntüle 82742

registerinin prescalar bitlerinden CS02 ve CS00 biti set edilmiş bu aşağıdaki tabloya göre

Ekli dosyayı görüntüle 82743

1024 presclar değeri girilmiş yani en üst değer. Formülden gidersek



Eğer prescalar değerini değerini 1 yaparsak yani CS00 bitini 1 yaparsak



formüle göre


olacaktır yani en yüksek 62.5Khz değere çıkabilirsin.

Aşağıdaki kod 62500Hz lik bir pwm üretecektir (pin5).

C++:
void pwm_ayarla(uint8_t);
void setup(){
  // WGM02/WGM01/WGM00 all set -> Mode 7, fast PWM
  TCCR0A = (1<<COM0B1) + (1<<WGM01) + (1<<WGM00); // Set OC2B at bottom, clear OC2B at compare match
  TCCR0B = (1<<CS00) + (1<<WGM02); // prescaler = 1;
  OCR0A = 255;
  OCR0B = 0;
  DDRD |= (1<<PD5);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri);
}

void pwm_ayarla(uint8_t duty){
  OCR0B = duty;
}

mosfetin birisini bu çıkışa diğerini ise aşağıdaki kodla timer2 ile üreteceğin çıkışa bağlayabilirsin (pin3).

C++:
void pwm_ayarla(uint8_t);
void setup(){
  TCCR2A = (1<<COM2B1) + (1<<WGM21) + (1<<WGM20); // Set OC2B at bottom, clear OC2B at compare match
  TCCR2B = (1<<CS20) + (1<<WGM22); // prescaler = 1;
  OCR2A = 255;
  OCR2B = 0;
  DDRD |= (1<<PD3);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri);
}

void pwm_ayarla(uint8_t duty){
  OCR2B = duty;
}

yani toparlarsak

C++:
void pwm_ayarla(uint8_t,uint8_t);
void setup(){
    // WGM02/WGM01/WGM00 all set -> Mode 7, fast PWM
  TCCR0A = (1<<COM0B1) + (1<<WGM01) + (1<<WGM00); // Set OC2B at bottom, clear OC2B at compare match
  TCCR0B = (1<<CS00) + (1<<WGM02); // prescaler = 1;
  OCR0A = 255;
  OCR0B = 0;
  TCCR2A = (1<<COM2B1) + (1<<WGM21) + (1<<WGM20); // Set OC2B at bottom, clear OC2B at compare match
  TCCR2B = (1<<CS20) + (1<<WGM22); // prescaler = 1;
  OCR2A = 255;
  OCR2B = 0;

  DDRD |= (1<<PD3);
  DDRD |= (1<<PD5);
}
void loop() {
  uint8_t duty_degeri = map(analogRead(A0),0,1024,0,255);
  pwm_ayarla(duty_degeri,255-duty_degeri);
}

void pwm_ayarla(uint8_t duty0,uint8_t duty2){
  OCR0B = duty0;
  OCR2B = duty2;
}


Test etmedim ama teorik olarak çalışması gerekiyor. A0 daki potun değerine göre bir çıkış artarken diğeri azalacaktır. Kaynağı aşağıya bırakıyorum tüm modları inceleyip kendin istediğini yapabilirsin

https://wolles-elektronikkiste.de/en/timer-and-pwm-part-1-8-bit-timer0-2
hocam kodu denedimde çalışmadı basit bi buck converter yaptım eski kodla çalışıyor ama bunla olmadı frekanstan kaynaklı olabilir mi acaba
 
hocam kodu denedimde çalışmadı basit bi buck converter yaptım eski kodla çalışıyor ama bunla olmadı frekanstan kaynaklı olabilir mi acaba
Şimdi devreyi kurup denedim çalıştı. Sen tam olarak neyi çalıştıramadın. d3 ve d5 e birer direnç ve led. A0 ucuna bi potansiyometre bağlarsan çalışacaktır. Yada potansiyometreyle uğraşmak istemezsen loop kısmını aşağıdaki kodla değiştir sana videodaki gibi güzel bir efekt verecektir.

C++:
void loop() {
  for(uint8_t i=0;i<255;i++){
    pwm_ayarla(i,255-i);
    delay(250);
    }
  for(uint8_t i=0;i<255;i++){
    pwm_ayarla(255-i,i);
    delay(250);
    }
}

 
Son düzenleme:
Şimdi devreyi kurup denedim çalıştı. Sen tam olarak neyi çalıştıramadın. d3 ve d5 e birer direnç ve led. A0 ucuna bi potansiyometre bağlarsan çalışacaktır. Yada potansiyometreyle uğraşmak istemezsen loop kısmını aşağıdaki kodla değiştir sana videodaki gibi güzel bir efekt verecektir.

C++:
void loop() {
  for(uint8_t i=0;i<255;i++){
    pwm_ayarla(i,255-i);
    delay(250);
    }
  for(uint8_t i=0;i<255;i++){
    pwm_ayarla(255-i,i);
    delay(250);
    }
}

bidirectional converter yapiyorumda mosfet anahtarlamada kullanıcam. pwm ayarlama kisminda degisiklik yaptim duty'e gore cikis gerilimini artirmasi veya azaltmasi gerekiyor fakat istedigim gibi olmadı frekansla mı alakalı acaba frekansı 10k veya 30k gibi yapmak icon kodda nereyi degistirmek gerekir
 
Yukarıda hepsini yazmışım zaten, kaynak olarak verdiğim adreste de her türlü örnek yazılmış. Onlara bakarak yapabilirsin. Genel bir soru sormuşsun ve ben ona cevap verdim. Bundan sonrası senin şahsi projen.
 

Forum istatistikleri

Konular
129,735
Mesajlar
929,371
Kullanıcılar
452,457
Son üye
powerotomasyon.net

Yeni konular

Geri
Üst