Daftar Isi:

SmartBin: 8 Langkah
SmartBin: 8 Langkah

Video: SmartBin: 8 Langkah

Video: SmartBin: 8 Langkah
Video: Xiaomi Mi Band 8 Smartband 2024, November
Anonim
SmartBin
SmartBin

Este é um projeto para um sistema inteligente de coletas, no qual os caminhões de lixo recebem dados das lixeiras, identificando a quantidade de lixo presente em cada uma delas, e uma rota de coleta traçada, com base nas informações.

Para montar este projeto, é necessário:

  • NodeMCU
  • Sensor Ultrassnico de Distancia
  • Caixa de papelão
  • Protoboard
  • cabo
  • Dispositivo Android

Langkah 1: Sensor Conectando O

Primeiramente, vamos efetuar a conexão entre o sensor ultrassnico e o NODEMCU. Para tanto, vamos conectar sebagai pemicu portas e echo lakukan sensor nas portas D4 e D3 lakukan NodeMCU:

// mendefinisikan nomor pin #define pino_trigger 2 //D4

#define pino_echo 0 //D3

Para efetuar a leitura dos dados lakukan sensor, foi seguido atau tutorial elaborado pelo FilipeFlop, disponível aqui.

float cmMsec, inMsec;

mikrodetik panjang = ultrasonik.timing();

cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM);

inMsec = ultrasonic.convert(microsec, Ultrasonic::IN);

// Exibe informacoes tidak ada monitor serial

Serial.print("Jarak em cm: ");

Serial.print(cmMsec);

Serial.print(" - Jarak tempuh: ");

Serial.println(dalamMsec);

String data = String(cmMsec);

Serial.println(data);

Langkah 2: Montando a Lixeira

Agora, vamos montar a lixeira inteligente. Precisaremos conectar atau sensor ultrassônico no "teto" da lixeira. Sebagai contoh, manfaatkan cabo e fita isolante. Em seguida, temos que medir a distância inicial, para saber o valor para a lixeira vazia. No meu caso, foi de 26, 3cm. Esse é o valor que mempertimbangkanarmos para uma lixeira vazia.

Untuk simulao, visto que não possuo mais de um sensor ultrassônico, foi feito um algoritmo para salvar randomicamente a distancia lida em 4 lixeiras diferentes.

//Simulando 4 lixeiras

lixeiraID panjang;

lingkaran kosong() {

lixeiraID = acak(1, 5);

}

Langkah 3: Unggah Para a Nuvem

Agora, precisamos enviar estes dados para a nuvem. Eu escolhi o ThingSpeak, atau familiaridade com o mesmo. Primeiramente, é necessário criar um novo canal, recebendo 4 parâmetros, referentes ao volume de cada lixeira.

Pará conectar a aplicação com o ThingSpeak, é necessário salvar o número da API do canal criado. Siga os passos descritos tidak ada situs resmi.

De volta aplicação, vamos utilizar a biblioteca ESP8266WiFi.h untuk efetuar conexão com o ThingSpeak, dan transfer os dados.

Primeiramente, uma função para efetuar conexão com a rede (defina previamente duas variáveis, ssid e pass, bersaing o identificador e a senha de sua rede).

batalkan koneksi Wifi(){

Serial.print("Menghubungkan ke "+ *ssid);

WiFi.begin(ssid, pass);

sementara (WiFi.status() != WL_CONNECTED) {

penundaan (500);

Serial.print(".");

}

Serial.println("");

Serial.print("Conectado dan rede");

Serial.println(ssid);

Serial.print("IP: ");

Serial.println(WiFi.localIP());

}

Untuk persiapan, tentamos efetuar a conexão com a rede.

batalkan pengaturan() {

Serial.begin(9600);

Serial.println("Lendo dados melakukan sensor…");

//Konektando dengan Wi-Fi

hubungkan Wifi();

}

E, para enviar os dados para o ThingSpeak, basta abrir uma conexão HTTP padrão, passando o número da API e os parâmetros.

void sendDataTS(float cmMsec, id panjang){

if (klien.koneksi(server, 80)) {

Serial.println("Enviando dados para o ThingSpeak ");

String postStr = apiKey;

postStr += "&bidang";

postStr += id;

postStr += "=";

postStr += String(cmMsec);

postStr += "\r\n\r\n";

Serial.println(postStr);

client.print( POST /update

client.print("Host: api.thingspeak.com\n");

client.print("Koneksi: tutup\n");

client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n");

client.print("Jenis Konten: application/x-www-form-urlencoded\n");

client.print("Panjang Konten: ");

client.print(postStr.length());

klien.print("\n\n");

klien.print(postStr);

penundaan (1000);

}

klien.berhenti();

}

O primeiro parâmetro korespondensi distância em centímetros encontrada pelo sensor ultrassônico. O segundo parâmetro é o ID da lixeira que foi lida (que foi gerado randomicamente, um número de 1 a 4).

O ID da lixeira serve também para identificar para qual campo será feito o upload do valor lido.

Langkah 4: Recuperando Dados Lakukan ThingSpeak

O ThingSpeak izinkan efetuar leitura dos dados do seu canal, através de um serviço retornando um JSON. As diferentes opções para leitura do feed do seu canal estão descritas aqui:

www.mathworks.com/help/thingspeak/get-a-ch…

Neste projeto, optou-se por ler diretamente os dados de cada campo. O padrão de URL para este cenário é:

api.thingspeak.com/channels/CHANNEL_ID/fields/FIELD_NUMBER/last.json?api_key=API_KEY&status=true

Cada campo está descrito no link informado previamente. Os mais importantes para o projeto são:

  • CHANNEL_ID: kanal número do seu
  • FIELD_NUMBER: o número do campo
  • API_KEY: chave de API do seu canal

Tetapkan URL untuk mencari aplikasi untuk Android, untuk memulihkan dari hal-hal yang harus dilakukan.

Langkah 5: Criando a Aplikasi Android

Tidak ada Android Studio, menangislah um novo projeto Android. Para o correto funcionamento da aplicação, perlu dikonfigurasi sebagai izin abaixo no AndroidManifest.xml.

Para utilizar o Google Maps, será necessário pegar uma chave junto ao Google. Siga os passos descritos no link Obter chave de API.

Uma vez com a chave, você deve também configurá-la na aplicação.

Kunci API untuk API berbasis Google Maps didefinisikan sebagai sumber daya string.

(Lihat file "res/values/google_maps_api.xml").

Perhatikan bahwa kunci API ditautkan ke kunci enkripsi yang digunakan untuk menandatangani APK. Anda memerlukan kunci API yang berbeda untuk setiap kunci enkripsi, termasuk kunci rilis yang digunakan untuk menandatangani APK untuk penerbitan. Anda dapat menentukan kunci untuk target debug dan rilis di src/debug/ dan src/release/.

<meta-data

android:nama="com.google.android.geo. API_KEY"

android:value="@string/google_maps_key" />

Sebuah konfigurasi lengkap untuk memulai AndroidManifest anexado ao projeto.

n

Langkah 6: Recuperando O Umpan Tanpa Android

Tidak ada prinsip dasar Android, MainActivity, menangis 4 variáveis para identificar cada um dos canais do ThingSpeak a serem lidos:

private String url_a = "https://api.thingspeak.com/channels/429823/fields/1/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; private String url_b = "https://api.thingspeak.com/channels/429823/fields/2/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; private String url_c = "https://api.thingspeak.com/channels/429823/fields/3/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; private String url_d = "https://api.thingspeak.com/channels/429823/fields/4/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true";

Para efetuar a leitura dos dados, iremos utilizar uma classe do Android específica, chamada JSONObject. Mais uma vez, vamos criar um objeto para cada URL:

JSONObject responseLixeiraA; JSONObject responseLixeiraB; JSONObject responseLixeiraC; JSONObject responseLixeiraD;

Para abrir a conexão com sebagai url, vamos usar criar uma classe auxiliar, chamada HttpJsonParser. Esta classe será responsável por abrir uma conexão com um URL, efetuar leitura dos dados encontrados, e retornar atau objeto JSON montado.

publik JSONObject makeHttpRequest(String url, metode String, Peta params) {

mencoba {

Pembangun Uri. Builder = Uri. Builder baru(); URL urlObj; String dikodekanParams = ""; if (params != null) { for (entri Peta. Entry: params.entrySet()) { builder.appendQueryParameter(entry.getKey(), entry.getValue()); } } if (builder.build().getEncodedQuery() != null) { encodedParams = builder.build().getEncodedQuery();

}

if ("GET".equals(method)) { url = url + "?" +Params yang disandikan; urlObj = URL baru(url); urlConnection = (HttpURLConnection) urlObj.openConnection(); urlConnection.setRequestMethod(metode);

} lain {

urlObj = URL baru(url); urlConnection = (HttpURLConnection) urlObj.openConnection(); urlConnection.setRequestMethod(metode); urlConnection.setRequestProperty("Tipe-Konten", "aplikasi/x-www-form-urlencoded"); urlConnection.setRequestProperty("Content-Length", String.valueOf(encodedParams.getBytes().length)); urlConnection.getOutputStream().write(encodedParams.getBytes()); } //Hubungkan ke server urlConnection.connect(); //Baca responnya adalah = urlConnection.getInputStream(); Pembaca BufferedReader = new BufferedReader(InputStreamReader baru(adalah)); StringBuilder sb = new StringBuilder(); Garis tali;

// Menguraikan tanggapan

while ((baris = reader.readLine()) != null) { sb.append(baris + "\n"); } dekat(); json = sb.toString(); //Mengonversi respons ke Objek JSON jObj = new JSONObject(json);

} tangkap (UnsupportedEncodingException e) {

e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { Log.e("JSON Parser", "Error parsing data" + e.toString()); } catch (Exception e) { Log.e("Exception", "Error parsing data" + e.toString()); }

// kembalikan Objek JSON

mengembalikan pekerjaan;

}

}

De volta atividade principal, vamos efetuar a chamada s url de forma assíncrona, escrevendo este código dentro do método doInBackground.

@Override Protected String doInBackground(String… params) { HttpJsonParser jsonParser = new

responseLixeiraA = jsonParser.makeHttpRequest(url_a, "GET", null);

responseLixeiraB = jsonParser.makeHttpRequest(url_b, "GET", null); responseLixeiraC = jsonParser.makeHttpRequest(url_c, "GET", null); responseLixeiraD = jsonParser.makeHttpRequest(url_d, "GET", null);

kembali nol;}

Quando o método doInBackgroundé encerrado, o controle de execução lakukan Android passa para o método onPostExecute. Neste método, vamos criar os objetos Lixeira, dan com os dados recuperados yang populer lakukan ThingSpeak:

protected void onPostExecute(String result) { pDialog.dismiss(); runOnUiThread(New Runnable() { public void run() {

//ListView listView =(ListView)findViewById(R.id.feedList);

Lihat mainView =(View)findViewById(R.id.activity_main); if (berhasil == 1) { try { //Cria feedDetail para cada lixeira Lixeira feedDetails1 = new Lixeira(); Lixeira feedDetails2 = Lixeira baru(); Lixeira feedDetails3 = Lixeira baru(); Lixeira feedDetails4 = Lixeira baru();

feedDetails1.setId('A');

feedDetails1.setPesoLixo(Double.parseDouble(responseLixeiraA.getString(KEY_FIELD1))); feedDetails1.setVolumeLixo(Double.parseDouble(responseLixeiraA.getString(KEY_FIELD1)));

feedDetails2.setId('B');

feedDetails2.setPesoLixo(Double.parseDouble(responseLixeiraB.getString(KEY_FIELD2))); feedDetails2.setVolumeLixo(Double.parseDouble(responseLixeiraB.getString(KEY_FIELD2)));

feedDetails3.setId('C');

feedDetails3.setPesoLixo(Double.parseDouble(responseLixeiraC.getString(KEY_FIELD3))); feedDetails3.setVolumeLixo(Double.parseDouble(responseLixeiraC.getString(KEY_FIELD3)));

feedDetails4.setId('D');

feedDetails4.setPesoLixo(Double.parseDouble(responseLixeiraD.getString(KEY_FIELD4))); feedDetails4.setVolumeLixo(Double.parseDouble(responseLixeiraD.getString(KEY_FIELD4)));

feedList.add(feedDetails1);

feedList.add(feedDetails2); feedList.add(feedDetails3); feedList.add(feedDetails4);

//Menghitung dados das lixeiras

Kalkulator SmartBinService = SmartBinService baru(); kalkulator.montaListaLixeiras(daftarumpan);

//Komponen Recupera

TextView createDate = (TextView) mainView.findViewById(R.id.date); ListView listaDeLixeiras = (ListView) findViewById(R.id.lista); adapter.addAll(daftarumpan);

//Data sebenarnya

Tanggal currentTime = Calendar.getInstance().getTime(); SimpleDateFormat simpleDate = new SimpleDateFormat("dd/MM/yyyy"); String currentDate = simpleDate.format(currentTime); createDate.setText(KEY_DATE + currentDate + " "); listaDeLixeiras.setAdapter(adaptor);

} tangkap (JSONException e) {

e.printStackTrace(); }

} lain {

Toast.makeText(MainActivity.this, "Beberapa kesalahan terjadi saat memuat data", Toast. LENGTH_LONG).show();

}

} }); }

Agora, na tela inicial do aplicativo, serão listados os dados de cada lixeira.

Langkah 7: Mostrando No Mapa

Mostrando No Mapa
Mostrando No Mapa

Ainda na atividade principal, vamos adicionar uma ação a ser relacionada ao botão Mapa, na tela inicial.

/** Dipanggil saat pengguna menekan tombol Mapa */ public void openMaps(View view) { Intent intent = new Intent(this, LixeiraMapsActivity.class);

//Passa a lista de lixeiras

Bundel bundel = Bundel baru(); bundle.putParcelableArrayList("lixeiras", feedList); intent.putExtras(bundel);

startActivity(niat);

}

Tidak ada mapa, temos três atividades a executar:

  1. marcar a posição sebenarnya melakukan caminha de lixo
  2. marcar os pontos koresponden a cada lixeira no mapa
  3. traar a rota entre os pontos

Para executar os passos acima, vamos menggunakan API Google Directions. Para desenhar as rotas, foram seguidos os passos do tutorial Menggambar petunjuk arah rute mengemudi antara dua lokasi menggunakan Google Directions di Google Map Android API V2

Primeiro, vamos criar localidades para cada um dos pontos que desejamos marcar:

//Lokasi

arus LatLng pribadi;

lixeiraA LatLng pribadi; lixeiraB LatLng pribadi; lixeiraC LatLng pribadi; lixeiraD LatLng pribadi;.

Para adicionar a posição atual no mapa, foi criado o método:

private void checkLocationandAddToMap() { //Memeriksa apakah pengguna telah memberikan izin jika (ActivityCompat.checkSelfPermission(this, android. Manifest.permission. ACCESS_FINE_LOCATION) != PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android. Manifest.permission. ACCESS_COARSE_LOCATION) != PackageManager. PERMISSION_GRANTED) { //Meminta izin Lokasi ActivityCompat.requestPermissions(this, new String{android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); kembali; }

//Mengambil lokasi terakhir yang diketahui menggunakan Fus

Lokasi lokasi = LocationServices. FusedLocationApi.getLastLocation(googleApiClient);

//MarkerOptions digunakan untuk membuat Marker baru. Anda dapat menentukan lokasi, judul dll dengan MarkerOptions

this.current = new LatLng(location.getLatitude(), location.getLongitude()); MarkerOptions markerOptions = new MarkerOptions().position(current).title("Posição aktual");

//Menambahkan penanda yang dibuat di peta, memindahkan kamera ke posisi

markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory. HUE_GREEN)); System.out.println("++++++++++++++ Passei aqui! +++++++++++++"); mMap.addMarker(markerOptions);

// Pindahkan kamera secara instan ke lokasi dengan zoom 15.

mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(saat ini, 15));

// Memperbesar, menganimasikan kamera.

mMap.animateCamera(CameraUpdateFactory.zoomTo(14), 2000, null);

}

Em seguida, para cada lixeira, foram criados métodos similares ao abaixo:

private void addBinALocation() { //Memeriksa apakah pengguna telah memberikan izin if (ActivityCompat.checkSelfPermission(this, android. Manifest.permission. ACCESS_FINE_LOCATION) != PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android. Manifest.permission. ACCESS_COARSE_LOCATION) != PackageManager. PERMISSION_GRANTED) { //Meminta izin Lokasi ActivityCompat.requestPermissions(this, new String{android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); kembali; }

//Praça da Estação

lintang ganda = -19.9159578; bujur ganda = -43.9387856; this.lixeiraA = new LatLng(lintang, bujur);

MarkerOptions markerOptions = new MarkerOptions().position(lixeiraA).title("Lixeira A");

markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory. HUE_RED)); mMap.addMarker(markerOptions); }

Sebagai posies de latitude e longitude de cada lixeira foram recuperadas através do próprio Google Maps, e deixadas fixas no código. Idealmente, estes valores ficariam salvos em um banco de dados (sebagai contoh Firebase). Será a primeira evolução deste projeto!

O ltimo passo agora é traçar sebagai rotas entre os pontos. Para tal, um conceito muito importante, e que será utilizado neste projeto, são os Waypoints!

Foi criado um método para traçar a rota entre dois dados pontos:

private String getDirectionsUrl(Asal LatLng, tujuan LatLng, Daftar waypointsList){

// Asal rute

String str_origin = "asal="+origin.latitude+", "+origin.longitude;

// Tujuan rute

String str_dest = "destination="+dest.latitude+", "+destination.longitude;

//Titik jalan di sepanjang rute

//waypoints=optimize:true|-19.9227365, -43.9473546|-19.9168006, -43.9361124 String waypoints = "waypoints=optimize:true"; for (titik LatLng: waypointsList){ titik jalan += "|" + titik.lintang + "," + titik.bujur; }

// Sensor diaktifkan

Sensor string = "sensor = salah";

// Membangun parameter ke layanan web

Parameter string = str_origin+"&"+str_dest+"&"+sensor + "&" + titik arah;

// Format output

Keluaran string = "json";

// Membangun url ke layanan web

String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters; System.out.println("++++++++++++++"+url);

kembali url;

}

E, por fim, juntando tudo no método principal da classe, onMapReady:

@Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap;

checkLocationandAddToMap();

if (lixeirasList.get(0).getVolumeLixo() > Lixeira. MIN_VOLUME_GARBAGE

|| lixeirasList.get(0).getPesoLixo()-10 > Lixeira. MIN_SIZE_GARBAGE){ addBinALocation(); } if (lixeirasList.get(1).getVolumeLixo() > Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get(1).getPesoLixo() > Lixeira. MIN_SIZE_GARBAGE){ addBinBLocation(); } if (lixeirasList.get(2).getVolumeLixo() > Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get(2).getPesoLixo() > Lixeira. MIN_SIZE_GARBAGE){ addBinCLocation(); } if (lixeirasList.get(3).getVolumeLixo() > Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get(3).getPesoLixo() > Lixeira. MIN_SIZE_GARBAGE){ addBinDLocation(); }

//Menggambar rute

// Mendapatkan URL ke Google Directions API

Daftar poin = new ArrayList(); poin.add(lixeiraB); poin.add(lixeiraC); poin.add(lixeiraD);

String url = getDirectionsUrl(saat ini, lixeiraA, poin);

DownloadTask downloadTask = new DownloadTask(); // Mulai mengunduh data json dari Google Directions API downloadTask.execute(url); }

Aqui passamos apenas pelos pontos principais. O código completo do projeto será disponibilizado untuk konsultasi.

Langkah 8: Kesimpulan

Este foi um projeto trabalhando conceitos de IoT, mostrando uma das várias opções de conectar dispositivos através da nuvem, efetuar tomada de decisões sem interferência humana direta. Em anexo, segue um vídeo do projeto completo, para ilustração, e os fontes das atividades criadas no Android.

Direkomendasikan: