cycle RingLED

回覆文章
cajhbb
系統管理員
文章: 983
註冊時間: 2018年 6月 30日, 02:16

cycle RingLED

文章 cajhbb »

2024-12-05_111806.jpg
2024-12-05_111806.jpg (29.88 KiB) 已瀏覽 226 次

代碼: 選擇全部

#include <Adafruit_NeoPixel.h>

/*<1>紅色按鈕-外部中斷腳位PB2(INT0):具照明及警示作用
  <2>綠色按鈕-PB3內含上拉電阻:遊戲鍵\開始及設定鍵
  <3>環燈訊號腳-PB0
  <4>無源蜂鳴器-PB1
----------------------------------------------------------------
*/ 
//--------------------------------------------------------
#include <Adafruit_NeoPixel.h>//載入第三方程式控制環燈
#define LED_PIN 0 //環號串列訊號腳位PB0
#define KEY_PUSH 3//按鈕控制腳位(內建上拉電阻,平時為HIGH)
#define NUMLEDS 16//環燈=總顆數
#define BRIGHTNESS 250//燈亮度在15~50即可,最大亮度為255
#define buzzerPin 1 //無源蜂鳴器訊號腳位PB1
int period = 1000; //計時器延時週期
int Int_period = 700;//中斷延時週期
int GameState = 0; //遊戲初始狀態=0 1(第1關-3燈) 2(第2關-2燈) 3(第3關-1燈)
byte RingSpeed[] = {110, 100, 60, 40}; //共有4個等級的遊戲
byte Speed=0;//速度盒編號 RingSpeed陣列編號
byte Set_Led[]={0, 0, 0};//用陣列設定號燈(3燈=3個陣列.2燈2個陣列.1燈1個陣列)
byte led_run_at = 0; //跑馬燈號現在位置(led跑到那個位置)
byte Setting_Led = 0; //燈號設定點(亂數值存放)
byte LEVEL=0;//關卡
byte Score=0;//計分用
unsigned long Time_Get = 0;//擷取時間點,開機55天會溢位(歸0)
unsigned long IntTime_Get = 0;//中斷擷取時間點
boolean Go_Play = false;//遊戲處於等待狀態(布林值)
volatile byte Int_state = 0; //定義輸入狀態
//宣告環燈 顆數 腳位
Adafruit_NeoPixel RingLED = Adafruit_NeoPixel(NUMLEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
//--------------------------------------------------------
//-----重置函式
void(* resetFunc)(void)=0;
//-----環燈初始化動作
void setup() {
  RingLED.begin(); //初始化(環燈)
  RingLED.setBrightness(BRIGHTNESS); //環燈亮度
  Time_Get = millis();//擷取開機時間
  pinMode(KEY_PUSH, INPUT_PULLUP);//按鈕輸入腳3(KEY_PUSH),內建上拉電阻
  pinMode(buzzerPin, OUTPUT);//
// Serial.begin(9600);//串列傳輸啟動
  randomSeed(analogRead(KEY_PUSH));//(擷取亂數因子)解決亂數不亂的問題
//######以下是將GIMSK中斷暫存器的INT0啟用,MCUCR控制暫存器設為負緣觸發
  pinMode(2, INPUT_PULLUP);//紅色按鈕,外部中斷腳位
  sei();     //enabling global interrupt
  GIMSK |= (1<<INT0);     // INT0啟用 
  MCUCR |= (1<<ISC01);    // MCUCR控制暫存器設為負緣觸發

}
//--------------------------------------------------------
//------無窮迴圈
void loop() {
    if (GameState == 0){
      //Go_Play == false等待按鈕被按下去,則往下做3關,每關4種變速
        if (digitalRead(KEY_PUSH) == LOW && Go_Play == false) { 
            delay(1000);//除火花,延遲 1000 毫秒,也就是 1 秒鐘。
            PlayStar();//奏音樂
            led_run_at = 0;//跑馬燈現在位置
            Go_Play = true;//變數為true,可以取設定點(亂數)
            //Serial.print("!");//※判斷按鈕準不準
            GameState=1; //開始玩第1關
        }
    Z_Random();//亂數顯示燈號(等待綠鍵被按!)
    }
    if (GameState == 1){Level_1();}//往第1關開始遊戲(每關4種變速)
    if (GameState == 2){Level_2();}//往第2關開始遊戲(每關4種變速)
    if (GameState == 3){Level_3();}//往第3關開始遊戲(每關4種變速)
}
//--------------------------------------------------------
//-----第1關(3顆設定燈):------
void Level_1(){
  RingLED.clear();//清除燈號
  led_run_at=0;//跑馬燈歸零
    while (GameState == 1) { 
      period = RingSpeed[Speed];  //[0][1][2][3]存放不同速度值
              //=====取亂數置入設定點-->再延伸成3個設定燈=====
              if (millis()-Time_Get > period){ //延時 (亮燈週期過了,再重設週期)
                    Time_Get = millis(); // 擷取當下時間放入Time_Get
                    if(Go_Play==true){ //Go_Play為true,可以取設定點(亂數)
                      Setting_Led = random(NUMLEDS); //隨機-取設定點
                      Go_Play = false; //隨機設定號燈完畢,等待按鈕!
                    }
              //----設定3個點---------------------------------
                    //以下亮3個號燈(跨14-15-0)
                    Set_Led[0]=Setting_Led; //陣列0=放入亂數值
                    if(Setting_Led == (NUMLEDS-2)){ //第14顆:(若16顆為例)
                      Set_Led[1]=(NUMLEDS-1);//第15顆
                      Set_Led[2]=0;}//第0顆
                    //以下亮3個號燈(跨15-0-1)
                    else if(Setting_Led == (NUMLEDS-1)){
                      Set_Led[1]=0;
                      Set_Led[2]=1;}
                    else{
                      Set_Led[1]=Set_Led[0]+1;
                      Set_Led[2]=Set_Led[0]+2;}
                    //---點亮3個燈[][][]---
                    RingLED.setPixelColor(Set_Led[0], 0, 255, 0);//(綠)
                    RingLED.setPixelColor(Set_Led[1], 0, 255, 0);//(綠)
                    RingLED.setPixelColor(Set_Led[2], 0, 255, 0);//(綠) 
                    RingLED.show(); 
                    LED_Runing();//呼叫跑馬燈
                    Check_Push(GameState);//檢查按鈕是否被按下?
                }
    }
}
//---------------------------------------------------------------
//-----第2關(2顆設定燈):------
void Level_2(){
  RingLED.clear();//清除燈號
  led_run_at=0;//跑馬燈歸零
    while (GameState == 2) { 
      period = RingSpeed[Speed];  //(陣列中的數字愈大愈慢)
              //=====取亂數置入設定點-->再延伸成2個設定燈=====
              if (millis()-Time_Get > period){ //延時 (亮燈週期過了,再重設週期)
                    Time_Get = millis(); // 擷取當下時間放入Time_Get
                    //====亂數設定OK了嗎? Yes(改false)
                    if(Go_Play==true){ //Go_Play為true,可以取設定點(亂數)
                      Setting_Led = random(NUMLEDS); 
                      Go_Play = false; //隨機設定號燈完畢,等待按鈕!
                    }
              //---設定2個點---------------------------------
                    //====以下亮2個號燈(跨15-0)====
                    Set_Led[0]=Setting_Led; //陣列0=放入亂數值
                    if(Setting_Led==(NUMLEDS-1)){Set_Led[1]=0;}
                    else{Set_Led[1]=Set_Led[0]+1;}
                    RingLED.setPixelColor(Set_Led[0], 0, 255, 0);//(綠)
                    RingLED.setPixelColor(Set_Led[1], 0, 255, 0);//(綠)
                    RingLED.show(); 
                    LED_Runing();//呼叫跑馬燈
                    Check_Push(GameState);//檢查按鈕是否被按下?      
                }
    }
}
//---------------------------------------------------------------
//-----第3關(1顆設定燈):------
void Level_3(){
  RingLED.clear();//清除燈號
  led_run_at=0;//跑馬燈歸零
    while (GameState == 3) { 
      period = RingSpeed[Speed];  //(陣列中的數字愈大愈慢)
              //=====取亂數置入設定點=====
              if (millis()-Time_Get > period){ //延時 (亮燈週期過了,再重設週期)
                    Time_Get = millis(); // 擷取當下時間放入Time_Get
                    //====亂數設定OK了嗎? Yes(改false)
                    if(Go_Play==true){ //Go_Play為true,可以取設定點(亂數)
                      Setting_Led = random(NUMLEDS); 
                      Go_Play = false; //隨機設定號燈完畢,回歸,等待按鈕!
                    }
              //-------------------------------------------
                    //====以下亮1個號燈====
                    Set_Led[0]=Setting_Led; 
                    RingLED.setPixelColor(Set_Led[0], 0, 255, 0);//(綠)
                    RingLED.show(); 
                    LED_Runing();//呼叫跑馬燈
                    Check_Push(GameState);//檢查按鈕是否被按下?         
                }
    }
}
//---------------------------------------------------------------

//---------------------------------------------------------------
//----跑馬燈----
void LED_Runing(){
    led_run_at++; //循環燈...往下累加
  if (led_run_at >= NUMLEDS) { //如果循環紅點位置=60符合則歸零
    RingLED.setPixelColor(led_run_at-1, 0, 0, 0);//最後一顆歸0
    led_run_at = 0;//歸零
  }
  RingLED.setPixelColor(led_run_at, 255, 0, 0);//亮燈
  RingLED.setPixelColor(led_run_at-1, 0, 0, 0);//往後關燈
  RingLED.show();
}
//-----------------------------------------------------------
//----壓下去(檢查是否得分?)-------
void Check_Push(byte LV){ //Go_Play == false為等待的意思
  if (digitalRead(KEY_PUSH) == LOW && Go_Play == false ) { //按鈕被按下去,往下做
  delay(1000);
  Go_Play=true;
  //Serial.print("S");//判斷按鈕準不準
  //-----------------------------------------------------------
  //----得分-------
  if(LV==1){
  if (Set_Led[0]==led_run_at || Set_Led[1]==led_run_at || Set_Led[2]==led_run_at) { 
        Score++;
        ScreLed(Score,550);//呼叫計分燈號函式(累計得分,高音頻)
       }
  else{ScreLed(Score,150);}//呼叫計分燈號函式(不累計,低音頻)
  }
  else if(LV==2){
  if (Set_Led[0]==led_run_at || Set_Led[1]==led_run_at) { 
        Score++;
        ScreLed(Score,550);//呼叫計分燈號函式(累計得分,高音頻)
       }
  else{ScreLed(Score,150);}//呼叫計分燈號函式(不累計,低音頻)
  }
  else if(LV==3){
  if (Set_Led[0]==led_run_at) { 
        Score++;
        ScreLed(Score,550);//呼叫計分燈號函式(累計得分,高音頻)
       }
  else{ScreLed(Score,150);}//呼叫計分燈號函式(不累計,低音頻)
  }
//---換速度檔次--------
  Speed++; //換下個速度檔次
    //Serial.print(Speed);//查看勝利或失敗  */
    //Serial.print(">");
  //若4種檔次完成,換第二關
  if(Speed==4){
    //Serial.println("-");
    GameState++;//下一大關
    if(GameState==4){GameState=0; Go_Play=false;Score=0;}//3大關全部完成
    Speed=0;   
    PlayFamily(); 
    }
  } 
}
//-----------------------------------------------------------
//----計分燈號+鳴----
void ScreLed(byte Gain,int Freq){//接收得分值,及音頻
	RingLED.clear();//清除燈號
	for(byte i=0;i<Gain;i++){RingLED.setPixelColor(i, 255 , 255, 0);}
	RingLED.show();
  //--鳴--
  for (byte j = 0; j <2; j++){
    tinyTone(Freq, 400);} 
  delay(450);
  RingLED.clear();//清除燈號	
}
//-----------------------------------------------------------
//----亂數顯示燈號----
void Z_Random(){
for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
        RingLED.setPixelColor(i, random(0, 255), random(0, 255), random(0, 255));//黃色
        delay(15);
        RingLED.show(); 
    }
}
//-----------------------------------------------------------
//----星際爭霸----
void PlayStar(){
int Star[] = {440,440,440,349,523,440,349,523,440,659,659,659,698,523,415,349,523,440};
int StarDur[] = {400, 400, 400, 250, 50, 400, 250, 50, 900, 400, 400, 400, 250, 50, 400, 250, 50, 900};
  for (int thisNote = 0; thisNote < 18; thisNote++) {//18個音符
      tinyTone(Star[thisNote],StarDur[thisNote]);
      delay(30);// 音符之間的間隔
  }
}
//-----------------------------------------------------------
//----全家音樂----
void PlayFamily(){
 int FamilyMusic[]={330, 262, 196, 262, 294, 392, 0, 0, 294, 330,0, 294, 196, 262,0};
   for (int thisNote = 0; thisNote < 15; thisNote++) {//14個音符
      tinyTone(FamilyMusic[thisNote],200);
      delay(30);// 音符之間的間隔
  }
}
//-----------------------------------------------------------
//----中斷函式----(處理第一次中斷無效問題)
ISR (INT0_vect){
if ( millis() - IntTime_Get > Int_period ){
    IntTime_Get = millis();
    Int_state++;//累計按下次數
    //Serial.print(Int_state);
    while(Int_state==1){ //按1次-->手電筒模式
          for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
              RingLED.setPixelColor(i,255,255,255);//白色
              RingLED.setBrightness(180); //環燈亮度
              RingLED.show();
          }
    }
    while(Int_state==2){ //按2次-->閃白光模式
          for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
              RingLED.setPixelColor(i,255,255,255);//白色
              RingLED.setBrightness(180); //環燈亮度
              RingLED.show();
           }
          delay(400);
          for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
              RingLED.setPixelColor(i,0,0,0);//黑色
              RingLED.show();
           }
          delay(400);
    }
        while(Int_state==3){ //按3次-->閃紅光模式
          for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
              RingLED.setPixelColor(i,255,0,0);//紅色
              RingLED.setBrightness(180); //環燈亮度
              RingLED.show();
           }
          delay(400);
          for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
              RingLED.setPixelColor(i,0,0,0);//黑色
              RingLED.show();
           }
          delay(400);
    }
        while(Int_state==4){ //按4次-->閃紅光+警示音模式
          for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
              RingLED.setPixelColor(i,255,0,0);//紅色
              RingLED.setBrightness(180); //環燈亮度
              RingLED.show();
           }
          tinyTone(650, 200);
          delay(300);
          for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
              RingLED.setPixelColor(i,0,0,0);//黑色
              RingLED.show();
           }
          tinyTone(900, 200);
          delay(300);
    }
       if(Int_state==5){ //按5次-->重置模式
          Int_state=0;
          resetFunc();
          }
  }
}
//-----------------------------------------------------------
//----音樂播放函式(傳音符[頻率],聲音長度)
void tinyTone(int frequency, int length){
  unsigned long period;
  unsigned long n;
  period=1000000/frequency;
  n=1000*(long)length/period; 
  for(int j=1;j<n;j++){
    digitalWrite(buzzerPin,HIGH);
    delayMicroseconds(period/2);
    digitalWrite(buzzerPin,LOW);
    delayMicroseconds(period/2);
  }
}

Ring_for_ATTiny_reset_OK.zip
(3.77 KiB) 已下載 1 次
cajhbb
系統管理員
文章: 983
註冊時間: 2018年 6月 30日, 02:16

函式庫

文章 cajhbb »

代碼: 選擇全部

// NeoPixel環簡易範例 (c) 2013 Shae Erisson
// 根據GPLv3授權發布,以配合其餘的Adafruit NeoPixel函式庫

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // 對於16 MHz的Adafruit Trinket是必需的
#endif

// Arduino上的哪一個腳位連接到NeoPixels?
#define PIN        6 // 在Trinket或Gemma上,建議將此更改為1

// 有多少個NeoPixels連接到Arduino?
#define NUMPIXELS 16 // 常見的NeoPixel環大小

// 在設置NeoPixel函式庫時,我們告訴它有多少像素,以及哪個腳位用來發送信號。
// 注意,對於舊的NeoPixel條,你可能需要更改第三個參數 -- 
// 請參閱strandtest範例以獲取更多可能值的信息。
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

#define DELAYVAL 500 // 在像素間暫停的時間(毫秒)

void setup() {
  // 這些行專門支持Adafruit Trinket 5V 16 MHz。
  // 任何其他板子都可以移除這部分(但保留也無妨):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // Trinket特定代碼的結尾。

  pixels.begin(); // 初始化NeoPixel條物件(必需)
}

void loop() {
  pixels.clear(); // 將所有像素顏色設置為'關閉'

  // 一個串中的第一個NeoPixel是#0,第二個是1,以此類推,
  // 直到像素數減一。
  for(int i=0; i<NUMPIXELS; i++) { // 對於每個像素...

    // pixels.Color()接收RGB值,範圍從0,0,0到255,255,255
    // 這裡我們使用一個適中的亮綠色:
    pixels.setPixelColor(i, pixels.Color(0, 150, 0));

    pixels.show();   // 發送更新的像素顏色到硬體。

    delay(DELAYVAL); // 在進入下一次循環前暫停
  }
}

cajhbb
系統管理員
文章: 983
註冊時間: 2018年 6月 30日, 02:16

焊接接腳

文章 cajhbb »

1.發展板接腳
發展板接腳.jpg
發展板接腳.jpg (78.63 KiB) 已瀏覽 11 次
電源.jpg
電源.jpg (66.04 KiB) 已瀏覽 6 次
cajhbb
系統管理員
文章: 983
註冊時間: 2018年 6月 30日, 02:16

開關接腳

文章 cajhbb »

開關.jpg
開關.jpg (46.86 KiB) 已瀏覽 10 次
按鈕.jpg
按鈕.jpg (54.05 KiB) 已瀏覽 9 次
回覆文章