ArduinoでPWM制御

前回の記事で正弦波を作ったので、
それを使って、PWM制御でLEDを点滅させてみる。

use v5.14;
use strict;
use warnings;

use Math::Trig qw( pi );
use constant PI => pi();

sub wav_sin {
    my $n = 256;

    return map {
        my $tmp = sin( ($_ / $n) * (2.0 * PI) );
        if ( $tmp < .0 ) {
            int( ($tmp * (128.0 / 1.125)) - .5 );
        }
        else {
            int( ($tmp * (128.0 / 1.125)) + .5 );
        }
    } 0..($n - 1);
}

while ( <DATA> ) {
    if ( /{{wav_sin}}/ ) {
        my @wav = wav_sin();
        while ( @wav ) {
            my $tmp = join( ' ', map { sprintf('%4d,', $_) } splice(@wav, 0, 8) );
            chop $tmp if ( not @wav );
            print '    ', $tmp, "\n";
        }
    }
    else {
        print $_;
    }
}

__DATA__
// sin wave
// +128.0 / 1.125 〜 -128.0 / 1.125
const static signed char wavSine[] = {
{{wav_sin}}
};

byte timer = 0;
byte max = 0;
byte i = 0;
ISR ( TIMER0_COMPA_vect ) {
    if ( timer == 0 ) {
        short tmp = wavSine[ i & 0xFF ];
        max = (byte)(tmp + 128);
        i++;
    }

    digitalWrite( 13, (timer < max) ? HIGH : LOW );

    timer++;
}

void setup() {
  pinMode( 13, OUTPUT );
  digitalWrite( 13, LOW );

  TCCR0A = 0b00000010; // CTC
  TCCR0B = 0b00000010; // 1/8
  OCR0A = 130;
  TIMSK0 = 0b00000010;

  sei();
}

void loop() {
  // nop
}

これを実行すると、こうなる。

// sin wave
// +128.0 / 1.125 〜 -128.0 / 1.125
const static signed char wavSine[] = {
       0,    3,    6,    8,   11,   14,   17,   19,
      22,   25,   28,   30,   33,   36,   38,   41,
      44,   46,   49,   51,   54,   56,   58,   61,
      63,   66,   68,   70,   72,   74,   76,   78,
      80,   82,   84,   86,   88,   90,   91,   93,
      95,   96,   98,   99,  100,  102,  103,  104,
     105,  106,  107,  108,  109,  110,  110,  111,
     112,  112,  113,  113,  113,  113,  114,  114,
     114,  114,  114,  113,  113,  113,  113,  112,
     112,  111,  110,  110,  109,  108,  107,  106,
     105,  104,  103,  102,  100,   99,   98,   96,
      95,   93,   91,   90,   88,   86,   84,   82,
      80,   78,   76,   74,   72,   70,   68,   66,
      63,   61,   58,   56,   54,   51,   49,   46,
      44,   41,   38,   36,   33,   30,   28,   25,
      22,   19,   17,   14,   11,    8,    6,    3,
       0,   -3,   -6,   -8,  -11,  -14,  -17,  -19,
     -22,  -25,  -28,  -30,  -33,  -36,  -38,  -41,
     -44,  -46,  -49,  -51,  -54,  -56,  -58,  -61,
     -63,  -66,  -68,  -70,  -72,  -74,  -76,  -78,
     -80,  -82,  -84,  -86,  -88,  -90,  -91,  -93,
     -95,  -96,  -98,  -99, -100, -102, -103, -104,
    -105, -106, -107, -108, -109, -110, -110, -111,
    -112, -112, -113, -113, -113, -113, -114, -114,
    -114, -114, -114, -113, -113, -113, -113, -112,
    -112, -111, -110, -110, -109, -108, -107, -106,
    -105, -104, -103, -102, -100,  -99,  -98,  -96,
     -95,  -93,  -91,  -90,  -88,  -86,  -84,  -82,
     -80,  -78,  -76,  -74,  -72,  -70,  -68,  -66,
     -63,  -61,  -58,  -56,  -54,  -51,  -49,  -46,
     -44,  -41,  -38,  -36,  -33,  -30,  -28,  -25,
     -22,  -19,  -17,  -14,  -11,   -8,   -6,   -3
};

byte timer = 0;
byte max = 0;
byte i = 0;
ISR ( TIMER0_COMPA_vect ) {
    if ( timer == 0 ) {
        short tmp = wavSine[ i & 0xFF ];
        max = (byte)(tmp + 128);
        i++;
    }

    digitalWrite( 13, (timer < max) ? HIGH : LOW );

    timer++;
}

void setup() {
  pinMode( 13, OUTPUT );
  digitalWrite( 13, LOW );

  TCCR0A = 0b00000010; // CTC
  TCCR0B = 0b00000010; // 1/8
  OCR0A = 130;
  TIMSK0 = 0b00000010;

  sei();
}

void loop() {
  // nop
}

でもって、これをArduinoに書き込むと、
PCがスリープしてるときのアレっぽい点滅をする。
(43行目のマスク処理は、ここを0x7Fとかにして試してた時のなごり。)

あと、Arduino IDEで書き込もうとしたら、
初めてMacが固まって、フリーズ画面になって、再起動したんだけど
フリーズなんて数年ぶりでビビった。

おしまい。

Leave a Comment