Mục lục:
- Bước 1: Cảm biến Conectando O
- Bước 2: Montando a Lixeira
- Bước 3: Tải lên Para a Nuvem
- Bước 4: Recuperando Dados Do ThingSpeak
- Bước 5: Criando một Aplicação Android
- Bước 6: Recuperando O Feed No Android
- Bước 7: Mostrando No Mapa
- Bước 8: Kết luận
Video: SmartBin: 8 bước
2024 Tác giả: John Day | [email protected]. Sửa đổi lần cuối: 2024-01-31 10:26
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
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:
- marcar a posição atual do caminha de lixo
- marcar os pontos phóng viên a cada lixeira no mapa
- 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:
Động cơ bước Điều khiển động cơ bước Không cần vi điều khiển !: 6 bước
Động cơ bước Điều khiển động cơ bước Không cần vi điều khiển !: Trong phần Hướng dẫn nhanh này, chúng tôi sẽ tạo một bộ điều khiển động cơ bước đơn giản bằng cách sử dụng động cơ bước. Dự án này không yêu cầu mạch phức tạp hoặc vi điều khiển. Vì vậy, không cần thêm ado, chúng ta hãy bắt đầu
Động cơ bước được điều khiển Động cơ bước không có vi điều khiển (V2): 9 bước (có hình ảnh)
Động cơ bước được điều khiển bằng động cơ bước Không cần vi điều khiển (V2): Trong một trong những Hướng dẫn trước đây của tôi, tôi đã chỉ cho bạn cách điều khiển động cơ bước bằng cách sử dụng động cơ bước mà không cần vi điều khiển. Đó là một dự án nhanh chóng và thú vị nhưng nó đi kèm với hai vấn đề sẽ được giải quyết trong Có thể hướng dẫn này. Vì vậy, hóm hỉnh
Đầu máy mô hình điều khiển động cơ bước - Động cơ bước như một bộ mã hóa quay: 11 bước (có hình ảnh)
Đầu máy mô hình điều khiển động cơ bước | Động cơ bước làm bộ mã hóa quay: Trong một trong những phần Hướng dẫn trước, chúng ta đã học cách sử dụng động cơ bước làm bộ mã hóa quay. Trong dự án này, bây giờ chúng ta sẽ sử dụng bộ mã hóa quay động cơ bước đó để điều khiển đầu máy mô hình bằng vi điều khiển Arduino. Vì vậy, không có fu
Động cơ bước Điều khiển động cơ bước Động cơ bước - Động cơ bước như một bộ mã hóa quay: 11 bước (có hình ảnh)
Động cơ bước Điều khiển động cơ bước Động cơ bước | Động cơ bước như một bộ mã hóa quay: Có một vài động cơ bước nằm xung quanh và muốn làm điều gì đó? Trong Có thể hướng dẫn này, hãy sử dụng động cơ bước làm bộ mã hóa quay để điều khiển vị trí của động cơ bước khác bằng vi điều khiển Arduino. Vì vậy, không cần phải quảng cáo thêm, chúng ta hãy
SmartBin: 4 bước
SmartBin: Mục đích chính của dự án này là tạo ra một thiết bị điện tử sử dụng ít nhất một Raspberry Pi. Đội gồm 5 kỹ sư cơ khí tương lai và một kỹ sư tự động hóa. Dự án của chúng tôi bao gồm việc chế tạo một thùng rác có thể đóng mở