Isi kandungan:
- Langkah 1: Sensor Conectando O
- Langkah 2: Montando a Lixeira
- Langkah 3: Muat naik Para a Nuvem
- Langkah 4: Recuperando Dados Do ThingSpeak
- Langkah 5: Criando a Aplicação Android
- Langkah 6: Recuperando O Feed Tanpa Android
- Langkah 7: Mostrando No Mapa
- Langkah 8: Kesimpulannya
Video: SmartBin: 8 Langkah
2024 Pengarang: John Day | [email protected]. Diubah suai terakhir: 2024-01-31 10:23
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 recuperadas.
Para montar este projeto, perlu:
- NodeMCU
- Sensor Ultrassônico de Distancia
- Caixa de papelão
- Papan Protob
- Cabos
- Dispositivo Android
Langkah 1: Sensor Conectando O
Primeiramente, vamos efetuar a conexão entre o sensor ultrassônico e o NODEMCU. Sebagai tanto, conectar vamos sebagai porta mencetuskan echo do sensor nas portas D4 e D3 do NodeMCU:
// mentakrifkan nombor pin #menentukan pino_trigger 2 // D4
#tentukan pino_echo 0 // D3
Para efetuar a leitura dos dados do sensor, juga seguido o tutorial elaborado pelo FilipeFlop, disponível aqui.
terapung cmMsec, inMsec;
panjang mikro = ultrasonik.timing ();
cmMsec = ultrasonic.convert (microsec, Ultrasonic:: CM);
inMsec = ultrasonic.convert (microsec, Ultrasonic:: IN);
// Exibe informacoes tiada monitor bersiri
Serial.print ("Distancia em cm:");
Serial.print (cmMsec);
Serial.print ("- Distancia em polegadas:");
Serial.println (dalamMsec);
Data rentetan = Rentetan (cmMsec);
Serial.println (data);
Langkah 2: Montando a Lixeira
Agora, vamos montar a lixeira inteligente. Precisaremos conectar o sensor ultrassônico no “teto” da lixeira. Sebagai contoh, gunakan isolante. Em seguida, temos que medir a distância inicial, para saber o valor para a lixeira vazia. Tanpa meu caso, juga 26, 3cm. Esse é o valor que mempertimbangkanarmos para uma lixeira vazia.
Para simulação, visto que não possuo mais de um sensor ultrassônico, juga feito um algoritmo para salvar randomicamente a distancia lida em 4 lixeiras diferentes.
// Simulando 4 lixeiras
lixeiraID panjang;
gelung kosong () {
lixeiraID = rawak (1, 5);
}
Langkah 3: Muat naik Para a Nuvem
Agora, precisamos enviar estes dados para a nuvem. Eu escolhi o ThingSpeak, daripada familiar comade mes o mesmo. Primeiramente, canal umri novo canal, recebendo 4 parâmetros, referentes ao volume de cada lixeira.
Pará conectar a aplicação com o ThingSpeak, perlu Salvar o número da API do canal criado. Siga os passos descritos tiada laman rasmi.
De volta à aplicação, vamos utilizar a biblioteca ESP8266WiFi.h para efetuar conexão com o ThingSpeak, e transferir os dados.
Primeiramente, uma função para efetuar conexão com a rede (defina previamente duas variáveis, ssid e pass , contendo o identificador e a senha de sua rede).
batal connectWifi () {
Serial.print ("Menyambung ke" + * ssid);
WiFi.begin (ssid, lulus);
sementara (WiFi.status ()! = WL_CONNECTED) {
kelewatan (500);
Cetakan bersiri (".");
}
Serial.println ("");
Serial.print ("Conectado na rede");
Serial.println (ssid);
Serial.print ("IP:");
Serial.println (WiFi.localIP ());
}
Durante o setup, tentamos efetuar a conexão com a rede.
batal persediaan () {
Serial.begin (9600);
Serial.println ("Lendo dados do sensor…");
// Conectando ao Wi-Fi
sambungWifi ();
}
E, para enviar os dados para o ThingSpeak, basta abrir uma conexão HTTP padrão, passando o número da API dan os parâmetros.
batal sendDataTS (apungan cmMsec, panjang id) {
jika (client.connect (pelayan, 80)) {
Serial.println ("Enviando dados para o ThingSpeak");
String postStr = apiKey;
postStr + = "& bidang";
postStr + = id;
postStr + = "=";
postStr + = Rentetan (cmMsec);
postStr + = "\ r / n / r / n";
Serial.println (postStr);
client.print ("POST / kemas kini HTTP / 1.1 / n");
client.print ("Host: api.thingspeak.com / n");
client.print ("Sambungan: tutup / n");
client.print ("X-THINGSPEAKAPIKEY:" + apiKey + "\ n");
client.print ("Content-Type: application / x-www-form-urlencoded / n");
client.print ("Panjang Kandungan:");
client.print (postStr.length ());
client.print ("\ n / n");
client.print (postStr);
kelewatan (1000);
}
pelanggan.stop ();
}
O primeiro parâmetro koresponden à 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 melayani também para identificar para qual campo será feito o upload do valor lido.
Langkah 4: Recuperando Dados Do ThingSpeak
O ThingSpeak izin efetuar leitura dos dados do seu canal, através de um serviço retornando um JSON. Sebagai diferentes opções para leitura melakukan 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: terusan número do seu
- FIELD_NUMBER: o número do campo
- API_KEY: saluran chave de API do seu
Ini adalah URL que será lida do aplicativa Android, para recuperar os dados do ThingSpeak.
Langkah 5: Criando a Aplicação Android
Tanpa Android Studio, crie um novo projeto Android. Para o correto funcionamento da aplicação, perlu konfigurasi sebagai izin abaixo no AndroidManifest.
Para pengguna Peta Google, será requá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 berasaskan Peta Google didefinisikan sebagai sumber rentetan.
(Lihat fail "res / values / google_maps_api.xml").
Perhatikan bahawa kunci API dihubungkan dengan kunci penyulitan yang digunakan untuk menandatangani APK. Anda memerlukan kunci API yang berbeza untuk setiap kunci penyulitan, termasuk kunci pelepasan yang digunakan untuk menandatangani APK untuk penerbitan. Anda boleh menentukan kunci untuk sasaran debug dan rilis dalam src / debug / dan src / release /.
<meta-data
android: name = "com.google.android.geo. API_KEY"
android: value = "@ string / google_maps_key" />
Konfigurasi yang sesuai untuk Android, Manifest anexado ao projeto.
n
Langkah 6: Recuperando O Feed Tanpa Android
Na atividade principal no Android, MainActivity, crie 4 variáveis para identificar cada um dos canais do ThingBeritahu serid lidos:
rentetan peribadi url_a = "https://api.thingspeak.com/channels/429823/fields/1/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; rentetan peribadi url_b = "https://api.thingspeak.com/channels/429823/fields/2/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; rentetan peribadi url_c = "https://api.thingspeak.com/channels/429823/fields/3/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; rentetan peribadi 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:
JSONObjectjectLixeiraA; JSONObjectjectLixeiraB; JSONObjectjectLixeiraC; JSONObject responsLixeiraD;
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 o objeto JSON montado.
public JSONObject makeHttpRequest (String url, String method, Map params) {
cuba {
Pembangun Uri. Builder = Uri. Builder baru (); URL urlObj; String encodedParams = ""; if (params! = null) {untuk (Map. Entry entri: params.entrySet ()) {builder.appendQueryParameter (entry.getKey (), entry.getValue ()); }} if (builder.build (). getEncodedQuery ()! = null) {encodedParams = builder.build (). getEncodedQuery ();
}
jika ("GET". sama (kaedah)) {url = url + "?" + Param dikodkan; urlObj = URL baru (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (kaedah);
} lain {
urlObj = URL baru (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (kaedah); urlConnection.setRequestProperty ("Content-Type", "application / x-www-form-urlencoded"); urlConnection.setRequestProperty ("Content-Length", String.valueOf (encodedParams.getBytes (). panjang)); urlConnection.getOutputStream (). tulis (encodedParams.getBytes ()); } // Sambungkan ke pelayan urlConnection.connect (); // Baca jawapannya ialah = urlConnection.getInputStream (); Pembaca BufferedReader = BufferedReader baru (InputStreamReader baru (adalah)); StringBuilder sb = StringBuilder baru (); Garisan tali;
// Luruskan tindak balas
sementara ((line = reader.readLine ())! = null) {sb.append (baris + "\ n"); } ialah.tutup (); json = sb.toString (); // Tukarkan tindak balas ke Objek JSON jObj = JSONObject baru (json);
} tangkapan (UnsupportedEncodingException e) {
e.printStackTrace (); } tangkapan (ProtocolException e) {e.printStackTrace (); } tangkapan (IOException e) {e.printStackTrace (); } tangkapan (JSONException e) {Log.e ("JSON Parser", "Ralat menguraikan data" + e.toString ()); } tangkapan (Pengecualian e) {Log.e ("Pengecualian", "Ralat menguraikan data" + e.toString ()); }
// kembali Objek JSON
kembali jObj;
}
}
De volta a atividade principal, vamos efetuar a chamada às urls de forma assíncrona, escrevendo este código dentro do método doInBackground.
@Override dilindungi String doInBackground (String… params) {HttpJsonParser jsonParser = HttpJsonParser baru ();
responsLixeiraA = jsonParser.makeHttpRequest (url_a, "GET", null);
responsLixeiraB = jsonParser.makeHttpRequest (url_b, "GET", null); responsLixeiraC = jsonParser.makeHttpRequest (url_c, "GET", null); responsLixeiraD = jsonParser.makeHttpRequest (url_d, "GET", null);
kembali kosong;}
Quando o método doInBackgroundé encerrado, o controle de execução do Android passa para o método onPostExecute. Neste método, vamos criar os objetos Lixeira, e recuperados com os dados yang popular melakukan perkara yang Bercakap:
void dilindungi onPostExecute (Hasil rentetan) {pDialog.dismiss (); runOnUiThread (Runnable baru () {public void run () {
// ListView listView = (ListView) findViewById (R.id.feedList);
Lihat mainView = (Lihat) findViewById (R.id.activity_main); jika (kejayaan == 1) {cuba {// Cria feedDetail para cada lixeira Lixeira feedDetails1 = Lixeira baru (); Lixeira feedDetails2 = Lixeira baru (); Lixeira feedDetails3 = Lixeira baru (); Lixeira feedDetails4 = Lixeira baru ();
feedDetails1.setId ('A');
feedDetails1.setPesoLixo (Double.parseDouble (responsLixeiraA.getString (KEY_FIELD1))); feedDetails1.setVolumeLixo (Double.parseDouble (ResponsLixeiraA.getString (KEY_FIELD1)));
feedDetails2.setId ('B');
feedDetails2.setPesoLixo (Double.parseDouble (ResponsLixeiraB.getString (KEY_FIELD2))); feedDetails2.setVolumeLixo (Double.parseDouble (ResponsLixeiraB.getString (KEY_FIELD2)));
feedDetails3.setId ('C');
feedDetails3.setPesoLixo (Double.parseDouble (ResponsLixeiraC.getString (KEY_FIELD3))); feedDetails3.setVolumeLixo (Double.parseDouble (ResponsLixeiraC.getString (KEY_FIELD3)));
feedDetails4.setId ('D');
feedDetails4.setPesoLixo (Double.parseDouble (ResponsLixeiraD.getString (KEY_FIELD4))); feedDetails4.setVolumeLixo (Double.parseDouble (ResponsLixeiraD.getString (KEY_FIELD4)));
feedList.add (feedDetails1);
feedList.add (feedDetails2); feedList.add (feedDetails3); feedList.add (feedDetails4);
// Calcula dados das lixeiras
Kira SmartBinService = SmartBinService baru (); kalkulator.montaListaLixeiras (feedList);
// Recupera komponen
TextView createDate = (TextView) mainView.findViewById (R.id.date); ListView listaDeLixeiras = (ListView) findViewById (R.id.lista); adapter.addAll (feedList);
// Data secara automatik
Date currentTime = Calendar.getInstance (). GetTime (); SimpleDateFormat simpleDate = SimpleDateFormat baru ("dd / MM / yyyy"); String currentDate = simpleDate.format (currentTime); createDate.setText (KEY_DATE + currentDate + ""); listaDeLixeiras.setAdapter (penyesuai);
} tangkapan (JSONException e) {
e.printStackTrace (); }
} lain {
Toast.makeText (MainActivity.this, "Beberapa ralat berlaku semasa memuatkan 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 prinsipal, vamos adicionar uma ação a ser relacionada ao botão Mapa, na tela inicial.
/ ** Dipanggil semasa pengguna mengetuk butang Mapa * / public void openMaps (View view) {Intent intent = Intent baru (ini, LixeiraMapsActivity.class);
// Passa a lista de lixeiras
Bundle bundle = Bundle baru (); bundle.putParcelableArrayList ("lixeiras", feedList); intent.putExtras (bundle);
startActivity (niat);
}
Tidak ada ayah, temos ini membezakan seorang pelaksana:
- marcar a posição atual do caminha de lixo
- koresponden marcar os pontos a cada lixeira no mapa
- traçar a rota entre os pontos
Para pelaksana os passos acima, vamos menggunakan API Petunjuk Google. Para desenhar as rotas, foram seguidos os passos do tutorial Melukis arah laluan pemanduan antara dua lokasi menggunakan Google Petunjuk di Google Map Android API V2
Primeiro, vamos criar localidades para cada um dos pontos que desejamos marcar:
// Lokasi
LatLng peribadi semasa;
LatLng lixeiraA peribadi; LatLng lixeiraB peribadi; LatLng lixeiraC peribadi; LatLng lixeiraD peribadi;.
Sebagai tambahan dan positif, tidak ada mapa, juga criado o método:
periksa kekosongan peribadiLocationandAddToMap () {// Memeriksa sama ada pengguna telah memberikan kebenaran sekiranya (ActivityCompat.checkSelfPermission (this, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (ini, android. Android. ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Meminta kebenaran Lokasi ActivityCompat.requestPermissions (ini, String baru {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 boleh menentukan lokasi, tajuk dll dengan MarkerOptions
this.current = LatLng baru (location.getLatitude (), location.getLongitude ()); MarkerOptions markerOptions = MarkerOptions baru (). Kedudukan (semasa). Tajuk ("Posição atual");
// Menambahkan penanda yang dibuat di peta, memindahkan kamera ke kedudukan
markerOptions.icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory. HUE_GREEN)); System.out.println ("+++++++++++++ Passei aqui! ++++++++++++++"); mMap.addMarker (markerOptions);
// Pindahkan kamera seketika ke lokasi dengan zoom 15.
mMap.moveCamera (CameraUpdateFactory.newLatLngZoom (semasa, 15));
// Zum masuk, animasikan kamera.
mMap.animateCamera (CameraUpdateFactory.zoomTo (14), 2000, null);
}
Em seguida, para cada lixeira, foram criados métodos serupa dengan abaixo:
private void addBinALocation () {// Memeriksa sama ada pengguna telah memberikan kebenaran jika (ActivityCompat.checkSelfPermission (this, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED & ActivityCompat.checkSelfPermission (ini, android. Manifest.per. ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Meminta kebenaran Lokasi ActivityCompat.requestPermissions (ini, String baru {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); kembali; }
// Praça da Estação
garis lintang berganda = -19.9159578; bujur dua kali = -43.9387856; this.lixeiraA = LatLng baru (garis lintang, garis bujur);
MarkerOptions markerOptions = kedudukan MarkerOptions baru (). (LixeiraA).title ("Lixeira A");
markerOptions.icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory. HUE_RED)); mMap.addMarker (markerOptions); }
Sebagai kedudukan lintang dan garis bujur 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 (por exemplo Firebase). Será a primeira evolução deste projeto!
Oltimo passo agora é traçar sebagai rotas entre os pontos. Sebaliknya, um confito 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:
String getDirectionsUrl peribadi (LatLng asal, LatLng dest, List waypointsList) {
// Asal laluan
String str_origin = "origin =" + origin.latitude + "," + origin.longitude;
// Destinasi laluan
String str_dest = "destination =" + dest.latitude + "," + dest.longitude;
// Titik arah di sepanjang laluan
//waypoints=optimize:true|-19.9227365, -43.9473546 | -19.9168006, -43.9361124 String waypoints = "waypoints = optimize: true"; untuk (Titik LatLng: waypointsList) {waypoints + = "|" + point.latitude + "," + point.longitude; }
// Sensor diaktifkan
Sensor rentetan = "sensor = false";
// Membangun parameter ke perkhidmatan web
Parameter rentetan = str_origin + "&" + str_dest + "&" + sensor + "&" + titik jalan;
// Format output
Output rentetan = "json";
// Membangunkan url ke perkhidmatan web
Rentetan url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameter; System.out.println ("++++++++++++++" + url);
mengembalikan url;
}
E, por fim, juntando tudo no método principal da classe, onMapReady:
@ Override public void onMapReady (GoogleMap googleMap) {mMap = googleMap;
checkLocationandAddToMap ();
jika (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 (); }
// Lukis laluan
// Mendapatkan URL ke API Petunjuk Google
Titik senarai = ArrayList baru (); points.add (lixeiraB); points.add (lixeiraC); poin.add (lixeiraD);
String url = getDirectionsUrl (semasa, lixeiraA, mata);
DownloadTask downloadTask = DownloadTask baru (); // Mula memuat turun data json dari Google Arah API downloadTask.execute (url); }
Aqui passamos apenas pelos pontos Principais. O código completeo do projeto será disponibilizado para consulta.
Langkah 8: Kesimpulannya
Este foi um projeto trabalhando conceitos de IoT, mostrando uma das várias opções de conectar dispositivos através da nuvem, e efetuar tomada de decisões sem interferência humana direta. Em anexo, segue um vídeo do projeto completeo, para ilustração, e os fontes das atividades criadas no Android.
Disyorkan:
Sistem Makluman Tempat Letak Balik Kereta Arduino - Langkah demi Langkah: 4 Langkah
Sistem Makluman Tempat Letak Balik Kereta Arduino | Langkah demi Langkah: Dalam projek ini, saya akan merancang Litar Sensor Tempat Letak Kereta Berbalik Arduino yang ringkas menggunakan Sensor Ultrasonik Arduino UNO dan HC-SR04. Sistem amaran Car Reverse berasaskan Arduino ini dapat digunakan untuk Navigasi Autonomi, Robot Ranging dan rangkaian lain
Langkah demi Langkah Pembinaan PC: 9 Langkah
Langkah demi Langkah Pembinaan PC: Persediaan: Perkakasan: MotherboardCPU & CPU cooler PSU (Unit bekalan kuasa) Penyimpanan (HDD / SSD) RAMGPU (tidak diperlukan) Alat kes: Pemutar skru Gelang ESD / tampal matsthermal dengan aplikator
Tiga Litar Pembesar Suara -- Tutorial Langkah demi Langkah: 3 Langkah
Tiga Litar Pembesar Suara || Tutorial Langkah-demi-Langkah: Loudspeaker Circuit menguatkan isyarat audio yang diterima dari persekitaran ke MIC dan menghantarnya ke Speaker dari tempat audio diperkuat dihasilkan. Di sini, saya akan menunjukkan kepada anda tiga cara berbeza untuk membuat Loudspeaker Circuit ini menggunakan:
Pengangkatan Akustik Dengan Arduino Uno Langkah demi Langkah (8-langkah): 8 Langkah
Acoustic Levitation With Arduino Uno Step-by Step (8-step): transduser suara ultrasonik L298N Dc power adaptor wanita dengan pin dc lelaki Arduino UNOBreadboardBagaimana ini berfungsi: Pertama, anda memuat naik kod ke Arduino Uno (ia adalah mikrokontroler yang dilengkapi dengan digital dan port analog untuk menukar kod (C ++)
SmartBin: 4 Langkah
SmartBin: Tujuan utama projek ini adalah untuk membuat peranti elektronik yang menggunakan sekurang-kurangnya satu Raspberry Pi. Pasukan ini terdiri daripada 5 jurutera mekanikal masa depan dan seorang jurutera automasi. Projek kami terdiri daripada membuat tong sampah yang terbuka dan ditutup