17/11/2567

ปีการศึกษา 2567 ภาคเรียนที่ 2 ครูเต้ง เทคโนฯ ระบบวงจร NeoPixel Ring

 📣ความรู้ไปประยุกต์ใช้อุปกรณ์อิเล็กทรอนิกส์เพื่อสร้างสรรค์เป็นโครงงานตามที่โจทย์กำหนดได้วงจร


📣ความรู้ไปประยุกต์ใช้อุปกรณ์อิเล็กทรอนิกส์เพื่อสร้างสรรค์เป็นโครงงานตามที่โจทย์กำหนดได้คำสั่งเขียน 

#include <Adafruit_NeoPixel.h>
#ifdef __AVR_ATtiny85__
#define PIN_NEOPIXEL 1
#define PIN_IR       2
#define PIN_SWITCH   3
#else
#define PIN_IR_VCC   2
#define PIN_IR_GND   3
#define PIN_IR       4
#define PIN_NEOPIXEL 5
#define PIN_SWITCH   6
#endif
#define NEOPIXEL_COUNT 12

#define MODE_SOLID 0
#define MODE_SLOW_RAINBOW 1
#define MODE_SPIRAL_RAINBOW 2
#define MODE_WHITE 3
#define MODE_MAX 3

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NEOPIXEL_COUNT, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);

volatile unsigned long irValue = 0;
volatile bool irAvailable = false;

#ifdef __AVR_ATtiny85__
ISR(PCINT0_vect)       // interrupt service routine
#else // Assume regular Arduino
ISR (PCINT2_vect)
#endif
{          // called when PCINT0 changes state
  static unsigned long irIntermediate = 0;
  static int irBits = 0;
  static unsigned long lastTime = 0;
  unsigned long now = micros();
  unsigned long delta = now - lastTime;
  lastTime = now;
  if (delta > 20000) {
    irIntermediate = 0;
    irBits = 0;
  } else if (digitalRead(PIN_IR) == LOW) { // Low-to-high transition
    irIntermediate <<= 1;
    irIntermediate |= (delta > 800) ? 1 : 0;
    ++irBits;
    if (irBits == 33) {
      irValue = irIntermediate;
      irAvailable = true;
    }
  }
   return;
}

void hsvToRgb(int hue, int saturation, int brightness, int& red, int& green, int& blue) {
  int base;
  int hexant;
  int shade;
 
  if (saturation == 0) { // Acromatic color (gray). Hue doesn't matter.
    red = green = blue = brightness;
  } else {
    base = ((255 - saturation) * brightness) >> 8;
    hexant = hue / 60;
    shade = (hexant & 1)
      ? (((brightness - base) * (60 - (hue % 60))) / 60) + base
      : (((brightness - base) * (hue % 60)) / 60) + base;
 
    switch(hexant) {
      case 0:
        red = brightness;
        green = shade;
        blue = base;
        break;
      case 1:
        red = shade;
        green = brightness;
        blue = base;
        break;
      case 2:
        red = base;
        green = brightness;
        blue = shade;
        break;
      case 3:
        red = base;
        green = shade;
        blue = brightness;
        break;
      case 4:
        red = shade;
        green = base;
        blue = brightness;
        break;
      case 5:
        red = brightness;
        green = base;
        blue = shade;
        break;
    }
  }
}

void rgbToHsv(int red, int green, int blue, int& hue, int& saturation, int& brightness) {
  int min;
  int max;
  int delta;
  
  min = (red <= green & red <= blue) ? red : (green <= blue) ? green : blue;
  max = (red >= green & red >= blue) ? red : (green >= blue) ? green : blue;
  brightness = max; // Brightness

  delta = max - min;
  if (max != 0) {
  saturation = 255 * delta / max; // Saturation
  } else {
  // r = g = b = 0    // s = 0, v is undefined
    saturation = 0;
    hue = 0;
    return;
  }
  
  if (red == max) {
    hue = 60 * (green - blue) / delta;    // between yellow & magenta
  } else if (green == max) {
    hue = 120 + 60 * (blue - red) / delta;  // between cyan & yellow
  } else {
    hue = 240 + (red - green) / delta;  // between magenta & cyan
  }
  if (hue < 0) {
    hue += 360;
  }
}

void setPixelColor(int n, unsigned char red, unsigned char green, unsigned char blue, unsigned int brightness = 256) {
  if (brightness >= 256) {
    strip.setPixelColor(n, red, green, blue);
  } else {
    strip.setPixelColor(n,
      (((unsigned int)red) * brightness) >> 8,
      (((unsigned int)green) * brightness) >> 8,
      (((unsigned int)blue) * brightness) >> 8
    );
  }
}

void setPixelHueSat(int index, int hue, int saturation, int brightness) { 
  int red;
  int green;
  int blue;
  hsvToRgb(hue, saturation, brightness, red, green, blue); 
  strip.setPixelColor(index, red, green, blue); 
}

int bound(int value, int max = 255, int min = 0) {
  return (value > max) ? max : (value < min) ? min : value;
}

void setup() {
  pinMode(PIN_SWITCH, INPUT);     // Switch is input
  digitalWrite(PIN_SWITCH, HIGH); // enable internal pullup

#ifdef PIN_IR_GND
  pinMode(PIN_IR_GND, OUTPUT);
  digitalWrite(PIN_IR_GND, LOW);
#endif
#ifdef PIN_IR_VCC
  pinMode(PIN_IR_VCC, OUTPUT);
  digitalWrite(PIN_IR_VCC, HIGH);
#endif

  strip.begin();
  strip.show();
  
  pinMode(PIN_IR, INPUT);

#ifdef __AVR_ATtiny85__
  PCMSK |= (1<<PCINT2); // pin change mask: listen to portb bit 3
  GIMSK |= (1<<PCIE); // enable PCINT interrupt 
  sei();      // enable all interrupts
#else // Assume full Arduino
  *digitalPinToPCMSK(PIN_IR) |= bit (digitalPinToPCMSKbit(PIN_IR));  // enable pin
  PCIFR  |= bit (digitalPinToPCICRbit(PIN_IR)); // clear any outstanding interrupt
  PCICR  |= bit (digitalPinToPCICRbit(PIN_IR)); // enable interrupt for the group
  Serial.begin(9600);
  Serial.println("\nStarting...\n");
#endif
}

void loop() {
  static int mode = MODE_SPIRAL_RAINBOW;
  static int lastButton = HIGH;
  
  static int hue = 0;
  static int saturation = 255;
  static int brightness = 128;
  static int timeIndex = 0;
  static int speed = 100;
  
  int red;
  int green;
  int blue;  
  
  if (irAvailable) {
    irAvailable = false;
    switch (irValue) {
      
      // DFRobot remote
      case 0xFD30CF: if (++mode > MODE_MAX) mode = 0; break;                // "0"
      case 0xFD08F7: brightness += 17; if (brightness > 255) brightness = 255; break;       // "1"
      case 0xFD8877: brightness -= 17; if (brightness < 0) brightness = 0; break;     // "2"
      case 0xFD48B7: hue -= 5; if (hue < 0) hue += 360; break;     // "3"
      case 0xFD28D7: hue += 5; if (hue >= 360) hue -= 360; break;     // "4"
      case 0xFDA857: speed += 5; if (speed > 100) speed = 100; break;   // "5"
      case 0xFD6897: speed -= 5; if (speed < 5) speed = 5; break;   // "6"
      case 0xFD18E7: break;      // "7"  
/*      
      case 0xFD9867: // "8"
        {
          hsvToRgb(hue, saturation, brightness, red, green, blue);
          red = (red >= 17) ? red - 17 : 0;
          rgbToHsv(red, green, blue, hue, saturation, brightness);
        }
        break;    
      case 0xFD58A7: // "9"
        {
          hsvToRgb(hue, saturation, brightness, red, green, blue);
          red = (red >= 17) ? red - 17 : 0;
          rgbToHsv(red, green, blue, hue, saturation, brightness);
        }
        break;
*/
      // IPOD Remote
//      case 0x77E1D05A: saturation += 17; if (saturation > 255) saturation = 255; break;     // UP         77E1D05A
//      case 0x77E1B05A: saturation -= 17; if (saturation < 0) saturation = 0; break;       // DOWN       77E1B05A
      case 0x77E1D05A: brightness += 17; if (brightness > 255) brightness = 255; break;     // UP         77E1D05A
      case 0x77E1B05A: brightness -= 17; if (brightness < 0) brightness = 0; break;       // DOWN       77E1B05A
      case 0x77E1E05A: hue -= 15; if (hue < 0) hue += 360; break;   // RIGHT      77E1E05A
      case 0x77E1105A: hue += 15; if (hue >= 360) hue -= 360; break;     // LEFT       77E1105A
      case 0x77E17A5A: speed += 5; if (speed > 100) speed = 100; break; // PLAY/PAUSE 77E17A5A / 77E1205A
      case 0x77E1405A: speed -= 5; if (speed < 5) speed = 5; break;   // MENU       77E1405A
      case 0x77E1BA5A: if (++mode > MODE_MAX) mode = 0; break;                                  // SELECT     77E1BA5A / 77E1205A
/*
      // LED 44-button remote
      case 0xFF3AC5: // Brighter
        brightness = bound(brightness + 5);
        break;
      case 0xFFBA45: // Dimmer
        brightness = bound(brightness - 5);
        break;
      case 0xFF827D: break; // Play
      case 0xFF02FD: break; // Power on/off
      case 0xFF1AE5: saturation = 255; hue = 0; break;   // Red
      case 0xFF2AD5: saturation = 255; hue = 15; break;  // Red-Orange
      case 0xFF0AF5: saturation = 255; hue = 30; break;  // Orange
      case 0xFF38C7: saturation = 255; hue = 45; break;  // Yellow-orange
      case 0xFF18E7: saturation = 255; hue = 60; break;  // Yellow
      case 0xFF9A65: saturation = 255; hue = 120; break; // Green
      case 0xFFAA55: saturation = 255; hue = 135; break; // Green-blue
      case 0xFF8A75: saturation = 255; hue = 150; break; // Aqua
      case 0xFFB847: saturation = 255; hue = 165; break; // Blue-green
      case 0xFF9867: saturation = 255; hue = 180; break; // Cyan
      case 0xFFA25D: saturation = 255; hue = 240; break; // Blue
      case 0xFF926D: saturation = 255; hue = 120; break; // Periwinkle
      case 0xFFB24D: saturation = 255; hue = 120; break; // Purple
      case 0xFF7887: saturation = 255; hue = 120; break; // Purple/Red
      case 0xFF58A7: saturation = 255; hue = 120; break; // Magenta
      case 0xFF22DD: saturation = 0; break;              // White
      case 0xFF12ED:                                     // Pink1
      case 0xFF32CD: saturation = 127; hue = 0; break;   // Pink2
      case 0xFFF807:                                     // PaleBlue1
      case 0xFFD827: saturation = 127; hue = 240; break; // PaleBlue2
      case 0xFF28D7: // Red Up
        hsvToRgb(hue, saturation, brightness, red, green, blue);
        red = bound(red + 17);
        rgbToHsv(red, green, blue, hue, saturation, brightness);
        break;
      case 0xFF08F7: // Red Down
        hsvToRgb(hue, saturation, brightness, red, green, blue);
        red = bound(red - 17);
        rgbToHsv(red, green, blue, hue, saturation, brightness);
        break;
      case 0xFFA857: // Green Up
        hsvToRgb(hue, saturation, brightness, red, green, blue);
        green = bound(green + 17);
        rgbToHsv(red, green, blue, hue, saturation, brightness);
        break;
      case 0xFF8877: // Green Down
        hsvToRgb(hue, saturation, brightness, red, green, blue);
        green = bound(green - 17);
        rgbToHsv(red, green, blue, hue, saturation, brightness);
        break;
      case 0xFF6897: // Blue Up
        hsvToRgb(hue, saturation, brightness, red, green, blue);
        blue = bound(blue + 17);
        rgbToHsv(red, green, blue, hue, saturation, brightness);
        break;
      case 0xFF48B7: // Blue Down
        hsvToRgb(hue, saturation, brightness, red, green, blue);
        blue = bound(blue - 17);
        rgbToHsv(red, green, blue, hue, saturation, brightness);
        break;
      case 0xFF30CF: break; // DIY1
      case 0xFFB04F: break; // DIY2
      case 0xFF708F: break; // DIY3
      case 0xFF10EF: break; // DIY4
      case 0xFF906F: break; // DIY5
      case 0xFF50AF: break; // DIY6
      case 0xFFE817: break; // Quick
      case 0xFFC837: break; // Slow
      case 0xFFF00F: break; // Auto
      case 0xFFD02F: break; // Flash
      case 0xFF20DF: break; // Jump3
      case 0xFFA05F: break; // Jump7
      case 0xFF609F: break; // Fade3
      case 0xFFE01F: break; // Fade7      
*/
    }
#ifndef __AVR_ATtiny85__
    Serial.println(irValue, HEX);
#endif
  }
  
  strip.clear();
  int i;
  if (mode == MODE_WHITE) {
    for (i = 0; i < NEOPIXEL_COUNT; ++i) {
      setPixelHueSat(i, hue, 32, brightness);
    }
  } else if (mode == MODE_SLOW_RAINBOW) {
    for (i = 0; i < NEOPIXEL_COUNT; ++i) {
      setPixelHueSat(i, hue, saturation, brightness);
    }
    hue += 5;
    if (hue >= 360) hue = 0;
  } else if (mode == MODE_SOLID) {
    for (i = 0; i < NEOPIXEL_COUNT; ++i) {
      setPixelHueSat(i, hue, saturation, brightness);
    }    
  } else if (mode == MODE_SPIRAL_RAINBOW) {
    for (i = 0; i < NEOPIXEL_COUNT; ++i) {
      setPixelHueSat((i + timeIndex) % NEOPIXEL_COUNT, i * 360 / NEOPIXEL_COUNT, saturation, brightness); 
    }
    if (++timeIndex >= NEOPIXEL_COUNT) timeIndex = 0;
  }
  strip.show();
  
  // Handle button pushes
  if (digitalRead(PIN_SWITCH) == LOW) {
    if (lastButton == HIGH) {
      if (++mode > MODE_MAX) mode = 0;
    }
    lastButton = LOW;
  } else {
    lastButton = HIGH;
  }

  delay(speed);
}

ไม่มีความคิดเห็น:

แสดงความคิดเห็น

ครูเต้ง เทคโนฯ