산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

Arduino 기반 물병

구성품 및 소모품

SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
방수 초음파 센서
× 1
실시간 시계(RTC)
× 1
SparkFun 공통 음극 4자리 7세그먼트 디스플레이
× 1
부저
× 1
SparkFun 푸시버튼 스위치 12mm
× 1
범용 트랜지스터 NPN
× 1
리튬 이온 배터리 1000mAh
× 1
Adafruit USB 리튬 이온 배터리 충전기
× 1
저항 221옴
× 8
저항 1k 옴
× 4
저항 4.75k 옴
× 2

필요한 도구 및 기계

납땜 인두(일반)
뜨거운 글루건(일반)

앱 및 온라인 서비스

Arduino IDE

이 프로젝트 정보

소개:

충분한 물을 마시는 것은 우리의 건강에 매우 중요합니다. 물을 더 많이 마시면 ​​더 깨끗한 피부, 더 나은 전반적인 건강, 생산성 및 뇌 기능 개선, 에너지 수준 증가, 심지어 체중 감소로 이어질 수 있습니다.

바쁜 일상에서 물을 충분히 마시는 것을 기억하는 것은 정말 어렵습니다. 그리고 대부분의 경우 우리는 집, 사무실 또는 이동 중에 충분한 물을 마시는 것을 잊습니다. 미국인의 약 75%는 항상 만성적으로 탈수 상태입니다.

따라서 건강한 물 마시는 습관을 기르기 위해서는 매일 물 섭취량을 추적하는 것이 중요합니다.

물 섭취량을 추적하기 위해 Arduino를 사용하여 물병을 스마트하게 만들었습니다. 다음을 수행할 수 있습니다.

1. 일일 수분 섭취량 추적

2. 나의 주간 평균 수분 섭취량 추적

3. 물을 먹으라고 알려줘

4. 마지막 섭취 시간 추적

5. 한 번 충전으로 한 달 이상 사용하세요.

RTC 모듈 만들기

취수 정보를 기록하거나 추적하려면 현재 시간 및 날짜 정보가 축적된 데이터와 함께 저장되어야 합니다. 적절한 백업 배터리가 있는 DS1307과 같은 실시간 클록(RTC) 칩을 사용하여 필요한 정보를 제공할 수 있습니다. RTC 칩(소프트웨어)의 프로그래밍 프로세스도 매우 간단하며 대부분의 프로그래밍 환경에서 지원됩니다.

다음은 일상적인 마이크로컨트롤러 프로젝트를 위한 인기 있는 RTC IC DS1307을 기반으로 하는 소형 RTC 모듈의 설계입니다. DS1307 직렬 실시간 클록(RTC)은 저전력, 완전한 BCD(binary coded decimal) 클록/캘린더에 56바이트의 NV SRAM을 더한 것입니다. 주소와 데이터는 I2C, 양방향 버스를 통해 직렬로 전송됩니다. 24시간/12시간 형식 시계/달력은 윤년 수정을 포함하여 초, 분, 시, 일, 날짜, 월 및 연도 정보를 제공합니다.

첨부된 회로도에 따라 실시간 클럭 모듈을 만들어 봅시다. DS1307 RTC가 올바르게 작동하려면 외부 크리스털이 필요합니다. IC의 SCL 및 SDA 핀에는 2개의 풀업 저항이 필요합니다. 저항 값은 약 2k ~ 10k일 수 있습니다. 4.7k 사용했습니다. 납땜하는 동안 내 회로를 위한 공간이 제한되어 있기 때문에 모듈을 가능한 한 작게 유지하려고 했습니다. DS1307 대신 DS3231을 사용할 수 있으며 IC에는 내부 수정 발진기가 있습니다. 따라서 외부 크리스탈을 추가할 필요가 없습니다. 자체적으로 만들고 싶지 않다면 기성품의 작은 RTC 모듈을 구입할 수도 있습니다. 전체 시스템은 배터리로 작동하므로 코인 셀을 사용하지 않고 RTC의 VBAT 핀을 접지에 연결했습니다.

DS1307의 중요 핀:

<울>
  • 5V 핀 :이 핀이 high이면 ds1307이 데이터를 보내고, low이면 백업 버튼 셀에서 실행합니다.
  • <울>
  • GND :모듈의 접지 핀입니다. 배터리 접지와 전원 공급 장치가 함께 묶여 있습니다.
  • <울>
  • SCL :마이크로컨트롤러와 통신하는 I2C 클럭 핀입니다. Arduino SCL 핀과 연결해야 합니다.
  • <울>
  • SDA :마이크로컨트롤러와 통신하는 I2C 데이터 핀입니다. Arduino SDA 핀과 연결해야 합니다.
  • <울>
  • VBAT :모든 표준 3V 리튬 셀 또는 기타 에너지 소스용 배터리 입력. 사용하지 않을 경우 접지해야 합니다.
  • 7세그먼트 디스플레이 보드 만들기

    디스플레이 모듈의 경우 간단한 문자로 숫자 데이터를 표시하는 데 적합한 4개의 7-세그먼트 LED 숫자 디스플레이가 포함된 독립형 소형 공통 음극 모듈을 사용했습니다.

    디스플레이 모듈의 각 세그먼트는 다중화되어 동일한 양극 연결 지점을 공유합니다. 그리고 모듈의 네 자리 각각에는 고유한 공통 음극 연결 지점이 있습니다. 이를 통해 각 숫자를 독립적으로 켜거나 끌 수 있습니다. 또한 이 다중화 기술은 디스플레이를 제어하는 ​​데 필요한 엄청난 양의 마이크로컨트롤러 핀을 32개가 아닌 11개 또는 12개로 변환합니다!

    디스플레이의 LED 세그먼트는 5V 로직 핀에서 전원이 공급될 때 전류 제한 저항이 필요합니다. 저항 값은 일반적으로 5V의 경우 330~470옴입니다. 리튬 이온 배터리 작동의 경우 220옴이 될 수 있습니다. 또한 마이크로컨트롤러의 각 핀은 거의 40mA의 전류만 소싱하거나 싱크할 수 있기 때문에 드라이버 트랜지스터는 LED 세그먼트에 추가 구동 전류를 제공하는 것이 좋습니다. 디스플레이의 모든(7개) 세그먼트가 한 번에 켜지면(숫자 8), 전류 수요는 이 40mA 제한을 초과합니다. 아래 이미지는 전류 제한 저항과 드라이버 트랜지스터의 기본 배선도를 나타냅니다.

    이 4자리 7세그먼트 디스플레이 섹션은 4개의 공통 음극 7세그먼트 LED 디스플레이와 4개의 2N2222 NPN 트랜지스터 주위에 배선됩니다. 1K 저항은 기본 전류 제한에 사용되며 220R 저항은 LED 디스플레이 세그먼트의 작동 전류를 제한합니다.

    Arduino 보드에서 D10 ~ D17의 디지털 출력은 세그먼트(a ~ g &dp)를 구동하는 데 사용되며 디지털 출력 D6 ~ D9는 4×7 LED 디스플레이의 숫자(D0-D3)에 사용됩니다.

    버튼 스위치가 디스플레이 모듈과 함께 추가되어 다양한 옵션에 액세스할 수 있습니다. 또한 외부 하드웨어 인터럽트를 사용하여 절전 모드에서 Arduino를 깨우는 데 사용됩니다. 따라서 버튼은 Arduino 디지털 핀 #2(INT0)에 연결됩니다.

    Arduino Mini Pro와 디스플레이 보드 연결

    모든 세그먼트 핀을 Arduino 미니 핀에 납땜하기 전에 제공된 회로도에 따라. 그런 다음 트랜지스터의 컬렉터 핀에 4개의 공통 핀을 납땜합니다. 트랜지스터의 베이스는 Arduino 핀에 연결됩니다. 디스플레이를 연결한 후 버튼 스위치를 Arduino 디지털 핀 2(INT 0)에 연결합니다. 이 버튼을 사용하여 Arduino를 절전 모드에서 깨우기 위해 외부 하드웨어 인터럽트를 구현하므로 Arduino 핀 2에 버튼을 연결했는지 확인하십시오.

    RTC 모듈과 부저 연결

    이제 앞에서 만든 RTC 모듈을 아두이노 보드에 연결합니다. 모듈의 SDA 핀은 아두이노 핀의 SDA(A4) 핀에, 모듈의 SCL 핀은 아두이노의 SCL(A5) 핀에 연결해야 합니다. 그런 다음 부저를 Arduino 보드에 연결합니다.

    연결:

    RTC ------> Arduino 미니 프로

    <울>
  • SDA ------> A4
  • <울>
  • SCL ------> A5
  • <울>
  • 부저 ------> D3
  • 병뚜껑이 있는 초음파 센서 부착

    그림과 같이 병뚜껑에 구멍을 뚫습니다. 구멍을 통해 초음파 센서의 전선 4개를 빼내고 병뚜껑 중앙에 초음파 센서를 고정합니다. 센서는 병뚜껑 안쪽에 부착해야 하며 중앙에 위치해야 합니다.

    연결:

    초음파 센서 ------> Arduino Mini Pro

    <울>
  • VCC ------> VCC
  • <울>
  • GND ------> GND
  • <울>
  • 트리거 ------> D4
  • <울>
  • 에코 ------> D5
  • 프로그램 업로드 및 테스트

    모든 연결이 완료되면 Arduino 보드에 프로그램을 업로드하고 기능을 테스트할 적기입니다. 프로그램이 올바르게 작동하려면 여러 라이브러리가 필요합니다. 버튼 인터페이스를 위해서는 OneButton 라이브러리를 추가해야 합니다. 장치가 배터리로 작동하기 때문에 전력 소비는 중요한 문제입니다. 내 Arduino 스케치에 절전 모드를 구현했습니다. 워치독 타이머와 외부 하드웨어 인터럽트는 Arduino를 절전 모드에서 깨우는 데 사용되었습니다. 아두이노는 3번의 센서 판독을 받아 평균을 내서 필요한 정보를 계산하고 10초간 정보를 표시하고 1분간 슬립 모드로 들어간다. INT0(디지털 핀 2)에 연결된 버튼을 누르면 언제든지 깨어납니다. 따라서 섭취량에 대한 정보를 보려면 언제든지 옵션 버튼을 누르십시오. 그것은 당신을 위해 깨울 것입니다. 버튼을 누르지 않으면 1분마다 읽는 데 소요됩니다. 절전 모드를 구현하기 위해 Arduino 저전력 라이브러리를 사용했습니다. DS1307 RTC 모듈에서 읽기 시간을 위해 DS1307RTC 라이브러리를 사용했습니다. 따라서 첨부된 프로그램을 컴파일하려면 모든 라이브러리를 환경에 추가하십시오.

    여기서는 계산 알고리즘만 간략하게 설명하겠습니다. 전체 스케치는 첨부된 채우기를 참조하십시오. 충분히 정확하도록 5개의 센서 판독값의 평균에서 계산이 수행됩니다. 일일 읽기는 24시간으로 재설정되고 새로운 날을 위한 새로운 읽기를 준비합니다.

    평균 수분 섭취량은 이전 7일의 일일 섭취량 평균에서 작성됩니다. 물을 마시지 않고 2시간이 경과하면 15분마다 두 번 경고음으로 사용자에게 경고하고 물을 마신 후 다음 2시간 동안 중지합니다.

    첨부된 코드를 다운로드하여 Arduino Mini Pro에 업로드하십시오. 모든 모듈을 연결하고 전원을 켜서 모든 구성 요소가 올바르게 작동하는지 테스트하십시오. 디스플레이에 결과가 표시되면 축하합니다! 당신은 이미 어려운 일을 해냈습니다.

    병뚜껑으로 Arduino 고정

    뜨거운 접착제를 사용하여 Arduino mini를 병 뚜껑의 위쪽에 부착하십시오. 모든 구성 요소를 병 뚜껑에 고정해야 합니다. 병 뚜껑에 단단히 부착되도록 접착제를 충분히 추가합니다.

    배터리 및 충전기 모듈 부착

    이제 아두이노 상단에 리튬이온 배터리를 고정합니다. 열린 핀으로 배터리를 단락시키지 않도록 주의하십시오. 그런 다음 충전기 모듈을 캡과 연결합니다. USB 포트를 외부에서 쉽게 접근할 수 있도록 하여 충전기에 쉽게 연결할 수 있도록 하십시오.

    모든 회로를 방수 처리하기

    모든 구성 요소를 연결하고 모듈화한 후에는 장치를 완전히 방수 처리할 수 있는 적절한 시간입니다. 물병이기 때문에 언제든지 물이 회로에 떨어져 회로가 손상될 수 있으므로 매우 중요합니다. 완전히 방수되도록 하려면 USB 포트가 없는 회로의 모든 외부 부분에 충분한 접착제를 추가하십시오. 글루를 이용하여 모자를 원형으로 만들 수 있습니다.

    병뚜껑을 물에 담그지 마세요.

    즐기세요

    <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

    코드

    <울>
  • 아두이노 스케치
  • Arduino 스케치Arduino
    // I2C 및 Wire lib#include #include #include #include #include " LowPower.h#include "OneButton.h" OneButton 버튼(2, true); const byte interruptPin =2;volatile int state =0;const int trigPin =4;const int echoPin =5;int piezoPin =3;const int digit[4] ={9,6,7,8};int digit_value[4];int digit_value1[4];int button_press_count =1;const int 세그먼트[8] ={16,10,12,14,15, 17,11,13};const 바이트 수[10][8] ={{1,1,1,1,1,1,0,0}, //0 {0,1,1,0,0, 0,0,0}, //1 {1,1,0,1,1,0,1,0}, //2 {1,1,1,1,0,0,1,0}, / /3 {0,1,1,0,0,1,1,0}, //4 {1,0,1,1,0,1,1,0}, //5 {1,0,1 ,1,1,1,1,0}, //6 {1,1,1,0,0,0,0,0}, //7 {1,1,1,1,1,1,1 ,0}, //8 {1,1,1,1,0,1,1,0}}; //9const 바이트 d[8] ={0,1,1,1,1,0,1,1}; const 바이트 a[8] ={1,1,1,0,1,1,1,1 }; 상수 바이트 r[8] ={0,0,0,0,1,0,1,1}; 상수 바이트 t[8] ={0,0,0,1,1,1,1,1 };int 초, 분, 시간; int water_in_ounch[15];int water_intake_ounch[15];int water_intake_days[7];int water_intake_times =0;int previous_water_amount =0;int total_water_intake_today =0;int Average_intake_last_week =0; 1; 부동 평균_물_수위 =0; //여러 판독값의 평균을 저장합니다.int water_amount_in_ounce =0; //계산된 물의 양을 저장int idle_time =0;int intake_day =1;int previous_value =0;void setup() { Serial.begin(9600); 핀모드(인터럽트핀, INPUT_PULLUP); // 여기에 설정 코드를 넣어 한 번 실행합니다. for(int i=6; i<=17; i++) pinMode(i, OUTPUT); 핀모드(trigPin, 출력); 핀모드(에코핀, 입력); button.attachClick(누른); button.attachDoubleClick(더블클릭); 버튼.attachLongPressStart(longPressStart); button.attachDuringLongPress(longPress);}long previous_state =millis();int count =1;int daily_intake =0;intweek_intake =0;긴 sleep_time =millis();void 루프() { read_time(); 버튼.틱(); // 누름 버튼을 계속 주시하십시오. 계산(); Daily_intake =total_water_intake_in_day(); Weekly_intake =평균_물_섭취_마지막_주(); if(button_press_count ==1){ display_d(); display_number(일일 섭취량); } else if(버튼 누름 횟수 ==2){ display_a(); display_number(주간 섭취량); } else if(button_press_count ==3){ display_r(); display_number(water_amount_in_ounce); } else if(button_press_count ==4){ display_first_2(시간); display_last_2(분); } if(idle_time>=120){ 경고(); 알리다(); } if((millis() - sleep_time)>=15000){ display_off(); attachInterrupt(digitalPinToInterrupt(interruptPin), 공백, FALLING); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); detachInterrupt(디지털핀투인터럽트(인터럽트핀)); sleep_time =millis(); } } 무효 display_digit(int digit){ for(int i=0; i<8; i++){ digitalWrite(segment[i], number[digit][i]); } } 무효 display_number(int number){ int i=0; 동안(숫자>0){ 숫자 값[2-i] =숫자%10; 숫자 =숫자/10; 나는 ++; } 디지털 쓰기(숫자[1], 높음); 디지털 쓰기(숫자[2], 낮음); 디지털 쓰기(숫자[3], 낮음); display_digit(digit_value[0]); 지연(5); 디지털 쓰기(숫자[1], 낮음); 디지털 쓰기(숫자[2], 높음); 디지털 쓰기(숫자[3], 낮음); display_digit(digit_value[1]); 지연(5); 디지털 쓰기(숫자[1], 낮음); 디지털 쓰기(숫자[2], 낮음); 디지털 쓰기(숫자[3], 높음); display_digit(digit_value[2]); 지연(5); 디지털 쓰기(숫자[3], 낮음); 숫자 값[0] =0; 숫자 값[1] =0; 숫자 값[2] =0; }void display_first_2(int number){ digitalWrite(digit[2], LOW); 디지털 쓰기(숫자[3], 낮음); 정수 i=0; 동안(숫자>0){ 숫자 값[1-i] =숫자%10; 숫자 =숫자/10; 나는 ++; } 디지털 쓰기(숫자[0], 높음); 디지털 쓰기(숫자[1], 낮음); display_digit(digit_value[0]); 지연(3); 디지털 쓰기(숫자[0], 낮음); 디지털 쓰기(숫자[1], 높음); display_digit(digit_value[1]); 지연(3); }void display_last_2(int number){ digitalWrite(digit[0], LOW); 디지털 쓰기(숫자[1], 낮음); 정수 i=0; 동안(숫자>0){ digit_value1[1-i] =숫자%10; 숫자 =숫자/10; 나는 ++; } 디지털 쓰기(숫자[2], 높음); 디지털 쓰기(숫자[3], 낮음); display_digit(digit_value1[0]); 지연(3); 디지털 쓰기(숫자[2], 낮음); 디지털 쓰기(숫자[3], 높음); display_digit(digit_value1[1]); 지연(3); } 무효 display_d(){ digitalWrite(digit[0], HIGH); for(int i=0; i<8; i++){ digitalWrite(세그먼트[i], d[i]); } 지연(5); 디지털 쓰기(숫자[0], 낮음); } 무효 display_a(){ digitalWrite(digit[0], HIGH); for(int i=0; i<8; i++){ digitalWrite(세그먼트[i], a[i]); } 지연(5); 디지털 쓰기(숫자[0], 낮음); } 무효 display_r(){ digitalWrite(digit[0], HIGH); for(int i=0; i<8; i++){ digitalWrite(세그먼트[i], r[i]); } 지연(5); 디지털 쓰기(숫자[0], 낮음); } 무효 display_t(){ digitalWrite(digit[0], HIGH); for(int i=0; i<8; i++){ digitalWrite(세그먼트[i], t[i]); } 지연(5); 디지털 쓰기(숫자[0], 낮음); } 무효 display_off(){ digitalWrite(digit[0], LOW); 디지털 쓰기(숫자[1], 낮음); 디지털 쓰기(숫자[2], 낮음); 디지털 쓰기(숫자[3], 낮음); for(int i=0; i<8; i++){ digitalWrite(세그먼트[i], LOW); } 지연(5); } 무효 read_time() { tmElements_t tm; if (RTC.read(tm)) { 초 =tm.Second; 분 =tm.Minute; 시간 =tm.시간; } }int distance_in_cm(){ 긴 지속 시간, cm; // 센서는 10마이크로초 이상의 HIGH 펄스에 의해 트리거됩니다. // 깨끗한 HIGH 펄스를 보장하기 위해 미리 짧은 LOW 펄스를 제공합니다. digitalWrite(trigPin, LOW); 지연 마이크로초(2); digitalWrite(trigPin, HIGH); 지연마이크로초(10); digitalWrite(trigPin, LOW); // 센서에서 신호를 읽습니다. HIGH 펄스의 // 지속 시간은 핑을 보내는 시간부터 // 물체의 에코 오프 수신까지의 시간(마이크로초)입니다. 지속 시간 =pulseIn(echoPin, HIGH); // 시간을 거리로 변환 cm =microsecondsToCentimeters(duration); 반환 cm; }long microsecondsToCentimeters(long microseconds) { // 소리의 속도는 센티미터당 340m/s 또는 29마이크로초입니다. // 핑은 앞뒤로 이동하므로 // 객체의 거리를 찾기 위해 이동 거리의 절반을 취합니다. 마이크로초를 반환 / 29 / 2; }알림 무효(){ tone(piezoPin, 2000, 50); 톤(piezoPin, 2000, 200); //지연(10); }void 공백() { //tone(piezoPin, 2000, 100); //state++;}// 이 함수는 button1이 1번 눌렸을 때 호출될 것입니다. (2. 버튼 누름이 뒤따르지 않습니다.).void pressed() { //Serial.println("Button 1 click."); button_press_count++; 알리다(); if(버튼 누름 횟수 ==5){ 버튼 누름 횟수 =1; }} // click// 이 함수는 짧은 시간 동안 button1이 2번 눌렸을 때 호출됩니다.void doubleclick() { Serial.println("Button 1 doubleclick.");} // doubleclick// 이 함수는 버튼 1을 오랫동안 눌렀을 때 한 번만 호출됩니다.void longPressStart() { Serial.println("Button 1 longPress start");} // longPressStart// 이 함수는 버튼 1을 길게 눌렀을 때 자주 호출됩니다. long time.void longPress() { Serial.println("버튼 1 longPress..."); water_intake_ounch[water_intake_times - 1] =0; //마지막 값 무시} // longPressvoid 계산(){ float water_level =0;// 모든 단계에서 레벨 저장 int read_value =0; //센서 판독값을 cm 단위로 읽음 for(int i=0; i<5; i++){ // 5개 읽기 read_value =distance_in_cm(); if(read_value>16 || read_value<3){// 불안정한 읽기 반환; //읽기가 불안정하므로 호출 함수로 복귀 } else if(read_value<=16 &&read_value>=3){//유효한 값 water_level =water_level + read_value; } 지연(10); } 평균 수위 =17 - 수위/5; //5개의 판독값에서 평균 찾기, 17 =보톨 높이 water_amount_in_ounce =int(average_water_level*1.87);//16cm 수위 =30온스 if(water_intake_times==0){ previous_water_amount =water_amount_in_ounce; water_intake_times =1; } if((water_amount_in_ounce  previous_water_amount){ //물을 다시 채웁니다 //여기에 물을 보충합니다. previous_water_amount =water_amount_in_ounce; } else if(water_amount_in_ounce ==previous_water_amount){ // 물 소비 없음 또는 다시 채우기 idle_time+=1; } if(hours==23 &&minutes==59){ // 하루가 끝나고 모든 값은 새로운 날짜에 대해 0부터 시작합니다. for(int i=0; i<15; i++){ water_intake_ounch[i] =0; } water_intake_times =0; 섭취일++; if(intake_day==8){ 섭취일 =1; } }}int total_water_intake_in_day(){//하루의 총 수분 섭취량 계산 total_water_intake_today =0; for(int i=0; i  

    회로도


    제조공정

    1. 잔디 스프링클러
    2. 식기세척기
    3. 물총
    4. 화장실
    5. 소화전
    6. 단열 병
    7. 샴푸
    8. 건식 벽체
    9. MOSMusic