Inhoudsopgave:

SmartBin: 8 stappen
SmartBin: 8 stappen

Video: SmartBin: 8 stappen

Video: SmartBin: 8 stappen
Video: Apple Watch 7 vs Google Fitbit Charge 5 SPO2 Test #shorts #applewatch #fitbit 2024, November
Anonim
SmartBin
SmartBin

Este e 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 recuperaadas information.

Para montar este projeto, é necessário:

  • KnooppuntMCU
  • Sensor Ultrassônico de Distancia
  • Caixa de papelão
  • Protobord
  • Cabos
  • Dispositivo Android

Stap 1: Conectando O-sensor

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

// definieert pinnummers #define pino_trigger 2 //D4

#define pino_echo 0 //D3

Voor elk moment van de dag waarop de sensor kan worden gebruikt, is er een uitgebreide uitleg van de FilipeFlop en de uitleg van de handleiding.

zweven cmMsec, inMsec;

lange microsec = ultrasone.timing();

cmMsec = ultrasoon.convert (microsec, ultrasoon::CM);

inMsec = ultrasoon.convert (microsec, ultrasoon::IN);

//Exibe informacoes geen seriële monitor

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

Serial.print (cmMsec);

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

Serial.println(inMsec);

Stringgegevens = String (cmMsec);

Serial.println(gegevens);

Stap 2: Montando a Lixeira

Agora, vamos montar a lixeira inteligente. Precisaremos conectar o sensor ultrassônico geen "teto" da lixeira. Para o exempplo, usei um cabo e fita isolante. Em seguida, temos que medir a distância inicial, para saber o valor para a lixeira vazia. Geen meu caso, foi de 26, 3cm. Esse é o valor que considerarmos para uma lixeira vazia.

Voor simulaço, visto que não possuo de um sensor ultrassônico, foi feito um algoritmo para salvar randomicamente a distancia lida em 4 lixeiras diferentes.

// Simulando 4 lixeiras

lange lixeiraID;

lege lus() {

lixeiraID = willekeurig (1, 5);

}

Stap 3: Upload Para a Nuvem

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

Sluit een toepassing aan op ThingSpeak, die nodig is om een API voor kanaalcriado te maken. Siga os passos descritos geen officiële site.

De volta à aplicação, vamos utilizar a biblioteca ESP8266WiFi.h para efetuar conexão com o ThingSpeak, en transferir os dados.

Primeiramente, uma função para efetuar conexão com a rede (defina previamente duas variáveis, ssid e pass, contesto o identificador e a senha de sua rede).

ongeldig verbindenWifi(){

Serial.print("Verbinding maken met "+ *ssid);

WiFi.begin(ssid, pas);

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

vertraging (500);

Serieel.print(".");

}

Serieel.println("");

Serial.print("Verbonden met rede ");

Seriële.println(ssid);

Serial.print("IP: ");

Serial.println(WiFi.localIP());

}

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

ongeldige setup() {

Serieel.begin(9600);

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

//Aansluitingen oa Wi-Fi

verbindenWifi();

}

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

void sendDataTS(float cmMsec, lange id){

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

Serial.println("Enviando voor ThingSpeak");

String postStr = apiKey;

postStr += "&veld";

postStr += id;

postStr += "=";

postStr += String (cmMsec);

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

Serial.println(postStr);

client.print( POST /update

client.print("Host: api.thingspeak.com\n");

client.print("Verbinding: sluiten\n");

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

client.print("Inhoudstype: applicatie/x-www-form-urlencoded\n");

client.print ("Inhoudslengte: ");

client.print(postStr.length());

cliënt.print("\n\n");

cliënt.print(postStr);

vertraging (1000);

}

klant.stop();

}

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

Stap 4: Recuperando Dados Do ThingSpeak

O ThingSpeak is toegestaan tijdens het spelen van het kanaal over het kanaal, door middel van dienstverlening aan JSON. Zoals verschillende mogelijkheden voor het voeden van het kanaal, is het volgende beschreven:

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 geen link vooraf informeren. Belangrijke informatie over het project:

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

Dit is een URL die u kunt gebruiken om Android te gebruiken, voor herstel en herstel van ThingSpeak.

Stap 5: Criando een Aplicação Android

Geen Android Studio, roep um novo projeto Android. Voor alle functies die u wilt gebruiken, moet u een configuratie uitvoeren zoals toegestaan voor AndroidManifest.

Para utilizar of Google Maps, será necessá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.

De API-sleutel voor op Google Maps gebaseerde API's wordt gedefinieerd als een tekenreeksresource.

(Zie het bestand "res/values/google_maps_api.xml").

Houd er rekening mee dat de API-sleutel is gekoppeld aan de coderingssleutel die wordt gebruikt om de APK te ondertekenen. Je hebt voor elke coderingssleutel een andere API-sleutel nodig, inclusief de releasesleutel die wordt gebruikt om de APK te ondertekenen voor publicatie. U kunt de sleutels voor de debug- en release-doelen definiëren in src/debug/ en src/release/.

<meta-gegevens

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

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

Een complete configuratie voor AndroidManifest anexado en projeto.

N

Stap 6: Recuperando O Feed Geen Android

Na atividade principal no Android, MainActivity, roep 4 variáveis para identificar cada um dos canais do ThingSpreek een aantal 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";

Voor elk van de onderstaande programma's, kunt u gebruik maken van de speciale klasse van Android, zoals het JSONObject. Meer informatie, meer informatie over het object van de cada URL:

JSONObjectresponsLixeiraA; JSONObjectresponsLixeiraB; JSONObjectresponsLixeiraC; JSONObjectresponsLixeiraD;

Para abrir a conexão com as urls, vamos usar criar uma classe auxiliar, chamada HttpJsonParser. Dit is een antwoord op de vraag naar een verbinding met de URL, die elke dag opnieuw wordt weergegeven, en een antwoord op JSON-montado.

public JSONObject makeHttpRequest (String-url, String-methode, Mapparams) {

proberen {

Uri. Builder-builder = nieuwe 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".is gelijk aan(methode)) { url = url + "?" + gecodeerde parameters; urlObj = nieuwe URL(url); urlConnection = (HttpURLConnection) urlObj.openConnection(); urlConnection.setRequestMethod(methode);

} anders {

urlObj = nieuwe URL(url); urlConnection = (HttpURLConnection) urlObj.openConnection(); urlConnection.setRequestMethod(methode); urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); urlConnection.setRequestProperty("Content-Length", String.valueOf(encodedParams.getBytes().length)); urlConnection.getOutputStream().write(encodedParams.getBytes()); } // Maak verbinding met de server urlConnection.connect(); //Lees het antwoord is = urlConnection.getInputStream(); BufferedReader-lezer = nieuwe BufferedReader (nieuwe InputStreamReader (is)); StringBuilder sb = nieuwe StringBuilder(); String lijn;

//Ontdek het antwoord

while ((regel = reader.readLine()) != null) { sb.append(regel + "\n"); } is dichtbij(); json = sb.toString(); // Converteer het antwoord naar JSON Object 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", "Fout bij het parseren van gegevens" + e.toString()); } catch (Uitzondering e) { Log.e("Uitzondering", "Fout bij het parseren van gegevens" + e.toString()); }

// retourneer JSON-object

retour jObj;

}

}

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

@Override protected String doInBackground(String… params) { HttpJsonParser jsonParser = new

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);

retourneer null;}

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, en populaire com os dados recuperados do ThingSpeak:

beschermde leegte onPostExecute(String resultaat) { pDialog.dismiss(); runOnUiThread(new Runnable() { public void run() {

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

Bekijk mainView =(View)findViewById(R.id.activity_main); if (succes == 1) {probeer {//Cria feedDetail para cada lixeira Lixeira feedDetails1 = new Lixeira(); Lixeira feedDetails2 = nieuwe Lixeira(); Lixeira feedDetails3 = nieuwe Lixeira(); Lixeira feedDetails4 = nieuwe 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);

// Bereken dados das lixeiras

SmartBinService-calculator = nieuwe SmartBinService(); rekenmachine.montaListaLixeiras(feedList);

//Recupera componenten

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

//Data atual

Datum currentTime = Calendar.getInstance().getTime(); SimpleDateFormat simpleDate = nieuw SimpleDateFormat("dd/MM/jjjj"); String huidigeDatum = simpleDate.format(currentTime); createDate.setText(KEY_DATE + huidigeDatum + " "); listaDeLixeiras.setAdapter(adapter);

} catch (JSONException e) {

e.printStackTrace(); }

} anders {

Toast.makeText(MainActivity.this, "Er is een fout opgetreden tijdens het laden van gegevens", Toast. LENGTH_LONG).show();

}

} }); }

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

Stap 7: Mostrando Geen Mapa

Mostrando Geen kaart
Mostrando Geen kaart

Ainda na atividade principal, heeft een aanvullende functie en een ser relacionada ao botão Mapa, na tela inicial.

/** Geroepen wanneer de gebruiker op de Mapa-knop tikt */ public void openMaps(View view) { Intent intent = new Intent(this, LixeiraMapsActivity.class);

//Passa a lista de lixeiras

Bundelbundel = nieuwe bundel(); bundel.putParcelableArrayList("lixeiras", feedList); intentie.putExtras(bundel);

startActiviteit(intentie);

}

No mapa, temos três atividades a executar:

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

Para executar os passos acima, vamos gebruikt een API Google Directions. Para desenhar as rotas, foram seguidos os passos do tutorial Routebeschrijvingen tekenen tussen twee locaties met Google Directions in Google Map Android API V2

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

//Locaties

particuliere LatLng-stroom;

privé LatLng lixeiraA; privé LatLng lixeiraB; privé LatLng lixeiraC; privé LatLng lixeiraD;.

Voor aanvullende informatie is er geen kaart, voor wat betreft de methode:

private void checkLocationandAddToMap() {//Controleren of de gebruiker de toestemming heeft verleend if (ActivityCompat.checkSelfPermission(this, android. Manifest.permission. ACCESS_FINE_LOCATION) != PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission.(Manthis.androidpermission) ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// De locatietoestemming aanvragen ActivityCompat.requestPermissions (this, new String {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); opbrengst; }

// De laatst bekende locatie ophalen met behulp van de Fus

Locatie locatie = LocationServices. FusedLocationApi.getLastLocation(googleApiClient);

//MarkerOptions worden gebruikt om een nieuwe Marker te maken. U kunt locatie, titel enz. specificeren met MarkerOptions

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

// De gemaakte markering op de kaart toevoegen, camera naar positie verplaatsen

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

// Verplaats de camera direct naar de locatie met een zoom van 15.

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

// Zoom in en animeer de camera.

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

}

Em seguida, para cada lixeira, foram criados métodos gelijkaardige oa abaixo:

private void addBinALocation() {//Controleren of de gebruiker de toestemming heeft verleend if (ActivityCompat.checkSelfPermission(this, android. Manifest.permission. ACCESS_FINE_LOCATION) != PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (this.permission. Manifest. ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// De locatietoestemming aanvragen ActivityCompat.requestPermissions (this, new String {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); opbrengst; }

//Praça da Estação

dubbele breedtegraad = -19,9159578; dubbele lengtegraad = -43.9387856; this.lixeiraA = nieuwe LatLng(breedtegraad, lengtegraad);

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

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

Zoals de breedtegraad en lengtegraad van het cada lixeira foram recuperadas através do próprio Google Maps, en deixadas fixas no código. Idealmente, estes valores ficariam salvos em um banco de dados (door voorbeeld Firebase). Será a primeira evolução deste projeto!

O último passo agora é traçar als rotas entre os pontos. Para tal, um conceito muito importante, e que será utilizado utilizado neste projeto, são os Waypoints!

Voor een aantal vragen kunt u een rota entre dois dados pontos bepalen:

private String getDirectionsUrl (LatLng-oorsprong, LatLng-bestemming, lijst met waypointsLijst){

// Oorsprong van de route

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

// Bestemming van de route

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

//Waypoints langs de route

//waypoints=optimaliseren:true|-19.9227365, -43.9473546|-19.9168006, -43.9361124 String waypoints = "waypoints=optimaliseren:true"; for (LatLng punt: waypointsList){ waypoints += "|" + punt.breedtegraad + ", " + punt.lengtegraad; }

// Sensor ingeschakeld

Stringsensor = "sensor=false";

// De parameters voor de webservice bouwen

String parameters = str_origin+"&"+str_dest+"&"+sensor + "&" + waypoints;

// Uitvoerformaat

String-uitvoer = "json";

// De url naar de webservice bouwen

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

retour-URL;

}

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

// Routes tekenen

// URL ophalen naar de Google Directions API

Lijstpunten = nieuwe ArrayList(); punten.add(lixeiraB); punten.add(lixeiraC); punten.add(lixeiraD);

String url = getDirectionsUrl (huidig, lixeiraA, punten);

DownloadTask downloadTask = nieuwe DownloadTask(); // Begin met het downloaden van json-gegevens van Google Directions API downloadTask.execute(url); }

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

Stap 8: Conclusie

Dit is een projekt van een concept van IoT, een groot aantal mogelijkheden voor het aansluiten van een nieuwe, en een laatste keer dat er besluiten zijn genomen over de menselijke direta. Voeg een volgende video toe om het volledige project te voltooien, voor illustraties, en andere lettertypen die geen Android nodig hebben.

Aanbevolen: