Satura rādītājs:

SmartBin: 8 soļi
SmartBin: 8 soļi

Video: SmartBin: 8 soļi

Video: SmartBin: 8 soļi
Video: SmartBin in Action 2024, Novembris
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 informationçees recuperadas.

Para montar este projeto, ja nepieciešams:

  • NodeMCU
  • Ultrassônico de Distancia sensors
  • Caixa de papelão
  • Protoboard
  • Cabos
  • Dispositivo Android

1. darbība: Conectando O sensors

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

// definē tapas numurus #define pino_trigger 2 // D4

#define pino_echo 0 // D3

Paredzēts sensoru, leitura dos dados do sensoru, sekošanas vai apmācības izstrādāto pelo FilipeFlop, displeja ūdens.

pludiņš cmMsec, inMsec;

garš mikrosekunde = ultraskaņas.laiks ();

cmMsec = ultraskaņas.konvertēt (mikrosekundes, ultraskaņas:: CM);

inMsec = ultraskaņas.konvertēt (mikrosekundes, Ultraskaņas:: IN);

// Exibe informationcoes nav sērijveida monitora

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

Sērijas nospiedums (cmMsec);

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

Serial.println (inMsec);

Stīgu dati = String (cmMsec);

Serial.println (dati);

2. solis: Montando un Lixeira

Agora, vamos montar un lixeira inteligente. Precizēts konvektors vai sensora ultrassônico no “teto” da lixeira. Piemēram, izmantojiet kabīni un izolantus. Em seguida, temos que medir a distância inicial, para saber o valor para a lixeira vazia. Nav meo caso, foi de 26, 3cm. Esse é o valor que Regardrarmos para uma lixeira vazia.

Para simulação, 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

garš lixeiraID;

void loop () {

lixeiraID = nejaušs (1, 5);

}

3. darbība: augšupielādējiet Nuvem

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

Parādiet konektoru un ThingSpeak aplicação com. Siga os passos descritos no site oficial.

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

void connectWifi () {

Serial.print ("Savienojuma izveide ar"+ *ssid);

WiFi.begin (ssid, pass);

kamēr (WiFi.status ()! = WL_CONNECTED) {

kavēšanās (500);

Sērijas nospiedums (".");

}

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.

void setup () {

Sērijas sākums (9600);

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

// Conectando ao Wi-Fi

connectWifi ();

}

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 (pludiņš cmMsec, garš id) {

ja (client.connect (serveris, 80)) {

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

Stīgu postStr = apiKey;

postStr += "& lauks";

postStr += id;

postStr += "=";

postStr += String (cmMsec);

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

Serial.println (postStr);

client.print ("POST /atjaunināt HTTP /1.1 / n");

client.print ("Saimnieks: api.thingspeak.com / n");

client.print ("Savienojums: aizvērt / 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);

kavēšanās (1000);

}

client.stop ();

}

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

4. solis. Recuperando Dados Do ThingSpeak

O ThingSpeak permite efetuar leitura dos dados do seu canal, através de um serviço retornando um JSON. Kā atšķirīgi 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. O padrão de URL para cen 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 svarīgākie para o projeto são:

  • CHANNEL_ID: número do seu kanāls
  • FIELD_NUMBER: o número do campo
  • API_KEY: Chave de API do seu kanāls

Šis ir vietrāža URL, kas paredzēts Android lietojumprogrammām, kā arī ThingSpeak rekuperators.

5. darbība. Criando a Aplicação Android

Nav Android Studio, iesakiet jaunu Android versiju. Pareiza vai pareiza funkcionāla aplikācijas programma, kas nepieciešama konfigurācijai kā atļauja abaixo no AndroidManifest.

Izmantojiet Google Maps, jums ir nepieciešams izmantot Google pakalpojumus. Siga os passos descritos no link Obter chave de API.

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

API atslēga uz Google Maps balstītām API ir definēta kā virkņu resurss.

(Skatiet failu "res/values/google_maps_api.xml").

Ņemiet vērā, ka API atslēga ir saistīta ar šifrēšanas atslēgu, ko izmanto APK parakstīšanai. Katrai šifrēšanas atslēgai ir nepieciešama cita API atslēga, ieskaitot atbrīvošanas atslēgu, kas tiek izmantota APK parakstīšanai publicēšanai. Atkļūdošanas un izlaišanas mērķu atslēgas varat definēt sadaļā src/debug/un src/release/.

<metadati

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

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

Ir pabeigta konfigurācija, kas paredzēta AndroidManifest aneksado lietošanai.

n

6. darbība. Atjaunojiet barību bez Android

Ja jums nav Android, MainActivity, 4 versijas, var identificēt cada um dos canais do ThingSpeak a serem lidos:

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

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

JSONObjekta atbildeLixeiraA; JSONObjekta atbildeLixeiraB; JSONObjekta atbildeLixeiraC; JSONObjekta atbildeLixeiraD;

Para abrir a conexão com as url, vamos usar criar uma classe auxiliar, chamada HttpJsonParser. Esta classe serā atbilde uz abrir uma conexão com um URL, efetuar leitura dos dados encontrados, e retornar or objeto JSON montado.

public JSONObject makeHttpRequest (virknes URL, virknes metode, kartes parametri) {

pamēģini {

Uri. Builder builder = jauns 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 ();

}

ja ("GET".vienāds (metode)) {url = url + "?" + kodētiParams; urlObj = jauns URL (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (metode);

} vēl {

urlObj = jauns URL (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (metode); urlConnection.setRequestProperty ("Content-Type", "application/x-www-form-urlencoded"); urlConnection.setRequestProperty ("Content-Length", String.valueOf (encodedParams.getBytes (). length)); urlConnection.getOutputStream (). write (encodedParams.getBytes ()); } // Savienojuma izveide ar serveri urlConnection.connect (); // Lasīt atbildi ir = urlConnection.getInputStream (); BufferedReader lasītājs = jauns BufferedReader (jauns InputStreamReader (ir)); StringBuilder sb = jauns StringBuilder (); Stīgu līnija;

// Parsēt atbildi

while ((rinda = lasītājs.lasīšanas rinda ())! = null) {sb.append (rinda + "\ n"); } is.close (); json = sb.toString (); // Pārvērst atbildi uz JSON objektu jObj = new JSONObject (json);

} catch (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 (Izņēmums e) {Log.e ("Izņēmums", "Kļūda parsējot datus" + e.toString ()); }

// atgriezt JSON objektu

atgriezties jObj;

}

}

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

@Pārvarēt aizsargātu virkni doInBackground (String… params) {HttpJsonParser jsonParser = jauns 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 passa para or método onPostExecute. Neste método, vamos criar os objetos Lixeira, e popular com os dados recuperados do ThingSpeak:

protected void onPostExecute (String rezultāts) {pDialog.dismiss (); runOnUiThread (jauns Runnable () {public void run () {

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

Skatīt mainView = (Skatīt) findViewById (R.id.activity_main); if (veiksme == 1) {try {// Cria feedDetail para cada lixeira Lixeira feedDetails1 = new Lixeira (); Lixeira feedDetails2 = jauna Lixeira (); Lixeira feedDetails3 = jauna Lixeira (); Lixeira feedDetails4 = jauna 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 kalkulators = jauns SmartBinService (); calculator.montaListaLixeiras (feedList);

// Recupera komponenti

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

// Datu aktualitāte

Datums currentTime = Calendar.getInstance (). GetTime (); SimpleDateFormat simpleDate = jauns SimpleDateFormat ("dd/MM/gggg"); String currentDate = simpleDate.format (currentTime); createDate.setText (KEY_DATE + currentDate + ""); listaDeLixeiras.setAdapter (adapteris);

} nozveja (JSONException e) {

e.printStackTrace (); }

} vēl {

Toast.makeText (MainActivity.this, "Ielādējot datus radās kāda kļūda", Toast. LENGTH_LONG).show ();

}

} }); }

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

7. solis: Mostrando No Mapa

Mostrando No Mapa
Mostrando No Mapa

Ainda na atividade principāls, vamos adicionar uma ação a ser relacionada ao botão Map, na tela inicial.

/ ** Izsaukts, kad lietotājs pieskaras pogai Karte*/ public void openMaps (Skatīt skatu) {Intent aim = new Intent (this, LixeiraMapsActivity.class);

// Passa a lista de lixeiras

Bundle bundle = jauns Bundle (); bundle.putParcelableArrayList ("lixeiras", feedList); aim.putExtras (saišķis);

startActivity (nodoms);

}

Nav kartes, temos três atividades a executar:

  1. marcar a posição atual do caminha de lixo
  2. marcar os precīzas korespondentes a cada lixeira no mapa
  3. traçar a rota entre os pontos

Lai izpildītu visas prasības, izmantojiet API Google norādījumus. Para desenhar as rotas, foram seguidos os passos do apmācība Braukšanas ceļa norāžu zīmēšana starp divām vietām, izmantojot Google norādes Google Map Android API V2

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

// Atrašanās vietas

privāta LatLng strāva;

privātā LatLng lixeiraA; privāts LatLng lixeiraB; privāts LatLng lixeiraC; privāta LatLng lixeiraD;.

Lai skatītu apo posional no mapa, foi criado o método:

private void checkLocationandAddToMap () {// Pārbaude, vai lietotājs ir piešķīris atļauju, ja (ActivityCompat.checkSelfPermission (šis, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat. Meck. Shemp. Shemp; ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Atrašanās vietas atļaujas pieprasīšana ActivityCompat.requestPermissions (šī, jaunā virkne {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); atgriešanās; }

// Pēdējās zināmās atrašanās vietas iegūšana, izmantojot Fus

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

// MarkerOptions tiek izmantotas, lai izveidotu jaunu marķieri. Izmantojot MarkerOptions, varat norādīt atrašanās vietu, nosaukumu utt.

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

// Izveidotā marķiera pievienošana kartei, kameras pārvietošana pozīcijā

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

// Nekavējoties pārvietojiet kameru uz atrašanās vietu ar 15 tālummaiņu.

mMap.moveCamera (CameraUpdateFactory.newLatLngZoom (pašreizējais, 15));

// Tuvināt, animēt kameru.

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

}

Em seguida, para cada lixeira, foram criados metodos similares ao abaixo:

private void addBinALocation () {// Pārbaude, vai lietotājs ir piešķīris atļauju, ja (ActivityCompat.checkSelfPermission (šis, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission.html, ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Atrašanās vietas atļaujas pieprasīšana ActivityCompat.requestPermissions (šī, jaunā virkne {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); atgriešanās; }

// Praça da Estação

dubults platums = -19.9159578; dubultā garums = -43,9387856; this.lixeiraA = new LatLng (platums, garums);

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

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

Kā atrašanās vietas platums un garums, 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 (piemēram 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!

Jautājums par to, kā to izdarīt, ir:

privāta virkne getDirectionsUrl (LatLng izcelsme, LatLng galamērķis, List waypointsList) {

// Maršruta izcelsme

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

// Maršruta galamērķis

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

// Maršruta punkti maršrutā

//waypoints=optimize:true|-19.9227365, -43.9473546 | -19.9168006, -43.9361124 String waypoints = "waypoints = optimize: true"; for (LatLng point: waypointsList) {waypoints += "|" + punkts. platums + "," + punkts.garums; }

// Sensors iespējots

Stīgu sensors = "sensors = nepatiess";

// Parametru veidošana tīmekļa pakalpojumam

Virknes parametri = str_origin+"&"+str_dest+"&"+sensors+"&"+ceļa punkti;

// Izvades formāts

Stīgu izvade = "json";

// URL veidošana tīmekļa pakalpojumam

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

atgriešanās URL;

}

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

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

checkLocationandAddToMap ();

ja (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 (); }

// Zīmēt maršrutus

// URL iegūšana Google virzienu API

Saraksta punkti = jauns ArrayList (); punkti.pievienot (lixeiraB); punkti.pievienot (lixeiraC); punkti.pievienot (lixeiraD);

String url = getDirectionsUrl (pašreizējais, lixeiraA, punkti);

DownloadTask downloadTask = jauns DownloadTask (); // Sāciet lejupielādēt json datus no Google Directions API downloadTask.execute (url); }

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

8. solis: 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. Tā ir aneksija, videomateriāls, kas paredzēts pilnīgai projektēšanai, ilustrācijai un e -fontu izmantošanai, izmantojot Android.

Ieteicams: