Mục lục:

SmartBin: 8 bước
SmartBin: 8 bước

Video: SmartBin: 8 bước

Video: SmartBin: 8 bước
Video: Hội thảo trực tuyến về KUKA.SmartBinPicking 2024, Tháng mười một
Anonim
SmartBin
SmartBin

Este é um projeto para um sistema inteligente de coletas, không có đủ điều kiện os caminhões de lixo Collectbem dados das lixeiras, Idificando 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, é needário:

  • NodeMCU
  • Cảm biến Ultrassônico de Distancia
  • Caixa de papelão
  • Protoboard
  • Cabos
  • Dispositivo Android

Bước 1: Cảm biến Conectando O

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

// xác định số chân #define pino_trigger 2 // D4

#define pino_echo 0 // D3

Para efetuar a leitura dos dados do sensor, foi seguido o hướng dẫn công phu về FilipeFlop, disponível aqui.

float cmMsec, inMsec;

dài microsec = ultrasonic.timing ();

cmMsec = ultrasonic.convert (microsec, Ultrasonic:: CM);

inMsec = ultrasonic.convert (microsec, Ultrasonic:: IN);

// Exibe thông báo không có màn hình nối tiếp

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

Serial.print (cmMsec);

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

Serial.println (inMsec);

Dữ liệu chuỗi = String (cmMsec);

Serial.println (dữ liệu);

Bước 2: Montando a Lixeira

Agora, vamos montar một lixeira inteligente. Precisaremos conectar o cảm biến ultrassônico không có "teto" da lixeira. Para o exelo, useizei um cabo e fita isolante. Em seguida, temos que medir a distância inicial, para saber o valor para a lixeira vazia. No meu caso, foi de 26, 3cm. Esse é o valor que coirarmos 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 a distancia lida em 4 lixeiras diferentes.

// Simulando 4 lixeiras

lixeiraID dài;

void loop () {

lixeiraID = ngẫu nhiên (1, 5);

}

Bước 3: Tải lên Para a Nuvem

Agora, Preisamos enviar estes dados para a nuvem. Eu escolhi o ThingSpeak, bởi quen thuộc với com o mesmo. Primeiramente, kênh đào é needário criar um novo, Rebendo 4 parâmetros, tham khảo ao volume de cada lixeira.

Pará conectar a aplicação com o ThingSpeak, é needário salvar o número da API do channel criado. Siga os passos descritos không có trang web của tư pháp.

De volta à aplicação, vamos usedizar 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 red (defina previamente duas variáveis, ssid e pass , Contendo o Idificador e a senha de sua red).

void connectWifi () {

Serial.print ("Đang kết nối với" + * ssid);

WiFi.begin (ssid, pass);

trong khi (WiFi.status ()! = WL_CONNECTED) {

chậm trễ (500);

Serial.print (".");

}

Serial.println ("");

Serial.print ("Conectado na red");

Serial.println (ssid);

Serial.print ("IP:");

Serial.println (WiFi.localIP ());

}

Durante o thiết lập, lều bạt efetuar a conexão com a red.

void setup () {

Serial.begin (9600);

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

// Conectando ao Wi-Fi

connectWifi ();

}

E, para enviar os dados para o ThingSpeak, bita 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 (server, 80)) {

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

Chuỗi postStr = apiKey;

postStr + = "& trường";

postStr + = id;

postStr + = "=";

postStr + = String (cmMsec);

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

Serial.println (postStr);

client.print ("ĐĂNG / cập nhật HTTP / 1.1 / n");

client.print ("Máy chủ: api.thingspeak.com / n");

client.print ("Kết nối: close / n");

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

client.print ("Loại-Nội dung: application / x-www-form-urlencoded / n");

client.print ("Nội dung-Độ dài:");

client.print (postStr.length ());

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

client.print (postStr);

chậm trễ (1000);

}

client.stop ();

}

O primeiro parâmetro tương ứng à 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 phục vụ também para Idificar para Qual campo será feito o upload do valor lido.

Bước 4: Recuperando Dados Do ThingSpeak

O ThingSpeak permite efetuar leitura dos dados do seu channel, através de um serviço retornando um JSON. As diferentes opções para leitura làm thức ăn do seu kênh estão descritas aqui:

www.mathworks.com/help/thingspeak/get-a-ch…

Neste projeto, optou-se bởi 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 không có liên kết Informado previamente. Os mais importantes para o projeto são:

  • CHANNEL_ID: kênh número do seu
  • FIELD_NUMBER: o número do campo
  • API_KEY: a chave de API do seu channel

Esta é a URL que será lida do aplicativa Android, para recuperar os dados do ThingSpeak.

Bước 5: Criando một Aplicação Android

Không có Android Studio, crie um novo projeto Android. Para o Correto funcionamento da aplicação, tôi cần thiết phải cấu hình như permissões abaixo no AndroidManifest.

Para Pracizar o Google Maps, será needá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.

Khóa API cho các API dựa trên Google Maps được định nghĩa là một tài nguyên chuỗi.

(Xem tệp "res / values / google_maps_api.xml").

Lưu ý rằng khóa API được liên kết với khóa mã hóa được sử dụng để ký APK. Bạn cần một khóa API khác nhau cho mỗi khóa mã hóa, bao gồm cả khóa phát hành được sử dụng để ký APK để xuất bản. Bạn có thể xác định các khóa cho mục tiêu gỡ lỗi và giải phóng trong src / debug / và src / release /.

<siêu dữ liệu

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

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

A configuração completa está mo arquivo AndroidManifest anexado ao projeto.

n

Bước 6: Recuperando O Feed No Android

Na atividade major no Android, MainActivity, crie 4 variáveis para Idificar cada um dos canais do Thing

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

Para efetuar a leitura dos dados, iremos Operatingizar 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 será responseável bởi abrir uma conexão com ô URL, efetuar leitura dos dados encontrados, e retornar o objeto JSON montado.

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

cố gắng {

Uri. Builder builder = new Uri. Builder (); URL urlObj; Chuỗi mã hóaParams = ""; 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".equals (method)) {url = url + "?" + mã hóaParams; urlObj = URL mới (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (phương thức);

} khác {

urlObj = URL mới (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (phương thức); urlConnection.setRequestProperty ("Content-Type", "application / x-www-form-urlencoded"); urlConnection.setRequestProperty ("Nội dung-Độ dài", String.valueOf (encodedParams.getBytes (). length)); urlConnection.getOutputStream (). write (encodedParams.getBytes ()); } // Kết nối với máy chủ urlConnection.connect (); // Đọc phản hồi is = urlConnection.getInputStream (); BufferedReader reader = new BufferedReader (new InputStreamReader (is)); StringBuilder sb = new StringBuilder (); Dòng chuỗi;

// Phân tích cú pháp phản hồi

while ((line = reader.readLine ())! = null) {sb.append (line + "\ n"); } is.close (); json = sb.toString (); // Chuyển đổi phản hồi thành 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 ("Trình phân tích cú pháp JSON", "Lỗi phân tích cú pháp dữ liệu" + e.toString ()); } catch (Exception e) {Log.e ("Exception", "Lỗi phân tích cú pháp dữ liệu" + e.toString ()); }

// trả về đối tượng JSON

trả về jObj;

}

}

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

@Override protected String doInBackground (String… params) {HttpJsonParser jsonParser = new 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);

trả về null;}

Quando o método doInBackgroundé encerrado, o controlle de executeução do Android passa para o método onPostExecute. Neste método, vamos criar os objetos Lixeira, e phổ biến com os dados recuperados do Thing

void onPostExecute được bảo vệ (Chuỗi kết quả) {pDialog.dismiss (); runOnUiThread (new Runnable () {public void run () {

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

Xem mainView = (Xem) findViewById (R.id.activity_main); if (thành công == 1) {try {// Cria feedDetail para cada lixeira Lixeira feedDetails1 = new Lixeira (); Lixeira feedDetails2 = new Lixeira (); Lixeira feedDetails3 = new Lixeira (); Lixeira feedDetails4 = new 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

Máy tính SmartBinService = new SmartBinService (); máy tính.montaListaLixeiras (feedList);

// Thành phần Recupera

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

// Dữ liệu tùy ý

Ngày currentTime = Calendar.getInstance (). GetTime (); SimpleDateFormat simpleDate = new SimpleDateFormat ("dd / MM / yyyy"); Chuỗi currentDate = simpleDate.format (currentTime); createDate.setText (KEY_DATE + currentDate + ""); listaDeLixeiras.setAdapter (bộ chuyển đổi);

} catch (JSONException e) {

e.printStackTrace (); }

} khác {

Toast.makeText (MainActivity.this, "Đã xảy ra lỗi khi tải dữ liệu", Toast. LENGTH_LONG).show ();

}

} }); }

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

Bước 7: Mostrando No Mapa

Mostrando No Mapa
Mostrando No Mapa

Ainda na atividade hiệu trưởng, vamos adicionar uma ação a ser relacionada ao botão Mapa, na tela inicial.

/ ** Được gọi khi người dùng chạm vào nút Mapa * / public void openMaps (View view) {Intent Ý định = new Intent (this, LixeiraMapsActivity.class);

// Chuyển một lista de lixeiras

Gói bó = new Bundle (); bó.putParcelableArrayList ("lixeiras", feedList); ý định.putExtras (gói);

startActivity (ý định);

}

Không có mapa, temos três atividades một người thực thi:

  1. marcar a posição atual do caminha de lixo
  2. marcar os pontos phóng viên a cada lixeira no mapa
  3. traçar a rota entre os pontos

Para executive os passos acima, vamos sử dụng API Google Directions. Para desenhar as rotas, foram seguidos os passos làm hướng dẫn Vẽ chỉ đường lái xe giữa hai địa điểm bằng Google Chỉ đường trong Google Map Android API V2

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

// Vị trí

LatLng riêng tư hiện tại;

LatLng lixeiraA riêng; LatLng lixeiraB riêng; LatLng lixeiraC riêng; LatLng lixeiraD riêng tư;.

Para adicionar a posição atual no mapa, foi criado o método:

private void checkLocationandAddToMap () {// Kiểm tra xem người dùng đã cấp quyền chưa nếu (ActivityCompat.checkSelfPermission (this, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (this, android. Manifestmission). ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Yêu cầu quyền Vị trí ActivityCompat.requestPermissions (this, new String {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); trở lại; }

// Tìm nạp vị trí đã biết cuối cùng bằng Fus

Vị trí vị trí = LocationServices. FusedLocationApi.getLastLocation (googleApiClient);

// MarkerOptions được sử dụng để tạo một Marker mới. Bạn có thể chỉ định vị trí, tiêu đề, v.v. với MarkerOptions

this.current = new LatLng (location.getLatitude (), location.getLongitude ()); MarkerOptions markerOptions = new MarkerOptions (). Position (hiện tại).title ("Posição atual");

// Thêm điểm đánh dấu đã tạo trên bản đồ, di chuyển máy ảnh đến vị trí

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

// Di chuyển máy ảnh ngay lập tức đến vị trí có độ phóng đại 15.

mMap.moveCamera (CameraUpdateFactory.newLatLngZoom (hiện tại, 15));

// Phóng to, tạo hoạt ảnh cho máy ảnh.

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

}

Em seguida, para cada lixeira, foram criados métodos tương tự ao abaixo:

private void addBinALocation () {// Kiểm tra xem người dùng đã cấp quyền chưa nếu (ActivityCompat.checkSelfPermission (this, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (this, android. Manifest.permission). ACCESS_COARSE_LOCATION)! = PackageManager. PERMISSION_GRANTED) {// Yêu cầu quyền Vị trí ActivityCompat.requestPermissions (this, new String {android. Manifest.permission. ACCESS_FINE_LOCATION}, LOCATION_REQUEST_CODE); trở lại; }

// Praça da Estação

vĩ độ kép = -19,9159578; kinh độ kép = -43,9387856; this.lixeiraA = new LatLng (vĩ độ, kinh độ);

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

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

Như posições de latitude e longitude de cada lixeira foram recuperadas através do próprio Google Maps, e deixadas fixas no hasdigo. Idealmente, estes valores ficariam salvos em um banco de dados (por miễn phí 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á Pracizado neste projeto, são os Waypoints!

Foi criado um método para traçar a rota entre dois dados pontos:

private String getDirectionsUrl (LatLng gốc, LatLng cuối, List waypointsList) {

// Nguồn gốc của tuyến đường

Chuỗi str_origin = "origin =" + origin.latitude + "," + origin.longitude;

// Điểm đến của tuyến đường

Chuỗi str_dest = "đích =" + dest.latitude + "," + dest.longitude;

// Các điểm dọc theo tuyến đường

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

// Đã bật cảm biến

Chuỗi cảm biến = "sensor = false";

// Xây dựng các tham số cho dịch vụ web

Tham số chuỗi = str_origin + "&" + str_dest + "&" + cảm biến + "&" + điểm tham chiếu;

// Định dạng đầu ra

Chuỗi đầu ra = "json";

// Xây dựng url cho dịch vụ web

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

trả về url;

}

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

// Vẽ các tuyến đường

// Nhận URL tới API chỉ đường của Google

Liệt kê điểm = new ArrayList (); điểm.add (lixeiraB); điểm.add (lixeiraC); điểm.add (lixeiraD);

String url = getDirectionsUrl (hiện tại, lixeiraA, điểm);

DownloadTask downloadTask = new DownloadTask (); // Bắt đầu tải xuống dữ liệu json từ Google Directions API downloadTask.execute (url); }

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

Bước 8: Kết luận

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 Decisionões sem interferência humana direta. Em anexo, segue um vídeo do projeto completo, para ilustração, e os fontes das atividades criadas no Android.

Đề xuất: