PIN_PA5 に 170Hz の PWM出力をします。
プログラム
pwm04/pwm04.ino
// ----------------------------------------------------------------
/*
pwm04.ino
Sep/21/2025
*/
// ----------------------------------------------------------------
#define PROGRAM "pwm04.ino"
#define VERSION "2025-09-21 PM 13:33"
// 20MHz, target 300Hz software PWM for PA5 (works with TinyCore 0.3.0)
#define LED_PIN PIN_PA5
// 170Hz の周期(マイクロ秒)
const uint32_t TARGET_HZ = 170;
const uint32_t PERIOD_US = 1000000UL / TARGET_HZ;
// = 3333 us (実測周波数 = 1000000/3333 ≈ 300.03 Hz)
// ----------------------------------------------------------------
void setup() {
Serial1.begin(19200);
delay(200);
Serial1.println("*** setup start ***");
delay(1000);
Serial1.println("*** ATtiny3224 ***");
Serial1.println(PROGRAM);
delay(1000);
Serial1.println(VERSION);
delay(1000);
Serial1.print("CPU Clock = "); Serial1.println(F_CPU);
Serial1.print("Using software PWM at approx "); Serial1.print(1000000.0f / (float)PERIOD_US, 3);
Serial1.println(" Hz");
pinMode(LED_PIN, OUTPUT);
}
// ----------------------------------------------------------------
// duty: 0..255
void pwmRunFor(uint8_t duty8, uint32_t duration_ms) {
uint32_t cycles = (duration_ms * 1000UL) / PERIOD_US;
uint32_t high_us = (uint32_t)((uint64_t)(PERIOD_US) * (uint32_t)duty8 / 255ULL);
// 特殊値の最適化
if (duty8 == 0) {
digitalWrite(LED_PIN, LOW);
delay(duration_ms);
return;
}
if (duty8 == 255) {
digitalWrite(LED_PIN, HIGH);
delay(duration_ms);
return;
}
for (uint32_t i = 0; i < cycles; ++i) {
if (high_us > 0) {
digitalWrite(LED_PIN, HIGH);
if (high_us > 1) delayMicroseconds(high_us);
else __asm__ __volatile__ ("nop");
}
uint32_t low_us = PERIOD_US - high_us;
if (low_us > 0) {
digitalWrite(LED_PIN, LOW);
if (low_us > 4) delayMicroseconds(low_us); // delayMicroseconds は 1us 単位
else for (volatile uint8_t k=0;k< (uint8_t)low_us; ++k) __asm__ __volatile__ ("nop");
}
}
}
// ----------------------------------------------------------------
void loop() {
// テスト:0->64->128->192->255->0 の各デューティを1秒ずつ表示
uint8_t dutySteps[] = {0, 32, 64, 128, 0};
for (int i=0;i < sizeof(dutySteps)/sizeof(dutySteps[0]); ++i) {
uint8_t d = dutySteps[i];
Serial1.print("Setting duty (0..255) = "); Serial1.println(d);
pwmRunFor(d, 1000);
// 1000ms = 1秒
delay(1000);
// 少し余裕
}
}
// ----------------------------------------------------------------
シリアルの出力
*** setup start ***
*** ATtiny3224 ***
pwm04.ino
2025-09-21 PM 13:33
CPU Clock = 20000000
Using software PWM at approx 170.010 Hz
Setting duty (0..255) = 0
Setting duty (0..255) = 32
Setting duty (0..255) = 64
Setting duty (0..255) = 128
Setting duty (0..255) = 0
Setting duty (0..255) = 0
Setting duty (0..255) = 32
Setting duty (0..255) = 64