1

Тема: Часы на адресной светодиодной ленте WS2812B (ATtiny2313)

http://forum.rcl-radio.ru/uploads/images/2022/01/ad4c99630f3094dcff3cdcc1bd339382.png


// ATtiny2313 20MHz
#include <avr/io.h>
#include <util/delay.h>
#define L_BIT    PORTB &= ~(1<<PB0)
#define H_BIT    PORTB |=  (1<<PB0) 
#define SDA      PD2  // PIN6
#define SCL      PD3  // PIN7
#define SQW      PD4  // PIN8
#define LED_MAX  88

  byte brig=1;
  bool r,g,b;
  bool rr[LED_MAX];
  byte hh,mm,hour,min;
  byte r_led=0,g_led=1,b_led=0;
  byte mode;
  bool sett,w,w1;
  
 
int main(void){
  DDRB |= (1<<PB0); // PIN12 WS2812B 
  DDRB &= ~(1<<PB1);// PIN13 BUTTON MODE
  DDRB &= ~(1<<PB2);// PIN14 BUTTON UP
  DDRB &= ~(1<<PB3);// PIN15 BUTTON DOWN
  DDRB &= ~(1<<PB4);// PIN16 BUTTON SET
  PORTB |= (1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB4);
  _delay_ms(100);
  if(EEPROM_read(100)!=1){for(int i1=0;i1<101;i1++){EEPROM_write(i1,1);}}// очистка памяти при первом включении 
  mode = EEPROM_read(0);brig = EEPROM_read(1);
//  set_time(21,3,3,9,21,52,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59

 
while(1){
   min =  (ds_read(1) & 0x0F) + (((ds_read(1) & 0x70) >> 4) * 10);
   hour = ((ds_read(2) & 0x0F) + ((ds_read(2) & 0x70) >> 4) * 10);
/////// BUTTON ///////////////////////////////////////////////
  if(((PINB >> PB1) & 1) == 0){mode++;if(mode>6){mode=0;}_delay_ms(300);w=1;}
  switch(mode){
    case 0: r_led=1,g_led=1,b_led=1; break;
    case 1: r_led=1,g_led=0,b_led=0; break;
    case 2: r_led=0,g_led=1,b_led=0; break;
    case 3: r_led=0,g_led=0,b_led=1; break;
    case 4: r_led=1,g_led=1,b_led=0; break;
    case 5: r_led=1,g_led=0,b_led=1; break;
    case 6: r_led=0,g_led=1,b_led=1; break;
    }
   if(((PINB >> PB2) & 1) == 0 && sett==0){brig++;if(brig>250){brig=250;}w=1;} 
   if(((PINB >> PB3) & 1) == 0 && sett==0){brig--;if(brig<1){brig=1;}w=1;} 
   if(((PINB >> PB4) & 1) == 0 && sett==0){sett=1;_delay_ms(300);}
   if(((PINB >> PB4) & 1) == 0 && sett==1){sett=0;_delay_ms(300);}   


////////// RGB ////////////////////////////////////////////////
    indd(hour / 10, 0);
    indd(hour % 10, 21);
 
    if(((PIND >> SQW) & 1) == 0 && sett==0){data_led(42, 1);data_led(43, 1);data_led(44, 1);data_led(45, 1);}
      else{data_led(42, 0);data_led(43,0);data_led(44, 0);data_led(45, 0);}
 
    if(sett==1){data_led(42, 1);data_led(43, 1);data_led(44, 1);data_led(45, 1);}
  
    indd(min / 10, 46);
    indd(min % 10, 67);
          
    led_rgb();res();
    _delay_ms(100);

//////////// SET TIME ////////////////////////////////////////////////////////////////////// 
 if(sett==1){
  hh=hour;
  mm=min;
  if(((PINB >> PB2) & 1) == 0){hh++;if(hh>23){hh=0;}_delay_ms(100);w1=1;} 
  if(((PINB >> PB3) & 1) == 0){mm++;if(mm>59){mm=1;}_delay_ms(100);w1=1;} 
  if(w1==1){w1=0;set_time(21,1,12,26,hh,mm,0);}
  }   
 
////// EEPROM ///////////////////
 if(w==1){w=0;EEPROM_write(0,mode);EEPROM_write(1,brig);}  
}} // end loop

void indd(byte t, byte sdv){
    switch(t){   
    case 0: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,0);ws(12+sdv,1);ws(15+sdv,1);ws(18+sdv,1);break;
    case 1: ws(0+sdv,0);ws(3+sdv,0);ws(6+sdv,1);ws(9+sdv,0);ws(12+sdv,0);ws(15+sdv,0);ws(18+sdv,1);break;
    case 2: ws(0+sdv,0);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,1);ws(15+sdv,1);ws(18+sdv,0);break;
    case 3: ws(0+sdv,0);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,0);ws(15+sdv,1);ws(18+sdv,1);break;
    case 4: ws(0+sdv,1);ws(3+sdv,0);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,0);ws(15+sdv,0);ws(18+sdv,1);break;
    case 5: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,0);ws(9+sdv,1);ws(12+sdv,0);ws(15+sdv,1);ws(18+sdv,1);break;
    case 6: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,0);ws(9+sdv,1);ws(12+sdv,1);ws(15+sdv,1);ws(18+sdv,1);break;
    case 7: ws(0+sdv,0);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,0);ws(12+sdv,0);ws(15+sdv,0);ws(18+sdv,1);break;
    case 8: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,1);ws(15+sdv,1);ws(18+sdv,1);break;
    case 9: ws(0+sdv,1);ws(3+sdv,1);ws(6+sdv,1);ws(9+sdv,1);ws(12+sdv,0);ws(15+sdv,1);ws(18+sdv,1);break;
    } 
  }

void ws(byte ind, bool datt){
  if(datt==1){data_led(ind, 1);data_led(ind+1, 1);data_led(ind+2, 1);}
  else{data_led(ind, 0);data_led(ind+1, 0);data_led(ind+2, 0);}}
 
void bit_0(){H_BIT;asm("nop");asm("nop");   L_BIT;asm("nop");asm("nop");asm("nop");   asm("nop");} 
void bit_1(){H_BIT;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");   L_BIT;}
void bit_w(bool x){if(x) bit_1(); else bit_0();}
void res(){_delay_us(100);}
void data_led(byte num, bool rrr){rr[num]=rrr;}
void led_rgb(){
  for(byte num_i=0;num_i<LED_MAX;num_i++){ 
  cli();
  for(int ii=7;ii>=0;ii--){bit_w((rr[num_i]*brig*r_led & (1<<ii))>>ii);}
  for(int ii=7;ii>=0;ii--){bit_w((rr[num_i]*brig*g_led & (1<<ii))>>ii);}  
  for(int ii=7;ii>=0;ii--){bit_w((rr[num_i]*brig*b_led & (1<<ii))>>ii);} 
  sei(); 
}}
    
 

bool i2c_read_bit() {
    bool i2c_bit = 1;        
    DDRD &= ~(1 << SDA);            
    _delay_us(10); 
    DDRD &= ~(1 << SCL);                
    if((PIND >> SDA) & 1) i2c_bit=0;                            
    _delay_us(10);  
    DDRD |= (1 << SCL);              
    return i2c_bit;  
}
 
byte i2c_write_byte(byte data){
    for (byte i=0; i<8; i++){i2c_write_bit((data&0x80)==0);data<<=1;}    
    return i2c_read_bit(); 
}
 
byte i2c_read_byte(byte a){
    byte data=0;                
    for(byte i=0; i<8; i++){if (!i2c_read_bit()) data++;if(i!=7) data<<=1;}        
    i2c_write_bit(a);return data;  
}
 
void i2c_write_bit(byte b){
    _delay_us(5);
    if(b){DDRD |= (1 << SDA);}else{DDRD &= ~(1 << SDA);}
    _delay_us(5);
    DDRD &= ~(1 << SCL);       
    _delay_us(10);
    DDRD |= (1 << SCL);
}
 
void i2c_start(){
     _delay_us(10);  
     DDRD &= ~(1 << SDA); DDRD &= ~(1 << SCL); 
     _delay_us(10); 
     DDRD |= (1 << SDA);  PORTD &= ~(1 << SDA);
     _delay_us(10); 
     DDRD |= (1 << SCL);  PORTD &= ~(1 << SCL);   
     _delay_us(10);
}
 
void i2c_stop()  {
     DDRD |= (1 << SDA);            
     _delay_us(10);
     DDRD &= ~(1 << SCL);               
     _delay_us(10); 
     DDRD &= ~(1 << SDA);             
}
 
byte ds_read(byte reg){
     byte data = 0;
     i2c_start();
     i2c_write_byte(0b11010000);
     i2c_write_byte(reg);
     i2c_start(); 
     i2c_write_byte(0b11010001); 
     data = i2c_read_byte(0);
     i2c_stop();
     return data;
  }
 
void ds_write(byte reg, byte data){
     i2c_start();
     i2c_write_byte(0b11010000);
     i2c_write_byte(reg);
     i2c_write_byte(data);
     i2c_stop();
  } 

void set_time(byte years, byte days, byte monts, byte datas, byte hours ,byte minute, byte second){
    if(second < 255){ds_write(0x00,(second/10<<4)+second%10);}
    if(minute < 255){ds_write(0x01,(minute/10<<4)+minute%10);} 
    if(hours < 255){ds_write(0x02,(hours/10<<4)+hours%10);}
    if(days < 255){ds_write(0x03,days);}
    if(datas < 255){ds_write(0x04,(datas/10<<4)+datas%10);}
    if(monts < 255){ds_write(0x05,(monts/10<<4)+monts%10);}
    if(years < 255)ds_write(0x06,(years/10<<4)+years%10);
  }  

unsigned char EEPROM_read(unsigned int uiAddress){
  while(EECR & (1<<EEPE));  // проверка готовности EEPROM 
    EEAR = uiAddress; // регистр адреса
    EECR |= (1<<EERE);// чтение EEPROM
    return EEDR; // вывод значения
}
 
void EEPROM_write(unsigned int uiAddress, unsigned char ucData){
  while(EECR & (1<<EEPE)); // проверка готовности EEPROM 
      EEAR = uiAddress; // регистр адреса
      EEDR = ucData; // регистр данных 
      EECR |= (1<<EEMPE);// Разрешение записи в EEPROM
      EECR |= (1<<EEPE); // Запись в EEPROM
}      

Скетч использует 1926 байт (94%) памяти устройства. Всего доступно 2048 байт.
Глобальные переменные используют 100 байт (78%) динамической памяти, оставляя 28 байт для локальных переменных. Максимум: 128 байт.

2

Re: Часы на адресной светодиодной ленте WS2812B (ATtiny2313)

ATtiny2313 20 MHz

Данный контент доступен только зарегистрированным пользователям.

http://forum.rcl-radio.ru/uploads/images/2022/01/5132f8fc8903f08087a07e5fe0ac28a1.png

3

Re: Часы на адресной светодиодной ленте WS2812B (ATtiny2313)

Видео есть? Термометр можно добавить?

4

Re: Часы на адресной светодиодной ленте WS2812B (ATtiny2313)

Термометр только в проекте для Arduino Nano - http://forum.rcl-radio.ru/viewtopic.php?pid=5003#p5003

5

Re: Часы на адресной светодиодной ленте WS2812B (ATtiny2313)

Для термометра места не хватает ,если только 2313 заменить на тини 85,а порты ввода и вывода кнопок сделать на mcp23017 либо часы загрузить через ардуино и без кнопок,ставил DHT11 и DHT22 полное дерьмо врут, лучше и можно сказать из них ведёт себя отлично AHT10,работает по шине I2C параллельно часам,вот тогда можно сделать три кнопки ,предварительно заблокировав RST