Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Arduino-aangedreven waterfles

Componenten en benodigdheden

SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
Waterdichte ultrasone sensor
× 1
Real Time Clock (RTC)
× 1
SparkFun Common-kathode 4-cijferig 7-segments display
× 1
Zoemer
× 1
SparkFun Drukknopschakelaar 12 mm
× 1
Transistor-NPN voor algemeen gebruik
× 1
Li-ion batterij 1000mAh
× 1
Adafruit USB Li-ion-batterijlader
× 1
Weerstand 221 ohm
× 8
Weerstand 1k ohm
× 4
Weerstand 4.75k ohm
× 2

Benodigde gereedschappen en machines

Soldeerbout (algemeen)
Hot lijmpistool (algemeen)

Apps en online services

Arduino IDE

Over dit project

Inleiding:

Voldoende water drinken is erg belangrijk voor onze gezondheid. Meer water drinken kan leiden tot een helderdere huid, een betere algehele gezondheid, verbeterde productiviteit en hersenfunctie, meer energie en zelfs gewichtsverlies.

In ons drukke leven is het heel moeilijk om te onthouden dat we genoeg water moeten drinken. En meestal vergeten we voldoende water te drinken, of we nu thuis, op kantoor of onderweg zijn. Ongeveer 75% van de Amerikanen is voortdurend chronisch uitgedroogd.

Om een ​​gezonde gewoonte om water te drinken op te bouwen, is het dus belangrijk om uw waterinname elke dag bij te houden.

Om mijn waterinname bij te houden, heb ik mijn waterfles slim gemaakt met Arduino. Het kan:

1. Houd mijn dagelijkse waterinname bij

2. Volg mijn wekelijkse gemiddelde waterinname

3. Herinner me eraan om water te nemen

4. Volg de laatste innametijd

5. Gebruik meer dan een maand met één keer opladen.

RTC-module maken

Om informatie over de wateropname te loggen of te volgen, moet de huidige tijd- en datuminformatie samen met de verzamelde gegevens worden opgeslagen. Een Real-Time Clock (RTC) chip zoals DS1307 met een geschikte back-up batterij kan worden gebruikt om de benodigde informatie te leveren. Het programmeerproces van de RTC-chip (in software) is ook heel eenvoudig en wordt in de meeste programmeeromgevingen ondersteund.

Hier is het ontwerp van een compacte RTC-module, gebaseerd op de populaire RTC IC DS1307, voor uw dagelijkse microcontrollerprojecten. De DS1307 seriële real-time klok (RTC) is een low power, volledig binair gecodeerde decimale (BCD) klok/kalender plus 56 bytes NV SRAM. Adres en gegevens worden serieel overgedragen via een I2C, bidirectionele bus. De 24-uurs/12-uurs klok/kalender biedt informatie over seconden, minuten, uren, dag, datum, maand en jaar, inclusief correcties voor schrikkeljaar.

Laten we de real-time klokmodule maken volgens het bijgevoegde schema. DS1307 RTC vereist een extern kristal om correct te werken. Er zijn twee pull-up weerstanden nodig voor SCL &SDA pin van het IC. De waarde van de weerstand kan ongeveer 2k tot 10k zijn. Ik gebruikte 4.7k. Tijdens het solderen heb ik geprobeerd de module zo klein mogelijk te houden omdat de ruimte voor mijn circuit beperkt is. Je kunt DS3231 gebruiken in plaats van DS1307 en het IC heeft een interne kristaloscillator. U hoeft dus geen extern kristal toe te voegen. U kunt ook een kant-en-klare kleine RTC-module kopen als u deze niet zelf wilt maken. Omdat het hele systeem op een batterij werkt, heb ik om die reden de VBAT-pin van de RTC op aarde aangesloten zonder een knoopcel te gebruiken.

Belangrijke pinnen van DS1307:

  • 5V-pin :Wanneer deze pin hoog is, verzendt de ds1307 de gegevens, en wanneer deze laag is, wordt deze uitgevoerd op de back-up knoopcel.
  • GND :Dit is de aardingspin voor de module. Zowel de massa van de batterij als de voeding zijn met elkaar verbonden.
  • SCL :Het is de I2C-klokpen - die communiceert met de microcontroller. Moet verbinding maken met Arduino SCL-pin.
  • SDA :Het is de I2C-gegevenspin - die communiceert met de microcontroller. Moet verbinding maken met Arduino SDA-pin.
  • VBAT :Batterij-ingang voor elke standaard 3V lithiumcel of andere energiebron. Moet geaard zijn als het niet wordt gebruikt.

Displaybord met zeven segmenten maken

Voor de weergavemodule hier heb ik een op zichzelf staande, compacte gemeenschappelijke kathodemodule gebruikt die vier 7-segments LED-numerieke displays bevat die goed zijn voor het weergeven van numerieke gegevens met een eenvoudig karakter.

Elk segment in de displaymodule is gemultiplext, wat betekent dat het dezelfde anode-aansluitpunten deelt. En elk van de vier cijfers in de module heeft zijn eigen gemeenschappelijke kathode-aansluitpunt. Hierdoor kan elk cijfer afzonderlijk worden in- of uitgeschakeld. Bovendien verandert deze multiplextechniek de enorme hoeveelheid microcontroller-pinnen die nodig zijn om een ​​display te besturen in slechts elf of twaalf (in plaats van tweeëndertig)!

De LED-segmenten van het display hebben stroombeperkende weerstanden nodig wanneer ze worden gevoed via een logische pin van 5 V. De waarde van de weerstand ligt typisch tussen 330 en 470 ohm voor 5 V. Voor gebruik met een Li-ionbatterij kan dit 220 ohm zijn. En drivertransistors worden aanbevolen om extra stuurstroom naar de LED-segmenten te leveren, omdat elke pin van een microcontroller slechts in de buurt van 40 mA stroom kan leveren of zinken. Wanneer alle (zeven) segmenten van het display tegelijk zijn ingeschakeld (het cijfer 8), zal de huidige vraag deze 40 mA-limiet overschrijden. De onderstaande afbeelding toont het basisbedradingsschema van de stroombeperkende weerstanden en drivertransistors.

Dit 4-cijferige 7-segments displaygedeelte is bedraad rond vier 7-segments LED-displays met gemeenschappelijke kathode en vier 2N2222 NPN-transistoren. De 1K-weerstanden worden gebruikt voor basisstroombegrenzing en de 220R-weerstanden beperken de bedrijfsstroom van de LED-displaysegmenten.

In het Arduino-bord worden digitale uitgangen van D10 tot D17 gebruikt om segmenten (a tot g &dp) aan te sturen, en digitale uitgangen D6 tot D9 worden gebruikt voor de cijfers (D0-D3) van het 4×7 LED-display.

Een knopschakelaar is toegevoegd aan de displaymodule om toegang te krijgen tot verschillende opties. Het zal ook worden gebruikt om de Arduino uit de slaapstand te halen met behulp van externe hardware-interrupt. dus de knop is verbonden met Arduino digitale pin #2 (INT0).

Display Board verbinden met Arduino Mini Pro

Volgens het eerder verstrekte schema soldeer je alle segmenten op de Arduino-minipin. Soldeer vervolgens 4 gemeenschappelijke pins aan de collectorpin van de transistor. De bases van de transistor zijn verbonden met de Arduino-pin. Sluit na het aansluiten van het display de knopschakelaar aan op de Arduino digitale pin 2 (INT 0). Zorg ervoor dat je de knop op Arduino pin 2 hebt aangesloten, want we zullen een externe hardware-interrupt implementeren om Arduino uit de slaapstand te halen met behulp van deze knop.

RTC-module en zoemer aansluiten

Sluit nu de RTC-module die u eerder hebt gemaakt aan op het Arduino-bord. De SDA-pin van de module moet worden aangesloten op de SDA (A4)-pin van de Arduino-pin en de SCL-pin van de module moet worden aangesloten op de SCL (A5)-pin van de Arduino. Sluit vervolgens de zoemer aan op het Arduino-bord.

Verbindingen:

RTC ------> Arduino Mini Pro

  • SDA ------> A4
  • SCL ------> A5
  • Zoemer ------> D3

Ultrasone sensor met flesdop bevestigen

Maak een gat in de dop van de fles, zoals weergegeven in de afbeelding. Haal vier draden van de ultrasone sensor door het gat en bevestig de ultrasone sensor in het midden van de dop van de fles. De sensor moet aan de binnenkant van de dop van de fles worden bevestigd en moet in het midden worden geplaatst.

Verbindingen:

Ultrasone sensor ------> Arduino Mini Pro

  • VCC ------> VCC
  • GND ------>GND
  • Trigger ------> D4
  • Echo ------> D5

Programma uploaden en testen

Nadat alle verbindingen zijn gemaakt, is het het juiste moment om het programma naar het Arduino-bord te uploaden en de functionaliteit te testen. U hebt verschillende bibliotheken nodig om het programma correct te laten werken. Voor knopinterface moet u de OneButton-bibliotheek toevoegen. Aangezien het apparaat op batterij werkt, is het stroomverbruik een belangrijk punt. Ik heb de slaapmodus geïmplementeerd in mijn Arduino-schets. Watchdog-timer en externe hardware-interrupt werden gebruikt om de Arduino uit de slaapstand te halen. Arduino meet de sensor drie keer, neemt het gemiddelde en berekent de benodigde informatie en geeft informatie weer voor 10 seconden en gaat dan 1 minuut naar de slaapmodus. Het wordt op elk moment wakker met een ingedrukte knop die is aangesloten op INT0 (digitale pin 2). Dus als u de informatie over uw waterinname wilt zien, drukt u op elk gewenst moment op de optieknop. Het zal voor je wakker worden. Zonder enige druk op de knop wordt elke minuut gelezen. Voor het implementeren van de slaapmodus heb ik de Arduino Low-Power-bibliotheek gebruikt. Voor het lezen van de tijd van de DS1307 RTC-module heb ik de DS1307RTC-bibliotheek gebruikt. Dus, voor het compileren van het bijgevoegde programma, voeg de hele bibliotheek toe aan je omgeving.

Ik zal hier alleen het rekenalgoritme in het kort uitleggen. Zie de bijgevoegde vulling voor de volledige schets. De berekening wordt gedaan op basis van het gemiddelde van vijf sensormetingen om het nauwkeurig genoeg te maken. De dagelijkse lezing wordt op 24 uur gereset en voorbereid op nieuwe lezing voor de nieuwe dag.

De gemiddelde wateropname wordt berekend op basis van het gemiddelde van de dagelijkse inname van de afgelopen zeven dagen. Als u 2 uur bent verstreken zonder inname van water, wordt de gebruiker elke 15 minuten gewaarschuwd met een dubbele piep en stopt de volgende 2 uur na het innemen van water.

Download de bijgevoegde code en upload deze naar uw Arduino Mini Pro. Sluit alle modules aan en schakel deze in om te testen of alle componenten correct werken of niet. Als het display enig resultaat laat zien, gefeliciteerd! Je hebt de moeilijke dingen al gedaan.

Arduino repareren met kroonkurk

Bevestig Arduino mini met behulp van hete lijm aan de bovenzijde van de dop van de fles. Houd er rekening mee dat u alle componenten in de dop van de fles moet bevestigen. Voeg voldoende lijm toe zodat deze stevig aan de dop van de fles vastzit.

Batterij- en opladermodule bevestigen

Bevestig nu de Li-ion-batterij in de bovenkant van de Arduino. Wees voorzichtig met het kortsluiten van de batterij met een open pin. Verbind vervolgens de oplaadmodule met de dop. Houd de USB-poort gemakkelijk toegankelijk vanaf de buitenkant, zodat deze eenvoudig op de oplader kan worden aangesloten.

Alle circuits waterdicht maken

Na het aansluiten van alle componenten en module is het de juiste tijd om ons apparaat volledig waterdicht te maken. Het is erg belangrijk omdat het een waterfles is en er op elk moment water in het circuit kan vallen en het circuit kan beschadigen. Om het volledig waterdicht te maken, voegt u voldoende lijm toe in elk buitenste deel van de circuits zonder de USB-poort. Je kunt de dop mooi maken met lijm om hem rond te maken op de originele dop.

Laat de dop van de fles niet in het water zinken.

Geniet ervan

Code

  • Arduino-schets
Arduino SchetsArduino
// Datum- en tijdfuncties met behulp van een DS1307 RTC aangesloten via I2C en Wire lib#include #include #include #include #include " LowPower.h"#include "OneButton.h"OneButton-knop(2, true);const byte interruptPin =2;vluchtige 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 segment[8] ={16,10,12,14,15, 17,11,13};const byte nummer [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 byte d[8] ={0,1,1,1,1,0,1,1};const byte a[8] ={1,1,1,0,1,1,1,1 };const-byte r[8] ={0,0,0,0,1,0,1,1};const-byte t[8] ={0,0,0,1,1,1,1,1 };int seconden, minuten, uren;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 gemiddelde_intake_last_week =0;int inatke_day =1;float gemiddelde_water_level =0; // bewaar gemiddelde van meerdere uitlezingen water_amount_in_ounce =0; // berekende hoeveelheid water opslaanint idle_time =0;int intake_day =1;int previous_value =0;void setup() {Serial.begin(9600); pinMode (interruptPin, INPUT_PULLUP); // plaats hier je setup-code om een ​​keer uit te voeren:for(int i=6; i<=17; i++) pinMode(i, OUTPUT); pinMode (trigPin, UITGANG); pinMode (echoPin, INPUT); button.attachClick(ingedrukt); button.attachDoubleClick(dubbelklik); button.attachLongPressStart(longPressStart); button.attachDuringLongPress(longPress);}long previous_state =millis();int count =1;int daily_intake =0;int wekelijkse_intake =0;long sleep_time =millis();void loop() { read_time(); knop.tick(); // blijf de drukknoppen in de gaten houden:berekening(); daily_intake =totale_water_intake_in_day(); wekelijkse_intake =gemiddelde_water_intake_last_week(); if(button_press_count ==1){ display_d(); display_number (dagelijkse_inname); } else if(button_press_count ==2){ display_a(); display_number (wekelijkse_intake); } else if(button_press_count ==3){ display_r(); display_number(water_amount_in_ounce); } else if(button_press_count ==4){ display_first_2(hours); display_last_2(minuten); } if(idle_time>=120){ alert(); waarschuwing(); } if((millis() - sleep_time)>=15000){ display_off(); attachInterrupt(digitalPinToInterrupt(interruptPin), blanco, 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(digitalPinToInterrupt(interruptPin)); sleep_time =millis(); } }void display_digit(int digit){ for(int i=0; i<8; i++){ digitalWrite(segment[i], number[digit][i]); } }void display_number (int nummer){ int i=0; while(getal>0){ digit_value[2-i] =aantal%10; getal =getal/10; i++; } digitalWrite(cijfer [1], HOOG); digitalWrite(cijfer [2], LAAG); digitalWrite(cijfer [3], LAAG); display_digit(digit_value[0]); vertraging (5); digitalWrite(cijfer [1], LAAG); digitalWrite(cijfer[2], HOOG); digitalWrite(cijfer [3], LAAG); display_digit(digit_value[1]); vertraging (5); digitalWrite(cijfer [1], LAAG); digitalWrite(cijfer [2], LAAG); digitalWrite(cijfer [3], HOOG); display_digit(digit_value[2]); vertraging (5); digitalWrite(cijfer [3], LAAG); cijferwaarde[0] =0; cijferwaarde[1] =0; cijferwaarde[2] =0; }void display_first_2(int nummer){ digitalWrite(digit[2], LOW); digitalWrite(cijfer [3], LAAG); int i=0; while(getal>0){ digit_value[1-i] =getal%10; getal =getal/10; i++; } digitalWrite(cijfer [0], HOOG); digitalWrite(cijfer [1], LAAG); display_digit(digit_value[0]); vertraging (3); digitalWrite(cijfer [0], LAAG); digitalWrite(cijfer [1], HOOG); display_digit(digit_value[1]); vertraging (3); }void display_last_2(int nummer){ digitalWrite(digit[0], LOW); digitalWrite(cijfer [1], LAAG); int i=0; while(getal>0){ digit_value1[1-i] =getal%10; getal =getal/10; i++; } digitalWrite(cijfer [2], HOOG); digitalWrite(cijfer [3], LAAG); display_digit(digit_value1[0]); vertraging (3); digitalWrite(cijfer [2], LAAG); digitalWrite(cijfer [3], HOOG); display_digit(digit_value1[1]); vertraging (3); }void display_d(){ digitalWrite(digit[0], HIGH); for(int i=0; i<8; i++){ digitalWrite(segment[i], d[i]); } vertraging (5); digitalWrite(cijfer [0], LAAG); }void display_a(){ digitalWrite(digit[0], HIGH); for(int i=0; i<8; i++){ digitalWrite(segment[i], a[i]); } vertraging (5); digitalWrite(cijfer [0], LAAG); } void display_r(){ digitalWrite(digit[0], HIGH); for(int i=0; i<8; i++){ digitalWrite(segment[i], r[i]); } vertraging (5); digitalWrite(cijfer [0], LAAG); } void display_t(){ digitalWrite(digit[0], HIGH); for(int i=0; i<8; i++){ digitalWrite(segment[i], t[i]); } vertraging (5); digitalWrite(cijfer [0], LAAG); }void display_off(){ digitalWrite(digit[0], LOW); digitalWrite(cijfer [1], LAAG); digitalWrite(cijfer [2], LAAG); digitalWrite(cijfer [3], LAAG); for(int i=0; i<8; i++){digitalWrite(segment[i], LOW); } vertraging (5); }void read_time() { tmElements_t tm; if (RTC.read(tm)) {seconden =tm.Second; minuten =tm.Minuut; uur =tm.Uur; } }int distance_in_cm(){ lange duur, cm; // De sensor wordt geactiveerd door een HOGE puls van 10 of meer microseconden. // Geef vooraf een korte LOW-puls om een ​​zuivere HIGH-puls te garanderen:digitalWrite(trigPin, LOW); vertragingMicroseconden(2); digitalWrite(trigPin, HOOG); vertraging Microseconden (10); digitalWrite(trigPin, LAAG); // Lees het signaal van de sensor:een HOGE puls waarvan de // duur de tijd (in microseconden) is vanaf het verzenden van // van de ping tot de ontvangst van zijn echo van een object. duur =pulseIn(echoPin, HOOG); // zet de tijd om in een afstand cm =microsecondenToCentimeters (duur); retour cm; }lange microsecondenToCentimeters(lange microseconden) { // De geluidssnelheid is 340 m/s of 29 microseconden per centimeter. // De ping reist heen en terug, dus om de afstand van het //-object te vinden, nemen we de helft van de afgelegde afstand. retour microseconden / 29 / 2; }nietig alarm(){ tone(piezoPin, 2000, 50); toon (piezoPin, 2000, 200); //vertraging (10); }void blank() { //tone(piezoPin, 2000, 100); //state++;}// Deze functie wordt aangeroepen wanneer de knop1 1 keer werd ingedrukt (en er volgde geen 2. druk op de knop). button_press_count++; waarschuwing(); if(button_press_count ==5){ button_press_count =1; }} // click// Deze functie wordt aangeroepen wanneer de button1 2 keer werd ingedrukt in een korte tijdspanne.void doubleclick() { Serial.println("Button 1 doubleclick.");} // doubleclick// Deze functie zal één keer worden aangeroepen, wanneer knop1 lang wordt ingedrukt.void longPressStart() { Serial.println("Button 1 longPress start");} // longPressStart// Deze functie wordt vaak aangeroepen, terwijl knop1 wordt ingedrukt voor a long time.void longPress() { Serial.println("Knop 1 longPress..."); water_intake_ounch[water_intake_times - 1] =0; // laatste waarde negeren} // longPressvoid-berekening () { float water_level =0;// winkelniveau in elke stap int read_value =0; // lees sensorwaarde in cm for (int i=0; i<5; i++) {//neem vijf aflezing read_value =distance_in_cm (); if(read_value>16 || read_value<3){// onstabiele leesretour; // keer terug naar de aanroepfunctie omdat lezen onstabiel is} else if(read_value<=16 &&read_value>=3){//valid value water_level =water_level + read_value; } vertraging(10); } gemiddeld_waterniveau =17 - waterniveau/5; // vind gemiddelde van vijf metingen, 17 =botole hoogte water_amount_in_ounce =int(average_water_level*1.87);//16 cm water level =30 ounce if(water_intake_times==0){ previous_water_amount =water_amount_in_ounce; water_intake_times =1; } if((water_amount_in_ounce  previous_water_amount){ // water wordt bijgevuld // water refil here previous_water_amount =water_amount_in_ounce; } else if(water_amount_in_ounce ==previous_water_amount){ // geen water verbruikt of bijvullen idle_time+=1; } if(hours==23 &&minutes==59){ // een dag is voorbij en alle waarden beginnen vanaf nul voor nieuwe dag for(int i=0; i<15; i++){ water_intake_ounch[i] =0; } water_intake_times =0; intake_dag++; if(intake_day==8){ intake_day =1; } }}int total_water_intake_in_day(){//bereken de totale wateropname op een dag total_water_intake_today =0; for(int i=0; i  

Schema's


Productieproces

  1. Gazonsproeier
  2. Vaatwasser
  3. Waterpistool
  4. Toilet
  5. Brandkraan
  6. Geïsoleerde fles
  7. Water
  8. Shampoo
  9. Drywall
  10. Geïntegreerd circuit
  11. MOSMusic