Cov txheej txheem:
- Kauj ruam 1: Conectando O Sensor
- Kauj Ruam 2: Montando a Lixeira
- Kauj ruam 3: Upload Para a Nuvem
- Kauj ruam 4: Recuperando Dados Ua ThingSpeak
- Kauj Ruam 5: Criando thiab Aplicação Android
- Kauj Ruam 6: Recuperando O Pub Tsis Android
- Kauj Ruam 7: Mostrando No Mapa
- Kauj Ruam 8: Xaus
Video: SmartBin: 8 Kauj Ruam
2024 Tus sau: John Day | [email protected]. Kawg hloov kho: 2024-01-31 10:20
Este é um projeto para um sistema inteligente de coletas, tsis muaj peev xwm os caminhões de lixo recebem dados das lixeiras, txheeb ze thiab muaj nuj nqis de lixo presente em cada uma delas, e uma rota de coleta traçada, com base nas informações recuperadas.
Nyob rau lub caij ntuj sov, nws yog qhov tsim nyog:
- NodeMCU
- Sensor Ultrassônico de Distancia
- Caixa de papelão
- Protoboard
- Cabos
- Dispositivo Android
Kauj ruam 1: Conectando O Sensor
Primeiramente, vamos efetuar a conexão entre o sensor ultrassônico e o NODEMCU. Piv txwv li, vamos conectar li portas trigger e ncho do sensor nas portas D4 e D3 do NodeMCU:
// txhais tus lej lej #define pino_trigger 2 // D4
#define pino_echo 0 // D3
Para efetuar a leitura dos dados sensor, foi seguido o tutorial elaborado pelo FilipeFlop, disponível aqui.
ntab cmMsec, inMsec;
ntev microsec = ultrasonic.timing ();
cmMsec = ultrasonic.convert (microsec, Ultrasonic:: CM);
inMsec = ultrasonic.convert (microsec, Ultrasonic:: IN);
// Exibe informacoes tsis muaj tus saib xyuas
Serial.print ("Distancia em cm:");
Serial.print (cmMsec);
Serial.print (" - Distancia em polegadas:");
Serial.println (inMsec);
Txoj hlua cov ntaub ntawv = Txoj hlua (cmMsec);
Serial.println (cov ntaub ntawv);
Kauj Ruam 2: Montando a Lixeira
Yog lawm, cov neeg saib xyuas kev noj qab haus huv tau txais txiaj ntsig zoo. Precisaremos conectar o sensor ultrassônico no “teto” da lixeira. Los ntawm qhov ua piv txwv, siv cov cuab yeej cuab tam tshwj xeeb. Em seguida, temos que medir a distância inicial, para saber o valor para lixeira vazia. Tsis muaj meu caso, foi de 26, 3cm. Esse é o valor que considerarmos 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 lub lis piam
ntev lixeiraID;
void voj () {
lixeiraID = random (1, 5);
}
Kauj ruam 3: Upload Para a Nuvem
Agora, precisamos enviar estes dados para nuvem. Eu escolhi o ThingSpeak, rau tsev neeg sib koom los yog mesmo. Primeiramente, é necessário criar um novo kwj dej, recebendo 4 parâmetros, referentes ao volume de cada lixeira.
Pará conectar aplicação com o ThingSpeak, é necessário salvar o número da API ua kwj dej criado. Siga os passos descritos tsis muaj qhov chaw raug cai.
Nyob rau hauv cov ntaub ntawv, 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 identificador e a senha de sua rede).
void connectWifi () {
Serial.print ("Txuas rau"+ *ssid);
WiFi.begin (ssid, dhau);
thaum (WiFi.status ()! = WL_CONNECTED) {
ncua (500);
Serial.print (".");
}
Serial.println ("");
Serial.print ("Conectado na rede");
Serial.println (ssid);
Serial.print ("IP:");
Serial.println (WiFi.localIP ());
}
Durante o teeb tsa, lub tsev pheeb suab ntaub ntawv thiab kev sib koom ua ke.
void teeb tsa () {
Serial.begin (9600);
Serial.println ("Lendo dados ua sensor …");
// Txuas Wi-nkaus
txuasWifi ();
}
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 (ntab cmMsec, ntev id) {
yog (client.connect (server, 80)) {
Serial.println ("Enviando dados para o ThingSpeak");
Txoj hlua postStr = apiKey;
postStr += "& teb";
postStr += id;
postStr += "=";
postStr += Txoj hlua (cmMsec);
postStr += "\ r / n / r / n";
Serial.println (postStr);
client.print ("POST /hloov tshiab HTTP /1.1 / n");
client.print ("Tus tswv tsev: api.thingspeak.com / n");
client.print ("Kev sib txuas: kaw / n");
client.print ("X-THINGSPEAKAPIKEY:" + apiKey + "\ n");
client.print ("Cov ntsiab lus-Hom: thov/x-www-form-urlencoded / n");
client.print ("Cov ntsiab lus-Ntev:");
client.print (postStr.length ());
client.print ("\ n / n");
client.print (postStr);
ncua (1000);
}
client.stop (); cov.
}
O primeiro parâmetro sib tham à 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 pabcuam também para identificar para qual campo será feito o upload do valor lido.
Kauj ruam 4: Recuperando Dados Ua ThingSpeak
O ThingSpeak tso cai efetuar leitura dos dados do seu kwj dej, através de um serviço retornando um JSON. Raws li diferentes opções para leitura ua pub rau seu kwj dej estão descritas aqui
www.mathworks.com/help/thingspeak/get-a-ch…
Neste projeto, optou-se por ler diretamente os dados de cada campo. Hauv kab ntawv URL rau qhov zoo sib xws:
api.thingspeak.com/channels/CHANNEL_ID/fields/FIELD_NUMBER/last.json?api_key=API_KEY&status=true
Cada campo está descrito tsis muaj qhov txuas xov xwm yav dhau los. Os mais importantes para o projeto são:
- CHANNEL_ID: nyob zoo cov phooj ywg
- FIELD_NUMBER: o número do campo
- API_KEY: chave de API ua seu kwj dej
Esta é a URL que será lida do aplicativa Android, para recuperar os dados ua ThingSpeak.
Kauj Ruam 5: Criando thiab Aplicação Android
Tsis muaj Android Studio, tsim tawm tshiab rau hauv Android. Para o correto funcionamento da aplicação, é necessário configurar as permissões abaixo no AndroidManifest.
Txhawm rau siv Google Maps, siv cov txiv maj phaub uma chave junto rau Google. Siga os passos descritos no link Obter chave de API.
Uma vez com chave, você deve também configurá-la na aplicação.
API qhov tseem ceeb rau Google Maps-based APIs tau txhais tias yog txoj hlua siv.
(Saib cov ntawv "res/values/google_maps_api.xml").
Nco ntsoov tias tus yuam sij API txuas nrog tus yuam sij encryption siv los kos npe APK. Koj xav tau tus lej API sib txawv rau txhua tus yuam sij encryption, suav nrog tus lej tso tawm uas tau siv los kos npe APK rau tshaj tawm. Koj tuaj yeem txhais cov yuam sij rau kev debug thiab tso lub hom phiaj hauv src/debug/thiab src/release/.
<meta-cov ntaub ntawv
android: lub npe = "com.google.android.geo. API_KEY"
android: tus nqi = "@hlua /google_maps_key" />
Ib qho kev teeb tsa ua tiav raws li cov lus qhia hauv AndroidManifest anexado ao projeto.
n
Kauj Ruam 6: Recuperando O Pub Tsis Android
Yog tus thawj xibfwb tsis muaj Android, MainActivity, crie 4 variáveis para identificar cada um dos canais ua ThingSpeak a serem 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";
Txhawm rau ua kom tau txais txiaj ntsig zoo, siv iremos siv uma classe rau Android específica, chamada JSONObject. Ntxiv rau, vamos criar um objeto para cada URL:
JSONObject tebLixeiraA; JSONObject tebLixeiraB; JSONObject tebLixeiraC; JSONObject tebLixeiraD;
Para abrir a conexão com as urls, vamos usar criar uma classe auxiliar, chamada HttpJsonParser. Esta classe será responsável por abrir uma conexão com um URL, efetuar leitura dos dad encontrados, e retornar o objeto JSON montado.
pej xeem JSONObject makeHttpRequest (Txoj hlua url, Txoj hlua txoj cai, Daim ntawv qhia chaw params) {
sim {
Uri. Builder builder = tshiab Uri. Builder (); URL urlObj; Txoj hlua encodedParams = ""; yog (params! = null) {rau (Map. Entry nkag: params.entrySet ()) {builder.appendQueryParameter (entry.getKey (), entry.getValue ()); }} yog (builder.build (). getEncodedQuery ()! = null) {encodedParams = builder.build (). getEncodedQuery ();
}
yog ("Tau".equals (txoj kev)) {url = url + "?" + encodedParams; urlObj = URL tshiab (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (txoj kev);
lwm yam {
urlObj = URL tshiab (url); urlConnection = (HttpURLConnection) urlObj.openConnection (); urlConnection.setRequestMethod (txoj kev); urlConnection.setRequestProperty ("Content-Type", "application/x-www-form-urlencoded"); urlConnection.setRequestProperty ("Content-Length", String.valueOf (encodedParams.getBytes (). ntev)); urlConnection.getOutputStream (). sau (encodedParams.getBytes ()); } // Txuas rau server urlConnection.connect (); // Nyeem cov lus teb yog = urlConnection.getInputStream (); BufferedReader nyeem ntawv = tshiab BufferedReader (tshiab InputStreamReader (yog)); StringBuilder sb = tshiab StringBuilder (); Txoj hlua;
// Txheeb cais cov lus teb
thaum ((kab = nyeem ntawv.readLine ())! = null) {sb.append (kab + "\ n"); } yog.close (); json = sb.toString (); // Hloov cov lus teb rau JSON Object jObj = tshiab JSONObject (json);
} ntes (UnsupportedEncodingException e) {
e.printStackTrace (); } ntes (ProtocolException e) {e.printStackTrace (); } ntes (IOException e) {e.printStackTrace (); } ntes (JSONException e) {Log.e ("JSON Parser", "Yuam kev cais cov ntaub ntawv" + e.toString ()); } ntes (Kev zam e) {Log.e ("Kev zam", "Yuam kev cais cov ntaub ntawv" + e.toString ()); }
// rov JSON Object
rov jObj;
}
}
Los ntawm tus thawj xibfwb atividade, vamos efetuar a chamada's url de forma assíncrona, escrevendo este código dentro do método doInBackground.
@Override tiv thaiv txoj hlua doInBackground (Txoj hlua… params) {HttpJsonParser jsonParser = tshiab HttpJsonParser ();
responseLixeiraA = jsonParser.makeHttpRequest (url_a, "GET", tsis muaj)
responseLixeiraB = jsonParser.makeHttpRequest (url_b, "Tau", tsis muaj); responseLixeiraC = jsonParser.makeHttpRequest (url_c, "GET", tsis muaj) responseLixeiraD = jsonParser.makeHttpRequest (url_d, "GET", tsis muaj)
rov null;}
Quando o método doInBackgroundé encerrado, los ntawm kev tswj hwm ua tiav rau Android passa rau o método onPostExecute. Neste método, vamos criar os objetos Lixeira, e nrov com os dados recuperados ua ThingSpeak:
tiv thaiv tsis muaj dab tsi onPostExecute (Cov txiaj ntsig txoj hlua) {pDialog.dismiss (); runOnUiThread (Runnable tshiab () {pej xeem tsis muaj dab tsi khiav () {
// ListView listView = (ListView) findViewById (R.id.feedList);
Saib mainView = (Saib) findViewById (R.id.activity_main); yog (ua tiav == 1) {sim {// Cria feedDetail para cada lixeira Lixeira feedDetails1 = tshiab Lixeira (); Lixeira feedDetails2 = tshiab Lixeira (); Lixeira feedDetails3 = tshiab Lixeira (); Lixeira feedDetails4 = tshiab Lixeira ();
feedDetails1.setId ('A');
feedDetails1.setPesoLixo (Double.parseDouble (tebLixeiraA.getString (KEY_FIELD1)))); feedDetails1.setVolumeLixo (Double.parseDouble (tebLixeiraA.getString (KEY_FIELD1)));
feedDetails2.setId ('B');
feedDetails2.setPesoLixo (Double.parseDouble (tebLixeiraB.getString (KEY_FIELD2))); feedDetails2.setVolumeLixo (Double.parseDouble (tebLixeiraB.getString (KEY_FIELD2)));
feedDetails3.setId ('C');
feedDetails3.setPesoLixo (Double.parseDouble (tebLixeiraC.getString (KEY_FIELD3))); feedDetails3.setVolumeLixo (Double.parseDouble (tebLixeiraC.getString (KEY_FIELD3)));
feedDetails4.setId ('D');
feedDetails4.setPesoLixo (Double.parseDouble (responseLixeiraD.getString (KEY_FIELD4)))); feedDetails4.setVolumeLixo (Double.parseDouble (tebLixeiraD.getString (KEY_FIELD4)));
feedList.add (feedDetails1);
feedList.add (feedDetails2); feedList.add (feedDetails3); feedList.add (feedDetails4);
// Txheeb xyuas cov txiv neej das lixeiras
SmartBinService lub laij lej = SmartBinService tshiab (); calculator.montaListaLixeiras (feedList);
// Recupera tivthaiv
TextView createDate = (TextView) mainView.findViewById (R.id.date); ListView listaDeLixeiras = (ListView) findViewById (R.id.lista); adapter.addAll (feedList);
// Cov ntaub ntawv atual
Hnub timTimeTime = Calendar.getInstance (). GetTime (); SimpleDateFormat simpleDate = tshiab SimpleDateFormat ("dd/MM/yyyy"); Txoj hlua currentDate = simpleDate.format (currentTime); createDate.setText (KEY_DATE + currentDate + ""); listaDeLixeiras.setAdapter (adapter);
} ntes (JSONException e) {
e.printStackTrace (); }
lwm yam {
Toast.makeText (MainActivity.this, "Qee qhov yuam kev tshwm sim thaum thauj cov ntaub ntawv", Toast. LENGTH_LONG).show ();
}
} }); }
Agora, na tela inicial do aplicativo, serão listados os dados de cada lixeira.
Kauj Ruam 7: Mostrando No Mapa
Ua raws li tus thawj xibfwb, vamos adicionar uma ação a ser relacionada ao botão Mapa, na tela inicial.
/ ** Hu thaum tus neeg siv coj mus rhaub khawm Mapa*/ pej xeem tsis muaj dab tsi openMaps (Saib pom) {Lub hom phiaj xav = xav tshiab (qhov no, LixeiraMapsActivity.class);
// Hla ib daim ntawv teev npe lixeiras
Bundle bundle = Bundle tshiab (); bundle.putParcelableArrayList ("lixeiras", feedList); intent.putExtras (nras);
startActivity (txhob txwm);
}
Tsis muaj mapa, temos três atividades tus executar:
- marcar a posição atual do caminha de lixo
- marcar os pontos correspondentes a cada lixeira no mapa
- traçar a rota entre os pontos
Para executar os passos acima, vam tias siv API Google Cov Lus Qhia. Para desenhar as rotas, foram seguidos os passos do tutorial Teeb duab tsav tsheb qhia kev ntawm ob qhov chaw siv Google Cov Lus Qhia hauv Google Daim Ntawv Qhia Android API V2
Primeiro, vamos criar localidades para cada um dos pontos que desejamos marcar:
// Qhov chaw
ntiag tug LatLng tam sim no;
ntiag tug LatLng lixeiraA; ntiag tug LatLng lixeiraB; ntiag tug LatLng lixeiraC; private LatLng lixeiraD;
Txhawm rau kom ua tiav cov txiaj ntsig zoo ntawm daim ntawv qhia, ua raws cov lus qhia hauv qab no:
ntiag tug void checkLocationandAddToMap () {// Txheeb xyuas yog tias tus neeg siv tau tso cai yog (ActivityCompat.checkSelfPermission (qhov no, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPerman (no, android. ACCESS_COARSE_LOCATION! rov qab; }
// Nrhiav qhov chaw paub kawg uas siv Fus
Qhov chaw nyob = LocationServices. FusedLocationApi.getLastLocation (googleApiClient);
// MarkerOptions tau siv los tsim tus cim tshiab. Koj tuaj yeem hais qhia qhov chaw, npe thiab lwm yam nrog MarkerOptions
this.current = tshiab LatLng (qhov chaw.getLatitude (), qhov chaw.getLongitude ()); MarkerOptions markerOptions = tshiab MarkerOptions (). Txoj haujlwm (tam sim no).title ("Posição atual");
// Ntxiv qhov tsim tus cim rau ntawm daim duab qhia chaw, txav lub koob yees duab mus rau txoj haujlwm
markerOptions.icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory. HUE_GREEN)); System.out.println ("+++++++++++++ Passei aqui! +++++++++++++++"); mMap.addMarker (markerOptions);
// Tsiv lub koob yees duab tam sim ntawd mus rau qhov chaw nrog kev nthuav dav ntawm 15.
mMap.moveCamera (CameraUpdateFactory.newLatLngZoom (tam sim no, 15));
// Zoom hauv, ua kom lub koob yees duab muaj zog.
mMap.animateCamera (CameraUpdateFactory.zoomTo (14), 2000, tsis muaj dab tsi);
}
Nyob rau hauv qhov tseeb, nyob rau hauv cov ntaub ntawv ntawm lub cev, foram criados métodos similares ao abaixo:
ntiag tug void addBinALocation () {// Txheeb xyuas yog tias tus neeg siv tau tso cai yog (ActivityCompat.checkSelfPermission (qhov no, android. Manifest.permission. ACCESS_FINE_LOCATION)! = PackageManager. PERMISSION_GRANTED && ActivityCompat.checkSelfPermission (qhov no, android. Manifest.per. ACCESS_COARSE_LOCATION! rov qab; }
// Tshaj tawm ntawm Estação
ob txoj kab nruab nrab = -19.9159578; ob qhov ntev = -43.9387856; this.lixeiraA = tshiab LatLng (latitude, longitude);
MarkerOptions markerOptions = tshiab MarkerOptions (). Txoj haujlwm (lixeiraA).title ("Lixeira A");
markerOptions.icon (BitmapDescriptorFactory.defaultMarker (BitmapDescriptorFactory. HUE_RED)); mMap.addMarker (markerOptions); }
Raws li qhov nruab nrab txoj kab nruab nrab thiab txoj kab nruab nrab ntev ntawm cada lixeira foram recuperadas através ua próprio Google Maps, e deixadas fixas no código. Qhov zoo tshaj plaws, estes valores ficariam salvos em um banco de dados (piv txwv li Firebase). Qhov tseem ceeb ntawm kev hloov pauv mus rau txoj kev npaj!
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!
Ua raws li cov lus pom zoo los ntawm tus kws kho mob hauv qab no:
private String getDirectionsUrl (keeb kwm LatLng, LatLng dest, Sau cov npe waypointsList) {
// Keeb kwm ntawm txoj kev
Txoj hlua str_origin = "keeb kwm ="+keeb kwm.latitude+","+keeb kwm.longitude;
// Lub hom phiaj ntawm txoj kev
Txoj hlua str_dest = "destination ="+dest.latitude+","+dest.longitude;
// Waypoints raws txoj kev
//waypoints=optimize:true|-19.9227365, -43.9473546 | -19.9168006, -43.9361124 String waypoints = "waypoints = optimize: true"; rau (LatLng point: waypointsList) {waypoints += "|" + point.latitude + "," + point.longitude; }
// Sensor qhib
Txoj hlua sensor = "sensor = false";
// Tsim cov kev txwv rau kev pabcuam web
Txoj hlua tsis = str_origin+"&"+str_dest+"&"+sensor+"&"+waypoints;
// Tso zis hom
Txoj hlua tso tawm = "json";
// Tsim lub url rau lub vev xaib pabcuam
Txoj hlua url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters; System.out.println ("++++++++++++++"+url);
rov qab url;
}
E, por fim, juntando tudo no método tus thawj xib fwb da classe, onMapReady:
@Override pej xeem void onMapReady (GoogleMap googleMap) {mMap = googleMap;
checkLocationandAddToMap ();
yog (lixeirasList.get (0).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE
|| lixeirasList.get (0).getPesoLixo ()-10> Lixeira. MIN_SIZE_GARBAGE) {addBinALocation (); } yog (lixeirasList.get (1).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get (1).getPesoLixo ()> Lixeira. MIN_SIZE_GARBAGE) {addBinBLocation (); } yog (lixeirasList.get (2).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get (2).getPesoLixo ()> Lixeira. MIN_SIZE_GARBAGE) {addBinCLocation (); } yog (lixeirasList.get (3).getVolumeLixo ()> Lixeira. MIN_VOLUME_GARBAGE || lixeirasList.get (3).getPesoLixo ()> Lixeira. MIN_SIZE_GARBAGE) {addBinDLocation (); }
// Kos txoj kev
// Tau txais URL rau Google Cov Lus Qhia API
Sau cov ntsiab lus = tshiab ArrayList (); points.add (lixeiraB); points.add (lixeiraC); points.add (lixeiraD);
Txoj hlua url = getDirectionsUrl (tam sim no, lixeiraA, cov ntsiab lus);
DownloadTask downloadTask = tshiab DownloadTask (); // Pib rub tawm json cov ntaub ntawv los ntawm Google Cov Lus Qhia API downloadTask.execute (url); }
Aqui passamos apenas pelos pontos tus thawj tswj hwm. Nws yog qhov ua tiav ntawm cov phiaj xwm kev faib tawm rau kev sib tham.
Kauj Ruam 8: Xaus
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 direta. Ua ntej tshaj plaws, segue um vídeo ua projeto tiav, para ilustração, e os fontes das atividades criadas ntawm Android.
Pom zoo:
Arduino Tsheb Rov Qab Chaw Nres Tsheb Ceeb Toom - Cov Kauj Ruam ntawm Kauj Ruam: 4 Kauj Ruam
Arduino Tsheb Rov Qab Chaw Nres Tsheb Ceeb Toom | Cov kauj ruam ib kauj ruam: Hauv txoj haujlwm no, kuv yuav tsim qhov yooj yim Arduino Tsheb Rov Qab Tsheb Nres Tsheb Nres Sensor Siv Arduino UNO thiab HC-SR04 Ultrasonic Sensor. Qhov no Arduino raws Lub Tsheb Rov Qab ceeb toom tuaj yeem siv rau Kev Tshawb Fawb Txog Tus Kheej, Robot Ranging thiab lwm yam
Tsev Automation Kauj Ruam ntawm Kauj Ruam Siv Wemos D1 Mini Nrog PCB Tsim: 4 Kauj Ruam
Tsev Automation Kauj Ruam Ib Leeg Siv Wemos D1 Mini Nrog PCB Tsim: Tsev Automation Kauj Ruam los ntawm Kauj Ruam siv Wemos D1 Mini nrog PCB Tsim cov tub ntxhais kawm ntawv qib siab. Tom qab ntawd ib tus ntawm peb cov tswv cuab tuaj
RC Taug Qab Neeg Hlau Siv Arduino - Kauj Ruam Ib kauj ruam: 3 Kauj Ruam
RC Tracked Robot Siv Arduino - Kauj Ruam Ib Nrab: Hav guys, Kuv rov qab los nrog lwm tus neeg hlau txias chassis los ntawm BangGood. Vam tias koj tau dhau los ntawm peb cov phiaj xwm yav dhau los - Spinel Crux V1 - Tus Cwj Pwm Tswj Tus Neeg Hlau, Spinel Crux L2 - Arduino Xaiv thiab Muab Neeg Hlau nrog Robotic caj npab thiab Badland Braw
SmartBin: 4 Kauj Ruam
SmartBin: Lub hom phiaj tseem ceeb ntawm txoj haujlwm no yog tsim cov khoom siv hluav taws xob uas siv tsawg kawg ib qho Raspberry Pi. Pab neeg no yog ua los ntawm 5 tus kws kho tshuab yav tom ntej thiab ib tus kws tshaj lij tshuab tshuab. Peb tes num suav nrog ua cov thoob khib nyiab uas qhib thiab kaw
Kawm Yuav Ua Li Cas Kos Tus Tswm Ciab - Kauj Ruam Ib Kauj Ruam: 6 Kauj Ruam
Kawm Yuav Ua Li Cas Thiaj Li Tswmciab - Kauj Ruam Ib kauj ruam: Cov tswm ciab no siv sijhawm 10 feeb los kos yog tias koj ua raws kuv cov kauj ruam ua tib zoo