INHOUDSOPGAWE:
- Stap 1: Conectando O -sensor
- Stap 2: Montando a Lixeira
- Stap 3: Laai Para a Nuvem op
- Stap 4: Recuperando Dados Do ThingSpeak
- Stap 5: Maak gebruik van Android
- Stap 6: Herstel die voer sonder Android
- Stap 7: Mostrando No Mapa
- Stap 8: Gevolgtrekking
Video: SmartBin: 8 stappe
2024 Outeur: John Day | [email protected]. Laas verander: 2024-01-31 10:16
Este é um projeto para um system inteligente de coletas, no qual os caminhões de lixo recebem dados das lixeiras, identifierando 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, en noodsaaklik:
- NodeMCU
- Sensor Ultrassônico de Distancia
- Caixa de papelão
- Protobord
- Cabos
- Beskik oor Android
Stap 1: Conectando O -sensor
Primeiramente, vamos efetuar a conexão entre o sensor ultrassônico e o NODEMCU. Dit is ook moontlik om die portale te aktiveer en 'n eggo te maak vir die sensor D4 en D3 vir NodeMCU:
// definieer penne nommers #definieer pino_trigger 2 // D4
#definieer pino_echo 0 // D3
Vir meer inligting oor hoe om sensore te gebruik, kan ons ook 'n tutoriaal oor hoe om FilipeFlop te gebruik, beskikbaar stel.
dryf cmMsec, inMsec;
lang mikrosek = ultrasoniese.timing ();
cmMsec = ultrasonic.convert (mikrosek, ultraklank:: CM);
inMsec = ultrasonic.convert (mikrosek, ultraklank:: IN);
// Daar is geen seriële monitor nie
Serial.print ("Distancia em cm:");
Serial.print (cmMsec);
Serial.print (" - Distancia em polegadas:");
Serial.println (inMsec);
Stringdata = String (cmMsec);
Serial.println (data);
Stap 2: Montando a Lixeira
Agora, vamos montar a lixeira inteligente. Die presiese metode is om 'n ultraklank sensor te gebruik. Byvoorbeeld, gebruik dit om 'n isolasie te gebruik. Ons kan dit nie eers in die amptelike tyd gebruik nie, maar ook as 'n waarde vir ons. Geen grootte, 26 cm, 3 cm. Dit is 'n waarde wat ons oorweeg om ons te help.
Para simulação, ons kan nie meer as 'n maksimum sensor gebruik nie, maar dit is ook 'n algoritme vir willekeurige afwykings en 4 verskillende afdelings.
// Simulando 4 lixeiras
lang lixeiraID;
leemte -lus () {
lixeiraID = random (1, 5);
}
Stap 3: Laai Para a Nuvem op
Agora, precisamos enviar estes dados para a nuvem. Eu escolhi o ThingSpeak, deur 'n bekende com o mesmo. Primeiramente, é needsário criar um novo canal, recebendo 4 parâmetros, referentes ao volume de cada lixeira.
Vir die gebruik van ThingSpeak, is dit 'n noodsaaklike oplossing vir 'n API vir kanaalverskuiwing. Ons kan nie die amptelike webwerf besoek nie.
Die volta à aplicação, ons kan ook 'n biblioteca gebruik ESP8266WiFi.h para efetuar conexão com of ThingSpeak, and transferir os dados.
Primeiramente, uma função para efetuar conexão com a rede (defina previamente duas variáveis, ssid e pass , contendo o identifierador e a senha de sua rede).
ongeldig connectWifi () {
Serial.print ("Koppel aan"+ *ssid);
WiFi.begin (ssid, pass);
terwyl (WiFi.status ()! = WL_CONNECTED) {
vertraging (500);
Serial.print (".");
}
Serial.println ("");
Serial.print ("Conectado na rede");
Serial.println (ssid);
Serial.print ("IP:");
Serial.println (WiFi.localIP ());
}
Tydens die opstelling, kan u dit ook maklik gebruik.
ongeldige opstelling () {
Serial.begin (9600);
Serial.println ("Lendo dados do sensor …");
// Verbinding met Wi-Fi
connectWifi ();
}
E, vir ons kan u ThingSpeak gebruik, maar ons kan ook HTTP -bladsye gebruik, ons kan ook die API -e -pos en ons parameters gebruik.
void sendDataTS (float cmMsec, long id) {
if (client.connect (bediener, 80)) {
Serial.println ("Enviando dados para o ThingSpeak");
String postStr = apiKey;
postStr += "& veld";
postStr += id;
postStr += "=";
postStr += String (cmMsec);
postStr += "\ r / n / r / n";
Serial.println (postStr);
client.print ("POST /opdater HTTP /1.1 / n");
client.print ("Gasheer: api.thingspeak.com / n");
client.print ("verbinding: sluit / n");
client.print ("X-THINGSPEAKAPIKEY:" + apiKey + "\ n");
client.print ("Inhoudstipe: toepassing/x-www-vorm-urlencoded / n");
client.print ("Inhoudlengte:");
client.print (postStr.length ());
client.print ("\ n / n");
client.print (postStr);
vertraging (1000);
}
client.stop ();
}
O primeiro parâmetro corresponde à distância em centímetros encontrada pelo sensor ultrassônico. Dit is 'n identiteit wat ons kan identifiseer (wat die willekeurige weergawe van die nommer 1 tot 4).
O ID kan ons dien as 'n identifikasie vir 'n werklike feit om dit te laai.
Stap 4: Recuperando Dados Do ThingSpeak
O ThingSpeak laat u toe om die kanale van die kanaal te herstel, om die diens terug te stuur na JSON. Aangesien verskillende opções para leitura voer, kan ons die kanaal kan beskryf:
www.mathworks.com/help/thingspeak/get-a-ch…
Neste projeto, optou-se por ler diretamente os dados de cada campo. Die URL vir 'n enkele cenário é:
api.thingspeak.com/channels/CHANNEL_ID/fields/FIELD_NUMBER/last.json?api_key=API_KEY&status=true
Cada campo está descrito geen skakel informado previamente. Ons belangrikste aspekte vir die volgende is:
- CHANNEL_ID: 'n nuwe kanaal
- FIELD_NUMBER: o número do campo
- API_KEY: 'n kanaal van API vir die kanaal
Dit is 'n URL wat Android kan gebruik, en vir ThingSpeak kan herstel word.
Stap 5: Maak gebruik van Android
Geen Android Studio, 'n nuwe Android -program. Para o correto funcionamento da aplicação, en noodsaaklik konfigurasie as permissões abaixo no AndroidManifest.
Vir die gebruik van Google Maps, is dit noodsaaklik om 'n Google -webwerf te gebruik. Ons kan nie die skakel beskryf nie.
Uma vez com a chave, você deve também configurá-la na aplicação.
Die API-sleutel vir Google Maps-gebaseerde API's word gedefinieer as 'n stringbron.
(Sien die lêer "res/values/google_maps_api.xml").
Let daarop dat die API -sleutel gekoppel is aan die enkripsiesleutel wat gebruik is om die APK te onderteken. U benodig 'n ander API -sleutel vir elke enkripsiesleutel, insluitend die vrystellingsleutel wat gebruik word om die APK vir publikasie te onderteken. U kan die sleutels vir die ontfoutings- en vrystellingsdoelwitte definieer in src/debug/en src/release/.
<metadata
android: name = "com.google.android.geo. API_KEY"
android: value = "@string /google_maps_key" />
'N Konfigurasie van 'n volledige weergawe van Android kan op 'n ander manier plaasvind.
n
Stap 6: Herstel die voer sonder Android
Na die hoofhoof sonder Android, MainActivity, 4 verskillende weergawes vir 'n identifikasie van dinge wat u kan doen:
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";
Vir meer inligting oor ons, kan u ook 'n Android -klas vir Android, of vir JSONObject gebruik. Meer inligting, meer inligting oor die URL:
JSONObject responseLixeiraA; JSONObject responseLixeiraB; JSONObject responseLixeiraC; JSONObject responseLixeiraD;
Para abrir a conexão com as urls, vamos usar criar uma classe auxiliar, chamada HttpJsonParser. Eerstens kan ons 'n antwoord op 'n URL, 'n e -posadres of 'n terugvoering van JSON -installasies, gee.
publiek JSONObject makeHttpRequest (String -url, String -metode, kaartparameters) {
probeer {
Uri. Builder bouer = nuwe Uri. Builder (); URL urlObj; String encodedParams = ""; if (params! = null) {for (Map. Entry entry: params.entrySet ()) {builder.appendQueryParameter (entry.getKey (), entry.getValue ()); }} if (builder.build (). getEncodedQuery ()! = null) {encodedParams = builder.build (). getEncodedQuery ();
}
if ("GET".gelyk (metode)) {url = url + "?" + encodedParams; urlObj = nuwe URL (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (metode);
} anders {
urlObj = nuwe URL (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (metode); urlConnection.setRequestProperty ("Inhoudstipe", "toepassing/x-www-vorm-urlencoded"); urlConnection.setRequestProperty ("Content-Length", String.valueOf (encodedParams.getBytes (). length)); urlConnection.getOutputStream (). skryf (encodedParams.getBytes ()); } // Koppel aan die bediener urlConnection.connect (); // Lees die antwoord is = urlConnection.getInputStream (); BufferedReader reader = new BufferedReader (new InputStreamReader (is)); StringBuilder sb = nuwe StringBuilder (); Snaarlyn;
// Ontleed die antwoord
terwyl ((line = reader.readLine ())! = null) {sb.append (reël + "\ n"); } is.close (); json = sb.toString (); // Skakel die antwoord om na JSON Object jObj = nuwe JSONObject (json);
} catch (UnsupportedEncodingException e) {
e.printStackTrace (); } vang (ProtocolException e) {e.printStackTrace (); } vang (IOException e) {e.printStackTrace (); } catch (JSONException e) {Log.e ("JSON Parser", "Fout tydens ontleding van data" + e.toString ()); } catch (Uitsondering e) {Log.e ("Uitsondering", "Fout tydens die ontleding van data" + e.toString ()); }
// terugkeer JSON Object
terugkeer jObj;
}
}
Die volta en hoof van die atividade, ons kan ook 'n webwerf of 'n URL vir formele assincrona, escrevendo este código dentro do método doInBackground gebruik.
@Override beskermde string doInBackground (string … params) {HttpJsonParser jsonParser = nuwe HttpJsonParser ();
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);
gee null terug;}
Met die agtergrond kan u die uitvoer van Android op die PostExecute -stelsel beheer. Ons kan ook nie meer inligting oor Lixeira kry nie, maar ook 'n gewilde rekord van ThingSpeak:
beskermde leemte onPostExecute (string resultaat) {pDialog.dismiss (); runOnUiThread (new Runnable () {public void run () {
// ListView listView = (ListView) findViewById (R.id.feedList);
Bekyk mainView = (Bekyk) findViewById (R.id.activity_main); as (sukses == 1) {probeer {// Cria feedDetail para cada lixeira Lixeira feedDetails1 = nuwe Lixeira (); Lixeira feedDetails2 = nuwe Lixeira (); Lixeira feedDetails3 = nuwe Lixeira (); Lixeira feedDetails4 = nuwe Lixeira ();
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);
// Calcula dados das lixeiras
SmartBinService sakrekenaar = nuwe SmartBinService (); sakrekenaar.montaListaLixeiras (feedList);
// Recupera -komponente
TextView createDate = (TextView) mainView.findViewById (R.id.date); ListView listaDeLixeiras = (ListView) findViewById (R.id.lista); adapter.addAll (feedList);
// Gegewens
Date currentTime = Calendar.getInstance (). GetTime (); SimpleDateFormat simpleDate = nuwe SimpleDateFormat ("dd/MM/jjjj"); String currentDate = simpleDate.format (currentTime); createDate.setText (KEY_DATE + currentDate + ""); listaDeLixeiras.setAdapter (adapter);
} vang (JSONException e) {
e.printStackTrace (); }
} anders {
Toast.makeText (MainActivity.this, "Sommige foute het voorgekom tydens die laai van data", Toast. LENGTH_LONG).show ();
}
} }); }
Agora, in die eerste plek, kan u ook 'n lys met ons doen.
Stap 7: Mostrando No Mapa
Ons kan ook die hoof van 'n aparte hoof herken, maar dit kan amptelik nie.
/ ** Bel as die gebruiker op die Mapa -knoppie tik*/ openbaar leeg openMaps (Bekyk aansig) {Voorneme bedoeling = nuwe Voorneme (hierdie, LixeiraMapsActivity.class);
// Gee 'n lys van lys
Bundelbundel = nuwe Bundel (); bundle.putParcelableArrayList ("lixeiras", feedList); intention.putExtras (bundel);
startActivity (bedoeling);
}
Geen kaart, tydskrifte kan die uitvoerende gesag nie:
- marcar a posição atual do caminha de lixo
- marcar os pontos correspondentes a cada lixeira no mapa
- traçar a rota entre os pontos
Vir die uitvoer van ons werk, kan ons ook 'n API -aanwysing van Google gebruik. Vir meer inligting, kan u ook instruksies opstel om die padroete tussen twee plekke met behulp van Google -aanwysings in Google Map Android API V2 te teken
Primeiro, vamos criar localidades para cada um dos pontos que desejamos marcar:
// Plekke
private LatLng huidige;
private LatLng lixeiraA; private LatLng lixeiraB; private LatLng lixeiraC; private LatLng lixeiraD;.
Para adicionar a posição atual no mapa, foi criado of método:
private void checkLocationandAddToMap () {// Kontroleer of die gebruiker toestemming verleen het as (ActivityCompat.checkSelfPermission (this, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Versoek die liggingstoestemming ActivityCompat.requestPermissions (hierdie, nuwe string {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); terugkeer; }
// Haal die laaste bekende ligging met die Fus
Location location = LocationServices. FusedLocationApi.getLastLocation (googleApiClient);
// MarkerOptions word gebruik om 'n nuwe merker te skep. U kan ligging, titel ens met MarkerOptions spesifiseer
this.current = nuwe LatLng (location.getLatitude (), location.getLongitude ()); MarkerOptions markerOptions = nuwe MarkerOptions (). Posisie (huidige).title ("Posição atual");
// Voeg die gemerkte merker op die kaart by en skuif die kamera na die posisie
markerOptions.icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory. HUE_GREEN)); System.out.println ("++++++++++++++ Passei aqui! +++++++++++++"); mMap.addMarker (markerOptions);
// Beweeg die kamera onmiddellik na die plek met 'n zoom van 15.
mMap.moveCamera (CameraUpdateFactory.newLatLngZoom (huidige, 15));
// Zoom in en animeer die kamera.
mMap.animateCamera (CameraUpdateFactory.zoomTo (14), 2000, null);
}
Em seguida, para cada lixeira, foram criados métodos similares ao abaixo:
private void addBinALocation () {// Kontroleer of die gebruiker toestemming verleen het as (ActivityCompat.checkSelfPermission (this, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (hierdie, android. Permission. ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Versoek die liggingstoestemming ActivityCompat.requestPermissions (hierdie, nuwe string {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); terugkeer; }
// Praça da Estação
dubbele breedtegraad = -19,9159578; dubbele lengte = -43,9387856; this.lixeiraA = nuwe LatLng (breedtegraad, lengtegraad);
MarkerOptions markerOptions = nuwe MarkerOptions (). Posisie (lixeiraA).title ("Lixeira A");
markerOptions.icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory. HUE_RED)); mMap.addMarker (markerOptions); }
As postições of latitude and 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 (by voorbeeld Firebase). Será a primeira evolução deste projeto!
O último passo agora é traçar as rotas entre os pontos. Para tal, um conitoito muito importante, e que será utilize next projeto, or waypoints!
Ons kan dit vir ons 'n draai gee:
private String getDirectionsUrl (LatLng -oorsprong, LatLng -dest, List waypointsList) {
// Oorsprong van roete
String str_origin = "origin ="+origin.latitude+","+origin.longitude;
// Bestemming van roete
String str_dest = "destination ="+dest.latitude+","+dest.longitude;
// Waypoints langs die roete
//waypoints=optimize:true|-19.9227365, -43.9473546 | -19.9168006, -43.9361124 String waypoints = "waypoints = optimize: true"; vir (LatLng -punt: waypointsList) {waypoints += "|" + punt.breedte + "," + punt.lengtegraad; }
// Sensor aangeskakel
String sensor = "sensor = false";
// Bou die parameters vir die webdiens
String parameters = str_origin+"&"+str_dest+"&"+sensor+"&"+waypoints;
// Uitsetformaat
Stringuitset = "json";
// Bou die URL vir die webdiens
String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters; System.out.println ("++++++++++++++"+url);
terugkeer url;
}
E, por fim, juntando tudo no método principal da classe, onMapReady:
@Overheers openbare leemte onMapReady (GoogleMap googleMap) {mMap = googleMap;
checkLocationandAddToMap ();
as (lixeirasList.get (0).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE
|| lixeirasList.get (0).getPesoLixo ()-10> Lixeira. MIN_SIZE_GARBAGE) {addBinALocation (); } as (lixeirasList.get (1).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get (1).getPesoLixo ()> Lixeira. MIN_SIZE_GARBAGE) {addBinBLocation (); } as (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 (); }
// Teken roetes
// Kry URL na die Google Directions API
Lyspunte = nuwe ArrayList (); punte.add (lixeiraB); punte.add (lixeiraC); punte.add (lixeiraD);
String url = getDirectionsUrl (huidige, lixeiraA, punte);
DownloadTask downloadTask = nuwe DownloadTask (); // Begin aflaai van json -data van Google Directions API downloadTask.execute (url); }
Aqui passamos apenas pelos pontos principais. Dit is moontlik om 'n volledige verskaffing van konsultasies moontlik te maak.
Stap 8: Gevolgtrekking
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 as interferência humana direta. U kan dit ook vir ons voltooi, sowel as vir die lettertipes wat vir Android beskikbaar is.
Aanbeveel:
Spelontwerp in vyf stappe: 5 stappe
Spelontwerp in fliek in 5 stappe: Flick is 'n baie eenvoudige manier om 'n speletjie te maak, veral iets soos 'n legkaart, visuele roman of avontuurlike spel
Gesigsopsporing op Raspberry Pi 4B in 3 stappe: 3 stappe
Gesigsopsporing op Raspberry Pi 4B in 3 stappe: in hierdie instruksies gaan ons gesigsopsporing uitvoer op Raspberry Pi 4 met Shunya O/S met behulp van die Shunyaface-biblioteek. Shunyaface is 'n biblioteek vir gesigherkenning/opsporing. Die projek het ten doel om die vinnigste opsporing en herkenningssnelheid te bereik met
DIY Vanity Mirror in eenvoudige stappe (met LED -strookligte): 4 stappe
DIY Vanity Mirror in eenvoudige stappe (met behulp van LED Strip Lights): In hierdie pos het ek 'n DIY Vanity Mirror gemaak met behulp van die LED strips. Dit is regtig cool, en u moet dit ook probeer
Arduino Halloween Edition - Zombies pop -out skerm (stappe met foto's): 6 stappe
Arduino Halloween Edition - Zombies pop -out skerm (stappe met foto's): wil u u vriende skrik en 'n skreeu geraas maak tydens Halloween? Of wil u net 'n goeie grap maak? Hierdie pop-up skerm van Zombies kan dit doen! In hierdie instruksies sal ek u leer hoe u maklik Zombies kan spring deur Arduino te gebruik. Die HC-SR0
SmartBin: 4 stappe
SmartBin: Die hoofdoel van hierdie projek is om 'n elektroniese toestel te skep wat ten minste een Raspberry Pi gebruik. Die span bestaan uit 5 toekomstige meganiese ingenieurs en een outomatiseringsingenieur. Ons projek bestaan uit die maak van 'n asblik wat oop en toe maak