ArduinoのSoftPWMについて

#例
13pinを$duty=100/255$でpwmする．プログラム

```C
#include <SoftPWM.h>
void setup()
{
  SoftPWMBegin();  
  SoftPWMSet(13, 0);
}

void loop()
{
  SoftPWMSet(13, 255);  
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/cb4da887-a193-84d1-593a-6a494453cf03.png)

LOW:66μs
HIGH:16692μs
少し，LOWが入るようだ

###SoftPWMSet(13, 256); 
ー＞すべてLOW


###SoftPWMSet(13, 100);
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/7bd143f6-39a1-9656-c864-e0103da1c5f0.png)
1周期=16.7ms
HIGH=6.53ms
LOW=10.2ms


#まとめ

* 60Hz(変更する方法不明)
* 255(max)指定時一瞬LOWが入る

インストールは
「スケッチ」->「ライブラリをインクルード」->「ライブラリを管理」->「softPWM」
でインストールできます．

#もっと高周波が欲しい方
私は，200Hzぐらいは最低で欲しいので，もう少し考えます．
ソフト割り込みでは，かなりArduinoのリソースを消耗することになってしまうので注意が必要です．
分解能を下げることで対応は一応可能です．

TimerOneを使用します．
分解能10,

```C
#include <TimerOne.h>

volatile byte duty1=0;
volatile byte duty2=0;
volatile byte duty3=0;
volatile byte duty4=0;
volatile byte pwm_count = 0;

void soft_pwm(){
  pwm_count++;
  if(pwm_count>=10){
    pwm_count = 0;
    PORTD |= _BV(6);    //pin6 HIGH
    PORTD |= _BV(7);    //pin7
    PORTB |= _BV(0);    //pin8
    PORTB |= _BV(1);    //pin9
  }
  if(pwm_count>=duty1){
    PORTD &= ~_BV(6);    //pin6 LOW
  }
  if(pwm_count>=duty2){
    PORTD &= ~_BV(7);    //pin7 LOW
  }
  if(pwm_count>=duty3){
    PORTB &= ~_BV(0);    //pin8 LOW
  }
  if(pwm_count>=duty4){
    PORTB &= ~_BV(1);    //pin9 LOW
  }
  
}

void setup() {
  Timer1.initialize(200);           //0.2ms
  Timer1.attachInterrupt(soft_pwm);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  
}

void loop() {
  

}
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/68c57ea5-4429-4e36-bedf-32e4a43d5355.png)

周期0.2ms＊10=2ms(500Hz),分解能10
4出力で，duty0とすると一瞬1がプログラムの都合上入ります．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/a974e021-ce93-8890-77df-060728374303.png)
割り込みには2μs使用しています．

分解能を256にすると（byte）
周期0.2ms＊256=2ms(19.5Hz),分解能256
で遅くなります．

分解能を20ぐらいがちょうどよさそうです．
周期0.2ms＊20=2ms(250Hz),分解能20

```C
#include <TimerOne.h>

volatile byte duty1 = 0;
volatile byte duty2 = 1;
volatile byte duty3 = 2;
volatile byte duty4 = 3;
volatile byte pwm_count = 0;

void soft_pwm() {
  pwm_count++;
  if (pwm_count >= 20) {
    pwm_count = 0;
    if (duty1 != 0) {
      PORTD |= _BV(6);    //pin6 HIGH
    }
    if (duty2 != 0) {
      PORTD |= _BV(7);    //pin7
    }
    if (duty3 != 0) {
      PORTB |= _BV(0);    //pin8
    }
    if (duty4 != 0) {
      PORTB |= _BV(1);    //pin9
    }
  } else {
    if (pwm_count >= duty1) {
      PORTD &= ~_BV(6);    //pin6 LOW
    }
    if (pwm_count >= duty2) {
      PORTD &= ~_BV(7);    //pin7 LOW
    }
    if (pwm_count >= duty3) {
      PORTB &= ~_BV(0);    //pin8 LOW
    }
    if (pwm_count >= duty4) {
      PORTB &= ~_BV(1);    //pin9 LOW
    }
  }
}

void setup() {
  Timer1.initialize(200);           //0.2ms
  Timer1.attachInterrupt(soft_pwm);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  Serial.begin(250000);

}

void loop() {
  Serial.println("hello");
}
```

これだと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405484/ba4d0bfa-5518-1f1f-89f4-ce64db85ce34.png)
こんな感じになります．

duty1->200μs
duty2->400μs
duty3->600μs
周期4ms=250Hz

となります．