用于 4 个 LED 的 ATTiny85 PWM
ATTiny85 PWM for 4 LEDs
我需要在 ATTiny85 上通过 PWM 控制 4 个独立的 LED。我找到了很多关于如何控制 3 个 LED 的信息。但显然要用 PWM 控制 4,你必须真正将 85 扭成结。有没有更简单的方法来处理 85 上的 4 个 LED,还是换成 84 会更好?如果我选择 84,我是否有可能 运行 进入与 85 相同的砖墙?
我找到了这个在85上控制4的代码,但它超出了我的技能水平。有人发现它有任何问题吗?
/* Four PWM Outputs */
// ATtiny85 outputs
const int Red = 0;
const int Green = 1;
const int Blue = 4;
const int White = 3;
volatile uint8_t* Port[] = {&OCR0A, &OCR0B, &OCR1A, &OCR1B};
void setup() {
pinMode(Red, OUTPUT);
pinMode(Green, OUTPUT);
pinMode(Blue, OUTPUT);
pinMode(White, OUTPUT);
// Configure counter/timer0 for fast PWM on PB0 and PB1
TCCR0A = 3<<COM0A0 | 3<<COM0B0 | 3<<WGM00;
TCCR0B = 0<<WGM02 | 3<<CS00; // Optional; already set
// Configure counter/timer1 for fast PWM on PB4
TCCR1 = 1<<CTC1 | 1<<PWM1A | 3<<COM1A0 | 7<<CS10;
GTCCR = 1<<PWM1B | 3<<COM1B0;
// Interrupts on OC1A match and overflow
TIMSK = TIMSK | 1<<OCIE1A | 1<<TOIE1;
}
ISR(TIMER1_COMPA_vect) {
if (!bitRead(TIFR,TOV1)) bitSet(PORTB, White);
}
ISR(TIMER1_OVF_vect) {
bitClear(PORTB, White);
}
// Sets colour Red=0 Green=1 Blue=2 White=3
// to specified intensity 0 (off) to 255 (max)
void SetColour (int colour, int intensity) {
*Port[colour] = 255 - intensity;
}
void loop() {
for (int i=-255; i <= 254; i++) {
OCR0A = abs(i);
OCR0B = 255-abs(i);
OCR1A = abs(i);
OCR1B = 255-abs(i);
delay(10);
}
}
一个简单的策略是将 4 个 LED 多路复用到一个 PWM 引脚上。这将允许使用总共 5 个引脚独立控制 ATTINY 上每个 LED 的亮度。
因此,例如,您可以将所有 4 个阴极连接在一起,并将它们连接到一个 PWM 引脚。然后将 4 个阳极中的每一个连接到不同的 IO 引脚。
在任何给定时刻,只有一个阳极处于输出模式 - 其他阳极处于浮动状态。这意味着最多 1 个 LED 处于活动状态,其亮度由 PWM 占空比控制。
然后您可以使用 PWM 定时器的溢出 ISR 在每个 PWM 周期后激活序列中的下一个 LED。您还可以更新 PWM 匹配以反映下一个 LED 的亮度。
如果您快速旋转 LED(比例如每秒 60 次更快),那么在视觉上它们看起来就像以所需的亮度亮起一样。毕竟,PWM 只是使 LED 闪烁得太快以至于看不见,所以我们只是在其上添加第二个维度。
一个缺点:由于任何时候只有一个 LED 点亮,理论上最大总亮度将是独立驱动所有 LED 时的 1/4。在实践中,这可能是一个问题,因为如果您尝试同时点亮所有 LED,阁楼会受到限制,如果它的引脚同时通过所有引脚,它可以通过多少电流。
一个提示:在设置PWM定时器时,make是让LED在周期开始时熄灭,在周期中间点亮。这将使 ISR 有时间在所有 LED 熄灭时进入下一个 LED。这更好,因为很容易看到不应该点亮的 LED,但很难看到应该点亮的 LED 熄灭。
一个建议:我会因此而被激怒,但是你可以在这样做时省去任何限流电阻,因为每个 LED 最多只有 1/4 的时间亮着。这将为您提供更多亮度,并使您可以调低 PWM 占空比,以便在每个周期开始时有更多关闭时间以进入下一个 LED。
我已经多次成功使用这种技术,甚至能够将 6 个 RGB LED(每个三个通道)多路复用到一个芯片上,而且效果很好。
如果您对细节有任何疑问,请更新问题!
如果你想以更复杂的策略为代价来节省引脚,你可以通过像这样将 LED 连接成两组,每组两个,只使用 3 个引脚...
不是使用内置 PWM,而是需要通过设置定时器手动执行 PWM,然后在每次定时器到期时更改每个引脚的 INPUT/OUTPUT 和 ON/OFF .
+-----+----------+----------+----------+
| LED | A | B | C |
+-----+----------+----------+----------+
| 1 | OUTPUT 1 | INPUT | OUTPUT 0 |
| 2 | OUTPUT 0 | INPUT | OUTPUT 1 |
| 3 | INPUT | OUTPUT 1 | OUTPUT 0 |
| 4 | INPUT | OUTPUT 0 | OUTPUT 1 |
+-----+----------+----------+----------+
如果您想了解有关此策略的更多详细信息,请更新或发表评论。
我需要在 ATTiny85 上通过 PWM 控制 4 个独立的 LED。我找到了很多关于如何控制 3 个 LED 的信息。但显然要用 PWM 控制 4,你必须真正将 85 扭成结。有没有更简单的方法来处理 85 上的 4 个 LED,还是换成 84 会更好?如果我选择 84,我是否有可能 运行 进入与 85 相同的砖墙?
我找到了这个在85上控制4的代码,但它超出了我的技能水平。有人发现它有任何问题吗?
/* Four PWM Outputs */
// ATtiny85 outputs
const int Red = 0;
const int Green = 1;
const int Blue = 4;
const int White = 3;
volatile uint8_t* Port[] = {&OCR0A, &OCR0B, &OCR1A, &OCR1B};
void setup() {
pinMode(Red, OUTPUT);
pinMode(Green, OUTPUT);
pinMode(Blue, OUTPUT);
pinMode(White, OUTPUT);
// Configure counter/timer0 for fast PWM on PB0 and PB1
TCCR0A = 3<<COM0A0 | 3<<COM0B0 | 3<<WGM00;
TCCR0B = 0<<WGM02 | 3<<CS00; // Optional; already set
// Configure counter/timer1 for fast PWM on PB4
TCCR1 = 1<<CTC1 | 1<<PWM1A | 3<<COM1A0 | 7<<CS10;
GTCCR = 1<<PWM1B | 3<<COM1B0;
// Interrupts on OC1A match and overflow
TIMSK = TIMSK | 1<<OCIE1A | 1<<TOIE1;
}
ISR(TIMER1_COMPA_vect) {
if (!bitRead(TIFR,TOV1)) bitSet(PORTB, White);
}
ISR(TIMER1_OVF_vect) {
bitClear(PORTB, White);
}
// Sets colour Red=0 Green=1 Blue=2 White=3
// to specified intensity 0 (off) to 255 (max)
void SetColour (int colour, int intensity) {
*Port[colour] = 255 - intensity;
}
void loop() {
for (int i=-255; i <= 254; i++) {
OCR0A = abs(i);
OCR0B = 255-abs(i);
OCR1A = abs(i);
OCR1B = 255-abs(i);
delay(10);
}
}
一个简单的策略是将 4 个 LED 多路复用到一个 PWM 引脚上。这将允许使用总共 5 个引脚独立控制 ATTINY 上每个 LED 的亮度。
因此,例如,您可以将所有 4 个阴极连接在一起,并将它们连接到一个 PWM 引脚。然后将 4 个阳极中的每一个连接到不同的 IO 引脚。
在任何给定时刻,只有一个阳极处于输出模式 - 其他阳极处于浮动状态。这意味着最多 1 个 LED 处于活动状态,其亮度由 PWM 占空比控制。
然后您可以使用 PWM 定时器的溢出 ISR 在每个 PWM 周期后激活序列中的下一个 LED。您还可以更新 PWM 匹配以反映下一个 LED 的亮度。
如果您快速旋转 LED(比例如每秒 60 次更快),那么在视觉上它们看起来就像以所需的亮度亮起一样。毕竟,PWM 只是使 LED 闪烁得太快以至于看不见,所以我们只是在其上添加第二个维度。
一个缺点:由于任何时候只有一个 LED 点亮,理论上最大总亮度将是独立驱动所有 LED 时的 1/4。在实践中,这可能是一个问题,因为如果您尝试同时点亮所有 LED,阁楼会受到限制,如果它的引脚同时通过所有引脚,它可以通过多少电流。
一个提示:在设置PWM定时器时,make是让LED在周期开始时熄灭,在周期中间点亮。这将使 ISR 有时间在所有 LED 熄灭时进入下一个 LED。这更好,因为很容易看到不应该点亮的 LED,但很难看到应该点亮的 LED 熄灭。
一个建议:我会因此而被激怒,但是你可以在这样做时省去任何限流电阻,因为每个 LED 最多只有 1/4 的时间亮着。这将为您提供更多亮度,并使您可以调低 PWM 占空比,以便在每个周期开始时有更多关闭时间以进入下一个 LED。
我已经多次成功使用这种技术,甚至能够将 6 个 RGB LED(每个三个通道)多路复用到一个芯片上,而且效果很好。
如果您对细节有任何疑问,请更新问题!
如果你想以更复杂的策略为代价来节省引脚,你可以通过像这样将 LED 连接成两组,每组两个,只使用 3 个引脚...
不是使用内置 PWM,而是需要通过设置定时器手动执行 PWM,然后在每次定时器到期时更改每个引脚的 INPUT/OUTPUT 和 ON/OFF .
+-----+----------+----------+----------+
| LED | A | B | C |
+-----+----------+----------+----------+
| 1 | OUTPUT 1 | INPUT | OUTPUT 0 |
| 2 | OUTPUT 0 | INPUT | OUTPUT 1 |
| 3 | INPUT | OUTPUT 1 | OUTPUT 0 |
| 4 | INPUT | OUTPUT 0 | OUTPUT 1 |
+-----+----------+----------+----------+
如果您想了解有关此策略的更多详细信息,请更新或发表评论。