Tartalomjegyzék:
- 1. lépés: Conectando O érzékelő
- 2. lépés: Montando és Lixeira
- 3. lépés: Töltsön fel egy Nuvemet
- 4. lépés: Recuperando Dados Do ThingSpeak
- 5. lépés: Criando és Aplicação Android
- 6. lépés: O -takarmány helyreállítása Nincs Android
- 7. lépés: Mostrando No Mapa
- 8. lépés: Conclusão
Videó: SmartBin: 8 lépés
2024 Szerző: John Day | [email protected]. Utoljára módosítva: 2024-01-31 10:20
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
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:
- marcar a posição atual do caminha de lixo
- marcar os pontos tudósítói a cada lixeira no mapa
- 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:
DC - DC feszültség Lépés lekapcsoló mód Buck feszültségátalakító (LM2576/LM2596): 4 lépés
DC-DC feszültség Lépés lekapcsoló üzemmód Buck feszültségátalakító (LM2576/LM2596): A rendkívül hatékony bakkonverter készítése nehéz feladat, és még a tapasztalt mérnököknek is többféle kivitelre van szükségük, hogy a megfelelőt hozzák létre. egy DC-DC áramátalakító, amely csökkenti a feszültséget (miközben növeli
Akusztikus levitáció az Arduino Uno-val Lépésről lépésre (8 lépés): 8 lépés
Akusztikus lebegés az Arduino Uno-val Lépésről lépésre (8 lépés): ultrahangos hangátvivők L298N Dc női adapter tápegység egy egyenáramú tűvel Arduino UNOBreadboard és analóg portok a kód konvertálásához (C ++)
Élő 4G/5G HD videó streamelés DJI drónról alacsony késleltetéssel [3 lépés]: 3 lépés
Élő 4G/5G HD videó streaming a DJI Drone-tól alacsony késleltetéssel [3 lépés]: Az alábbi útmutató segít abban, hogy szinte bármilyen DJI drónról élő HD minőségű videó streameket kapjon. A FlytOS mobilalkalmazás és a FlytNow webes alkalmazás segítségével elindíthatja a videó streamingjét a drónról
Bolt - DIY vezeték nélküli töltő éjszakai óra (6 lépés): 6 lépés (képekkel)
Bolt - DIY vezeték nélküli töltés éjszakai óra (6 lépés): Az induktív töltés (más néven vezeték nélküli töltés vagy vezeték nélküli töltés) a vezeték nélküli áramátvitel egyik típusa. Elektromágneses indukciót használ a hordozható eszközök áramellátásához. A leggyakoribb alkalmazás a Qi vezeték nélküli töltő
SmartBin: 4 lépés
SmartBin: A projekt fő célja egy olyan elektronikus eszköz létrehozása, amely legalább egy Raspberry Pi -t használ. A csapat 5 leendő gépészmérnökből és egy automatizálási mérnökből áll. Projektünk abból áll, hogy kinyitunk és bezárunk egy kukát