Tartalomjegyzék:

SmartBin: 8 lépés
SmartBin: 8 lépés

Videó: SmartBin: 8 lépés

Videó: SmartBin: 8 lépés
Videó: Xiaomi Smart Band 7 Pro — всё плохо? 2024, November
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, é requiredário:

  • NodeMCU
  • Ultrassônico de Distancia érzékelő
  • Caixa de papelão
  • Protoboard
  • Cabos
  • Dispositivo Android

1. lépés: Conectando O érzékelő

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:

// meghatározza a csapok számát #define pino_trigger 2 // D4

#define pino_echo 0 // D3

Segítségével a leitura dos dados do érzékelő, a keverő vagy oktatóanyag kidolgozott pelo FilipeFlop, diszponível aqui.

úszó cmMsec, inMsec;

hosszú mikroszekund = ultrahangos.időzítés ();

cmMsec = ultrahangos.konvert (microsek, Ultrahangos:: CM);

inMsec = ultrahangos.konvert (microsek, Ultrasonic:: IN);

// Exibe informacoes no serial monitor

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

Soros.nyomat (cmMsec);

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

Soros.println (inMsec);

String adatok = String (cmMsec);

Serial.println (adatok);

2. lépés: Montando és Lixeira

Agora, vamos montar a lixeira inteligente. Előre beállított vagy ultraszenzoros érzékelő, nincs „teto” da lixeira. Példaként említse meg a cabo és a fito isolante használatát. Em seguida, temos que medir a distância inicial, para saber o valor para a lixeira vazia. Nincs meu caso, foi de 26, 3cm. Esse é o valor que Regardrarmos para uma lixeira vazia.

A szimuláció, a visto que não possuo mais de um ultrassônico, foi feito um algoritmo para salvar randomicamente and distancia lida em 4 lixeiras diferentes.

// Simulando 4 lixeiras

hosszú lixeiraID;

void loop () {

lixeiraID = véletlenszerű (1, 5);

}

3. lépés: Töltsön fel egy Nuvemet

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

Pará conectar a aplicação com o ThingSpeak, é saláta salvar o número da API do canal criado. Siga os passos descritos no site official.

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 identifador e a senha de sua rede).

void connectWifi () {

Serial.print ("Csatlakozás"+ *ssid);

WiFi.begin (ssid, pass);

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

késleltetés (500);

Soros.nyomtatás (".");

}

Serial.println ("");

Serial.print ("Conectado na rede");

Soros.println (ssid);

Serial.print ("IP:");

Serial.println (WiFi.localIP ());

}

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

void setup () {

Sorozat.kezdet (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 (float cmMsec, long id) {

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

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

String postStr = apiKey;

postStr += "& mező";

postStr += id;

postStr += "=";

postStr += Karakterlánc (cmMsec);

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

Serial.println (postStr);

client.print ("POST /frissítés HTTP /1.1 / n");

client.print ("Gazdagép: api.thingspeak.com / n");

client.print ("Kapcsolat: bezár / 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);

késleltetés (1000);

}

client.stop ();

}

O primeiro parâmetro megfelel a 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 qual campo será feito o upload do valor lido.

4. lépés: 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. 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 svargi para o projeto são:

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

Ez egy URL az Android alkalmazáshoz, a ThingSpeak helyreállításához.

5. lépés: Criando és Aplicação Android

Nincs Android Stúdió, ki kell dolgozni az Androidot. A helyes vagy korrekt funcionamento da aplicação, szükség van a konfigurációra, mint engedélyezett, nincs AndroidManifest.

Használja a Google Térképet, és szükség szerint használja a Google -t. Siga os passos descritos no link Obter chave de API.

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

A Google Térkép-alapú API-k API-kulcsa karakterlánc-erőforrásként van definiálva.

(Lásd a "res/values/google_maps_api.xml" fájlt).

Vegye figyelembe, hogy az API -kulcs az APK aláírásához használt titkosítási kulccsal van összekapcsolva. Minden egyes titkosítási kulcshoz más API -kulcsra van szüksége, beleértve a közzétételhez szükséges APK aláírásához használt kiadási kulcsot is. Meghatározhatja a hibakeresési és kiadási célok kulcsait az src/debug/és az src/release/fájlokban.

<meta-adatok

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

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

A konfiguráció teljes egészében elkészíthető az AndroidManifest anexado segítségével.

n

6. lépés: O -takarmány helyreállítása Nincs Android

Nem az Android, a MainActivity, a 4 változata, amely azonosítja a cada um dos canais do ThingSpeak a serem lidos címet:

private String url_a = "https://api.thingspeak.com/channels/429823/fields/1/last.json?api_key="+API_THINGSPEAK_KEY+"&status=true"; privát karakterlánc 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";

A 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 as urls, vamos usar criar uma classe auxiliar, chamada HttpJsonParser. Esta classe sera responseavel por abrir uma conexão com um URL, efetuar leitura dos dados encontrados, e retornar or objeto JSON montado.

public JSONObject makeHttpRequest (String url, String method, Map params) {

próbáld ki {

Uri. Builder builder = új Uri. Builder (); URL urlObj; String encodedParams = ""; if (params! = null) {for (Map. Entry bejegyzés: params.entrySet ()) {builder.appendQueryParameter (entry.getKey (), entry.getValue ()); }} if (builder.build (). getEncodedQuery ()! = null) {encodedParams = builder.build (). getEncodedQuery ();

}

if ("GET". egyenlő (módszer)) {url = url + "?" + kódoltParams; urlObj = új URL (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (módszer);

} más {

urlObj = új URL (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (módszer); urlConnection.setRequestProperty ("Content-Type", "application/x-www-form-urlencoded"); urlConnection.setRequestProperty ("Content-Length", String.valueOf (encodedParams.getBytes (). length)); urlConnection.getOutputStream (). write (encodedParams.getBytes ()); } // Csatlakozás a szerverhez urlConnection.connect (); // Olvassa el a választ = urlConnection.getInputStream (); BufferedReader olvasó = new BufferedReader (új InputStreamReader (is)); StringBuilder sb = új StringBuilder (); String vonal;

// A válasz elemzése

while ((sor = olvasó.olvasor ())! = null) {sb.append (sor + "\ n"); } zárva(); json = sb.toString (); // A válasz konvertálása JSON objektummá jObj = new JSONObject (json);

} catch (UnsupportedEncodingException e) {

e.printStackTrace (); } fogás (ProtocolException e) {e.printStackTrace (); } catch (IOException e) {e.printStackTrace (); } catch (JSONException e) {Log.e ("JSON Parser", "Hiba az adatok elemzésekor" + e.toString ()); } catch (Kivétel e) {Log.e ("Kivétel", "Hiba az adatok elemzésekor" + e.toString ()); }

// return JSON Object

visszatér 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.

@Védett karakterlánc felülbírálása doInBackground (String… params) {HttpJsonParser jsonParser = új 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 controle de 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 eredmény) {pDialog.dismiss (); runOnUiThread (new Runnable () {public void run () {

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

MainView megtekintése ([View] findViewById (R.id.activity_main); if (siker == 1) {try {// Cria feedDetail para cada lixeira Lixeira feedDetails1 = new Lixeira (); Lixeira feedDetails2 = új Lixeira (); Lixeira feedDetails3 = új Lixeira (); Lixeira feedDetails4 = új 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 számológép = új SmartBinService (); calculator.montaListaLixeiras (feedList);

// Recupera komponensek

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

// Adatok

Dátum currentTime = Calendar.getInstance (). GetTime (); SimpleDateFormat simpleDate = új SimpleDateFormat ("dd/MM/yyyy"); String currentDate = simpleDate.format (currentTime); createDate.setText (KEY_DATE + aktuálisDátum + ""); listaDeLixeiras.setAdapter (adapter);

} fogás (JSONException e) {

e.printStackTrace (); }

} más {

Toast.makeText (MainActivity.this, "Valamilyen hiba történt az adatok betöltése közben", Toast. LENGTH_LONG).show ();

}

} }); }

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

7. lépés: Mostrando No Mapa

Mostrando No Mapa
Mostrando No Mapa

Ainda na atividade igazgatónő, nézze meg az ç ação a ser relacionada ao botão Mapa, na tela inicial.

/ ** Akkor hívják, amikor a felhasználó megérinti a Térkép gombot*/ public void openMaps (Nézet megtekintése) {Intent aim = new Intent (this, LixeiraMapsActivity.class);

// Passa a lista de lixeiras

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

startActivity (szándék);

}

Nincs térkép, temos três atividades a executar:

  1. marcar a posição atual do caminha de lixo
  2. marcar os pontos tudósítói a cada lixeira no mapa
  3. traçar a rota entre os pontos

A végrehajtáshoz os passos acima, és használja a Google Útvonal API -t. Para desenhar as rotas, foram seguidos os passos do tutorial A vezetési útvonaltervek rajzolása két helyszín között a Google Útvonal segítségével a Google Térkép Android API V2 verziójában

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

// Helyszínek

magán LatLng áram;

magán LatLng lixeiraA; magán LatLng lixeiraB; magán LatLng lixeiraC; magán LatLng lixeiraD;.

A hirdetések megjelenítése, a térkép megjelenítése nélkül, foi criado o método:

private void checkLocationandAddToMap () {// Annak ellenőrzése, hogy a felhasználó megadta -e az engedélyt, ha (ActivityCompat.checkSelfPermission (ez, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat. MeckPifest ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// A helymeghatározási engedély kérése ActivityCompat.requestPermissions (ez, új karakterlánc {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); Visszatérés; }

// Az utolsó ismert hely lekérése a Fus segítségével

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

// A MarkerOptions új Marker létrehozására szolgál. A MarkerOptions segítségével megadhatja a helyet, a címet stb.

this.current = new LatLng (location.getLatitude (), location.getLongitude ()); MarkerOptions markerOptions = új MarkerOptions (). Pozíció (jelenlegi).title ("Posição atual");

// A létrehozott jelölő hozzáadása a térképhez, a kamera mozgatása pozícióba

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

// Vigye a fényképezőgépet azonnal a helyére 15 -ös nagyítással.

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

// Nagyítás, a kamera animálása.

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

}

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

private void addBinALocation () {// Annak ellenőrzése, hogy a felhasználó megadta -e az engedélyt, ha (ActivityCompat.checkSelfPermission (ez, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission.html, ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// A helymeghatározási engedély kérése ActivityCompat.requestPermissions (ez, új karakterlánc {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); Visszatérés; }

Praça da Estação

kettős szélesség = -19.9159578; kettős hosszúság = -43,9387856; this.lixeiraA = new LatLng (szélesség, hosszúság);

MarkerOptions markerOptions = új MarkerOptions (). Pozíció (lixeiraA).title ("Lixeira A");

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

As posições de latitude e longitude de cada lixeira foram recuperadas através do próprio Google Maps, e deixadas fixas no código. Ideális, estes valores ficariam salvos em um banco de dados (például a 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 pontos:

privát karakterlánc getDirectionsUrl (LatLng eredet, LatLng dest, List waypointsList) {

// Az útvonal eredete

Karakterlánc str_origin = "origin ="+origin.latitude+","+origin.longitude;

// Úticél

String str_dest = "cél ="+rendeltetési hely+","+rendeltetési hosszúság;

// Útpontok az útvonal mentén

// útvonalak=optimizál: igaza for (LatLng point: waypointsList) {waypoints += "|" + pont.szélesség + "," + pont.hosszúság; }

// Az érzékelő engedélyezve

Karakterlánc -érzékelő = "szenzor = hamis";

// A paraméterek kiépítése a webszolgáltatáshoz

String paraméterek = str_origin+"&"+str_dest+"&"+sensor+"&"+útpontok;

// Kimeneti formátum

Karakterlánc kimenet = "json";

// Az URL létrehozása a webszolgáltatáshoz

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

visszatérési URL;

}

E, por fim, juntando tudo no método princip da dalasse, onMapReady:

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

// Útvonalak rajzolása

// URL -cím lekérése a Google Directions API -hoz

Listapontok = új ArrayList (); points.add (lixeiraB); points.add (lixeiraC); points.add (lixeiraD);

String url = getDirectionsUrl (aktuális, lixeiraA, pontok);

DownloadTask downloadTask = új DownloadTask (); // Indítsa el a json adatok letöltését a Google Directions API -ból downloadTask.execute (url); }

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

8. lépés: 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. In anexo, segéd videók a teljes projekthez, illusztrációhoz, és minden betűtípushoz, amely nem Android.

Ajánlott: