Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Elmin Delibašić
Published © GPL3+

Home Security System

Sony Spresense Board + NodeMCU + Google Firebase + Android Studio

ExpertFull instructions providedOver 4 days7,347

Things used in this project

Story

Read more

Custom parts and enclosures

Sound1.mp3

Sound2.mp3

Sound3.mp3

Schematics

Complete scheme (1)

Complete scheme (2)

Code

test.ino

Arduino
void setup() {
    pinMode(LED0, OUTPUT);
    pinMode(LED1, OUTPUT);
    pinMode(LED2, OUTPUT);
    pinMode(LED3, OUTPUT);
}

void loop() {
    digitalWrite(LED0, HIGH);
    delay(100);
    digitalWrite(LED1, HIGH);
    delay(100);
    digitalWrite(LED2, HIGH);
    delay(100);
    digitalWrite(LED3, HIGH);
    delay(1000);

    digitalWrite(LED0, LOW);
    delay(100);
    digitalWrite(LED1, LOW);
    delay(100);
    digitalWrite(LED2, LOW);
    delay(100);
    digitalWrite(LED3, LOW);
    delay(1000);
}

sony_spresense_board.ino

Arduino
#include<SoftwareSerial.h>
#include <SDHCI.h>
#include <Audio.h>


int IN1 = 3, IN2 = 5, IN3 = 6, IN4 = 9, d = 10; //Stepper motor control
int pirPin = 13,micPin = 8, trigPin = 10, echoPin = 11, distance; //Sensor pin
int resPin = 2, LED = 12;



//Sound data
SDClass theSD;
AudioClass *theAudio;

File myFile;

bool ErrEnd = false;

static void audio_attention_cb(const ErrorAttentionParam *atprm)
{
  puts("Attention!");
  
  if (atprm->error_code >= AS_ATTENTION_CODE_WARNING)
    {
      ErrEnd = true;
   }
}

//end


void setup() {
  //Serial S Begin at 9600 Baud
  digitalWrite(resPin, HIGH);
  
  pinMode(resPin, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(trigPin, INPUT);
  pinMode(echoPin, INPUT);
  pinMode(LED, OUTPUT);
  }

void loop() {

  


    
    
  steppermotor();


  //PIR Sensor data -----------------------------------------------------------

  boolean pir_data = digitalRead(pirPin);
  if (pir_data == 1) {
    digitalWrite(LED, HIGH);
    audiosetup1();
    delay(5000);
    digitalWrite(resPin, LOW);   
    }
  else {

      digitalWrite(LED, LOW);
      
      }

  //HC-SR04 sensor data -------------------------------------------------------
  
    digitalWrite(trigPin, LOW); //turn off trigPin
    delayMicroseconds(2);   
    digitalWrite(trigPin, HIGH); //turn on trigPin
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW); //turn off trigPn
    long duration = pulseIn(echoPin, HIGH); //returns the sound wave travel time in microseconds
    int distance = duration*0.034/2; 
    
  if (distance < 7) {
  audiosetup2();
  delay(5000);
  digitalWrite(resPin, LOW);
  }

  //Microphone Module ---------------------------------------------------------

  
  boolean mic_data = digitalRead(micPin);

   if (mic_data == 1) {
  audiosetup3();
  delay(5000);
  digitalWrite(resPin, LOW);
  }
  

delay(500);
digitalWrite(resPin, LOW);

  
    
}




int steppermotor() {
  
  for (int i=0; i<150; i++) {
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
     delay(d); 
                         }
for (int i=0; i<150; i++) {
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);  
                        }
  
  }

  int audiofile() {
    
    
  puts("loop!!");

  /* Send new frames to decode in a loop until file ends */
  int err = theAudio->writeFrames(AudioClass::Player0, myFile);

  /*  Tell when player file ends */
  if (err == AUDIOLIB_ECODE_FILEEND)
    {
      printf("Main player File End!\n");
    }

  /* Show error code from player and stop */
  if (err)
    {
      printf("Main player error code: %d\n", err);
      goto stop_player;
    }

  if (ErrEnd)
    {
      printf("Error End\n");
      goto stop_player;
    }

  /* This sleep is adjusted by the time to read the audio stream file.
     Please adjust in according with the processing contents
     being processed at the same time by Application.
  */

  usleep(3000);




stop_player:
  sleep(1);
  theAudio->stopPlayer(AudioClass::Player0);
  myFile.close();
  exit(1);
    
    }


void audiosetup1() {
  
  // start audio system
  theAudio = AudioClass::getInstance();

  theAudio->begin(audio_attention_cb);

  puts("initialization Audio Library");

  /* Set clock mode to normal */
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);

  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);


  err_t err = theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);

  /* Verify player initialize */
  if (err != AUDIOLIB_ECODE_OK)
    {
      printf("Player0 initialize error\n");
      exit(1);
    }

  /* Open file placed on SD card */
  myFile = theSD.open("Sound1.mp3");

  /* Verify file open */
  if (!myFile)
    {
      printf("File open error\n");
      exit(1);
    }
  printf("Open! %d\n",myFile);

  /* Send first frames to be decoded */
  err = theAudio->writeFrames(AudioClass::Player0, myFile);

  if ((err != AUDIOLIB_ECODE_OK) && (err != AUDIOLIB_ECODE_FILEEND))
    {
      printf("File Read Error! =%d\n",err);
      myFile.close();
      exit(1);
    }

  puts("Play!");

  /* Main volume set to -16.0 dB */
  theAudio->setVolume(-160);
  theAudio->startPlayer(AudioClass::Player0); 
  
  }

  void audiosetup2() {
  
  // start audio system
  theAudio = AudioClass::getInstance();

  theAudio->begin(audio_attention_cb);

  puts("initialization Audio Library");

  /* Set clock mode to normal */
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);

  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);


  err_t err = theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);

  /* Verify player initialize */
  if (err != AUDIOLIB_ECODE_OK)
    {
      printf("Player0 initialize error\n");
      exit(1);
    }

  /* Open file placed on SD card */
  myFile = theSD.open("Sound2.mp3");

  /* Verify file open */
  if (!myFile)
    {
      printf("File open error\n");
      exit(1);
    }
  printf("Open! %d\n",myFile);

  /* Send first frames to be decoded */
  err = theAudio->writeFrames(AudioClass::Player0, myFile);

  if ((err != AUDIOLIB_ECODE_OK) && (err != AUDIOLIB_ECODE_FILEEND))
    {
      printf("File Read Error! =%d\n",err);
      myFile.close();
      exit(1);
    }

  puts("Play!");

  /* Main volume set to -16.0 dB */
  theAudio->setVolume(-160);
  theAudio->startPlayer(AudioClass::Player0); 
  
  }

  void audiosetup3() {
  
  // start audio system
  theAudio = AudioClass::getInstance();

  theAudio->begin(audio_attention_cb);

  puts("initialization Audio Library");

  /* Set clock mode to normal */
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);

  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);


  err_t err = theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);

  /* Verify player initialize */
  if (err != AUDIOLIB_ECODE_OK)
    {
      printf("Player0 initialize error\n");
      exit(1);
    }

  /* Open file placed on SD card */
  myFile = theSD.open("Sound3.mp3");

  /* Verify file open */
  if (!myFile)
    {
      printf("File open error\n");
      exit(1);
    }
  printf("Open! %d\n",myFile);

  /* Send first frames to be decoded */
  err = theAudio->writeFrames(AudioClass::Player0, myFile);

  if ((err != AUDIOLIB_ECODE_OK) && (err != AUDIOLIB_ECODE_FILEEND))
    {
      printf("File Read Error! =%d\n",err);
      myFile.close();
      exit(1);
    }

  puts("Play!");

  /* Main volume set to -16.0 dB */
  theAudio->setVolume(-160);
  theAudio->startPlayer(AudioClass::Player0); 
  
  }

activity_main.xml

XML
Android Studio
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f2f2f2"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:gravity="center">

        <ImageView
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:src="@drawable/camera"/>

    </RelativeLayout>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="260dp"
        android:layout_marginTop="270dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="#c2d1f0"
            android:alpha="0.6"></RelativeLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="80dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:textSize="20dp"
            android:text="Motion detect:"
            android:textColor="#404040"
            android:layout_marginLeft="10dp"/>
        <TextView
            android:id="@+id/text_pirdata"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginRight="50dp"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="25dp"
            android:gravity="center"
            android:textStyle="bold"
            android:textColor="#000000"
            android:textSize="20dp"
            android:text="N/A"
            />
</RelativeLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="80dp"
            android:background="#7094db"
            android:alpha="0.5"></RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="80dp">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:textSize="20dp"
            android:text="Distance detect:"
            android:textColor="#404040"
            android:layout_marginLeft="10dp"/>
        <TextView
            android:id="@+id/text_ultrasonic"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginRight="50dp"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="25dp"
            android:gravity="center"
            android:textSize="20dp"
            android:textStyle="bold"
            android:textColor="#000000"
            android:text="N/A"
            /> </RelativeLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="#3366cc"
            android:layout_marginTop="160dp"
            android:alpha="0.5"></RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="160dp">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="80dp"
                android:textSize="20dp"
                android:text="Speech detect:"
                android:textColor="#404040"
                android:layout_marginLeft="10dp"/>
            <TextView
                android:id="@+id/text_mic"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_marginRight="50dp"
                android:layout_marginLeft="50dp"
                android:layout_marginTop="25dp"
                android:gravity="center"
                android:textSize="20dp"
                android:textStyle="bold"
                android:textColor="#000000"
                android:text="N/A"
                /> </RelativeLayout>



    </RelativeLayout>

</RelativeLayout>

MainActivity.java

Java
Android Studio
package com.example.elmin.homesecuritysystem;

import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

public class MainActivity extends AppCompatActivity {

    DatabaseReference dref;
    TextView text_pir, text_distance, text_mic;
    String dist, mic, pir;
    int col = Color.parseColor("#b32d00");



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        text_pir = (TextView) findViewById(R.id.text_pirdata);
        text_distance = (TextView)findViewById(R.id.text_ultrasonic);
        text_mic = (TextView) findViewById(R.id.text_mic);


        dref = FirebaseDatabase.getInstance().getReference();
        dref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                 pir = dataSnapshot.child("pir_data").getValue().toString();
                 int pir_int = Integer.parseInt(pir);

                if (pir_int == 0){
                    text_pir.setText("No motion detected.");}
                    else {
                    text_pir.setText("Movement outside!");
                    text_pir.setTextColor(col);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        dref = FirebaseDatabase.getInstance().getReference();
        dref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                dist =  dataSnapshot.child("distance").getValue().toString();
                int dist_data = Integer.parseInt(dist);

                if (dist_data == 0){
                    text_distance.setText("Nothing detected.");}
                else {
                    text_distance.setText(dist +" meters away from entry!");
                    text_distance.setTextColor(col);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });


        dref = FirebaseDatabase.getInstance().getReference();
        dref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

               mic = dataSnapshot.child("mic").getValue().toString();
               int mic_data = Integer.parseInt(mic);

                if (mic_data == 0){
                    text_mic.setText("There is no one outside.");}
                else {
                    text_mic.setText("Conversation outside detected!");
                    text_mic.setTextColor(col);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });



    }
}

sony_android.ino

Arduino
#include<SoftwareSerial.h>
#include <SDHCI.h>
#include <Audio.h>

SoftwareSerial nodemcu(0, 1); // 0 -> Tx (nodemcu), 1 -> Rx (nodemcu)

int IN1 = 3, IN2 = 5, IN3 = 6, IN4 = 9, d = 10; //Stepper motor control
int trigPin = 10, echoPin = 11, distance; //Sensor pin
int resPin = 2;



//Sound data
SDClass theSD;
AudioClass *theAudio;

File myFile;

bool ErrEnd = false;

static void audio_attention_cb(const ErrorAttentionParam *atprm)
{
  puts("Attention!");
  
  if (atprm->error_code >= AS_ATTENTION_CODE_WARNING)
    {
      ErrEnd = true;
   }
}

//end


void setup() {
  //Serial S Begin at 9600 Baud
  digitalWrite(resPin, HIGH);
  
  nodemcu.begin(9600);
  pinMode(resPin, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(trigPin, INPUT);
  pinMode(echoPin, INPUT);
  }

void loop() {

  


    
    
  steppermotor();
  
    digitalWrite(trigPin, LOW); //turn off trigPin
    delayMicroseconds(2);   
    digitalWrite(trigPin, HIGH); //turn on trigPin
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW); //turn off trigPn
    long duration = pulseIn(echoPin, HIGH); //returns the sound wave travel time in microseconds
    int distance = duration*0.034/2; 
    nodemcu.write(distance);
    
  if (distance < 7) {
  audiosetup();
  delay(5000);
  digitalWrite(resPin, LOW);
  }
  

  
  delay(500);
  digitalWrite(resPin, LOW);
  
    
}




int steppermotor() {
  
  for (int i=0; i<150; i++) {
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
     delay(d); 
                         }
for (int i=0; i<150; i++) {
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);  
                        }
  
  }

  int audiofile() {
    
    
  puts("loop!!");

  /* Send new frames to decode in a loop until file ends */
  int err = theAudio->writeFrames(AudioClass::Player0, myFile);

  /*  Tell when player file ends */
  if (err == AUDIOLIB_ECODE_FILEEND)
    {
      printf("Main player File End!\n");
    }

  /* Show error code from player and stop */
  if (err)
    {
      printf("Main player error code: %d\n", err);
      goto stop_player;
    }

  if (ErrEnd)
    {
      printf("Error End\n");
      goto stop_player;
    }

  /* This sleep is adjusted by the time to read the audio stream file.
     Please adjust in according with the processing contents
     being processed at the same time by Application.
  */

  usleep(3000);




stop_player:
  sleep(1);
  theAudio->stopPlayer(AudioClass::Player0);
  myFile.close();
  exit(1);
    
    }


void audiosetup() {
  
  // start audio system
  theAudio = AudioClass::getInstance();

  theAudio->begin(audio_attention_cb);

  puts("initialization Audio Library");

  /* Set clock mode to normal */
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);

  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);


  err_t err = theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);

  /* Verify player initialize */
  if (err != AUDIOLIB_ECODE_OK)
    {
      printf("Player0 initialize error\n");
      exit(1);
    }

  /* Open file placed on SD card */
  myFile = theSD.open("Sound2.mp3");

  /* Verify file open */
  if (!myFile)
    {
      printf("File open error\n");
      exit(1);
    }
  printf("Open! %d\n",myFile);

  /* Send first frames to be decoded */
  err = theAudio->writeFrames(AudioClass::Player0, myFile);

  if ((err != AUDIOLIB_ECODE_OK) && (err != AUDIOLIB_ECODE_FILEEND))
    {
      printf("File Read Error! =%d\n",err);
      myFile.close();
      exit(1);
    }

  puts("Play!");

  /* Main volume set to -16.0 dB */
  theAudio->setVolume(-160);
  theAudio->startPlayer(AudioClass::Player0); 
  
  }

  

nodemcu_android.ino

Arduino
#include <PubSubClient.h>
#include <FirebaseArduino.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

#define FIREBASE_HOST "firebase_link"
#define FIREBASE_AUTH "firebase_secret_code"

#define WIFI_SSID "wifi_name"
#define WIFI_PASSWORD "wifi_password"

int pirPin = 5, micPin = 4, LED = 0;

void setup() {
  //Serial Begin at 9600 Baud 
  pinMode(pirPin, INPUT);
  pinMode(micPin, INPUT);
  pinMode(LED, OUTPUT);
  
  Serial.begin(9600);
     WiFi.begin (WIFI_SSID, WIFI_PASSWORD);
        while (WiFi.status() != WL_CONNECTED) {
           delay(500);
            Serial.print(".");
  
         }
          Serial.println ("");
          Serial.println ("WiFi Connected!");
          Serial.println(WiFi.localIP());
     Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);


  
}

void loop() {
    //PIR sensor data
    boolean pir_data = digitalRead(pirPin);
    Firebase.setInt("pir_data", pir_data);

    if (pir_data == 0) {
      digitalWrite(LED,LOW);
      }
    else {
      digitalWrite(LED, HIGH);
      }

    //Ultrasonic data
    int distance = Serial.read();
    Firebase.setInt("distance", distance);

    //Mic data from Sony Spresense
    boolean mic = digitalRead(micPin);
    Firebase.setInt("mic", mic);

    delay(1000);
  
}

Credits

Elmin Delibašić

Elmin Delibašić

12 projects • 81 followers
Bachelor of Electrical Engineering || Enthusiast for AI and IoT || Master Student at Faculty of Electrical Engineering

Comments