Arduino 시각장애인 시계

39100 단어 arduinoclockopensource
몇 년 전에 나는 스웨덴의 와지소에서 홀로 살았던 할머니를 찾아뵈었다.그녀의 시력이 서서히 악화되고 있는데, 그녀는 항상 우리에게 지금 몇 시인지 알려 달라고 한다.바깥에는 말을 할 수 있는 시계가 매우 많지만, 그것들 대부분은 영어이다.내가 스웨덴으로 여행을 가기 7일 전에, 나는 시간마다 오디오 알림이 나오는 아두노 시계를 만들기로 결정했다.그래서 나는 어머니의 목소리를 녹음했다(이것이 가장 어려운 부분이다!😛) 시간당 1분마다 보스니아어 인사말을 틀고 매일 아침 8시에 방송한다.할머니는 가족과 방문객에게 의지할 필요가 없기 때문에 흥분하고 기뻤다.이것은 그녀에게 급히 필요한 독립성을 주었다.
시계는 시간당 또는 리모컨을 사용하여 필요에 따라 오디오 알림을 생성합니다.
다음은 교과서입니다. - 유용하다고 생각하세요.
나는 현지의 한 상점에서 모든 부품을 샀다.다음이 필요합니다.
  • Arduino UNO
  • DS3231 실시간 클록 모듈
  • Wtv020sd16p 사운드 모듈
  • 적외선 수신기 모듈
  • 스피커
  • 버튼
  • SD 카드 2GB

  • 첫 번째는 원형을 만드는 것이다. 우리는 모든 것을 용접한 후에 다시 테스트를 하고 싶지 않다.



    우리가 원형 설계와 테스트를 완성한 후에, 우리는 이미 모든 물건을 함께 놓을 준비가 되어 있다.

    나는 용접을 도와주기 위해 친한 친구(아민 무히치)에게 전화를 걸었다.그는 정말 잘한다. 나는 관절을 느슨하게 하는 모험을 할 수 없다.

    이제 우리는 우리의 상자를 더욱 화려하게 보일 것이다.


    다음에 우리는 시계의 오디오를 녹음할 것이다


    이 부분은 우리 엄마에게 짜증난다. 나는 그녀에게 이 숫자들을 모두 되풀이하게 했다🤣
    나는 안드로이드 프로그램으로 오디오를 녹음하고 편집한다.

    몇 시간과 몇 분 동안 오디오를 녹음하고 파일을 '0000' 으로 명명합니다.wav''0001.wav'.이것은 앞으로 우리가 소리 모듈을 사용하여 오디오 파일을 재생할 때 매우 중요하다.

    sd 카드에 오디오 파일 추가


    계속하기 전에 SD 카드 포맷을 잊지 마십시오.

    이제 모든 파일을 SD 카드에 추가합니다.우리의 음성 모듈은ad4 파일 형식을 받아들이기 때문에 AD4CONVERTER를 사용하여 파일을 이 형식으로 변환해야 합니다.
    편의를 위해 파워셸을 만들었습니다. 폴더의 모든 파일을 AD4 형식으로 자동으로 변환합니다.
    $fileNames = Get-ChildItem -Path "your_audio_files location" -Recurse -Include *.wav
    foreach($file in $fileNames ){
     Write-Host  $file.FullName
     .\your_ad4_location\AD4CONVERTER.EXE -E4 $file
    
    }
    
    오디오 파일을 사용하여 폴더에서 이 스크립트를 실행하려면 AD4CONVERTER를 배치해야 합니다.같은 폴더에 있습니다.


    AD4 파일을 SD 카드에 추가합니다.

    인코딩 시간 다 됐어요.😍


    rar 형식의 모든 라이브러리를 ArduinoIDE에 추가한 다음 라이브러리를 포함합니다.
    #include <EEPROM.h>
    #include <RTClib.h>
    #include <Wtv020sd16p.h>
    #include "IRremote.h"
    
    현재 우리는 코드에 사용할 모든 파이프라인을 정의했다.
    // RTC setup
    RTC_DS3231 rtc;
    
    // Wtv020sd16p Pins
    #define RESET_PIN 2  // The pin number of the reset pin.
    #define CLOCK_PIN 3  // The pin number of the clock pin.
    #define DATA_PIN 4  // The pin number of the data pin.
    #define BUSY_PIN 5  // The pin number of the busy pin.
    
    // IR Pin
    #define RECEIVER_PIN 11 // Signal Pin of IR receiver to Arduino Digital Pin 11
    
    // DST Pin
    #define DST_PIN 9
    
    // DST check
    int DST;
    
    /*-----( Declare objects )-----*/
    IRrecv irrecv(RECEIVER_PIN);     // create instance of 'irrecv'
    decode_results results;      // create instance of 'decode_results'
    
    /*
      Create an instance of the Wtv020sd16p class.
      1st parameter: Reset pin number.
      2nd parameter: Clock pin number.
      3rd parameter: Data pin number.
      4th parameter: Busy pin number.
    */
    Wtv020sd16p wtv020sd16p(RESET_PIN, CLOCK_PIN, DATA_PIN, BUSY_PIN);
    
    DST는 버튼 상태를 유지하는 변수입니다.
    이 단추는 일광 절약 시간을 추적하는 역할을 합니다.누르면 1시간이 바뀐다.
    다음은 Arduino를 시작할 때 실행될 설정 기능에 대해 설명합니다.
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
    
      irrecv.enableIRIn(); // Start the receiver
    
      // this code will get state of DST variable from EEPROM memory
      // if there is nothing ine memory we will put 1 aka summertime
      DST = EEPROM.get(0, DST);
    
      if (DST != 0 && DST != 1)
      {
        DST = 1;
        EEPROM.put(0, DST);
      }
    
      // RTC clock
      // we will loop until RTC module start
      if (! rtc.begin()) {
        Serial.println("Couldn't find RTC");
        while (1);
      }
    
      // this condition will check if our RTC module lost power
      if (rtc.lostPower()) {
        Serial.println("RTC lost power, lets set the time!");
    
        // Following line sets the RTC to the date & time this sketch was compiled
        rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
      }
      // Comment out below lines once you set the date & time.
      // Following line sets the RTC with an explicit date & time
      // for example to set January 27 2017 at 12:56 you would call:
      // rtc.adjust(DateTime(2017, 1, 27, 12, 56, 0));
    
      // Initializes the sound module.
      wtv020sd16p.reset();
    
      // Setting up our DST button
      pinMode(DST_PIN, INPUT_PULLUP);
    }
    
    이 함수에서, 우리는 모듈에 초기 값을 설정할 것이다.EEPROM 스토리지에서 DST 버튼 상태를 가져오려고 합니다.만약 메모리에 아무런 내용이 없다면, 우리는 1을 기본값 (여름 시간) 으로 삼을 것이다.
    DST = EEPROM.get(0, DST);
    
      if (DST != 0 && DST != 1)
      {
        DST = 1;
        EEPROM.put(0, DST);
      }
    
    
    초기 설정이 완료되면 Arduino는 일정 시간 간격으로 실행되는 주기 함수를 실행합니다.
    void loop() {
      // Check if DST button is pressed
    
      if (digitalRead(DST_PIN) == LOW) {
        DateTime now = rtc.now();
        if (DST == 0) {
          rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour() + 1, now.minute(), now.second()));
          DST = 1;
          EEPROM.put(0, DST);
        } else if (DST == 1) {
          rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour() - 1, now.minute(), now.second()));
          DST = 0;
          EEPROM.put(0, DST);
        }
      }
    
      // Initialize time object
      DateTime  myTime = rtc.now();
    
      // Run hourly clock notifications
      hourly(myTime);
    
      // Run clock notification when remote controller button is pressed
      if (irrecv.decode(&results)) // have we received an IR signal?
      {
        if (IRvalues()) {
          switchTime(myTime, false);
          delay(1000);
        }
    
        irrecv.resume(); // receive the next value
    
      }
    
    }
    
    순환 기능에서 DST 버튼을 눌렀는지 확인하고 있습니다.그런 다음 DST 상태가 0인지 1인지 확인하고 그에 따라 시간을 조정합니다.DST 상태가 1이면 1시간이 추가됩니다.
    /*loop function*/
    // Check if DST button is pressed
    
      if (digitalRead(DST_PIN) == LOW) {
        DateTime now = rtc.now();
        if (DST == 0) {
          rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour() + 1, now.minute(), now.second()));
          DST = 1;
          EEPROM.put(0, DST);
        } else if (DST == 1) {
          rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour() - 1, now.minute(), now.second()));
          DST = 0;
          EEPROM.put(0, DST);
        }
      }
    
    모든 순환에서 우리는 사용할 것이다
    DateTime  myTime = rtc.now();
    
    다음에 우리는 hourly라는 함수를 호출해서 현재 시간을 받아들인다
    /*loop function*/
    // Run hourly clock notifications
    hourly(myTime);
    
    이 기능은 시간당 오디오를 재생합니다.
    /*hourly function*/
    void hourly(DateTime &myTime) {
      // 7 o'clock
      if (myTime.hour() == 7 && myTime.minute() == 00 && myTime.second() == 00) {
        wtv020sd16p.playVoice(86); delay(16000);
        delay(500);
        switchTime(myTime, true);
        delay(1000);
      }
      // 8 o'clock
      else if (myTime.hour() == 8 && myTime.minute() == 00 && myTime.second() == 00) {
        wtv020sd16p.playVoice(86); delay(16000); // the birds begin to sing
        switchTime(myTime, true); delay(1000); // tells what time it is
        wtv020sd16p.playVoice(84); delay(6500); // message from grandma's daughter
        wtv020sd16p.playVoice(85); delay(5500); // message from granddaughter
    
        delay(1000);
      }
      //.....
    }
    
    이 함수에서, 우리는 여러 개의if-else 문장을 사용하여 오디오를 재생할 것이다
    wtv020sd16p.playVoice(86); delay(16000);
    
    사운드를 재생할 때 SD 카드의 오디오 파일에 해당하는 숫자를 사용합니다.86번은 0086.SD 카드의ad4 파일입니다.내 예에서, 숫자가 86인ad4 파일은 새의 노래 소리를 재생할 것이다.이 오디오는 매 시간의 각 오디오 전에 재생됩니다.이 함수에서, 우리는 함수 switchTime이라고도 부른다. 이 함수는 현재 시간과 볼 값을 받아들일 것이다.만약 부울 값이 사실이라면, 우리는 분 대신 정확한 시간만 재생할 것이다.만약 이 값이 가짜라면, 우리는 시간과 분 단위의 정확한 시간을 방송할 것이다.
    시간당 함수에서 이 함수를 호출할 때true를 보냅니다.
    /*switchTime function*/
    void switchTime(DateTime &myTime, bool hourly) {
      int Hour = myTime.hour();
      int Minute = myTime.minute();
    
      switch (Hour) {
        case 0: wtv020sd16p.playVoice(0); delay(4500);    break;
        case 1: wtv020sd16p.playVoice(1); delay(3800);    break;
        case 2: wtv020sd16p.playVoice(2); delay(3800);    break;
        case 3: wtv020sd16p.playVoice(3); delay(3000);    break;
        case 4: wtv020sd16p.playVoice(4); delay(3000);    break;
        //......
        default:
          Serial.println("Erorr check files");
    
      }
    
      // Play minutes audio
      if (hourly != true) {
        switch (Minute) {
          case 0: wtv020sd16p.playVoice(24); delay(1000);    break;
          case 1: wtv020sd16p.playVoice(25); delay(1000);    break;
          case 2: wtv020sd16p.playVoice(26); delay(1000);    break;
          case 3: wtv020sd16p.playVoice(27); delay(1000);    break;
          case 4: wtv020sd16p.playVoice(28); delay(1000);    break;
          //....
    
          default:
            Serial.println("Erorr check files");
        }
    
      }
    
      delay(5000);
    
    }
    
    순환 기능으로 돌아가서 만약에 우리가 리모컨에서 적외선 신호를 받으면 우리는 반응을 할 것이다. 만약에 우리가 리모컨에서 신호를 받으면 우리는 같은 기능인 switchTime을 사용하여 시간과 분으로 현재 시간을 재생할 것이다.현재 우리는false를 두 번째 매개 변수로 보낼 것이다.
      /*loop function*/
      // Run clock notification when remote controller button is pressed
      if (irrecv.decode(&results)) // have we received an IR signal?
      {
        if (IRvalues()) {
          switchTime(myTime, false);
          delay(1000);
        }
    
        irrecv.resume(); // receive the next value
    
      }
    
    이런 상황에서 만약에 막히면 우리는 신호를 받았는지 확인하고 다른 리모컨, 예를 들어 텔레비전 리모컨을 무시할 것이다. 우리는 신호가 허용된 값 안에 있는지 검사할 것이다.
    bool IRvalues() {
      // Accept signals only from custom remote
      switch (results.value) {
        case 0xFFA25D: return true; break;
        case 0xFFE21D: return true; break;
        case 0xFF629D: return true; break;
        case 0xFF22DD: return true; break;
        case 0xFF02FD: return true; break;
        case 0xFFC23D: return true; break;
        case 0xFFE01F: return true; break;
        case 0xFFA857: return true; break;
        case 0xFF906F: return true; break;
        case 0xFF9867: return true; break;
        case 0xFFB04F: return true; break;
        case 0xFF6897: return true; break;
        case 0xFF30CF: return true; break;
        case 0xFF18E7: return true; break;
        case 0xFF7A85: return true; break;
        case 0xFF10EF: return true; break;
        case 0xFF38C7: return true; break;
        case 0xFF5AA5: return true; break;
        case 0xFF42BD: return true; break;
        case 0xFF4AB5: return true; break;
        case 0xFF52AD: return true; break;
        case 0xFFFFFFFF: return true; break;
    
        default:
          return false;
    
      } // End Case
    
    }
    
    나는 네가 이것이 매우 유용하다고 생각해서 너의 시각장애인 친구와 가족을 즐겁게 하기를 바란다.아두노종이 우리 할머니를 도와준 게 확실해.

    좋은 웹페이지 즐겨찾기