random box attiny85

xplp
Offline
Зарегистрирован: 21.12.2012

Прочитал вот эту статью , решил сделать нечто похожее. Что получилось можно посмотреть тут.


#include <avr/io.h>
#include <avr/sleep.h> 

const byte numLed[20][5] = {
          {0,1,2,3,4}, //1 20
          {0,1,4,2,3}, //2 15
          {0,3,4,1,2}, //3 10
          {0,2,4,3,1}, //4 5
          {1,0,2,3,4}, //5 19
          {1,0,4,2,3}, //6 14
          {1,3,4,0,2}, //7 9
          {1,3,4,2,0}, //8 4
          {2,1,0,3,4}, //9 18
          {2,0,4,1,3}, //10 13
          {2,4,3,0,1}, //11 8
          {2,4,3,1,0}, //12 3
          {3,0,1,2,4}, //13 17
          {3,0,4,2,1}, //14 12
          {3,1,4,0,2}, //15 7
          {3,2,4,1,0}, //16 2
          {4,0,3,2,1}, //17 16
          {4,0,1,2,3}, //18 11
          {4,3,1,0,2}, //19 6
          {4,2,3,1,0}, //20 1
}; 
long previousMillis = 0;
long previousMillisSP = 0;

byte ledM[4][5]={
  {20,16,12,8,4},
  {19,15,11,7,3},
  {18,14,10,6,2},
  {17,13, 9,5,1}
};

boolean _N0[4][5]={
  {0,1,1,1,0},  
  {1,0,0,0,1},
  {1,0,0,0,1},
  {0,1,1,1,0},
};

boolean _N1[4][5]={
  {0,0,0,0,0},  
  {1,0,0,1,0},
  {1,1,1,1,1},
  {1,0,0,0,0},
};

boolean _N2[4][5]={
  {1,0,0,1,0},  
  {1,1,0,0,1},
  {1,0,1,0,1},
  {1,0,0,1,0},
};

boolean _N3[4][5]={
  {0,1,0,0,1},  
  {1,0,0,0,1},
  {1,0,1,0,1},
  {0,1,0,1,1},
};

boolean _N4[4][5]={
  {0,0,1,1,1},  
  {0,0,1,0,0},
  {0,0,1,0,0},
  {1,1,1,1,1},
};

boolean _N5[4][5]={
  {1,0,1,1,1},  
  {1,0,1,0,1},
  {1,0,1,0,1},
  {0,1,0,0,1},
};

boolean _N6[4][5]={
  {0,1,1,1,0},  
  {1,0,1,0,1},
  {1,0,1,0,1},
  {0,1,0,0,1},
};

boolean _N7[4][5]={
  {0,0,0,0,1},  
  {0,0,0,0,1},
  {1,1,1,0,1},
  {0,0,0,1,1},
};

boolean _N8[4][5]={
  {0,1,0,1,0},  
  {1,0,1,0,1},
  {1,0,1,0,1},
  {0,1,0,1,0},
};

boolean _N9[4][5]={
  {0,0,0,1,0},  
  {1,0,1,0,1},
  {1,0,1,0,1},
  {0,1,1,1,0},
};

boolean _Bfl[6][7]={
  {0,0,0,0,0,0,0},  
  {0,0,0,1,0,0,0},
  {0,0,0,1,0,1,0},
  {0,0,0,1,1,0,0},
  {0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0},
};

boolean _Bft[6][7]={
  {0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0},
};

byte g = 0;
boolean h = 0;
byte k = 0;
 
void setup() {                
  
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
}

void sleep(){ 

  for(byte i=0; i<5; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }
  ADCSRA &= ~(1 << ADEN); // перед сном отключим АЦП
  ACSR |= (1 << ACD); // компаратор
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
  sleep_enable(); 
  sleep_cpu(); // спать
  
}
void paintM(boolean _arr[6][7]){
  for(byte i=0; i<5; i++){
    for(byte j=0; j<4; j++){
      if(_arr[j+1][i+1]==1)
        onLedOne(ledM[j][i]);
    } 
  }
}

void ledon (byte a, byte b, byte c, byte d, byte e){ //зажигает определённый светодиод
  pinMode(a, OUTPUT);
  digitalWrite(a, HIGH);   
  pinMode(b, INPUT);
  pinMode(c, INPUT);
  pinMode(d, INPUT);
  pinMode(e, OUTPUT);
  digitalWrite(e, LOW);
  delayMicroseconds(50);
 
  for(byte i=0; i<5; i++)//очищаем входы
  pinMode(i, INPUT);
}

void onLedOne (byte i){ //зажигает только один выбранный светодиод по его номеру
if(i<=20 && i>0){
    i--;
    byte a = numLed[i][0];
    byte b = numLed[i][1];
    byte c = numLed[i][2];
    byte d = numLed[i][3];
    byte e = numLed[i][4];
    ledon (a, b, c, d, e);
  }
}

void clearBf(boolean _arr[6][7]){
    for(byte i=0; i<6;i++){
    for(byte j =0; j<7; j++)
    _arr[i][j]=0;
  }
}

void copyArB(boolean _arr0[6][7], boolean _arr1[6][7]){
    for(byte i=0; i<6;i++){
      for(byte j=0; j<7; j++)
        _arr0[i][j]=_arr1[i][j];
  }
}

void copyArBfl(boolean _arr0[6][7], boolean _arr1[4][5]){
    for(byte i=0; i<4;i++){
      for(byte j=0; j<5; j++)
        _arr0[i+1][j+1]=_arr1[i][j];
  }
}

int KAI(int i)//вспомогательня функция клеточного автомата
{
  if(i<0){
    i=5;
  }else if(i>5){
    i=0;
  }
  return i;
}

int KAJ(int j)//вспомогательня функция клеточного автомата
{
    if(j<0){
    j=6;
  }else if(j>6){
    j=0;
  }
  return j;
}
void kletAvt()//функция клеточного автомата
{
  
 int _kk=0; 
  for(int i=0; i<6; i++){
    for(int j=0; j<7; j++){
      _kk=0; 
      for(int k=-1; k<2;k++)
      _kk += _Bfl[KAI(i-1)][KAJ(j+k)]+_Bfl[KAI(i)][KAJ(j+k)]+_Bfl[KAI(i+1)][KAJ(j+k)];
      
      if(_Bfl[i][j]==1 && _kk>=3 &&_kk<=4 ){
        _Bft[i][j]=1;
      }else if(_Bfl[i][j]==1 && _kk<3 && _kk>4){
        _Bft[i][j]=0;
      }else if(_Bfl[i][j]==0 && _kk==3){
        _Bft[i][j]=1;
      }else{
        _Bft[i][j]=0;
      }  
    
   }paintM(_Bfl);
  }
   
  copyArB(_Bfl,_Bft);
 
}

void loop() {

  if(digitalRead(3)==HIGH){
    if(millis() - previousMillisSP > 450)
    {
      previousMillis = millis();
      previousMillisSP = millis();
      g++;
    //  h=0;
      k=0;      
    }
  }
  if(millis() - previousMillisSP > 25000){
    sleep();
  }
  
  switch (g){
    
    case 1:
      if(k==0){
      k=(millis())%10+1;
      }
      
      switch (k){
        
      case 10:
        copyArBfl(_Bfl,_N0);
      break;
      
      case 1:
        copyArBfl(_Bfl,_N1);
      break;
      
      case 2:
        copyArBfl(_Bfl,_N2);       
      break;
      
      case 3:
        copyArBfl(_Bfl,_N3);
      break;
      
      case 4:
        copyArBfl(_Bfl,_N4);
      break;
      
      case 5:
        copyArBfl(_Bfl,_N5);
      break;
      
      case 6:
        copyArBfl(_Bfl,_N6);
      break;
      
      case 7:
        copyArBfl(_Bfl,_N7);
      break;
      
      case 8:
        copyArBfl(_Bfl,_N8);
      break;
      
      case 9:
        copyArBfl(_Bfl,_N9);
      break;
      
      default:
      onLedOne(random(0,21));
      break;
      }
      paintM(_Bfl);
     h=1; 
    break;
    
   case 0:  
      if(millis() - previousMillis > 100)
    {
      previousMillis = millis();
      kletAvt();
    }

   paintM(_Bfl);
   if(h==1)
    onLedOne(random(0,21));

    break;
 
  default:
   clearBf(_Bft);
   g=0;
   k=0;
   break;
   
  }
}

Может, кому интересно будет. Написано для ATtiny85, светодиоды подключены по типу лолшилда, кнопка включения повешена на ресет, кнопка выбора режима на 2ю ножку МК.

xplp
Offline
Зарегистрирован: 21.12.2012
faraddin
Offline
Зарегистрирован: 11.08.2013

Почему не сделать просто перебор всех вариантов, запускаемых по нажатию кнопки (минус отсечка дребезга) и выключаемый по етпускании кнопки? На частотах 8 МГц, даже перебор 20 различных значений даст 400 000 переборов в секунду. Нажать дважды одинаково кнопку при такой частоте просто невозможно. Вот вам и реальный рандом.

xplp
Offline
Зарегистрирован: 21.12.2012

Можно и так, у меня рендом берётся от времени, когда была нажата кнопка после включения, нажать одинаково сложно, единственно если зажать кнопку перед включением, то тогда всегда одинаковое значение получается. Можно попробовать и как вы сказали сделать. Только я не совсем понял, мы запоминаем время, когда была нажата кнопка, потом от времени, когда кнопку отпустили, вычитаем время, когда она была нажата, а дальше опять берём остаток от деления на 10 и всё? Или какой-то другой алгоритм?

faraddin
Offline
Зарегистрирован: 11.08.2013

Нет. Все куда проще. Нажимаем кнопку - ждем 500мс. Кнопка не отпущена - хорошо, отпущена - хрен вам а не результат, нечего так бытсро щелкать. Через 500 мс запускаем по кругу счетчик. Как только счетчик доходит до определенного значения (например до 20) тогда сбрасываем его на 0. При этом каждую интерацию проверяем кнопку: отпустили - стоп счетчик, получите результат. В варианте да-нет все еще проще, перед каждой проверкой кнопки просто инвертируем булевскую переменную. Это на ассемблере вообще в несколько строк можно уместить.

xplp
Offline
Зарегистрирован: 21.12.2012

ну сейчас у меня к слову сделано просто вот так:

k=(millis())%10+1;

и почему 500мс?  это долго ждать(=, а тут время от начала включения используется, и кнопку просто нельзя слишком часто нажимать, я вот хотел чтоб не просто цифры были, а скролл надписи, но если ещё пару букв можно проскроллить, то что то большее там толи оперативки на массив не хватает толи ещё что-то, в общем всё зависает. Вот такая функция скролла была:

void scrollM(int r, boolean _arr[][5]){
    if(millis()- previousMillis > 630){
     for(int i=0;i<5;i++){
     _Bf[0][i]=_Bf[1][i];
     _Bf[1][i]=_Bf[2][i];
     _Bf[2][i]=_Bf[3][i];
     _Bf[3][i]=_arr[k][i];
     
     }
     k++;
     previousMillis = millis()-500;
   }
    paintM(_Bf);
    if(k>=r){
      clearBf();
    }

}

r там это сколько по высоте надпись, сейчас всё убрано