cycle RingLED

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

cycle RingLED

文章 cajhbb »

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

代碼: 選擇全部

/*-----01-Arduino系列-Attiny85 遊戲及照明兩用---
  <1>紅色按鈕PB2腳-外部中斷腳位PB2-外部中斷腳位(INT0):具照明及警示作用
  <2>綠色按鈕PB3腳-內含上拉電阻:遊戲鍵\開始及設定鍵
  <3>環燈訊號腳-PB0腳
  <4>無源蜂鳴器-PB1腳
  <5>可使用的腳位共6支,可再增加一個按鈕調亮度
*/ 
//----02-C語言外部宣告--------------------------
#include <Adafruit_NeoPixel.h>//載入第三方程式控制環燈WS2812
#define LED_PIN 0 //環號WS2812訊號腳位接PB0
#define KEY_PUSH 3//按鈕(綠)控制腳位(內建上拉電阻,平時為HIGH)
#define NUMLEDS 16//依環燈WS2812顆數修正
#define BRIGHTNESS 250//燈亮度在15~50即可,最大亮度為255
#define buzzerPin 1 //無源蜂鳴器訊號腳位PB1

int period = 1000; //計時器延時週期
int Int_period = 700;//中斷延時週期

byte 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; //定義輸入狀態

//----03定義WS2812環燈: 顆數 腳位 頻率
Adafruit_NeoPixel RingLED = Adafruit_NeoPixel(NUMLEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

//----04 重置函式 ------
void(* resetFunc)(void)=0; //如果有呼叫 resetFunc函式,則軟體重啟

//----05 程式開始-1.進行WS2812環燈初始化動作 2.按鈕宣告輸入 3.蜂鳴器宣告輸出 4.外部中斷腳位宣告
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控制暫存器設為負緣觸發
}

//----06 進入無窮迴圈 1.等待綠按鈕被觸發 2.執行"亂數燈(彩色燈)"-----
void loop() {
    if (GameState == 0){ // 如果第0關-->等待按鈕(且)Go_Play == false遊戲等待中
        if (digitalRead(KEY_PUSH) == LOW && Go_Play == false) { 
            delay(1000);//除火花,延遲 1000 毫秒,也就是 1 秒鐘。
            PlayStar();//奏音樂
            led_run_at = 0;//跑馬燈現在位置
            Go_Play = true;//遊戲開始
            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種變速)
}

//-----07 第Level=1關(3顆設定燈):------
void Level_1(){
  RingLED.clear();//清除燈號
  led_run_at=0;//跑馬燈歸零
    //-----第1關遊戲迴圈
    while (GameState == 1) { 
      period = RingSpeed[Speed];  //取速度值陣列內容
              //---由燈數中,隨機取1顆--->再延伸左右各1形成3個燈
              if (millis()-Time_Get > period){ //延時 (亮燈週期過了,再重設週期)
                    Time_Get = millis(); // 擷取當下時間放入Time_Get
                    if(Go_Play==true){ //遊戲中,可以取設定點(亂數)
                      Setting_Led = random(NUMLEDS); //隨機取設定點
                      Go_Play = false; //隨機設定號燈完畢,等待按鈕!
                    }
					//----由隨機取1點,再延伸為3個點----------
                    //以下亮3個號燈(以16個燈為例:處理跨界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個號燈(以16個燈為例:處理跨界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);//檢查按鈕是否被按下?
                }
    }
}

//-----08 第Level=2關(2顆設定燈):------
void Level_2(){
  RingLED.clear();//清除燈號
  led_run_at=0;//跑馬燈歸零
    //-----第2關遊戲迴圈
    while (GameState == 2) { 
      period = RingSpeed[Speed];  //取速度值陣列內容
              //---由燈數中,隨機取1顆--->再延伸左右各1形成2個燈
              if (millis()-Time_Get > period){ //延時 (亮燈週期過了,再重設週期)
                    Time_Get = millis(); // 擷取當下時間放入Time_Get
                    if(Go_Play==true){ //Go_Play為true,可以取設定點(亂數)
                      Setting_Led = random(NUMLEDS); 
                      Go_Play = false; //隨機設定號燈完畢,等待按鈕!
                    }
              //---設定2個點[][]---------------------------------
                    //====以下亮2個號燈(以16個燈為例:處理跨界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);//檢查按鈕是否被按下?      
                }
    }
}

//-----09 第Level=3關(1顆設定燈):------
void Level_3(){
  RingLED.clear();//清除燈號
  led_run_at=0;//跑馬燈歸零
  //-----第3關遊戲迴圈
    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; //隨機設定號燈完畢,回歸,等待按鈕!
                    }
              //---設定2個點[][]---------------------------------
                    //====以下亮1個號燈====
                    Set_Led[0]=Setting_Led; 
                    RingLED.setPixelColor(Set_Led[0], 0, 255, 0);//(綠)
                    RingLED.show(); 
                    LED_Runing();//呼叫跑馬燈
                    Check_Push(GameState);//檢查按鈕是否被按下?         
                }
    }
}

//----10 跑馬燈函式 ----
void LED_Runing(){
    led_run_at++; //循環燈...往下累加
  if (led_run_at >= NUMLEDS) { //如果循環紅點位置=燈數(符合則歸零)
    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();
}

//----11 檢查按鈕是被按(檢查是否得分?)-------
void Check_Push(byte LV){ //Go_Play == false為等待的意思
  if (digitalRead(KEY_PUSH) == LOW && Go_Play == false ) { //按鈕被按下去,往下做
  delay(1000);//延時
  Go_Play=true;
  //----得分-------
  if(LV==1){ //第1關:3個燈選中其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){ //第2關:2個燈選中其1,則得分
  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){ //第3關:1個燈選中,則得分
  if (Set_Led[0]==led_run_at) { 
        Score++;
        ScreLed(Score,550);//呼叫計分燈號函式(累計得分,高音頻)
       }
  else{ScreLed(Score,150);}//呼叫計分燈號函式(不累計,低音頻)
  }
	//---切換速度陣列[][][][]--------
	  Speed++; //換下個檔速
	  //若4種檔速完成,換下一關
	  if(Speed==4){
		//Serial.println("-");
		GameState++;//下一關
		if(GameState==4){GameState=0; Go_Play=false;Score=0;}//3大關全部完成
		Speed=0;   
		PlayFamily(); 
		}
  } 
}

//----12 計分燈號(黃燈)+鳴(函式)----
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();//清除燈號	
}
//-----------------------------------------------------------
//----13 秀"亂數燈(彩色燈)"----
void Z_Random(){
for (byte i = 0; i < NUMLEDS; i++) { //環燈號訊號
        RingLED.setPixelColor(i, random(0, 255), random(0, 255), random(0, 255));//0~255隨機取數
        delay(15);
        RingLED.show(); 
    }
}

//----14 演奏"星際爭霸"音樂----
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);// 音符之間的間隔
  }
}

//----15 演奏"全家音樂"----
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);// 音符之間的間隔
  }
}

//----16 外部中斷PB2腳(紅)按鈕被觸發1.白光 2.閃白光 3.閃紅光 4.閃紅光+鳴 5.軟體重啟
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();
          }
  }
}

//----17 音樂播放函式(傳音符[頻率],聲音長度)
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-led-20250222.zip
(4.19 KiB) 已下載 1 次
cajhbb
系統管理員
文章: 993
註冊時間: 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
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

焊接接腳

文章 cajhbb »

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

開關接腳

文章 cajhbb »

開關.jpg
開關.jpg (46.86 KiB) 已瀏覽 73 次
按鈕.jpg
按鈕.jpg (54.05 KiB) 已瀏覽 72 次
2025-02-27-090930.jpg
2025-02-27-090930.jpg (29.2 KiB) 已瀏覽 29 次
cajhbb
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

程式區

文章 cajhbb »

全部程式.pdf
(257.62 KiB) 已下載 1 次
全部程式.txt
(14.24 KiB) 尚未被下載
全部程式-省電版.pdf
(247.11 KiB) 尚未被下載
全部程式-省電版.txt
(14.57 KiB) 已下載 2 次
全部程式-省電版-A-教學.txt
(13.58 KiB) 尚未被下載
回覆文章