본문 바로가기
아두이노 프로젝트

Arduino HID 초음파 볼륨 컨트롤 (미디어 컨트롤러)

by 다이올 2024. 10. 17.
반응형

프로젝트 소개

안녕하세요, 친구들! 우리는 다양한 작업에 키보드를 사용하지만, 미디어 제어와 밝기 조정 같은  가지 키를 다른 사람들보다  자주 사용합니다. 중요한 작업에 깊이 집중하는 경우, 계속해서 키보드에 손을 뻗고 싶지 않을 때가 있습니다. 이를 해결하기 위해 맞춤형 핸즈프리 솔루션을 제공하는 미디어 컨트롤 시스템을 만들기로 결정했습니다.

Arduino Pro Micro를 사용하여  시스템을 구축했습니다.  소형 마이크로 컨트롤러는 HID(Human Interface Device) 기능이 내장되어 있어 키보드, 마우스 또는 미디어 컨트롤러로 쉽게 작동할  있습니다. 추가 소프트웨어가 필요 없이 컴퓨터에 연결하기만 하면 준비 완료!

필요한 구성 요소

  • Arduino Pro Micro: HID 응용 프로그램에 적합
  • 초음파 센서: 손의 제스처를 감지하여 볼륨 조절
  • TP223 터치 센서: 추가 미디어 제어 기능 제공
  • 16비트 Neopixel : 시각적 피드백 제공
  • 7세그먼트 TM1637 디스플레이: 현재 볼륨 레벨 표시
  • 저항기, 전선, 브레드보드  납땜 도구

초음파 센서의 역할

초음파 센서는 손을  가까이 또는  멀리 움직여 볼륨을 조절합니다. 센서의 범위는 최대 60cm이며, 부드럽고 반응이 빠른 제어가 가능합니다.

TP223 터치 센서

TP223 정전식 터치 센서는 매우 민감하며, 터치를 통해 트랙 건너뛰기, 이전 트랙으로 돌아가기, 음소거 또는 일시 중지 등의 추가 제어 기능을 제공합니다.

Neopixel 링의 시각적 피드백

Neopixel 링은 컨트롤과 상호 작용할 때마다 아름다운 조명 애니메이션을 제공합니다. 예를 들어, 트랙을 건너뛸  링이 다채로운 회전 애니메이션으로 빛나며 훨씬  매력적인 경험을 제공합니다.

회로도  배선도

다음은  구성 요소를 연결하는 방법에 대한 지침입니다:

  • Arduino와 초음파 센서 연결:
    • VCC -> 5V
    • GND -> GND
    • TRIG -> D3
    • ECHO -> D2
  • Arduino와 TP223 터치 센서 연결:
    • VCC -> 5V
    • GND -> GND
    • SIG -> D4
  • Arduino와 Neopixel  연결:
    • VCC -> 5V
    • GND -> GND
    • Data IN -> D6
  • Arduino와 TM1637 디스플레이 연결:
    • CLK -> D7
    • DIO -> D8
    • VCC -> 5V
    • GND -> GND

소스 코드 예시

cpp
#include <Adafruit_NeoPixel.h>
#include <TM1637Display.h>
#include <HCSR04.h>

#define PIN 6
#define NUMPIXELS 16
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

TM1637Display display(D7, D8);
UltraSonicDistanceSensor distanceSensor(D3, D2);
const int touchPin = 4;

void setup() {
  pinMode(touchPin, INPUT);
  pixels.begin();
  display.setBrightness(0x0f);
  Serial.begin(9600);
}

void loop() {
  int distance = distanceSensor.measureDistanceCm();
  int touchState = digitalRead(touchPin);

  display.showNumberDec(distance, false);
  
  if (distance < 20) {
    pixels.fill(pixels.Color(0, 150, 0), 0, 16);
  } else if (distance < 40) {
    pixels.fill(pixels.Color(150, 150, 0), 0, 16);
  } else {
    pixels.fill(pixels.Color(150, 0, 0), 0, 16);
  }
  pixels.show();
  
  if (touchState == HIGH) {
    // Add code for touch control actions
    Serial.println("Touch detected");
  }

  delay(100);
}

 프로젝트는 창의성을 가미한 실용성을 제공하며, 일반적인 미디어 제어를 대화형  핸즈프리 환경으로 변화시킵니다. 깊이 빠져 일하거나 빈둥거릴   Arduino 기반 미디어 컨트롤러는 오디오 관리를 식은  먹기처럼 쉽게 만듭니다.

 



안녕하세요, 친구들을 환영합니다! 만큼 우리는 다양한 작업에 키보드를 사용하지만 다음과 같은 몇 가지 키가 있습니다. 우리는 다른 사람들보다 더 자주, 특히 미디어 제어를 위해 더 자주 사용합니다. 밝기 조정. 그러나 우리가 깊이 집중하는 경우가 있습니다 중요한 작업이며 조정하기 위해 키보드에 계속 손을 뻗고 싶지 않습니다. 볼륨을 높이거나 트랙을 건너뜁니다. 이것이 바로 맞춤형 핸즈프리 솔루션이 필요한 이유입니다 편리한!

미디어 컨트롤을 만들기로 결정했습니다. Arduino Pro Micro를 사용하는 시스템. 이 소형 마이크로 컨트롤러는 다음과 같은 경우에 적합합니다. HID(Human Interface Device) 기능이 내장되어 있기 때문에 작업, 즉, 키보드, 마우스 또는 미디어 컨트롤러로 쉽게 작동할 수 있습니다 추가 소프트웨어가 필요하지 않습니다. 컴퓨터에 연결하기만 하면 됩니다. 준비 완료!

이 프로젝트를 더욱 발전시키기 위해 직관적이고 사용자 친화적이며 손을 감지하는 초음파 센서를 통합했습니다. 제스처. 센서에서 손을 더 가까이 또는 더 멀리 움직이기만 하면 볼륨을 높이거나 낮출 수 있으므로 매우 쉽게 제어할 수 있습니다. 키보드를 건드리지 않고도 미디어. 센서의 범위는 최대 60cm이며, 부드럽고 반응이 빠른 제어가 가능합니다.

하지만 저는 거기서 멈추지 않았습니다! 나도 건너뛰기와 같은 추가 제어를 위해 터치 감지 TP223 센서가 추가되었습니다. 다음 트랙, 이전 트랙으로 돌아가기, 음소거 또는 일시 중지까지 탭 한 번으로 음악을 들을 수 있습니다. 이 정전식 센서는 매우 민감하며 작동합니다 Arduino Pro Micro와 원활하게 사용할 수 있습니다.

시각적 요소를 추가하려면, I 아름다운 조명 애니메이션을 제공하는 16비트 Neopixel 링을 통합했습니다. 컨트롤과 상호 작용할 때마다. 예를 들어, 로 건너뛸 때 다음 트랙에서는 링이 다채로운 회전 애니메이션으로 빛나며 훨씬 더 매력적인 경험을 하십시오.

마지막으로 4자리 숫자를 포함했습니다. 7세그먼트 TM1637 디스플레이는 현재 볼륨 레벨을 실시간으로 표시합니다. 이 추측할 필요 없이 음악이 얼마나 큰지 항상 정확히 알 수 있습니다.

전반적으로 이 프로젝트는 다음을 결합합니다. 창의성을 가미한 실용성, 일반 미디어 제어를 변화시킵니다. 대화형 및 핸즈프리 환경으로 설정합니다. 당신이 깊이 빠져 있는지 여부 일하거나 그냥 빈둥거리면 이 Arduino 기반 미디어 컨트롤러는 다음을 만듭니다. 오디오 관리는 식은 죽 먹기입니다!

필요한 구성 요소

 



아두이노 Pro Micro: 이것은 HID 응용 프로그램에 적합하며 주요 기능.

초음파의 센서: 초음파 센서의 작동 방식, 초음파 센서의 역할을 설명합니다. 프로젝트와 이 특정 모델을 선택한 이유.

TP223 시리즈 터치 센서: 정전식 터치 센서의 작동 방식 설명 그리고 터치 기반 컨트롤을 만들 때의 이점이 있습니다.

네오픽셀 반지: Neopixel 반지가 제공하는 시각적 피드백에 대해 논의합니다. 그리고 그것이 어떻게 사용자를 향상시키는지.

다른 구성 요소: 저항기, 전선, 브레드보드 또는 사용한 추가 도구.

 

회로 다이어그램:

다음은 자세한 내용과 함께 제공되는 회로도입니다. 배선도를 포함한 각 구성 요소를 연결하는 방법에 대한 지침. 너 브레드 보드에서 테스트하거나 평면 PCB 보드에 직접 납땜 할 수 있습니다.

 

조심스럽게 납땜하고 일반적인 실수를 피하라는 조언을 제공합니다. 안정적인 연결을 보장합니다.

 

코딩 및 프로젝트:

여기에서 저장하거나 복사할 수 있는 코드는 다음과 같습니다.

#include <HID-Project.h>                    // Include HID_Project library
#include <HID-Settings.h>
#include <NewPing.h>
#include <Adafruit_NeoPixel.h>              // Include Adafruit Neopixel library


// Define HID Consumer Control Codes for Brightness
#define CONSUMER_BRIGHTNESS_UP   0x006F
#define CONSUMER_BRIGHTNESS_DOWN 0x0070

#define TRIGGER_PIN 10
#define ECHO_PIN 9
#define MAX_DISTANCE 60 // Maximum distance we want to measure (in centimeters)

// Touch sensor pins
#define PREVIOUS_TOUCH_PIN 7
#define NEXT_TOUCH_PIN 14
#define PLAY_PAUSE_TOUCH_PIN 15
#define MUTE_TOUCH_PIN 16

// Define brightness control touch sensor pins
#define BRIGHTNESS_UP_PIN 8
#define BRIGHTNESS_DOWN_PIN 6

// Neopixel settings
#define NEOPIXEL_PIN 5
#define NUM_PIXELS 16
Adafruit_NeoPixel ring = Adafruit_NeoPixel(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

// Define the 8 corner LEDs indices
const int cornerLEDs[8] = {0, 2, 4, 6, 8, 10, 12, 14};

// Variables for continuous hue animation
unsigned long lastHueUpdate = 0;
const unsigned long hueUpdateInterval = 100; // Time between hue updates (in ms)
int hueContinuous = 0;                       // Current hue value
const uint8_t continuousBrightness = 100;     // Brightness level (0-255)


NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

int val = 0;
int previousval = -1;
int currentVolume = 0;
int smoothVal = 0;

// Variables for brightness control
int currentBrightness = 50;    // Current brightness level (0-100%)
int targetBrightness = 50;     // Target brightness level based on touch sensors
unsigned long lastBrightnessUpdate = 0;
const unsigned long brightnessCooldown = 100; // Cooldown time in ms between brightness adjustments
unsigned long lastDebounceTime_brightnessUp = 0;
unsigned long lastDebounceTime_brightnessDown = 0;
const unsigned long debounceDelay = 200; // 200ms debounce delay

void setup() {
  pinMode(PREVIOUS_TOUCH_PIN, INPUT);       // Set touch sensor pins as input
  pinMode(NEXT_TOUCH_PIN, INPUT);
  pinMode(PLAY_PAUSE_TOUCH_PIN, INPUT);
  pinMode(MUTE_TOUCH_PIN, INPUT);
  pinMode(BRIGHTNESS_UP_PIN, INPUT);
  pinMode(BRIGHTNESS_DOWN_PIN, INPUT);

  Consumer.begin();                         // Initialize computer connection
  ring.begin();                             // Initialize Neopixel ring
  ring.show();                              // Clear any previous data
  delay(1000);                              // Wait for computer to connect

  // Set initial volume to 0
  for (int a = 0; a < 50; a++) {
    Consumer.write(MEDIA_VOLUME_DOWN);
    delay(2);
  }
}

void loop() {

  unsigned long currentMillis = millis();
  unsigned long currentTime = millis();
  int distance = sonar.ping_cm();           // Read distance from ultrasonic sensor

  // Simple smoothing filter for ultrasonic sensor
  if (distance > 0 && distance <= MAX_DISTANCE) {
    smoothVal = (smoothVal * 3 + distance) / 4; // Average with previous values for smoothing
    val = map(smoothVal, 0, MAX_DISTANCE, 0, 100);  // Map smoothed distance to 0-100 range

    if (val != previousval) {               // Check if volume level has changed
      if (val > previousval) {
        // Increase volume slowly
        while (currentVolume < val) {
          Consumer.write(MEDIA_VOLUME_UP);
          currentVolume++;
          delay(50); // Slower delay for smoother volume control
        }
      } else {
        // Decrease volume slowly
        while (currentVolume > val) {
          Consumer.write(MEDIA_VOLUME_DOWN);
          currentVolume--;
          delay(50); // Slower delay for smoother volume control
        }
      }
      previousval = val;                    // Update previous value
    }
  }

  // Adjust brightness smoothly towards targetBrightness
  if (currentBrightness < targetBrightness && (currentMillis - lastBrightnessUpdate > brightnessCooldown)) {
    Consumer.write(CONSUMER_BRIGHTNESS_UP);
    currentBrightness++;
    lastBrightnessUpdate = currentMillis;
  }
  if (currentBrightness > targetBrightness && (currentMillis - lastBrightnessUpdate > brightnessCooldown)) {
    Consumer.write(CONSUMER_BRIGHTNESS_DOWN);
    currentBrightness--;
    lastBrightnessUpdate = currentMillis;
  }

  // Handle brightness touch sensors with debouncing
  handleBrightnessControls(currentMillis);

  delay(10); // Short delay to prevent overwhelming the loop

  // Handle Previous Media touch sensor activation (counterclockwise animation)
  if (digitalRead(PREVIOUS_TOUCH_PIN) == HIGH) {
    Consumer.write(MEDIA_PREV);
    animateRing(false);                     // Trigger ring animation for previous (counterclockwise)
    delay(500); // Debounce delay
  }

  // Handle Next Media touch sensor activation (clockwise animation)
  if (digitalRead(NEXT_TOUCH_PIN) == HIGH) {
    Consumer.write(MEDIA_NEXT);
    animateRing(true);                      // Trigger ring animation for next (clockwise)
    delay(500); // Debounce delay
  }

  // Handle Play/Pause touch sensor activation
  if (digitalRead(PLAY_PAUSE_TOUCH_PIN) == HIGH) {
    Consumer.write(MEDIA_PLAY_PAUSE);
    playPauseNeopixelEffect();
    delay(500); // Debounce delay
  }

  // Handle Mute touch sensor activation
  if (digitalRead(MUTE_TOUCH_PIN) == HIGH) {
    Consumer.write(MEDIA_VOLUME_MUTE);
    muteNeopixelEffect();                  // Trigger violet effect for mute
    delay(500); // Debounce delay
  }
  startUp();
  delay(100);                               // Adjust this delay for responsiveness
}

// Function to animate the Neopixel ring with hue colors
void animateRing(bool clockwise) {
  uint16_t startHue = 0;

  for (int i = 0; i < NUM_PIXELS; i++) {
    startHue += 65536 / NUM_PIXELS;         // Increment hue for each pixel (full rotation)
    int pixelIndex = clockwise ? i : (NUM_PIXELS - 1 - i);
    ring.setPixelColor(pixelIndex, ring.ColorHSV(startHue, 255, 255));
    ring.show();
    delay(50);                             // Delay between lighting each pixel
  }

  // Clear the ring after animation
  delay(300);
  ring.clear();
  ring.show();
}

// Function for Play/Pause Neopixel effect (Green for Play, Red for Pause)
void playPauseNeopixelEffect() {
  // Green for Play and Red for Pause (alternate for effect)
  for (int i = 0; i < 2; i++) {
    ring.fill(ring.Color(0, 255, 0));  // Green for Play
    ring.show();
    delay(200);
    ring.fill(ring.Color(255, 0, 0));  // Red for Pause
    ring.show();
    delay(200);
  }
  ring.clear();
  ring.show();
}

// Function for Mute Neopixel effect (Violet color)
void muteNeopixelEffect() {
  ring.fill(ring.Color(148, 0, 211));   // Violet color for mute
  ring.show();
  delay(500);
  ring.clear();
  ring.show();
}


// Function to handle brightness touch controls
void handleBrightnessControls(unsigned long currentMillis) {
  // Brightness Up Button
  if (digitalRead(BRIGHTNESS_UP_PIN) == HIGH && (currentMillis - lastDebounceTime_brightnessUp > debounceDelay)) {
    if (targetBrightness < 100) {
      targetBrightness += 1; // Increase brightness by 1%
      targetBrightness = constrain(targetBrightness, 0, 100);
    }
    lastDebounceTime_brightnessUp = currentMillis;
  }

  // Brightness Down Button
  if (digitalRead(BRIGHTNESS_DOWN_PIN) == HIGH && (currentMillis - lastDebounceTime_brightnessDown > debounceDelay)) {
    if (targetBrightness > 0) {
      targetBrightness -= 1; // Decrease brightness by 1%
      targetBrightness = constrain(targetBrightness, 0, 100);
    }
    lastDebounceTime_brightnessDown = currentMillis;
  }
}
/*
  // Function to set initial volume at startup
  void setInitialVolume(int initialVolume) {
  targetVolume = initialVolume;
  currentVolume = initialVolume; // Assume starting volume is already at initialVolume
  }
*/
// Function to set initial brightness at startup
void setInitialBrightness(int initialBrightness) {
  targetBrightness = initialBrightness;
  currentBrightness = initialBrightness; // Assume starting brightness is already at initialBrightness
}
void startUp() {
  unsigned long currentMillis = millis();

  // Check if it's time to update the hue
  if (currentMillis - lastHueUpdate >= hueUpdateInterval) {
    // Increment the hue value
    hueContinuous += 256; // Adjust this value to control hue change speed
    if (hueContinuous >= 65536) { // Hue range for ColorHSV is 0-65535
      hueContinuous = 0; // Reset hue after a full rotation
    }

    // Update each corner LED with a different hue to create a rotating effect
    for (int i = 0; i < 8; i++) {
      // Calculate hue offset for each LED
      int hueOffset = (hueContinuous + (i * 65536 / 8)) % 65536;

      // Convert HSV to RGB and set the pixel color
      uint32_t color = ring.ColorHSV(hueOffset, 255, continuousBrightness);
      ring.setPixelColor(cornerLEDs[i], color);
    }

    // Display the updated colors on the NeoPixel ring
    ring.show();

    // Update the last hue update time
    lastHueUpdate = currentMillis;

    // Optional: Debugging information
    // Serial.print("HueContinuous: ");
    // Serial.println(hueContinuous);
  }
}

 

테스트 및 디버깅

테스트 Arduino Pro Micro 기반 HID 미디어 제어 프로젝트는 다음을 위한 중요한 단계입니다. 모든 것이 의도한 대로 작동하는지 확인합니다. 각 구성 요소를 확인하는 것으로 시작합니다 개별적 으로. 초음파 센서가 정확한지 확인하여 시작하십시오. 손의 거리를 감지합니다. 간단한 직렬 모니터 출력을 사용할 수 있습니다 거리 판독값을 표시하여 내 기대치와 일치하는지 확인합니다. 0-60cm 범위. 센서 판독값이 격렬하게 변동하는 경우 를 추가하는 것이 좋습니다. 약간의 지연을 일으키거나 이동 평균 필터를 사용하여 출력을 안정화합니다.

다음 각 센서가 트리거하는지 확인하여 TP223 터치 센서를 테스트합니다. 의도된 미디어 제어 작업(예: 재생/일시 중지, 다음, 이전, 음소거) 없이 delay 또는 false 트리거. 센서가 응답하지 않으면 배선을 다시 확인하십시오 감도가 올바르게 조정되었는지 확인하십시오.

한 번 센서가 작동 중이면 HID 기능 테스트로 이동합니다. 다음을 확인합니다. Arduino는 미디어 제어 명령을 컴퓨터에 올바르게 보냅니다. 간단한 코드를 테스트하여 볼륨을 높이거나 낮추고 응답하는지 확인합니다. 매끄럽고 정확하게. 볼륨 컨트롤이 너무 민감하거나 그렇지 않은 경우 충분히 반응할 수 있으므로 센서 판독값의 매핑을 조정해야 할 수도 있습니다. 볼륨 레벨 또는 압도적인 것을 피하기 위해 명령 사이에 약간의 지연을 도입하십시오. 시스템.

이후 기본 기능이 작동하고 있으면 Neopixel 링을 테스트하여 다음을 제공하는지 확인하십시오. 올바른 시각적 피드백. 색상이 꺼져 있거나 애니메이션이 그렇지 않은 경우 smooth, 타이밍 문제나 잘못된 설정이 있는지 코드를 검토하십시오. Neopixel 라이브러리.

마침내 전체 시스템을 함께 실행하고 성능을 관찰하십시오. 무엇이든 찾으십시오. 지연, 잘못된 출력 또는 예기치 않은 동작. 디버깅에는 다음이 포함될 수 있습니다. 센서 감도 조정, 코드 로직 조정 또는 전원 공급 장치 개선 원활하고 신뢰할 수 있는 사용자 경험을 보장하기 위한 안정성.

 

결론

 



만들기 Arduino Pro Micro를 사용한 HID 미디어 제어 시스템은 단순한 것 이상입니다. 기술 프로젝트—보다 개인화되고 효율적인 업무 공간을 만들기 위한 단계입니다. 이 프로젝트는 일반적인 문제를 해결할 뿐만 아니라 다음과 같은 이점을 제공합니다. 자신의 필요에 맞는 도구를 제작하는 만족감. 다음을 수행할 수 있는 유연성 간단한 손 제스처로 미디어를 제어하거나 탭으로 레이어를 추가할 수 있습니다. 표준 장치로는 따라올 수 없는 편리함. 게다가, 생동감 넘치는 Neopixel 피드백은 약간의 감각을 더하여 설정을 시각적으로 매력적으로 만듭니다 기능적이기 때문입니다. 이 프로젝트에 뛰어들어 상호 작용 방식을 혁신하십시오. 당신의 미디어와 함께!

 

반응형