attiny85 выход из сна по кнопке.

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

Помогите разобраться с кодом. Взял такой пример:

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

const int switchPin                     = 3;
const int statusLED                     = 2;

void setup() {

    pinMode(switchPin, INPUT);
    digitalWrite(switchPin, HIGH);
    pinMode(statusLED, OUTPUT);

    // Flash quick sequence so we know setup has started
    for (int k = 0; k < 10; k = k + 1) {
        if (k % 2 == 0) {
            digitalWrite(statusLED, HIGH);
            }
        else {
            digitalWrite(statusLED, LOW);
            }
        delay(250);
        } // for
    } // setup

void sleep() {

    GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
    PCMSK |= _BV(PCINT3);                   // Use PB3 as interrupt pin
    ADCSRA &= ~_BV(ADEN);                   // ADC off
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement

    sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
    sei();                                  // Enable interrupts
    sleep_cpu();                            // sleep

    cli();                                  // Disable interrupts
    PCMSK &= ~_BV(PCINT3);                  // Turn off PB3 as interrupt pin
    sleep_disable();                        // Clear SE bit
    ADCSRA |= _BV(ADEN);                    // ADC on

    sei();                                  // Enable interrupts
    } // sleep

ISR(PCINT0_vect) {
    // This is called when the interrupt occurs, but I don't need to do anything in it
    }

void loop() {
    sleep();
    digitalWrite(statusLED, HIGH);
    delay(1000);
    digitalWrite(statusLED, LOW);
    }

И попробовал встроить в свой код:


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

const byte numLed[20][2] = { //какие пины дёргать чтоб загорался определённый светодиод
          {0,4}, //1 1
          {1,4}, //5 2
          {2,4}, //9 3
          {3,4}, //13 4
          {4,1}, //17 5
          {0,3}, //2 6
          {1,3}, //6 7
          {2,3}, //10 8
          {3,1}, //14 9
          {4,3}, //18 10
          {0,2}, //3 11
          {1,2}, //7 12
          {2,1}, //11 13
          {3,2}, //15 14
          {4,2}, //19 15
          {0,1}, //4 16
          {1,0}, //8 17
          {2,0}, //12 18
          {3,0}, //16 19
          {4,0}, //20 20
}; 


long previousMillis = 0;
long previousMillisSP = 0;

byte mode = 0;
byte i;                  //для циклов
byte j;
byte apl=8;            //яблоко
byte lgth = 1;          //длина змейки
byte _msnake = 0;       //направление движения
byte _snake[20] = {12,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  //голова и хвост змейки
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() { 
  delay(1);               
  if(digitalRead(3)==HIGH){
      mode=0;
    }
    delay(1); 
    if(digitalRead(4)==HIGH){
      mode=1;
    }
    delay(1); 
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  
}
void(* resetFunc) (void) = 0; // Reset MC function


void sleep(){ 

  for(byte i=0; i<5; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }
    for(byte i=0; i<5; i++){
    pinMode(i, INPUT);
  }
    GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
    PCMSK |= _BV(PCINT3);                   // Use PB3 as interrupt pin
    //PCMSK |= _BV(PCINT4);                   // Use PB4 as interrupt pin
    ADCSRA &= ~_BV(ADEN);                   // ADC off
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement
    sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
    sei();                                  // Enable interrupts
    sleep_cpu();                            // sleep

    cli();                                  // Disable interrupts
    PCMSK &= ~_BV(PCINT3);                  // Turn off PB3 as interrupt pin
   // PCMSK &= ~_BV(PCINT4);                  // Turn off PB4 as interrupt pin
    sleep_disable();                        // Clear SE bit
    ADCSRA |= _BV(ADEN);                    // ADC on
    //resetFunc();

    sei();                                  // Enable interrupts
   /* 
  ADCSRA &= ~(1 << ADEN); // перед сном отключим АЦП
  ACSR |= (1 << ACD); // компаратор
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
  sleep_enable(); 
  sleep_cpu(); // спать*/
 }
 

//ISR(PCINT3_vect) {
//  resetFunc();
//    // This is called when the interrupt occurs, but I don't need to do anything in it
//}

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


void onLedOne (byte i){ //зажигает только один выбранный светодиод по его номеру
if(i<=20 && i>0){
    i--;
    byte a = numLed[19-i][0];
    byte f = numLed[19-i][1];
    ledon (a, f);
  }
}
void aplRd(){       //генерируем яблоко там где нет хвоста и головы змейки
    do
    {
        i=0;
        apl=random(1,19);
        for(j=lgth+1; j>0; j--){
        if(_snake[j-1]==apl)
          i++;
        }
      }while(i>0);
      
}

void loop() {

//  for(byte i=0; i<21; i++){ // для отладки
//  onLedOne (i);
//  delay(10);
//  }
  
if(millis() - previousMillisSP > 1000){//проверяем спать или нет
sleep();
//sleepMode();
}
  switch (mode){
    
    case 0:
        rendom();
    break;
    case 1:
      snake();
    break;
    default:
    mode = 0;
    break;
  }
}


void snake(){
if(millis() - previousMillisSP > 30){    //смена неправления движения кнопками
  
  if(digitalRead(4)==HIGH){ 
      previousMillisSP = millis();
        if(_msnake>0){
          _msnake--;
        }else{_msnake=3;} 
  }
if(digitalRead(3)==HIGH){
      previousMillisSP = millis();
        if(_msnake<3){
          _msnake++;
        }else{_msnake=0;}   
    
  } 
}    


if(millis() - previousMillis > 40)
    {
      previousMillis = millis();
      
      if(_snake[0]==apl){          //если яблоко съели, хвост длиньше, и генерируем другое
          aplRd();          
          lgth++;
      }
      
       for(i=lgth; i>0; i--)      //тащим за собой хвост
        _snake[i]=_snake[i-1];
        
      switch (_msnake) {      //перемещаем змейку
      
        case 0:                    //вверх
          if(_snake[0]<=5){
            _snake[0]+=15;
          }else{_snake[0]-=5;}
        break;
        
        case 1:                    //вправо
          if(_snake[0]%5==0){
            _snake[0]-=4;
           //lgth++;
          }else{_snake[0]+=1;}
          
        break;
        
        case 2:                    //вниз
          if(_snake[0]>15){
            _snake[0]-=15;
          }else{_snake[0]+=5;}
        break;
        
        case 3:                    //влево
          if(_snake[0]%5==1){
            _snake[0]+=4;
          }else{_snake[0]-=1;}
        break;
      
      
      }

      
      for(i=lgth; i>0; i--){          //съеден ли хвост 
          if(_snake[0]==_snake[i]){
              _snake[0]=12;
              _snake[1]=17;
              for(j=1; j<lgth;j++){      //показываем длину хвоста
                onLedOne(j);
                delayMicroseconds(5750);
              }
              lgth=1;
              _msnake=0;
              apl=random(1,20);
              
              //aplRd();
          }
      }

  
}
     for(i=lgth; i>0; i--){     //рисуем хвост
      
          onLedOne(_snake[i]);
      }
    onLedOne(_snake[0]);        //рисуем голову
    if(millis()%20!=0){
    onLedOne(apl);              //рисуем яблоко
    }
}
void rendom() {

  
  if(digitalRead(3)==HIGH){
    if(millis() - previousMillisSP > 50)
    {
      previousMillis = millis();
      previousMillisSP = millis();
      g++;
      k=0;      
    }
  }
  if(digitalRead(4)==HIGH){
     //if(millis() - previousMillisSP > 50)
        resetFunc();
    }
  
  switch (g){
    
    case 1:
      if(k==0){
      k=(millis())%10+1;
      }
      clearBf(_Bft);
      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 > 20)
    {
      previousMillis = millis();
      kletAvt();
    }

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

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

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 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(j*5+i+1);
    } 
  }
}

Вроде с первого взгляда должно работать, но не работет. и Ещё вопрос, может не работать из-за того, что у меня кнопки притягиваются в высокое состояние HIGH, а не LOW? и как это исправить? Очень не хочется 3ю кнопку на ресет лепить и так места мало.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

xplp пишет:

Вроде с первого взгляда должно работать, но не работет.

1. Никому оно ничего не должно. Зачем Вы ISR выбросили?

2. Что у Вас там в строках 234-237? Вы понимаете. что при таком коде она после первого засыпания начнёт засыпать сразу же, немедленно по пробуждении?

И, кстати, пример-то у Вас работает? А то может Вы ещё кнопку не тот пин цепляете.

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

http://youtu.be/W5SMJwiCTzU

Видео где видно как оно работает(вначале я пытаюсь включить нажав на кнопку где прерывание, затем просто на ресет).

ISR я выбросил потому как, что я туда не вставлял, в функцию, ничего не меняется. Пример проверял работает. На видео видно, что просыпается и не засыпает, а рисует, но когда доходит до контакта на котором прерывание повешано, оно вновь исполняется. Так вот вопрос как убрать прерывание с кнопки после тго как проснулся МК? Функция cli();  PCMSK &= ~_BV(PCINT3); не выполняется, я пробовал программный рест resetFunc();, но мк не отключает прерывание поле просыпания.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

xplp пишет:

ISR я выбросил потому как, что я туда не вставлял, в функцию, ничего не меняется. 

А Вас не смущает, что в примере туда ничего не вставляется, но люди его почему-то не выбрасывают? Вы думаете, они его там случано забыли? Таки нет, он нужен. Пустой, но нужен.

xplp пишет:

 Так вот вопрос как убрать прерывание с кнопки после тго как проснулся МК? 

Не обрабатывать прерывние, пока кнопка не будет отпущена.

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

Спасибо за помошь.

Получилось, когда поменял ISR(PCINT3_vect) на ISR(PCINT0_vect)(что то по невнимательности напутал) и вставил туда 

    cli();                  // Disable interrupts
    PCMSK &= ~_BV(PCINT3);  // Turn off PB3 as interrupt pin
    resetFunc();

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А зачем Вам там reset? Впрочем, Ваше дело.

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

Без ресета игра продалжается, а не начинается заново. Я допишу немного функций и выложу, что получилось.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ничего не понимаю, а чем тогда плох ресет сам по себе? Зачем огород городить? Впрочем, как я уже говорил, дело Ваше.

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

Ресет плох тем, что нужно третью кнопку городить, и выходит некрасиво и нессиметрично. И корпус больше делать нужно для некоторых вариантов.