Daftar Isi:
- Langkah 1: Sensor Conectando O
- Langkah 2: Montando a Lixeira
- Langkah 3: Unggah Para a Nuvem
- Langkah 4: Recuperando Dados Lakukan ThingSpeak
- Langkah 5: Criando a Aplikasi Android
- Langkah 6: Recuperando O Umpan Tanpa Android
- Langkah 7: Mostrando No Mapa
- Langkah 8: Kesimpulan
Video: SmartBin: 8 Langkah
2024 Pengarang: John Day | [email protected]. Terakhir diubah: 2024-01-31 10:21
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
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:
- marcar a posição sebenarnya melakukan caminha de lixo
- marcar os pontos koresponden a cada lixeira no mapa
- 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:
Sistem Peringatan Parkir Terbalik Mobil Arduino - Langkah demi Langkah: 4 Langkah
Sistem Peringatan Parkir Mundur Mobil Arduino | Langkah demi Langkah: Pada proyek kali ini, saya akan merancang Rangkaian Sensor Parkir Mundur Mobil Arduino sederhana menggunakan Sensor Ultrasonik Arduino UNO dan HC-SR04. Sistem peringatan mundur mobil berbasis Arduino ini dapat digunakan untuk Navigasi Otonom, Jarak Robot, dan r
Langkah demi Langkah Membangun PC: 9 Langkah
Langkah demi Langkah Membangun PC: Perlengkapan: Perangkat Keras: MotherboardCPU & Pendingin CPUPSU (Unit catu daya)Penyimpanan (HDD/SSD)RAMGPU (tidak diperlukan)Kasing Alat: Obeng Gelang ESD/pasta matstermal dengan aplikator
Tiga Sirkuit Loudspeaker -- Tutorial Langkah-demi-Langkah: 3 Langkah
Tiga Sirkuit Loudspeaker || Tutorial Langkah-demi-Langkah: Sirkuit Loudspeaker memperkuat sinyal audio yang diterima dari lingkungan ke MIC dan mengirimkannya ke Speaker dari mana audio yang diperkuat diproduksi. Di sini, saya akan menunjukkan kepada Anda tiga cara berbeda untuk membuat Sirkuit Loudspeaker ini menggunakan:
Levitasi Akustik Dengan Arduino Uno Langkah-demi-Langkah (8-langkah): 8 Langkah
Akustik Levitation Dengan Arduino Uno Langkah-demi-Langkah (8-langkah): transduser suara ultrasonik L298N Dc female adapter power supply dengan pin dc laki-laki Arduino UNOBreadboardCara kerjanya: Pertama, Anda mengunggah kode ke Arduino Uno (ini adalah mikrokontroler yang dilengkapi dengan digital dan port analog untuk mengonversi kode (C++)
SmartBin: 4 Langkah
SmartBin: Tujuan utama dari proyek ini adalah untuk membuat perangkat elektronik yang menggunakan setidaknya satu Raspberry Pi. Tim ini terdiri dari 5 insinyur mesin masa depan dan satu insinyur otomasi. Proyek kami terdiri dari membuat tempat sampah yang bisa membuka dan menutup