1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ArduinoでPWMインバータ制御でHブリッジドライバから正弦波出力をする

Last updated at Posted at 2023-07-03

概要

ArduinoでPWMインバータ制御でHブリッジドライバから正弦波出力をする。
3kHzぐらいまで。

やり方

PWMのDuty比を正弦波に合わせて変更する。

Fast PWM mode
image.png

TCNT:Timerカウンターの最大値をICRレジスタとしたモード14を選択

image.png

OCR1A=TCNTになったときに自動的に、PB1(pin9),PB2(pin10)がClear(0)するように設定。
TOP(ICR)=TCNTになったとき自動的に、PB1(pin9),PB2(pin10)がSet(1)するように設定。

image.png

OCR1A割り込みが発生したときに

  • Duty比を読み出し、OCR1A値を変更

サンプルプログラム


/*
   PWMで正弦波を出す

*/

#define space_clock 10
volatile boolean sp_flag = false;
volatile int sin_pos = 0;
volatile int sin_length[100];
volatile int max_sin;


void setup() {
  pinMode(11, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(A0, INPUT);

  digitalWrite(11, HIGH);
  //digitalWrite(9,HIGH);
  //digitalWrite(10,LOW);

  //Timer1 max(ICR1) 正弦波 100分割 1/8分周
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1A |= (1 << WGM11) | (0 << WGM10) | (1 << COM1A1) | (1 << COM1B1);
  TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10);
  ICR1 = 1030;     //TOP:ICR1  周波数はこちら
  max_sin = 1030 - space_clock;

  //COMPA 割り込み
  TIMSK1 |= (1 << OCIE1A)  ;

}
ISR(TIMER1_COMPA_vect) {
  //コンペアマッチでclearされるように設定している
  //正弦波になるように調整
  OCR1A = sin_length[sin_pos];
  OCR1B = sin_length[sin_pos];
  sin_pos++;
  if (sin_pos >= 100) {
    sin_pos = 0;
    sp_flag = !sp_flag;
    if (sp_flag) {
      TCCR1A &= ~_BV(COM1A1);
      TCCR1A |= _BV(COM1B1);
    } else {
      TCCR1A &= ~_BV(COM1B1);
      TCCR1A |= _BV(COM1A1);
    }
  }
  if (sp_flag) {
    TCCR1C |= (1 << FOC1A);
  } else {
    TCCR1C |= (1 << FOC1B);
  }
}


void loop() {
  delay(100);
  int data = analogRead(A0);

  //double fz = 510 + (data/1024.0 -0.5)*500;
  double fz = data / 1024.0 * 1000;
  int onoff_time = 500000 / fz;         //1000000us/fz / 2

  ICR1 = onoff_time * 0.16;            //1clock = 1/16[us] ICR割り込み100回で半周期
  max_sin = ICR1 - space_clock;

  for (int i = 0; i < 100; i++) {
    sin_length[i] = sin(i / 100.0 * 3.141592) * max_sin;
  }

}

image.png

障害対応:ICR増加させた時に割り込みが発生しなくなる

原因

ICR1<OCR1A,ICR1<OCR1Bに一時的に設定されること

対策

  1. OCR1A,OCR1BをICR1より先に更新する
  2. OCR1A<ICR1,OCR1B <ICR1にする。
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?