Pametni kokošinjac

CTK Rijeka

Ljudi koji imaju domaće životinje, moraju stalno biti uz njih kako bi se brinuli o njima. Imaju problem ako moraju otići od kuće na više dana. Ljudi koji žive u gradu, a imaju vikendicu na selu, ne mogu imati domaće životinje koje bi željeli. Zato sam osmislila pametni kokošinjac. Pametni kokošinjac potpuno zamjenjuje čovjeka u dnevnoj brizi o kokošima i obavještava ga o stanju kokoši.

Video snimka

Izrada projekta

Kokošinjcu se može otvoriti krov te unutrašnjost izgleda ovako. Unutra se nalaze Ultrazvučni senzor na vrhu hranilice, dva servo motora, senzor temperature i vlage, senzor za svjetlost, dvije LED-ice koje predstavljaju grijalicu i ventilator, te MKR1000 koji upravlja cijelim radom.

Projekt ima tri različita napajanja. MKR1000 se napaja putem USB kabela s računala ili punjača za mobitel. Sva ostala elektronika se napaja posebno da ne preoptereti MKR1000. Dodatni ispravljač nam daje 5V za napajanje nekih senzora. Na pokusnoj pločici je sklop za pretvaranje 5V u 3,3V koji je potreban za ostale senzore.

Kokošinjac ima klizna vrata koja se pomiču gore dolje po drvenim štapićima pomoću servo motora. S obje strane vrata nalaze se rampe ispod kojih su RFID senzori. Kokoš mora prijeći preko njih kako bi izašla ili ušla, a na nozi ima RFID prsten. Senzori očitavaju svaki prolazak kokoši. Ako odaberemo automatsko otvaranje vrata, vrata će se sama otvarati i zatvarati kako bi propustila kokoši. Kokošinjac mjeri jačinu svjetla vani, i ako je vani mračno onda neće pustiti kokoš da izađe, već samo da uđe. Ako isključimo automatska vrata, onda možemo sami putem mobitela otvarati i zatvarati vrata, a na mobitelu vidimo koja je kokoš vani, a koja unutra.

Hranilica se sastoji od vertikalnog spremnika za hranu koji ima otvor na prednjoj strani kokošinjca. Otvor je blokiran diskom koji na jednom mjestu ima urezani otvor. Servo motor upravlja okretanjem diska. Kada se disk okrene tako da se otvor na disku poklopi s otvorom na spremniku za hranu, hrana ispada u dvorište.

Na vrhu spremnika za hranu je ultrazvučni senzor udaljenosti. On odašilje ultrazvučni impuls koji putuje prema hrani u spremniku i odbija se natrag u senzor. Mjeri se koliko je vremena prošlo do povratka i tako izračunava udaljenost do hrane. Nakon toga se ta udaljenost pretvara u stupanj popunjenosti spremnika koji se u postocima prikazuje na mobitelu.

Mobilna aplikacija

Blynk aplikacija se sastoji od 12 widgeta. Njihova imena su: vrata, koka, pijevac, svjetlo, auto vrata, količina, hrana, vlaga, ventilator, auto temp, temperatura, grijalica. Button vrata otvara ili zatvara vrata na kokošinjcu, a ako su se vrata sama otvorila ili zatvorila onda nam to prikazuje. LED widgeti koka i pijevac prikazuju koji od njih je vani, a koji unutra. Kada bi imali više kokoši, samo bi dodali još ovakvih widgeta. Labeled value svjetlo pokazuje jačinu dnevne svjetlosti u postocima. Button auto vrata pokreće automatsko otvaranje vrata. Ako je uključeno, vrata su cijelo vrijeme zatvorena osim kada kokoši žele proći. Kada je isključeno, onda mi kontroliramo kada se vrata otvaraju ili zatvaraju. Labeled value količina prikazuje količinu hrane u spremniku u postocima. Button hrana iz hranilice izbacuje hranu. Labeled value widgeti vlaga i temperatura pokazuju vlagu i temperaturu zraka u kokošinjcu. Buttoni ventilator i grijalica uključuju ili isključuju grijanje i hlađenje kokošinjca. Button auto temp uključuje automatsko održavanje temperature. Ako temperatura padne ispod minimalne vrijednosti uključuje se grijalica. Ako poraste iznad maksimalne pali se ventilator. I jedno i drugo nam se prikazuje na odgovarajućim widgetima. Ako je između maksimalne i minimalne vrijednosti ne radi ni grijalica ni ventilator.

Shema projekta

Na pokusnoj pločici su spojena dva RFID senzora. Spojeni su na sljedeće pinove: SDA (prvi RFID) = 6, SDA(drugi RFID) = 7 RST(oba) = 11, SCK(oba) = 9, MOSI (oba) = 8, MISO(oba) = 10, GND = GND, VCC = 3.3 V . Ultrazvučni senzor je spojen na pinove 5 (trigger) i 4 (echo) i na 5 V. DHT senzor je spojen na pin 3 i na 5 V i GND. Senzor svjetla spojen je na pin A1, na GND i na 5 V. Svjetleće diode su spojene na pinove 0 i 1. Na pokusnoj pločici se nalazi sklop koji 5 V pretvara u 3 V radi potrebe RFID-a. Servo motor koji otvara vrata je spojen na pin 13, na GND i 5 V, a servo koji otvara hranilicu je spojen na pin 12.

Arduino program

#define BLYNK_PRINT /*

/*
Nika Bošnjak
28.04.2018.
Pametni kokošinjac
Radi sve što radi i seljak, samo pametnije 🙂
*/


#define BLYNK_PRINT Serial      //Koristi se za debug library-ja BLYNK
#define TRIG_PIN 5    //Triger za ultrazvučni senzor je spojen na pin 5
#define ECHO_PIN 4    //Echo ultrazvučnog senzora je spojen na pin 4
#define DHTPIN 3    //Senzor temperature i vlage je spojen na pin 3
#define DHTTYPE DHT11     //Tip DHT senzora je DHT11
#define RST_PIN         11    //SPI komunikacija, Reset je spojen na pin 11
#define SS_1_PIN        7     //SPI komunikacija, prvi RFID čitač je spojen na pin 7
#define SS_2_PIN        6     //SPI komunikacija, drugi RFID čitač je spojen na pin 6
#define NR_OF_READERS   2     //Broj spojenih RFID čitača je 2

// Ovo su potrebni library dodaci kako bi svi senzori radili
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

char auth[] = "0a791d52f81d4ce59d3f75483a1322f8";     //podaci za blynk

char ssid[] = "";     //podaci za wifi: upišite ime mreže
char pass[] = "";    //podaci za wifi: upišite password

int prethodnostanje;    //Ovo prati gdje je bila koka prije nego je došla na rampu, vani ili unutra
int prethodnostanje2;     //Ovo prati gdje je bio pijevac prije nego je došao na rampu, vani ili unutra
long trajanje, cm;    //Ultrazvučni senzor mjeri vrijeme koliko putuje zvuk, i to se preračunava u centimetre
int hrana;    //Centimetri od senzora do vrha hrane se preračunavaju u postotke 0-100% popunjenosti spremnika
int svjetlo;    //Jačina dnevne svjetlosti izražena u postocima 0-100%
int temp;     //Temperatura zraka
int min_temp=27;    //Kada se automatski uključuje grijanje, vrijednost odabrana za probu
int max_temp=30;    //Kada se automatski uključuje ventilator, vrijednost odabrana za probu
int relvlaga;     //Relativna vlaga zraka
boolean grijanje;     //Je li uključeno grijanje?
boolean ventilacija;    //Je li uključena ventilacija?
boolean gdjejekoka;     //Kada koka uđe ili izađe, ovdje se zapisuje gdje je
boolean gdjejepijevac;    //Kada pijevac uđe ili izađe, ovdje se zapisuje gdje je
boolean autovrata=0;      //Je li uključeno automatsko otvaranje vrata?
boolean autotemp=0;     //Je li uključeno automatsko održavanje temperature?
DHT_Unified dht(DHTPIN, DHTTYPE);     //Definiranje varijable dht za čitanje temperature i vlage
byte ssPins[] = {SS_1_PIN, SS_2_PIN};     //Pinovi za RFID senzore
byte koka[] = {0x9A, 0x39, 0x52, 0xA3};     //RFID HEX kod koji pripada koki
byte pijevac[] = {0x40, 0x90, 0xB4, 0x73};    //RFID HEX kod koji pripada pijevcu
MFRC522 mfrc522[NR_OF_READERS];     //Definiranje varijable za čitanje RFID tagova
Servo vrata;    //Varijabla za upravljanje mehanizmom za vrata
Servo hranilica;    //Varijabla upravljanje mehanizmom za hranilicu
HCSR04 hcsr04(TRIG_PIN, ECHO_PIN, 20, 4000);    //Ultrazvučni senzor
WidgetLED led1(V6);     //Praćenje gdje je koka putem Blynka
WidgetLED led2(V7);     //Praćenje gdje je pijevac putem Blynka

//Kada se pritisne Blynk Button "vrata", pokrene se ova funkcija
BLYNK_WRITE(V0) 
{
  int pinValue = param.asInt();
  if (pinValue==HIGH)
  {
    otvorivrata();
  }
  else
  {
    zatvorivrata();
  }
}

//Kada se pritisne Blynk Button "hrana", pokrene se ova funkcija
BLYNK_WRITE(V1)
{
  int pinValue = param.asInt();
  if (pinValue==HIGH)
  {
    dajhranu();
  }
}

//Blynk Labeled Value "hrana" čita koliko ima hrane
BLYNK_READ(V2)
{
  Blynk.virtualWrite(V2,kolikoimahrane());
}

//Blynk Labeled Value "svjetlo" čita jačinu svjetla
BLYNK_READ(V3)
{
  Blynk.virtualWrite(V3,kolicinasvjetla());
}

//Blynk Labeled Value "temperatura" čita temperaturu
BLYNK_READ(V4)
{
  Blynk.virtualWrite(V4,temperatura());
}

//Blynk Labeled Value "vlaga" čita vlagu
BLYNK_READ(V5)
{
  Blynk.virtualWrite(V5,vlaga());
}

//Kada se pritisne Blynk Button "auto vrata", pokrene se ova funkcija
BLYNK_WRITE(V8)
{
  int pinValue = param.asInt();
  if (pinValue==HIGH)
  {
    autovrata=1;      //Automatsko upravljanje vratima uključeno
  }
  else
  {
    autovrata=0;      //Automatsko upravljanje vratima isključeno
  }
}

//Kada se pritisne Blynk Button "auto temp", pokrene se ova funkcija
BLYNK_WRITE(V9)
{
  int pinValue = param.asInt();
  if (pinValue==HIGH)
  {
    autotemp=1;     //Automatsko upravljanje temperaturom uključeno
  }
  else
  {
    autotemp=0;     //Automatsko upravljanje temperaturom isključeno
  }
}

//Kada se pritisne Blynk Button "ventilator", pokrene se ova funkcija
BLYNK_WRITE(V10)
{
  int pinValue = param.asInt();
  if (pinValue==HIGH)
  {
    digitalWrite(0,HIGH);     //Ventilator spojen na pin 0 je uključen
  }
  else
  {
    digitalWrite(0,LOW);    //Ventilator spojen na pin 0 je isključen
  }
}

//Kada se pritisne Blynk Button "grijalica", pokrene se ova funkcija
BLYNK_WRITE(V11)
{
  int pinValue = param.asInt();
  if (pinValue==HIGH)
  {
    digitalWrite(1,HIGH);     //Grijalica spojena na pin 1 je uključena
  }
  else
  {
    digitalWrite(1,LOW);      //Grijalica spojena na pin 1 je isključena
  }
}

//Funkcija za otvaranje vrata
void otvorivrata()
{
  vrata.write(15);
  Blynk.virtualWrite(V0,1);     //Stanje vrata se šalje na Blynk button "vrata"
}

//Funkcija za zatvaranje vrata
void zatvorivrata()
{
  vrata.write(180);
  Blynk.virtualWrite(V0,0);     //Stanje vrata se šalje na Blynk button "vrata"

}

//Funkcija za ispuštanje hrane
void dajhranu()
{
  hranilica.write(90);     //Otvara se otvor na spremniku hrane
  delay(500);     //Čeka se pola sekunde
  hranilica.write(120);      //Zatvara se otvor na spremniku hrane
}


//Funkcija za automatsko održavanje temperature
void auto_temp()
{
  if (tempmax_temp)    //Ako je temperatura veća od maksimalne dozvoljene
  {
    digitalWrite(0, HIGH);    //Uključi ventilator
    Blynk.virtualWrite(V10,1);    //Šalje se stanje ventilatora na Blynk button "ventilator"
  }
  else //Ako temperatura nije veća od maksimalne
  {
    digitalWrite(0, LOW);     //Isključi ventilator    
    Blynk.virtualWrite(V10,0);      //Šalje se stanje ventilatora na Blynk button "ventilator"

  }  
}

//Funkcija koja računa koliko još ima hrane u spremniku
int kolikoimahrane()
{
  digitalWrite(TRIG_PIN, LOW);      //Priprema za slanje ultrazvučnog impulsa
  delayMicroseconds(5);     //Čekanje 5 mikrosekundi prije impulsa
  digitalWrite(TRIG_PIN, HIGH);     //Slanje ultrazvučnog impulsa
  delayMicroseconds(10);      //Impuls traje 10 mikrosekundi
  digitalWrite(TRIG_PIN, LOW);      //Impuls se isključuje
  trajanje = pulseIn(ECHO_PIN, HIGH);     //Očitanje vremena koliko je zvuk putovao
  cm = (trajanje/2) / 29.1;     //Vrijeme se dijeli sa 2 i onda sa omjerom vremena i puta
  Serial.print(cm);     //Na serijski port se šalje izmjerena udaljenost
  Serial.print("cm");     //Dodaje se mjerna jedinica
  Serial.println();     //Preskače se linija
  hrana = map(cm, 23, 4, 0, 100);     //Izmjerena udaljenost od 23cm do 4cm se preračunava u vrijednost od 0% do 100%
  return (hrana);     //Vraća se izračunata vrijednost
}

//Čitanje jačine dnevnog svjetla
int kolicinasvjetla()
{
  svjetlo=analogRead(A1);     //Senzor svjetla je spojen na pin A1
  svjetlo=map(svjetlo, 0, 1024, 100, 0);      //Analogna vrijednost se preračunava u postotke
  return (svjetlo);     //Vraća se izračunata vrijednost
}

//Čitanje temperature, kopirano s uputa za DHT senzor
int temperatura()
{
  sensors_event_t event;  
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println("Error reading temperature!");
  }
  else {
    Serial.print("Temperature: ");
    Serial.print(event.temperature);
    Serial.println(" *C");
    temp=(event.temperature);
    return(temp);
  }
}

//Čitanje vlage, kopirano s uputa za DHT senzor
int vlaga()
{
    sensors_event_t event;  
   dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
  }
  else {
    Serial.print("Humidity: ");
    Serial.print(event.relative_humidity);
    Serial.println("%");
    relvlaga=(event.relative_humidity);
    return(relvlaga);
  }
}

//Ovo se izvršava samo jednom kod uključivanja
void setup() {
  SPI.begin();        // Pokretanje SPI komunikacije
  Serial.begin(9600);     //Pokretanje serijske komunikacije
  Blynk.begin(auth, ssid, pass);      //Pokretanje BLYNK-a
  vrata.attach(13);     //Vrata su spojena na pin13
  hranilica.attach(12);     //Hranilica je spojena na pin12
  pinMode(TRIG_PIN, OUTPUT);    //Pin za slanje ultrazvučnog signala
  pinMode(ECHO_PIN, INPUT);     //Pin za primanje signala sa ultrazvučnog senzora
  pinMode(A1, INPUT);     //Pin za senzor svjetlosti
  pinMode(0, OUTPUT);     //Pin za zelenu ledicu koja predstavlja ventilator
  pinMode(1, OUTPUT);     //Pin za crvenu ledicu koja predstavlja grijalicu
  dht.begin();      //Pokretanje komunikacije sa DHT senzorom
  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN);    //Pokretanje svih RFID čitača
    Serial.print(F("Reader "));
    Serial.print(reader);
    Serial.print(F(": "));
    mfrc522[reader].PCD_DumpVersionToSerial();      //Ako RFID rade ispravno onda se na Serial ispisuje verzija programa
  }
  prethodnostanje=0;      //Kod pokretanja programa definira se da je koka unutra
  prethodnostanje2=0;     //Kod pokretanja programa definira se da je pijevac unutra
}

//Ovo se izvodi cijelo vrijeme dok je Arduino uključen
void loop() {
  Blynk.run();      //Blynk stalno radi
    for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    // Gleda se je li na kojem RFID čitaču prislonjen RFID tag
    if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {
      Serial.print(F("Reader "));
      Serial.print(reader);
      //Na serijski port se šalje podatak sa RFID taga
      Serial.print(F(": Card UID:"));
      dump_byte_array(mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size, reader); 
      Serial.println();
      Serial.print(F("PICC type: "));
      MFRC522::PICC_Type piccType = mfrc522[reader].PICC_GetType(mfrc522[reader].uid.sak);
      Serial.println(mfrc522[reader].PICC_GetTypeName(piccType));

      //Kopirano sa uputa za RFID čitače
      mfrc522[reader].PICC_HaltA();
	  
      mfrc522[reader].PCD_StopCrypto1();
    } 
  } 
  if (autotemp==1)
  {
    auto_temp();
  }
}

//Uspoređivanje pročitanog RFID taga sa oznakama koje pripadaju koki i pijevcu
void dump_byte_array(byte *buffer, byte bufferSize, byte reader) 
{
  if (buffer[0]==koka[0] and buffer[1]==koka[1]and buffer[2]==koka[2]and buffer[3]==koka[3]) //buffer je pročitani tag, gleda se je li ista vrijednost kao koka
  {
    if (reader==0) //Ako je to koka, i ako je ona baš na vanjskom RFID čitaču
    {
    Serial.println("koka je vani");     //Na serijski port nam se ispisuje da je koka trenutno vani
    gdjejekoka=0;     //Sprema se informacija gdje je koka
    if (prethodnostanje==0 && autovrata==1){      //Ako je koka već bila vani onda sigurno želi ući, pa se gleda je li uključeno "auto vrata"
      otvorivrata();      //Otvaraju se vrata da puste koku unutra
    }
    if (prethodnostanje==1 && autovrata==1) {     //Ako je koka prije bila unutra a sad je vani, znači da je upravo izašla
      zatvorivrata();     //Ako je uključeno "auto vrata" onda će se vrata zatvoriti za kokom
    }
    prethodnostanje = 0;    //Sada zapamtimo da je koka vani
    led1.off();     //Šalje se stanje koke na mobitel
    }
    else    //Ako je to bila koka, ali nije na vanjskom nego unutarnjem čitaču
    {
    Serial.println("koka je unutra");     //Na serijski port nam se ispisuje da je koka trenutno unutra
    gdjejekoka=1;     //Sprema se informacija gdje je koka
    if (prethodnostanje==1 && autovrata==1 && svjetlo>15) {     //Ako koka želi vani, onda se gleda je li "auto vrata" i je li vani dan
      otvorivrata();    //Ako je vani dan, a koka želi izaći, onda se otvaraju vrata
    }
    if(prethodnostanje==0 && autovrata==1) {    //Ako je koka prije bila vani a sad unutra, znači da je upravo ušla
      zatvorivrata();     //Ako je "auto vrata" onda se vrata zatvaraju
    }
    prethodnostanje= 1;
    led1.on();
    }
  }
  //Isto kao za koku, sada se sve ponavlja za pijevca
    if (buffer[0]==pijevac[0] and buffer[1]==pijevac[1]and buffer[2]==pijevac[2]and buffer[3]==pijevac[3])
  {
    if (reader==0)
    {
    Serial.println("pijevac je vani");
    gdjejepijevac=0;
    if(prethodnostanje2==0 && autovrata==1) {
      otvorivrata();
    }
    if(prethodnostanje2==1 && autovrata==1) {
      zatvorivrata();
    }
    prethodnostanje2=0;
    led2.off();
    }
    else
    {
    Serial.println("pijevac je unutra");
    gdjejepijevac=1;
    if(prethodnostanje2==1 && autovrata==1 && svjetlo>15) {
      otvorivrata();
    }
    if(prethodnostanje2==0 && autovrata==1) {
      zatvorivrata();
    }
    prethodnostanje2=1;
    led2.on();
    }
  }
}

// Gotovo!!!
//Nika Bošnjak, 28.04.2018.

Arduino program ovoga projekta možete preuzeti ovdje.

Autori

Projekt je izradila Nika Bošnjak uz mentorstvo Ivane Žužić iz CTK Rijeka.

Projekt je prijavljen na temu: Internet of Things: Kućni ljubimci i domaće životinje.

Drugi projekti