// GNP_TreeLamp
// 10 NeoPixel Ring 16/each
#include <LCD_I2C.h>
#include <Adafruit_NeoPixel.h>
LCD_I2C lcd(0x27, 16, 2); // Default address of most PCF8574 modules, change according
#define LED_PIN 13
#define LED_TOTAL_COUNT 160
Adafruit_NeoPixel strip(LED_TOTAL_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); // 宣告 NeoPixel 物件,包含十組 LED
unsigned long previousMillis = 0;
unsigned long ADCpreviousMillis = 0;
unsigned long checkSwitchPreviousMillis = 0;
bool _serialDebugMode = false; // true or false
unsigned long _breatheInterval = 10;
unsigned long _ADCInterval = 3000;
unsigned long _checkSwitchInterval = 1000;
int _prizeW1 = 10;
int _prizeY2 = 50; // 欲設定的數值需手動加上_prizeW1取合 ex:40則為40+_prizeW1
int _prizeG3 = 50;
int _totalPrize = 100;
int _allUpSpeed = 20; // g1 y2 r3 prize all lamp lighting all the way up
int _brightnessLimit = 255; // max is 255 , half is 125
int bS = 3; // breatheSpeed, led vaule step (0~255 step)
int _lampActiveSpeed = 50; //放上杯子後繞一圈的燈速 delay time
int _allOffUpDelay = 2000 ; //整棵樹由下到上熄燈後等待多久回到呼吸燈
int _checkSwitchStateDelay = 10 ; // 檢查杯子是否有移開的delay time
int brightness[11] = {0, 25, 100, 200, 75, 250, 125, 50, 225, 150, 0};
int increment[11] = {bS, bS, bS, bS, bS, bS, bS, bS, bS, bS, bS};
int LED_SetStart[11] {0, 0, 16, 32, 48, 64, 80, 96, 112, 128, 144}; // 10 NeoPixel Ring 16/each
int LED_SetEnd[11] {0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160}; // 第0位址捨棄不用比較直觀
int swPin[10] { 32, 33, 25, 26, 27, 14, 12, 19, 18, 5}; //陣列位址從0算起
String TreeLampMode = "standyby";
byte sw1 = swPin[0]; byte sw2 = swPin[1]; byte sw3 = swPin[2]; byte sw4 = swPin[3];
byte sw5 = swPin[4]; byte sw6 = swPin[5]; byte sw7 = swPin[6]; byte sw8 = swPin[7];
byte sw9 = swPin[8]; byte sw10 = swPin[9];
bool sw1state = false; bool sw2state = false; bool sw3state = false; bool sw4state = false;
bool sw5state = false; bool sw6state = false; bool sw7state = false; bool sw8state = false;
bool sw9state = false; bool sw10state = false;
int _ADC1 = 4096;
int _ADC1map = 255;
int w1Count = 0; // 記錄g1的出現次數
int y2Count = 38; // 記錄y2的出現次數
int g3Count = 0; // 記錄r3的出現次數
int totalCount = 0;
String _countCode = "";
void setup() {
strip.begin();
Serial.begin(9600);
// 初始化 NeoPixel
for (int i = 0; i < 10; i++) {
pinMode(swPin[i], INPUT_PULLUP);
}
// randomSeed(analogRead(A0)); // 設定亂數種子
lcd.begin();
lcd.backlight();
// lcd.noBacklight();
lcd.clear();
lcd1602();
}
void loop() {
unsigned long currentMillis = millis();
unsigned long ADCcurrentMillis = millis();
unsigned long checkSwitchCurrentMillis = millis();
checkSwitch();
// 呼叫呼吸燈函式
if (TreeLampMode == "standyby") {
if (currentMillis - previousMillis >= _breatheInterval) {
previousMillis = currentMillis;
breatheLED(); // 呼叫呼吸燈函式
}
}
// 每秒檢查是否有杯子從杯架上移開
if (checkSwitchCurrentMillis - checkSwitchPreviousMillis >= _checkSwitchInterval) {
checkSwitchPreviousMillis = checkSwitchCurrentMillis;
checkSwitchState();
}
// 每三秒檢查一次是否可變電阻1(樹燈亮度設定)有被改變
if (ADCcurrentMillis - ADCpreviousMillis >= _ADCInterval) {
ADCpreviousMillis = ADCcurrentMillis;
_ADC1 = analogRead(36); // GIOP36
_ADC1map = map(_ADC1, 0, 4095, 100, 255);
// if (_serialDebugMode) Serial.print("ADC1map: ");
// if (_serialDebugMode) Serial.print(_ADC1map);
// if (_serialDebugMode) Serial.print(" _brightnessLimit: ");
// if (_serialDebugMode) Serial.println(_brightnessLimit);
lcd1602();
}
}
void lcd1602() {
lcd.setCursor(0, 0);
lcd.print("Br:"); lcd.print(_brightnessLimit);
lcd.print(" TOT:"); lcd.print(totalCount);
lcd.setCursor(0, 1);
lcd.print("W:"); lcd.print(w1Count); lcd.print(" y:"); lcd.print(y2Count);
lcd.print(" g:"); lcd.print(g3Count); lcd.print(" ");
lcd.print(_countCode); lcd.print(" ");
}
void randomPrize(int lampNum) {
// 開始亂數抽獎
// int randomNum = random(1, _totalPrize);
int _randomFilterValue;
if (w1Count <= 9 && y2Count <= 39 && g3Count <= 49) {
_countCode = "all";
}
else if (w1Count >= 10 && y2Count <= 39 && g3Count <= 49) {
_countCode = "a";
}
else if (w1Count <= 9 && y2Count >= 40 && g3Count <= 49) {
_countCode = "b";
}
else if (w1Count <= 9 && y2Count <= 39 && g3Count >= 50) {
_countCode = "c";
}
else if (w1Count >= 10 && y2Count >= 40 && g3Count <= 49) {
_countCode = "ab";
}
else if (w1Count >= 10 && y2Count <= 39 && g3Count >= 50) {
_countCode = "ac";
}
else if (w1Count <= 9 && y2Count >= 40 && g3Count >= 50) {
_countCode = "bc";
}
else if (w1Count >= 10 && y2Count >= 40 && g3Count >= 50) {
_countCode = "end";
}
if (_countCode == "all") {
_randomFilterValue = random(1, 101);
} else if (_countCode == "a") {
_randomFilterValue = random(11, 101);
} else if (_countCode == "b") {
do {
_randomFilterValue = random(1, 101);
} while (_randomFilterValue >= 11 && _randomFilterValue <= 50);
// int option = random(1, 3);
// if (option == 1) {
// _randomFilterValue = random(1, 11);
// } else {
// _randomFilterValue = random(51, 101);
// }
} else if (_countCode == "c") {
_randomFilterValue = random(1, 51);
} else if (_countCode == "ab") {
_randomFilterValue = random(51, 101);
} else if (_countCode == "ac") {
_randomFilterValue = random(11, 51);
} else if (_countCode == "bc") {
_randomFilterValue = random(1, 11);
} else {
_randomFilterValue = random(51, 101); // _countCode 不符合上述任何條件時跑三獎
return;
}
if (_serialDebugMode) Serial.print("_randomFilterValue = ");
if (_serialDebugMode) Serial.println(_randomFilterValue);
if (_randomFilterValue <= _prizeW1) { // 如果隨機數字小於等於_prizeW1,則顯示頭獎
w1Count ++ ;
w1prizeshow(lampNum); // 開始跑頭獎(白燈)流程
} else if (_randomFilterValue <= _prizeY2) { // 如果隨機數字小於等於_prizeY2,則顯示二獎
y2Count ++ ;
y2prizeshow(lampNum); //開始跑二獎(黃燈)流程
} else {
g3Count ++ ;
g3prizeshow(lampNum); // 其他情況開始跑三獎(綠燈)流程
}
totalCount = w1Count + y2Count + g3Count ;
String Str_totalCount = String(totalCount);
String Str_w1Count = String(w1Count);
String Str_y2Count = String(y2Count);
String Str_g3Count = String(g3Count);
if (_serialDebugMode) Serial.print("w1=" + Str_w1Count + " y2=" + Str_y2Count + " g3=" + Str_g3Count);
if (_serialDebugMode) Serial.println(" totalCount=" + Str_totalCount + " countCode=" + _countCode);
}
void checkSwitch() {
// check sw1
if (digitalRead(sw1) == LOW && sw1state == false ) {
TreeLampMode = "sw1";
if (_serialDebugMode) Serial.println("press #1");
sw1state = true;
int lampNum = 1; // this lampNum is sw1 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw2
if (digitalRead(sw2) == LOW && sw2state == false ) {
TreeLampMode = "sw2";
if (_serialDebugMode) Serial.println("press #2");
sw2state = true;
int lampNum = 2; // this lampNum is sw1 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw3
if (digitalRead(sw3) == LOW && sw3state == false) {
TreeLampMode = "sw3";
if (_serialDebugMode) Serial.println("press #3");
sw3state = true;
int lampNum = 3; // this lampNum is sw1 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw4
if (digitalRead(sw4) == LOW && sw4state == false ) {
TreeLampMode = "sw4";
if (_serialDebugMode) Serial.println("press #4");
sw4state = true;
int lampNum = 4; // this lampNum is sw1 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw5
if (digitalRead(sw5) == LOW && sw5state == false) {
TreeLampMode = "sw5";
if (_serialDebugMode) Serial.println("press #5");
sw5state = true;
int lampNum = 5; // this lampNum is sw1 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw6
if (digitalRead(sw6) == LOW && sw6state == false ) {
TreeLampMode = "sw6";
if (_serialDebugMode) Serial.println("press #6");
sw6state = true;
int lampNum = 6; // this lampNum is sw1 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw7
if (digitalRead(sw7) == LOW && sw7state == false) {
TreeLampMode = "sw7";
if (_serialDebugMode) Serial.println("press #7");
sw7state = true;
int lampNum = 7; // this lampNum is sw7 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw8
if (digitalRead(sw8) == LOW && sw8state == false ) {
TreeLampMode = "sw8";
if (_serialDebugMode) Serial.println("press #8");
sw8state = true;
int lampNum = 8; // this lampNum is sw8 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw9
if (digitalRead(sw9) == LOW && sw9state == false) {
TreeLampMode = "sw9";
if (_serialDebugMode) Serial.println("press #9");
sw9state = true;
int lampNum = 9; // this lampNum is sw9 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
// check sw10
if (digitalRead(sw10) == LOW && sw10state == false) {
TreeLampMode = "sw10";
if (_serialDebugMode) Serial.println("press #10");
sw10state = true;
int lampNum = 10; // this lampNum is sw1 been press(put cup)
allLampOff();
randomPrize(lampNum);
}
}
void checkSwitchState() {
if (sw1state == true ) {
if (digitalRead(sw1) == HIGH ) {
sw1state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw2state == true ) {
if (digitalRead(sw2) == HIGH ) {
sw2state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw3state == true ) {
if (digitalRead(sw3) == HIGH ) {
sw3state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw4state == true ) {
if (digitalRead(sw4) == HIGH ) {
sw4state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw5state == true ) {
if (digitalRead(sw5) == HIGH ) {
sw5state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw6state == true ) {
if (digitalRead(sw6) == HIGH ) {
sw6state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw7state == true ) {
if (digitalRead(sw7) == HIGH ) {
sw7state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw8state == true ) {
if (digitalRead(sw8) == HIGH ) {
sw8state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw9state == true ) {
if (digitalRead(sw9) == HIGH ) {
sw9state = false;
delay(_checkSwitchStateDelay);
}
}
if (sw10state == true ) {
if (digitalRead(sw10) == HIGH ) {
sw10state = false;
delay(_checkSwitchStateDelay);
}
}
// if (digitalRead(sw1) == HIGH && sw1state == true ) {
// sw1state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw2) == HIGH && sw2state == true ) {
// sw2state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw3) == HIGH && sw3state == true ) {
// sw3state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw4) == HIGH && sw4state == true ) {
// sw4state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw5) == HIGH && sw5state == true ) {
// sw5state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw6) == HIGH && sw6state == true ) {
// sw6state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw7) == HIGH && sw7state == true ) {
// sw7state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw8) == HIGH && sw8state == true ) {
// sw8state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw9) == HIGH && sw9state == true ) {
// sw9state = false;
// delay(_checkSwitchStateDelay);
// }
// if (digitalRead(sw10) == HIGH && sw10state == true ) {
// sw10state = false;
// delay(_checkSwitchStateDelay);
// }
}
void w1prizeshow(int lampSet) {
// lamp 繞綠圈表示放入杯子
for (int i = LED_SetStart[lampSet]; i < LED_SetEnd[lampSet]; i++) {
strip.setPixelColor(i, strip.Color(0, _brightnessLimit, 0));
strip.show();
delay(_lampActiveSpeed);
}
allWhiteUp(lampSet);
}
void y2prizeshow(int lampSet) {
// lamp 繞綠圈表示放入杯子
for (int i = LED_SetStart[lampSet]; i < LED_SetEnd[lampSet]; i++) {
strip.setPixelColor(i, strip.Color(0, _brightnessLimit, 0));
strip.show();
delay(_lampActiveSpeed);
}
allYellowUp(lampSet);
}
void g3prizeshow(int lampSet) {
// lamp 繞綠圈表示放入杯子
for (int i = LED_SetStart[lampSet]; i < LED_SetEnd[lampSet]; i++) {
strip.setPixelColor(i, strip.Color(0, _brightnessLimit, 0));
strip.show();
delay(_lampActiveSpeed);
}
allGreenUp(lampSet);
}
void allWhiteUp(int exclude) {
// 一組一組往上亮,漸層感差,時間也拖太久
for (int w = 10; w > 0; w--) {
// if (w == exclude) {
// continue; // 跳過指定的exclude,繼續下一個迴圈
// }
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[w]; i < LED_SetEnd[w]; i++) {
strip.setPixelColor(i, strip.Color(b, b, b));
}
strip.show();
}
}
allWhiteOffUp(exclude);
}
void allWhiteOffUp(int exclude) {
// 一組一組往上亮,漸層感差,時間也拖太久
for (int w = 10; w > 0; w--) {
if (w == exclude) {
continue; // 跳過指定的exclude,繼續下一個迴圈
}
for (int b = _brightnessLimit; b > 0; b = b - _allUpSpeed) {
for (int i = LED_SetStart[w]; i < LED_SetEnd[w]; i++) {
strip.setPixelColor(i, strip.Color(b, b, b));
}
strip.show();
}
}
delay(_allOffUpDelay);
TreeLampMode = "standyby";
}
void allYellowUp(int exclude) {
// 一組一組往上亮,漸層感差,時間也拖太久
for (int w = 10; w > 0; w--) {
// if (w == exclude) {
// continue; // 跳過指定的exclude,繼續下一個迴圈
// }
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[w]; i < LED_SetEnd[w]; i++) {
strip.setPixelColor(i, strip.Color(b, b, 0));
}
strip.show();
}
}
allYellowOffUp(exclude);
}
void allYellowOffUp(int exclude) {
// 一組一組往上亮,漸層感差,時間也拖太久
for (int w = 10; w > 0; w--) {
if (w == exclude) {
continue; // 跳過指定的exclude,繼續下一個迴圈
}
for (int b = _brightnessLimit; b > 0; b = b - _allUpSpeed) {
for (int i = LED_SetStart[w]; i < LED_SetEnd[w]; i++) {
strip.setPixelColor(i, strip.Color(b, b, 0));
}
strip.show();
}
}
delay(_allOffUpDelay);
TreeLampMode = "standyby";
}
void allGreenUp(int exclude) {
// 一組一組往上亮,漸層感差,時間也拖太久
for (int w = 10; w > 0; w--) {
// if (w == exclude) {
// continue; // 跳過指定的exclude,繼續下一個迴圈
// }
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[w]; i < LED_SetEnd[w]; i++) {
strip.setPixelColor(i, strip.Color(0, b, 0));
}
strip.show();
}
}
allGreenOffUp(exclude);
}
void allGreenOffUp(int exclude) {
// 一組一組往上亮,漸層感差,時間也拖太久
for (int w = 10; w > 0; w--) {
if (w == exclude) {
continue; // 跳過指定的exclude,繼續下一個迴圈
}
for (int b = _brightnessLimit; b > 0; b = b - _allUpSpeed) {
for (int i = LED_SetStart[w]; i < LED_SetEnd[w]; i++) {
strip.setPixelColor(i, strip.Color(0, b, 0));
}
strip.show();
}
}
delay(_allOffUpDelay);
TreeLampMode = "standyby";
}
void allLampOff() {
for (int i = 0; i < LED_TOTAL_COUNT; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
delay(300);
}
void LampSelectOff(int LampSelect) {
switch (LampSelect) {
case 0:
break;
case 1:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[1]; i < LED_SetEnd[1]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 2:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[2]; i < LED_SetEnd[2]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 3:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[3]; i < LED_SetEnd[3]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 4:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[4]; i < LED_SetEnd[4]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 5:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[5]; i < LED_SetEnd[5]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 6:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[6]; i < LED_SetEnd[6]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 7:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[7]; i < LED_SetEnd[7]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 8:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[8]; i < LED_SetEnd[8]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 9:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[9]; i < LED_SetEnd[9]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
case 10:
for (int b = 0; b < _brightnessLimit; b = b + _allUpSpeed) {
for (int i = LED_SetStart[10]; i < LED_SetEnd[10]; i++) {
strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}
break;
}
}
void breatheLED() {
if (_brightnessLimit >= _ADC1map) _brightnessLimit = _brightnessLimit - 1;
if (_brightnessLimit <= _ADC1map) _brightnessLimit = _brightnessLimit + 1;
for (int i = 1 ; i < 11 ; i++) { // 亮度遞增(或遞減)
brightness[i] = brightness[i] + increment[i];
}
for (int i = 1 ; i < 11 ; i++) { // 判斷亮度是否小於0或大於上限,如是,反向
if (brightness[i] <= 0 ) {
brightness[i] = 0;
increment[i] = -increment[i];
}
if (brightness[i] >= _brightnessLimit) {
brightness[i] = _brightnessLimit;
increment[i] = -increment[i];
}
}
for (int q = 1 ; q < 11; q ++) { // q是10個燈組
for (int i = LED_SetStart[q]; i < LED_SetEnd[q]; i++) {
strip.setPixelColor(i, strip.Color(0, brightness[q], 0));
}
}
strip.show();
}