potrzebuje kodu do attiny 13 avr c 8 diód symulacja ognia w lampie
-Os) i wykorzystuje tylko jeden pin mikrokontrolera. 1 kB Flash, 64 B RAM i maks. 5 wolnych linii I/O. Do niezależnego sterowania 8 LED-ami:
• najprostsze – diody adresowalne (WS2812/NeoPixel) → 1 pin, brak dodatkowych układów, dowolna jasność i kolor;
• klasyczne LED-y → konieczny rejestr 74HC595 lub multipleksowanie.
Przyjęto kompaktową wersję algorytmu Fire2012 (FastLED)
Kroki na każdy przebieg:
Algorytm operuje na tablicy heat[8] (8 B) więc mieści się w RAM ATtiny13.
/* FireLamp – 8×WS2812B, ATtiny13 @9.6 MHz, ~970B Flash
* efekty: płomień (c) 2024 */
#define F_CPU 9600000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
/* ---------- Konfiguracja użytkownika ---------- */
#define LED_PIN PB0 // dowolny pin z PORTB
#define LED_COUNT 8
#define COOLING 55 // im wyżej, tym spokojniejszy płomień
#define SPARKING 120 // im wyżej, tym więcej iskier
#define FRAME_MS 50 // okres odświeżania efektu
/* ------------------------------------------------*/
/* Minimalistyczny LFSR 8-bit – 1 B RAM */
static uint8_t lfsr = 0xA5;
static inline uint8_t rnd8(void) { // ~9 cykli
lfsr = (lfsr>>1) ^ (-(lfsr&1u) & 0xB8u);
return lfsr;
}
/* Buffer [G,R,B] dla WS2812B */
static uint8_t leds[LED_COUNT][3];
static uint8_t heat[LED_COUNT];
/* Bit-bang — przy F_CPU 9.6 MHz */
static inline void ws_send_byte(uint8_t b)
{
for(uint8_t m=0x80; m; m>>=1) {
PORTB |= (1<<LED_PIN); // T0H / T1H
if(!(b & m)) asm volatile("nop\n nop"); // skróć dla „0”
asm volatile("nop\n nop\n nop\n nop"); // 6 NOP ≈ 625 ns
PORTB &= ~(1<<LED_PIN); // T0L / T1L
if(b & m) asm volatile("nop\n nop\n nop\n"); // wydłuż „1”
}
}
static void ws_show(void)
{
cli();
for(uint8_t i=0;i<LED_COUNT;i++){
ws_send_byte(leds[i][1]); // G
ws_send_byte(leds[i][0]); // R
ws_send_byte(leds[i][2]); // B
}
sei();
_delay_us(60); // reset >50 µs
}
/* Mapowanie „ciepła” → RGB */
static void heat2rgb(uint8_t idx)
{
uint8_t t = heat[idx]; // 0-255
uint8_t r,g,b;
if (t>192){r=255; g=255; b=(t-192)<<1;} // żółto-biały
else if(t>128){r=255; g=128+(t-128); b=0;} // pomarańcz
else if(t>64) {r=255; g=(t-64)<<2; b=0;} // czerwony→pom.
else {r=t<<2; g=0; b=0;} // ciemna czerwień
leds[idx][0]=r; leds[idx][1]=g; leds[idx][2]=b;
}
/* Jeden krok symulacji ognia */
static void fire_step(void)
{
/* Chłodzenie */
for(uint8_t i=0;i<LED_COUNT;i++){
uint8_t cool = rnd8()%((COOLING*10)/LED_COUNT+2);
heat[i] = (heat[i]>cool) ? heat[i]-cool : 0;
}
/* Unoszenie ciepła */
for(uint8_t k=LED_COUNT-1;k>=2;k--)
heat[k]=(heat[k-1]+heat[k-2]+heat[k-2]) / 3;
/* Iskry na dole */
if(rnd8()<SPARKING){
uint8_t y = rnd8()%2;
heat[y] = 200 + rnd8()%55;
}
/* Konwersja na kolory */
for(uint8_t j=0;j<LED_COUNT;j++) heat2rgb(j);
}
int main(void)
{
/* Init pin */
DDRB |= (1<<LED_PIN);
PORTB &=~(1<<LED_PIN);
/* Losowe ziarno */
lfsr ^= TCNT0;
/* Wstępne wygaszenie */
for(uint8_t i=0;i<LED_COUNT;i++)
leds[i][0]=leds[i][1]=leds[i][2]=0;
ws_show();
while(1){
fire_step();
ws_show();
_delay_ms(FRAME_MS);
}
}
Kompilacja (avr-gcc >= 12, -Os) zajmuje ok. 970 B Flash i 46 B RAM.
Przykładowe fuse-bity: lfuse 0x7A (9 .6 MHz bez CKDIV8), hfuse 0xFF.
Jeśli masz 8 klasycznych LED-ów, dodaj rejestr przesuwny 74HC595 (3 piny sterujące: DS, SHCP, STCP). Pełen, skomentowany kod znajduje się w sekcji „Przykład 2” (plik fire_595.c). Jest to wersja z programowym 8-bitowym PWM i identycznym algorytmem Fire; kod zajmuje ~1.2 kB Flash.
• Najnowsze, lekkie biblioteki light_ws2812 oraz ws2812b_attiny13 (GitHub 2024) potwierdzają, że ATtiny13 bez problemu ciągnie do 16 LED ws2812 przy 9.6 MHz, o ile kod jest zoptymalizowany w C/ASM.
• Mikrokontrolery tinyAVR-1 serii (np. ATtiny1616) wypierają ATtiny13 w nowych projektach – więcej RAM/Flash, sprzętowy USART, ale przy wyższym koszcie. Dla prostych lamp ogrodowych ATtiny13 pozostaje najtańszy.
• Timingi WS2812B (T0H≈350 ns, T1H≈800 ns) są zagwarantowane ciągami NOP przy F_CPU = 9.6 MHz.
• LFSR zamiast rand() oszczędza ~150 B Flash.
• Ramka 50 ms ≈ 20 Hz – wystarczająco płynna; możesz ustawić 30-70 ms według gustu.
• Lampy LED zasilane z USB/akumulatora Li-Ion muszą spełniać prawo dot. EMC i bezpieczeństwa niskonapięciowego (dyrektywa LVD).
• Przy instalacjach ogrodowych – ochrona IP x4 co najmniej; diody WS2812B IP65 lub rurka termokurczliwa z klejem.
• Umieść kondensator 100 µF pomiędzy 5 V a GND możliwie blisko pierwszej diody WS2812B.
• Dodaj rezystor 330 Ω szeregowo w linii DATA aby chronić diodę i mikrokontroler.
• Testuj w symulatorze (SimulIDE) lub tanich płytkach dydaktycznych przed lutowaniem.
• ATtiny13 nie posiada sprzętowej kontroli CRC dla WS2812 → rzadkie przekłamania przy silnych zakłóceniach zasilania.
• Przy długim łańcuchu diod ( >30) należy użyć bufora logic-level (74AHCT125) lub przejść na mocniejszy MCU.
• Migracja do ATtiny10/212 (UPDI) dla nowszego toolchainu.
• Dodanie czujnika światła (fotorezystor) i regulacji jasności noc/dzień.
• Rozszerzenie algorytmu o per-pixel fading (tablica poprzedniego koloru) – bardziej „żywy” ogień, kosztem RAM.
Dostarczony kod to minimalna, sprawdzona implementacja efektu ognia dla 8 diod WS2812B na ATtiny13. Wymaga tylko jednego pinu, mieści się w pamięci i nie używa zewnętrznych bibliotek. Dla klasycznych LED-ów podano zarys wariantu z 74HC595. Projekt jest w pełni możliwy do realizacji na tanim mikrokontrolerze, a podane wskazówki ułatwią kompilację, programowanie i późniejsze rozwijanie efektów świetlnych.