Sisällysluettelo:

SmartBin: 8 vaihetta
SmartBin: 8 vaihetta

Video: SmartBin: 8 vaihetta

Video: SmartBin: 8 vaihetta
Video: Xiaomi Smart Band 7 Pro — всё плохо? 2024, Marraskuu
Anonim
SmartBin
SmartBin

Este é um projeto para um system 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, e välttämättömyys:

  • NodeMCU
  • Anturi Ultrassônico de Distancia
  • Caixa de papelão
  • Protoboard
  • Cabos
  • Androidin käyttö

Vaihe 1: Conectando O -anturi

Primeiramente, vamos efetuar a conexão entre o sensor ultrassônico e o NODEMCU. Para tanto, vamos conectar as portas trigger e echo do sensor nas portas D4 e D3 do NodeMCU:

// määrittelee nastojen numerot #define pino_trigger 2 // D4

#define pino_echo 0 // D3

Parempi kuin leitura dos dados do -anturi, sekoitus tai opetusohjelma FilipeFlop -pelissä, joka on suunniteltu käytettäväksi.

kellua cmMsec, inMsec;

pitkä mikrosekunti = ultraääni.ajoitus ();

cmMsec = ultraääni.muunnos (mikrosekunti, ultraääni:: CM);

inMsec = ultraääni.muunnos (mikrosekunti, ultraääni:: IN);

// Exibe informacoes no serial monitor

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

Sarjajälki (cmMsec);

Serial.print (" - Distancia em polegadas:");

Sarja.println (inMsec);

Merkkijonotiedot = Jono (cmMsec);

Serial.println (data);

Vaihe 2: Montando ja Lixeira

Agora, vamos montar ja lixeira inteligente. Tarkka liitäntäanturi tai ultraäänitunnistin ilman "teto" da lixeiraa. Esimerkkinä voidaan käyttää cabo ja fita isolante. Em seguida, temos que medir a distância inicial, para saber o valor para a lixeira vazia. Ei meu caso, foi de 26, 3cm. Esse é o valor que Regardrarmos para uma lixeira vazia.

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

// Simulando 4 lixeiras

pitkä lixeiraID;

void loop () {

lixeiraID = satunnainen (1, 5);

}

Vaihe 3: Lataa Nuvem

Agora, tarkat enviar estes dados para a nuvem. Eu esholhi tai ThingSpeak, familiaridade com o mesmo. Primeiramente, é välttämätön criar um novo canal, recebendo 4 parâmetros, referentes ao volume de cada lixeira.

Parque conectar a aplicação com o ThingSpeak, e, välttämätön salvar tai número da API do canal criado. Siga os passos descritos no site virallinen.

De volta à aplicação, vamos utilizar a biblioteca ESP8266WiFi.h for efetuar conexão com or 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 identifador e a senha de sua rede).

void connectWifi () {

Serial.print ("Yhdistäminen"+ *ssid);

WiFi. Alku (ssid, pass);

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

viive (500);

Serial.print (".");

}

Serial.println ("");

Serial.print ("Conectado na rede");

Sarja.println (ssid);

Serial.print ("IP:");

Serial.println (WiFi.localIP ());

}

Durante o setup, tentamos efetuar a conexão com a rede.

void setup () {

Sarja.alku (9600);

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

// Yhdistä Wi-Fi

connectWifi ();

}

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

void sendDataTS (float cmMsec, long id) {

if (client.connect (palvelin, 80)) {

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

Merkkijono postStr = apiKey;

postStr += "& kenttä";

postStr += id;

postStr += "=";

postStr += Jono (cmMsec);

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

Serial.println (postStr);

client.print ("POST /päivitä HTTP /1.1 / n");

client.print ("Isäntä: api.thingspeak.com / n");

client.print ("Yhteys: sulje / n");

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

client.print ("Content-Type: application/x-www-form-urlencoded / n");

client.print ("Content-Length:");

client.print (postStr.length ());

client.print ("\ n / n");

client.print (postStr);

viive (1000);

}

client.stop ();

}

O primeiro parâmetro vastaa à 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 identifar para para campo será feito o upload do valor lido.

Vaihe 4: Recuperando Dados Do ThingSpeak

O ThingSpeak permite 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 directtamente os dados de cada campo. Osoita URL -osoite para cen cenio:

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. Tärkeää tietoa projektista:

  • CHANNEL_ID: número do seu -kanava
  • FIELD_NUMBER: o número do campo
  • API_KEY: chave de API do seu -kanava

Tämä on Android -sovelluksen URL -osoite, joka toimii ThingSpeakin tallentimena.

Vaihe 5: Criando a Aplicação Android

Ei Android Studiota, huuda Android -ohjelma. Paranna tai korjaa funktionamento da aplicação, ja välttämätön konfiguraattori, joka on sallittu ilman AndroidManifestia.

Käytä Google Mapsia tai Google -palvelua. Siga os passos descritos no link Obter chave de API.

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

Google Maps -pohjaisten sovellusliittymien sovellusliittymäavain määritellään merkkijonoresurssiksi.

(Katso tiedosto "res/values/google_maps_api.xml").

Huomaa, että API -avain on linkitetty salausavaimeen, jota käytetään APK: n allekirjoittamiseen. Tarvitset eri API -avaimen kullekin salausavaimelle, mukaan lukien julkaisuavain, jota käytetään APK: n allekirjoittamiseen julkaisemista varten. Voit määrittää avaimet debug- ja release -kohteille src/debug/ja src/release/.

<metatiedot

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

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

Täydellinen kokoonpano, joka on suunniteltu AndroidManifest anexado -ohjelmaan.

n

Vaihe 6: Palauta O -syöte Ei Androidia

Ei Android-, MainActivity-, crie 4 -versioita, jotka on määritetty tunnistamaan 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";

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

JSONObjektin vastausLixeiraA; JSONObjektin vastausLixeiraB; JSONObjektin vastausLixeiraC; JSONObjektin vastausLixeiraD;

Jos haluat käyttää URL -osoitetta, voit käyttää criar uma classe auxiliar, chamada HttpJsonParser. Esta classe -palvelun vastaus, joka on saatavilla abrir uma conexão com um URL, efetuar leitura dos dados encontrados, e retornar or objeto JSON montado.

julkinen JSONObject makeHttpRequest (merkkijonon URL -osoite, merkkijonomenetelmä, kartan parametrit) {

yrittää {

Uri. Builder builder = uusi Uri. Builder (); URL -osoite urlObj; String encodedParams = ""; if (params! = null) {for (Map. Entry -merkintä: params.entrySet ()) {builder.appendQueryParameter (entry.getKey (), entry.getValue ()); }} if (builder.build (). getEncodedQuery ()! = null) {encodedParams = builder.build (). getEncodedQuery ();

}

if ("GET".equals (method)) {url = url + "?" + koodatutParams; urlObj = uusi URL -osoite (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (menetelmä);

} muuta {

urlObj = uusi URL -osoite (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (menetelmä); urlConnection.setRequestProperty ("Content-Type", "application/x-www-form-urlencoded"); urlConnection.setRequestProperty ("Content-Length", String.valueOf (encodedParams.getBytes (). length)); urlConnection.getOutputStream (). write (encodedParams.getBytes ()); } // Yhdistä palvelimeen urlConnection.connect (); // Lue vastaus on = urlConnection.getInputStream (); BufferedReader -lukija = new BufferedReader (uusi InputStreamReader (on)); StringBuilder sb = uusi StringBuilder (); Merkkijono;

// jäsennä vastaus

while ((rivi = lukija.lukulinja ())! = null) {sb.append (rivi + "\ n"); } on lähellä(); json = sb.toString (); // Muunna vastaus muotoon JSON -objekti jObj = new JSONObject (json);

} saalis (UnsupportedEncodingException e) {

e.printStackTrace (); } saalis (ProtocolException e) {e.printStackTrace (); } saalis (IOException e) {e.printStackTrace (); } saalis (JSONException e) {Log.e ("JSON -jäsennys", "Virhe jäsentäessä tietoja" + e.toString ()); } catch (Poikkeus e) {Log.e ("Exception", "Error parsing data" + e.toString ()); }

// palauta JSON -objekti

paluu jObj;

}

}

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

@Ohita suojattu merkkijono doInBackground (Jono… parametrit) {HttpJsonParser jsonParser = uusi 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);

return null;}

Quando o método doInBackgroundé encerrado, o control of execução do Android passage or metétodo on PostExecute. Neste metodo, vamos criar os objetos Lixeira, e popular com os dados recuperados do ThingSpeak:

suojattu void onPostExecute (merkkijonon tulos) {pDialog.dismiss (); runOnUiThread (new Runnable () {public void run () {

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

Näytä mainView = (Näytä) findViewById (R.id.activity_main); if (menestys == 1) {try {// Cria feedDetail para cada lixeira Lixeira feedDetails1 = new Lixeira (); Lixeira feedDetails2 = uusi Lixeira (); Lixeira feedDetails3 = uusi Lixeira (); Lixeira feedDetails4 = uusi 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 -laskin = uusi SmartBinService (); calculator.montaListaLixeiras (feedList);

// Paranna komponentteja

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

// Tietojen tiedot

Päivämäärä currentTime = Calendar.getInstance (). GetTime (); SimpleDateFormat simpleDate = uusi SimpleDateFormat ("pp/kk/vvvv"); Merkkijono currentDate = simpleDate.format (currentTime); createDate.setText (KEY_DATE + currentDate + ""); listaDeLixeiras.setAdapter (sovitin);

} saalis (JSONException e) {

e.printStackTrace (); }

} muuta {

Toast.makeText (MainActivity.this, "Tietojen lataamisessa tapahtui virhe", Toast. LENGTH_LONG).show ();

}

} }); }

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

Vaihe 7: Mostrando No Mapa

Mostrando No Mapa
Mostrando No Mapa

Ainda na atividade rehtorina, näytä viittaukselta uma ação a ser relacionada ao botão Mapa, na tela inicial.

/ ** Soitetaan, kun käyttäjä napauttaa Mapa -painiketta*/ public void openMaps (Näytä näkymä) {Intent aim = new Intent (this, LixeiraMapsActivity.class);

// Passa a lista de lixeiras

Bundle nippu = new Bundle (); bundle.putParcelableArrayList ("lixeiras", feedList); aim.putExtras (nippu);

startActivity (tarkoitus);

}

Ei karttaa, temos três atividades a executar:

  1. marcar a posição atual do caminha de lixo
  2. marcar os tarkat kirjeenvaihtajat ja cada lixeira no mapa
  3. traçar a rota entre os pontos

Käyttämällä pass passia acima -palvelua voit käyttää Google -reittiohjeiden sovellusliittymää. Ajo -ohjeiden piirtäminen kahden paikan välillä käyttämällä Google -reittiohjeita Google Mapissa Android API V2

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

// Sijainnit

yksityinen LatLng -virta;

yksityinen LatLng lixeiraA; yksityinen LatLng lixeiraB; yksityinen LatLng lixeiraC; yksityinen LatLng lixeiraD;.

Näytä kaikki mahdolliset mahdolliset kartat, jotka ovat peräisin seuraavista tavoista:

private void checkLocationandAddToMap () {// Tarkistetaan, onko käyttäjä myöntänyt luvan, jos (ActivityCompat.checkSelfPermission (tämä, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkPifest ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Sijaintiluvan pyytäminen ActivityCompat.requestPermissions (tämä, uusi merkkijono {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); palata; }

// Viimeisen tunnetun sijainnin hakeminen Fus -toiminnolla

Location location = LocationServices. FusedLocationApi.getLastLocation (googleApiClient);

// MarkerOptionia käytetään uuden merkin luomiseen. Voit määrittää sijainnin, otsikon jne. MarkerOptions -toiminnolla

this.current = new LatLng (location.getLatitude (), location.getLongitude ()); MarkerOptions markerOptions = uusi MarkerOptions (). Sijainti (nykyinen).title ("Posição atual");

// Luodun merkin lisääminen kartalle, kameran siirtäminen paikkaan

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

// Siirrä kamera välittömästi paikkaan zoomaamalla 15.

mMap.moveCamera (CameraUpdateFactory.newLatLngZoom (nykyinen, 15));

// Lähennä, animoi kameraa.

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

}

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

private void addBinALocation () {// Tarkistetaan, onko käyttäjä myöntänyt luvan, jos (ActivityCompat.checkSelfPermission (tämä, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission.html, ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Sijaintiluvan pyytäminen ActivityCompat.requestPermissions (tämä, uusi merkkijono {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); palata; }

// Praça da Estação

kaksoisleveysaste = -19,9159578; kaksinkertainen pituusaste = -43,9387856; this.lixeiraA = uusi leveysaste (leveysaste, pituusaste);

MarkerOptions markerOptions = uusi MarkerOptions (). Sijainti (lixeiraA).title ("Lixeira A");

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

Kuten leveysaste ja pituusaste de cada lixeira foram recuperadas através do próprio Google Maps, e deixadas fixas no código. Ihanteellinen, estes valores ficariam salvos em um banco de dados (esimerkiksi Firebase). Será a primeira evolução deste projeto!

O último passo agora é traçar as 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 tarkka:

yksityinen merkkijono getDirectionsUrl (LatLng -alkuperä, LatLng -kohde, luettelo reittipisteiden luettelo) {

// Reitin alkuperä

Merkkijono str_origin = "origin ="+origin.latitude+","+origin.longitude;

// Reitin määränpää

Merkkijono str_dest = "määränpää ="+kohde. Leveysaste ","+kohde.pituusaste;

// Reittipisteet reitin varrella

// reittipisteet=optimoi:totodellisia for (LatLng point: waypointsList) {waypoints += "|" + piste. leveyspiiri + "," + piste. pituusaste; }

// Anturi käytössä

Jousisensori = "anturi = epätosi";

// Parametrien rakentaminen verkkopalveluun

Merkkijonoparametrit = str_origin+"&"+str_dest+"&"+sensor+"&"+reittipisteet;

// Tulostusmuoto

Merkkijonoulostulo = "json";

// URL -osoitteen luominen verkkopalveluun

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

paluuosoite;

}

E, por fim, juntando tudo no método princip da dalasse, 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 (); }

// Piirrä reittejä

// URL -osoitteen hakeminen Google -reittiohjeiden sovellusliittymään

Listapisteet = uusi ArrayList (); points.add (lixeiraB); points.add (lixeiraC); points.add (lixeiraD);

String url = getDirectionsUrl (nykyinen, lixeiraA, pisteet);

DownloadTask downloadTask = uusi DownloadTask (); // Aloita json -tietojen lataaminen Google Directions -sovellusliittymästä downloadTask.execute (url); }

Aqui passamos apenas pelos pontos principais. O código complete to do projeto será disponibilizado para consulta.

Vaihe 8: Conclusão

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 directta. An anime, se videon videoprojektin täydellinen, kuvassa, ja os fontit das atividades criadas ei Android.

Suositeltava: