Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Kotak Sangat Cerdas

Komponen dan persediaan

Lembar akrilik (mis. perspex 3mm)
× 1
Arduino MKR FOX 1200
× 1
SparkFun HX711 Load Cell Amplifier
× 1
sel beban 5kg
× 2
Adafruit BME280
× 1

Alat dan mesin yang diperlukan

Pemotong laser (generik)
Printer 3D (generik)

Aplikasi dan layanan online

Tinamous
Sigfox

Tentang proyek ini

Platform Really Smart Box mengubah Kotak Benar-Benar Berguna (tm) menjadi kotak penyimpanan cerdas yang terhubung ke internet untuk pemantauan stok. Berdasarkan Sigfox Arduino MKR FOX 1200, alat ini mendeteksi berat barang yang disimpan di dalam kotak, bersama dengan suhu dan kelembapan, dan menggunakan radio Sigfox berdaya rendah untuk menyampaikan informasi ini.

Use Case - Penyimpanan Filamen Printer 3D:

Jika Anda memiliki printer 3D, kemungkinan besar Anda akan peduli tentang bagaimana filamen Anda disimpan, hal ini berlaku tidak hanya untuk filamen printer tetapi banyak hal lain yang perlu disimpan dalam kisaran suhu dan kelembaban yang dapat diterima (misalnya dempul cat mungkin menjadi tidak dapat digunakan jika terkena hingga di bawah suhu beku).

Sebagai salah satu orang yang bertanggung jawab untuk memelihara printer 3D di ruang pembuat lokal saya, saya perlu memastikan kami memiliki stok filamen yang cukup dan tetap kering.

Dengan Kotak yang Benar-benar Cerdas, saya dapat memantau berat filamen dan mengetahui apakah kami semakin rendah, bersama dengan pemantauan tingkat kelembaban di dalam kotak untuk mengetahui apakah gel silika perlu diganti.

Kasus Penggunaan - Kontrol Stok Barang Habis Pakai:

Kontraktor pembersih mungkin ingin menyimpan stok penyegar udara, sabun tangan, atau bahan habis pakai lainnya di lokasi klien, klien kemungkinan tidak akan mengizinkan akses WiFi kontraktor atau menyalakan perangkat seperti ini jika tidak ada, namun perusahaan kontraktor perlu tahu kapan harus mengirim stok baru, menambahkan overhead ke waktu petugas kebersihan dan dokumen tambahan yang tidak disukai siapa pun.

Platform Really Smart Box hanya dimasukkan ke dalam kotak penyimpanan, karena menggunakan Sigfox tidak perlu terhubung ke jaringan klien dan daya rendah sehingga berjalan dari satu set baterai. Karena isi kotak akan sangat jarang berubah, Arduino dapat ditahan dalam kondisi daya rendah untuk sebagian besar waktu membantu memperpanjang masa pakai baterai.

Platform dapat diberi tahu berat jenis barang yang disimpan di dalam kotak (yaitu penyegar udara) dan karenanya menghitung berapa banyak yang ada di dalam kotak. Ini kemudian dapat dikirim ke perusahaan kontraktor pembersih untuk memperingatkan mereka ketika mereka membutuhkan lebih banyak stok untuk dikirim ke situs klien.

Membuat Platform:

Platformnya berkonstruksi sederhana, bodi utamanya terbuat dari dua potong akrilik potong laser (saya menggunakan 3mm, lebih tebal akan lebih baik untuk barang berat seperti filamen printer) dengan sepasang sel beban di antaranya.

Saya secara manual menenggelamkan lubang sekrup untuk sel beban untuk memberikan hasil akhir yang lebih bagus, saya belum menemukan pemotong laser yang melakukan countersinking!

Akrilik dapat dipotong sesuai ukuran agar sesuai dengan kotak yang Anda suka, namun perhatikan posisi sel beban dan panjang kabelnya karena cukup pendek. Lembaran akrilik bagian atas sedikit lebih kecil daripada bagian bawah untuk memastikan tidak tersangkut di sisi kotak.

Lembaran bawah memiliki potongan untuk memungkinkan elektronik dipasang ke akrilik tanpa spacer dan kaki perangkat yang disolder menyembul. Saya menggunakan ketukan M3 di bagian sudut potongan untuk langsung memasang PCB ke sana. Kaki yang dicetak 3D juga dipasang di sudut untuk memastikan bahwa sekrup apa pun dari sel beban yang tidak rata dengan akrilik tidak memengaruhi keseimbangan.

Berat dirasakan menggunakan dua sel beban 5Kg. Satu set timbangan 4 biasanya digunakan dalam timbangan kamar mandi dan ini mungkin lebih baik, namun saya tidak dapat menemukan cara yang baik untuk memperbaikinya ke akrilik serta menyediakan jarak yang diperlukan untuk elektronik.

Sel beban memerlukan beberapa bantalan atas dan bawah untuk memungkinkan sedikit melenturkan dan sensor pengukur regangan yang sebenarnya (bagian putih pada gambar) dari sel beban lebih gemuk daripada blok pemasangan. Hal ini dicapai di bawah sel beban dengan dua pelat ujung Cetak 3D "Really Smart Box" yang memiliki blok kecil untuk menaikkan sel beban, di atas sel beban ada beberapa blok bantalan akrilik yang dipotong laser.

Sel beban terhubung ke penguat sel beban HX711. Ini memiliki dua saluran (A dan B) yang dapat dipilih yang sempurna untuk penggunaan ini.

Setiap sel beban dibangun dari pengukur regangan dalam konfigurasi jembatan Wheatstone, ini menciptakan pasangan pembagi potensial yang tidak seimbang, ketika sel beban ditempatkan di bawah beban, resistansi pengukur regangan berubah dan karenanya perbedaan antara dua pembagi potensial dibuat , ini diperkuat dan diukur oleh HX711 yang melakukan konversi analog ke digital untuk kami.

Saya telah menggunakan dua sel beban 5kg untuk proyek ini, Anda bisa mendapatkan peringkat yang berbeda (misalnya 1kg dan 10kg) yang bekerja persis sama tetapi dengan sensitivitas yang berbeda.

Saat menempatkan sel beban, pastikan panah di ujung sel mengarah ke bawah (ke arah beban). Sel-sel memiliki lubang yang disadap M5 di satu ujung (umumnya ujung tetap) dan M4 di ujung lainnya (sisi tempat Anda meletakkan beban.

Kabel merah / hitam adalah daya, ini memberi makan bagian atas dan bawah dari pembagi potensial dan dibagi antara dua sel beban. Hijau dan putih adalah kabel indra dari tengah pembagi potensial, ini terhubung ke Saluran A dan B pada HX711.

HX711 mendukung 3 faktor penguatan, namun ini juga digunakan untuk pemilihan saluran. Penguatan 128 dan 64 tersedia pada saluran A, sedangkan memilih penguatan 32 memilih saluran B. ini berarti channel kedua kita tidak akan sesensitif channel utama, ini bagus untuk aplikasi ini.

HX711 bisa disambungkan ke pin digital apapun di arduino, saya sudah menggunakan D0 (Data) dan D1 (Jam), lalu amplifier tinggal disambungkan ke supply 3v3 Arduino.

Anda dapat membaca lebih lanjut tentang sel beban dan HX711 di tutorial sel beban luar biasa SparkFuns.

Akhirnya BME280 terhubung ke bus I2C dan digunakan untuk merasakan suhu dan kelembaban di dalam kotak, ini juga dapat digunakan untuk merasakan tekanan namun ini mungkin tidak terlalu menarik dan kami hanya memiliki 12 byte data sigfox untuk dimainkan jadi ini tidak dilaporkan.

Elektronik dipasang pada papan Prototipe Arduino ThingySticks, saya menambahkan dudukan baterai (leburan panas yang direkatkan ke lembaran akrilik bawah) dan menghubungkan antena yang merupakan desain datar yang bagus sehingga bekerja dengan sempurna untuk platform.

Kalibrasi Sel Muat:

Sebelum kita dapat menggunakan platform, sel beban perlu dikalibrasi. Setiap sel beban unik, dibuat dengan menempelkan pengukur regangan ke balok logam dan lubang yang dibor di dalamnya untuk memberikan kelenturan yang cukup yang dapat dirasakan tanpa patah, karena itu kita perlu mengkalibrasi setiap sel beban untuk responsnya terhadap berat .

Setelah dikalibrasi, kami menerapkan persamaan y=mx+c ke nilai ADC terukur (x) untuk mendapatkan bobot aktual (y). Jadi kita perlu mencari c (offset) dan m (kemiringan) untuk load cell kita.

Saya menghapus bagian atas platform utama dan memasang kotak akrilik kecil ke setiap sel beban secara bergantian, dan memantau nilai yang diukur (mereka adalah perutean di firmware untuk melakukan ini yang dapat dimulai dengan mengirimkan "c" ke port serial.

Awalnya pembacaan untuk platform kosong diukur, ini memberikan nilai offset (c), kemudian menempatkan beban dengan berat yang diketahui pada sel, perbedaan pembacaan memberi kita kemiringan.

Kemiringan =(diukur - offset) / berat (g).  

Saya menggunakan kaleng pengharum ruangan kecil (ca. 230g) dan gulungan filamen printer (ca. 1.5kg) untuk memeriksa nilainya, keduanya memberikan kemiringan yang sama yang meyakinkan.

Tentu saja offset yang diukur dengan bantalan akrilik kecil berbeda dengan yang dialami dengan lembaran atas penuh, demikian juga perbedaan kemiringan yang kecil saat menggunakan kedua sel beban sehingga diperlukan kalibrasi sekunder. Untuk saat ini satu titik nol offset (tare) digunakan, ini diatur dalam firmware tetapi juga dapat diatur menggunakan koneksi serial USB atau melalui pesan downlink Sigfox setelah diterapkan.

Koneksi Sigfox:

Dengan kabel Really Smart Box, saya awalnya menggunakan port serial USB untuk memantau output guna membantu men-debug dan menyetel sistem. Dengan cara ini Anda dapat melihat sel beban individu, perubahan dan kebisingan. Namun ini tidak akan berfungsi untuk kotak yang digunakan karena harus benar-benar nirkabel.

Dengan Sigfox kami dapat mengirim 12 byte data hingga 140 kali sehari ke layanan online kami, ini lebih dari cukup untuk Kotak Benar-Benar Cerdas. Struktur data di bawah ini digunakan di Arduino menjelaskan bagaimana kami menggunakan 12 byte.

typedef struct __attribute__ ((dikemas)) sigfox_message { status uint8_t; // status menandai kelembapan int8_t; // kelembaban::int:8 - beberapa sensor (HTU21D) membaca -ve kelembaban) suhu int8_t; // suhu::int:8 (tidak ada tempat desimal). int16_t nolBerat; // zeroWeight::int:16:little-endian int16_t weight; // weight::int:16:little-endian int16_t itemCount; // itemCount::int:16:little-endian (100x jumlah item aktual untuk memungkinkan 2,01 (karena berat tidak akan sama persis) int8_t driftCorrection; // Koreksi Drift untuk perubahan bobot nol yang diterapkan pada timbangan. int8_t filler; // Tidak ada yang bisa dilihat di sini, lanjutkan.... int8_t lastStatus; // Status sigfox terakhir } SigfoxMessage;  

Byte (status) pertama dipecah menjadi flag bit untuk menunjukkan masalah:

// status::uint:8 -> Dibagi menjadi 8 bit // B7 - Jalankan pertama// B6 - Kesalahan HX711 // B5 - Kesalahan BME280// B4 - Alarm suhu// B3 - Alarm kelembaban // B2 - Alarm berat// B1 - Stok rendah// B0 - cadangan  

Struktur ini dipadatkan hingga 12 byte, namun kita perlu membongkarnya di ujung Sigfox untuk mendorong ke Tinamous. Kami menggunakan Konfigurasi Payload Kustom untuk itu dan yang terbaik adalah menyelesaikannya saat struktur data ditentukan. Milik kami adalah:

firstRun::bool:7 hx711Fault::bool:6 bmeFault::bool:5 temperatureAlarm::bool:4 moistureAlarm::bool:3 weightAlarm::bool:2 lowStock::bool:1 b0::bool:0 status::int:8 kelembaban::int:8 suhu::int:8 nolBerat::int:16:little-endian berat::int:16:little-endian itemJumlah::int:16:little -endian  

Payload khusus membagi 12 byte kami saat diurai.

Perhatikan bahwa kita perlu menentukan sifat little-endian dari sesuatu yang lebih besar dari 1 byte karena Sigfox default ke big-endian dan Arduino menggunakan little-endian (yaitu byte yang paling tidak signifikan adalah yang pertama dalam kata-kata multi-byte).

Perhatikan juga bahwa memisahkan flag boolean dalam byte pertama tidak membuat penanda byte maju seperti halnya dengan semua pembacaan lainnya sehingga byte status yang menampung semua flag juga dibaca untuk melewati byte pertama.

Termasuk dalam bendera adalah bendera alarm suhu, kelembaban dan berat, kami dapat menggunakan layanan online (yaitu Tinamous) untuk memantau suhu, kelembaban dan berat di luar jangkauan, namun ini mungkin berumur pendek (beberapa jam) dan kotak kami mungkin jarang mengirim (sekali atau dua kali sehari) kemungkinan kondisi lingkungan yang merusak dapat dengan mudah terlewatkan, sehingga kondisi tersebut ditandai pada perangkat dan dikirim (dan disetel ulang setelah pengiriman berhasil).

Jumlah item sebenarnya diatur ke 100 kali jumlah item yang sebenarnya. Saya ingin mengizinkan nilai seperti 2,2 item (karena kesalahan berat atau item lain di dalam kotak) tanpa memaksa pembulatan, demikian juga 2,95 mungkin dibulatkan ke 2 jika kita tidak hati-hati dan akan lebih sugestif dari 3 item dalam kotak dan kesalahan kecil. Saya juga tidak ingin menggunakan pelampung yang akan membutuhkan lebih banyak ruang jadi saya telah menggunakan kata 16 bit dan menerapkan faktor untuk memungkinkan konversi yang mudah (ini juga ditandatangani untuk memungkinkan kesalahan nol, yang mungkin menghasilkan tingkat stok dari -1 atau -2 dll.).

Sangat sedikit yang perlu dilakukan untuk mengaktifkan komunikasi Sigfox. Di dalam Arduino, library Sigfox ditambahkan dan fungsi yang sesuai dipanggil untuk mendorong data keluar sesuai dengan contoh Arduino untuk library Sigfox, namun kita perlu mendaftarkan perangkat kita ke Sigfox.

Mengirim "s" ke port serial Kotak Benar-Benar Cerdas akan mencetak ID Sigfox dan kode PAC, ini digunakan untuk mengaktifkan perangkat di backend Sigfox. Kami kemudian menuju ke layanan aktivasi backend Sigfox dan mengikuti wizard, pertama-tama pilih perangkat kami, lalu negara/penyedia dan kemudian beberapa detail.

Dan akhirnya perangkat kami diaktifkan dan terdaftar:

Sigfox menetapkan perangkat ke pengelompokan Jenis Perangkat yang masuk akal karena Anda biasanya memiliki banyak (ratusan, ribuan, dll.) dari jenis perangkat yang sama yang ingin Anda gunakan sebagai sebuah grup. Dengan Jenis Perangkat yang ditentukan, kami dapat mengonfigurasi panggilan balik khusus untuk mendorong data yang kami terima ke layanan online kami. Saya menggunakan Tinamous untuk ini (petunjuk:lihat nama profil saya - saya mungkin bias dalam pemilihan saya).

Menggunakan Kotak yang Sangat Cerdas:

Setelah disambungkan, dibaut bersama-sama, firmware di-flash dan baterai dipasang ke platform dengan mudah dimasukkan ke dalam Kotak yang Sangat Berguna (tm) dan siap digunakan.

Daya harus diterapkan selambat mungkin karena setelah perangkat dinyalakan, perangkat akan mengirim pesan Sigfox pertama setelah 2 menit dan meminta data downlink dengannya. Data ini dapat menyertakan perintah "Nol" untuk meniadakan bobot platform. Jika gagal, koneksi serial USB diperlukan atau menunggu permintaan downlink berikutnya - ini dilakukan setiap 12 jam.

Setelah aktif dan berjalan, platform akan menerbitkan pesan Sigfox setiap 15 menit untuk mengirim bobot, jumlah item, suhu, kelembapan, dan status alarm. Suhu, kelembaban, dan berat diukur setiap menit untuk memastikan ini tidak di luar jangkauan dengan alarm yang ditandai untuk transmisi berikutnya jika telah dinaikkan.

Pemantauan Dengan Tinamous:

Tinamous mendukung panggilan balik kustom Sigfox dengan menambahkan "Bot Sigfox" ke akun kami, untuk petunjuk tentang cara melakukannya, lihat tutorial Hackster.io "Dapatkan Sigfox Anda".

Saat menambahkan Bot Sigfox ke akun Tinamous Anda, jika Anda menyertakan pengaturan API, Bot Sigfox akan mencari perangkat Anda dan menambahkannya ke akun Tinamous Anda, namun Anda tidak perlu melakukan ini karena perangkat akan otomatis ditambahkan saat data diterbitkan.

Ketika Anda telah menambahkan Bot, kami akan disajikan dengan layar konfigurasi Callback untuk membantu menyiapkan Callback Sigfox.

Anda kemudian dapat membuat panggilan balik khusus di Sigfox, perhatikan bahwa Kotak Sangat Cerdas menggunakan DATA -> panggilan balik BIDIR yang menangani panggilan balik UPLINK normal dan panggilan balik BIDIR (atas dan bawah).

Di sinilah muatan kustom dari sebelumnya berguna, tempel ini dari kode sumber ke muatan kustom dan perbarui bagian bidang untuk mencerminkan hal ini.

Lat dan Lng ditentukan dalam panggilan balik ini yang memberikan perkiraan lokasi, namun Sigfox pada Arduino mendukung pengaturan lokasi yang ditingkatkan, tetapi ini membutuhkan panggilan balik kedua. Jika Anda menggunakan fasilitas lokasi Geo, jangan tentukan Lat/Lng dalam pesan ini karena Kotak Benar-benar Cerdas akan tampak berpindah antar lokasi.

Setelah dikonfigurasi, ini juga perlu diaktifkan untuk Downlink, ini dinonaktifkan secara default meskipun BIDIR telah disetel.

Perhatikan tangkapan layar di bawah opsi Downlink "dicentang", ini harus dilakukan secara manual, dan mungkin tidak tersedia jika Device Type belum disetel ke "CALLBACK" untuk data downlink (Device Type -> Edit -> Downlink Data) .

Dengan panggilan balik Downlink kami juga ingin menentukan LAYANAN -> panggilan balik ACKNOWLEDGE untuk mengetahui perangkat kami telah menerima data downlink. Dengan mengklik Bot Sigfox di Tinamous, konfigurasi panggilan balik lainnya akan ditampilkan, ikuti petunjuk untuk panggilan balik ACKNOWLEDGE dan GEOLOC.

Perhatikan bahwa Anda perlu menyalin header otorisasi dari panggilan balik uplink/bidir pertama karena ini adalah kata sandi yang dienkripsi satu arah di Tinamous dan tidak lagi tersedia untuk ditampilkan.

Dengan callback kami di tempat, data yang diterbitkan oleh perangkat kami sekarang harus dikirim ke Tinamous. Kami juga dapat menambahkan panggilan balik email di Sigfox yang dapat membantu mengonfirmasi data yang masuk (tetapi juga dapat menjadi sangat bising dengan sangat cepat).

Mengonfigurasi Perangkat Tinamous:

Setelah perangkat Sigfox terlihat di Tinamous (baik melalui pencarian api atau panggilan balik), itu akan ditampilkan di halaman Perangkat, dari sini kita dapat mengedit properti. Bidang ditambahkan secara otomatis saat berasal dari panggilan balik Sigfox, jadi sebaiknya tunggu hingga perangkat memublikasikan data.

Saya menyetel waktu "Tidak Melaporkan Setelah" menjadi 1 jam (Saat ini diterbitkan setiap 15 menit) sehingga saya dapat mengetahui apakah perangkat rusak dan secara opsional mendapatkan pemberitahuan tentang hal ini.

Saya tidak ingin melihat semua bidang yang dikirim oleh perangkat pada halaman bagan/detail (banyak jika Anda menyertakan semua bendera), jadi Tinamous dikonfigurasi hanya untuk menunjukkan berat dan jumlah item. Label dan unit yang ramah manusia juga diterapkan di sini.

Bidang Jumlah Barang adalah 100x jumlah barang yang sebenarnya, jadi kalibrasi diterapkan ke bidang itu untuk menguranginya 100 kali lipat.

Beberapa data downlink disetel yang akan menyebabkan Kotak Benar-benar Cerdas menjadi nol dan menerapkan batas rentang suhu dan kelembapan saat berikutnya meminta pesan downlink (2 menit setelah dihidupkan, lalu setiap 12 jam sekali).

Melihat Informasi Kotak yang Sangat Cerdas:

Sekarang bidang perangkat dikonfigurasi, kami dapat memantaunya melalui halaman detail perangkat (Perhatikan bahwa saya tidak akan membidik platform saat ini, oleh karena itu dianggap ada 1/2 unit - saya juga mengganti bagian atas akrilik dengan 5mm versi yang lebih berat tetapi akan menangani filamen printer lebih baik).

Kita juga dapat melihat interaksi callback Sigfox dari bagian Sigfox. Perhatikan di sini bahwa data downlink sedang dikirim dan di-ack namun Arduino melaporkan kesalahan. Lebih lanjut tentang itu di bagian akhir.

Di tab Lokasi kita juga bisa melihat di mana Benar-benar Smart Box kita, yang mungkin berguna jika Anda lupa pelanggan mana, atau jika di dalam van.

Dan tentu saja kami menginginkan tampilan dasbor yang bagus dari Kotak Sangat Cerdas kami, yang di bawah ini menunjukkan berat isi kotak, perkiraan unit di dalamnya, dan jumlah perangkat yang tidak melaporkan sehingga kami dapat mengetahui apakah ada yang rusak.

Menerima Notifikasi Dengan Tinamous:

Selanjutnya saya set-up Tinamous untuk mengirim email dan sms ketika jumlah item sedikit. Saya melakukan ini dengan menentukan rentang kerja 3 - 300 untuk bidang jumlah item. Jika nilainya di luar rentang ini, pengukuran di luar rentang genap akan dinaikkan.

Menambahkan Notifikasi ke Tinamous, kami dapat diberi tahu saat itu terjadi.

Kami dapat menentukan hanya bidang yang kami minati, tetapi membiarkannya kosong memberi kami pemberitahuan untuk bidang apa pun yang berada di luar jangkauan.

Demikian juga untuk perangkat, biarkan kosong untuk semua perangkat (yaitu satu-satunya yang kami miliki saat ini!)

Setel Notifikasi Ulangi untuk memicu sekali saja, hingga disetel ulang (setiap hari), jika tidak, notifikasi setiap 15 menit akan sangat cepat mengganggu!

Lalu pilih cara notifikasinya, saya set untuk email dan sms lalu buat notifikasinya:

Kesimpulan:

Saya sekarang dapat menggunakan Kotak Benar-Benar Cerdas dan (semoga) melupakannya. Ketika tingkat stok menipis, saya akan diberi tahu dan saya dapat memeriksa di dasbor untuk melihat bagaimana kinerjanya. Menggunakan Sigfox Saya tidak perlu khawatir tentang menyalakan perangkat selain penggantian baterai sesekali dan tidak ada pengaturan WiFi di situs yang diperlukan membuat penyebaran menjadi sangat sederhana.

Saya berencana untuk menerapkan unit ini ke salah satu kotak penyimpanan filamen kami di Cambridge Makespace untuk memantau tingkat stok filamen.

Masalah yang Harus Diselesaikan:

Tak perlu dikatakan bahwa ini bukan proyek akhir kualitas produksi, beberapa masalah masih perlu diselesaikan:

Tautan Bawah Sigfox:

Sigfox memungkinkan 4 pesan sehari untuk dikirim sebagai tanggapan atas pesan uplink. Kotak Benar-Benar Cerdas menggunakan ini untuk memungkinkan penimbangan ulang timbangan, pengaturan suhu dan rentang kelembaban atas dan bawah dan berat barang. Namun ketika mencoba membuatnya berfungsi, meskipun pesan downlink tampaknya dikirim dan sedang di-ack (seperti yang ditunjukkan di backend Sigfox), Arduino melaporkan kesalahan status 62, yang tidak memetakan ke tanda kesalahan apa pun kondisi yang tercantum untuk chip ATA8520, menggali driver perintah menggunakan permintaan untuk downlink yang juga tidak tercantum dalam lembar data, sehingga penyelidikan lebih lanjut perlu dilakukan.

Hanya Debug:

Menjalankan komunikasi Sigfox dengan debug dinonaktifkan menyebabkan pengaturan daya rendah Arduino diaktifkan dengan mematikan port serial USB.

Mode Daya Rendah:

Seperti yang dijelaskan untuk pengaturan debug Sigfox, menggunakan perpustakaan Daya Rendah Arduino menyebabkan serial USB terputus sehingga tidak diaktifkan saat ini.

Melayang:

Tidak ada kompensasi untuk penyimpangan yang ditambahkan, tidak diragukan lagi sel beban akan melayang ketika ditahan di bawah beban konstan.

Pengukuran Kebisingan / Non-Vertikal:

Mungkin Kotak Benar-Benar Cerdas ada di belakang van (mis. pembersih ponsel, tukang kayu, tukang ledeng, dll.). Sebaiknya tambahkan akselerometer ke platform dan lewati siklus pengukuran saat kotak tidak stabil, demikian juga jika kotak tidak vertikal, bobot tidak akan melewati sel beban seperti yang diharapkan.

Kode

  • Kode Arduino Kotak yang Sangat Cerdas
Smart Box Kode ArduinoArduino
Tambahkan Perpustakaan untuk Arduino MKR FOX 1200, HX711, AdaFruit BME280, Arduino Low Power. Gunakan Arduino IDE untuk memprogram seperti biasa.
// Really Smart Box// Mengukur berat isi kotak yang benar-benar pintar// Dibuat oleh dua lembar akrilik dengan 2 sel beban di antaranya // ditempatkan di tempat yang benar-benar kotak pintar.// Juga termasuk BME280 untuk mengukur suhu dan tekanan di dalam kotak.// Penulis:Stephen Harrison// Lisensi:MIT#include #include #include  #include #include // ---------------------------------- ----// BME280 pada port I2C.Adafruit_BME280 bme; // ---------------------------------------// Penguat sel beban HX711.// 0 :D0 - DOUT// 1:D1 - CLK// perolehan awal 128.HX711 scales(0, 1, 128);// Array untuk load cell. Index 0 ==Channel A, Index 1 ==Channel B.float gain[] ={128,32};// Faktor kalibrasi.// kita menggunakan y =mx + c (c =offset, m =scaleFactor)./ / untuk mengubah nilai terukur menjadi bobot.// Setel ini ke offset yang dilaporkan oleh sel beban.// tanpa bobot.float offset[] ={0,54940}; // Setel ini ke faktor yang dihitung ketika bobot ditempatkan pada timbangan.// Setel offset terlebih dahulu, flash ulang arduiono agar ini berlaku// letakkan bobot pada timbangan dan bagi nilai mentah yang diukur dengan weight.// using scaleFactor =nilai terukur / weight.float scaleFactor[] ={378.f,260.9f};// ---------------------- ----------------// Sigfox// This is the data structure we publish to Sigfox.// Split out the bits as bool flags from the first status byte but the byte still needs to be // included otherwise humidity becomes the status// firstRun::bool:7 hx711Fault::bool:6 bmeFault::bool:5 temperatureAlarm::bool:4 humidityAlarm::bool:3 weightAlarm::bool:2 lowStock::bool:1 b0::bool:0// status::int:8 humidity::int:8 temperature::int:8 zeroWeight::int:16:little-endian weight::int:16:little-endian itemCount::int:16:little-endiantypedef struct __attribute__ ((packed)) sigfox_message { uint8_t status; // status::uint:8 -> Split to 8 bits // B7 - First run, B6 - HX711 fault, B5 BME280 fault, B4 Temperature alarm, B3 - Humidity alarm, B2 - weight alarm, B1 - Low stock, B0 - spare int8_t humidity; // humidity::int:8 (yes some sensors (HTU21D read -ve humidity) int8_t temperature; // temperature::int:8 (no decimal places). int16_t zeroWeight; // zeroWeight::int:16:little-endian int16_t weight; // weight::int:16:little-endian int16_t itemCount; // itemCount::int:16:little-endian (100x actual item count to allow for 2.01 (as weight won't match exactly) int8_t driftCorrection; // Drift Correction for changes in zero weight applied to the scales. int8_t filler; int8_t lastStatus; // Last sigfox status} SigfoxMessage;// Time the last Sigfox message was published atlong lastPublish =0;// Time the last Sigfox downlink was requested.// Allowed max 4 per day of these.long lastDownlink =0;uint8_t lastSigfoxStatus =0;// --------------------------------------// Application/state// If the fist cycle (after a reset) for the measure/publish// cycle (this is used to request a downlink message from Sigfox).// Note that only 4 of them are allowed per day so becareful// when deploying code.bool isFirstCycle =true;// Application mode// 0:Normal// 1:Calibrationint mode =0;// Which channel should be read during calibration.int calibrate_channel =0;// The last average value measured for each channel.float lastAverage[] ={0,0};// The current weight of the contents of the boxfloat currentWeight =0;// The weight of the units the box will hold.// Updatable via Sigfox downlink message.float unitWeight =238;// Different to tare as it would be a manual// zero'd at a set reading from scales// This will most likely change with drift (time/temperature/etc)// and should be set once the scale is in place but not loaded.// Updatable via Sigfox downlink message.float zeroWeight =0;bool bmeOk =true;bool hx711Ok =true;// Alarms and alarm rangesfloat minTemperature =5.f;float maxTemperature =60.f;float minHumidity =0.f;float maxHumidity =60.f;float maxWeight =10000; // 10kgbool temperatureAlarm =false;bool humidityAlarm =false;bool weightAlarm =false;float currentTemperature =0;float currentHumidity =0;float stockLevel =0;bool lowStock =false;float minStock =5;// Setup the Arduino.void setup() { pinMode(LED_BUILTIN, OUTPUT); //Initialize serial:Serial.begin(9600); // NB:The sensor I'm using (from random eBay seller) // does not use the default address. bmeOk =bme.begin(0x76); if (!bmeOk) { Serial.println("Could not find a valid BME280 sensor!"); } // Delay for USB Serial connect and for the BME's first reading. penundaan(5000); Serial.println("Really Smart Box..."); printHeader();}int delayCounter =0;void loop() { switch (mode) { case 0:measureAndPublish(); //Sleep for 1 minutes // Causing problems with USB connected. //LowPower.sleep(1 * 60 * 1000); delay(60 * 1000); merusak; case 1:calibrate(); penundaan (1000); merusak; } // Check for user input via the serial port. checkSerial(); // measure is done on RTC timer tick (once per minute) delay(100);}void measureAndPublish() { // turn the LED on to indicate measuring. digitalWrite(LED_BUILTIN, HIGH); printBmeValues(); measureTemperatureAndHumidity(); measureWeight(true); // Weight, temperature and humidity are read every minute // however we only publish occasionally. if (shouldPublish()) { publishMeasurements(); } digitalWrite(LED_BUILTIN, LOW); }// Main measurement loop. Reads the weight from the load cells// and stores if no noise from the previous read.void measureWeight(bool printDetails) { scales.power_up(); penundaan (500); float delta =readDelta(printDetails); if (printDetails) { Serial.print("\t"); Serial.print(delta, 2); } // If the delta is between -1 and 1 (i.e. no noise) // update the change in overall weight and units contained // otherwise ignore and try again later on. // This ensures we use only stable readings when both channels have not changed for // two sets of measurements. if (delta <1.f &&delta> -1.f) { // Remember the previous measured weight so we can get a delta. float lastWeight =currentWeight; // Compute the weight. Take the weight of both load cells // added together then subtract the zero'd weight. currentWeight =lastAverage[0] + lastAverage[1] - zeroWeight; // Compute the difference in weight of the items in the box // compated to the last time we had a stable reading. float itemsWeightDelta =currentWeight - lastWeight; updateStockLevels(); if (printDetails) { Serial.print("\t"); Serial.print("\t"); Serial.print(currentWeight, 2); Serial.print("\t"); // divide by unit weight to estimate the stock level in the box Serial.print(currentWeight / unitWeight, 2); Serial.print("\t"); // the change in weight, (i.e. the weight if the items added) Serial.print(itemsWeightDelta, 2); Serial.print("\t"); // divide by unit weight to estimate the units removed/added Serial.print(itemsWeightDelta / unitWeight, 2); } } checkWeightLimits(); if (printDetails) { Serial.println(); } // put the ADC in sleep mode and switch // off the LED now we're done measuring. scales.power_down(); }void updateStockLevels() { stockLevel =currentWeight / unitWeight; // Unlike other alarms the low stock level // is reset if the stock is re-stocked. lowStock =stockLevel  maxWeight ) { weightAlarm =true; } if (lastAverage[0]> (maxWeight /2)) { weightAlarm =true; } if (lastAverage[1]> (maxWeight /2)) { weightAlarm =true; }}// Read the difference in weight from the last // average to this time across both load cells.// average value is stored in the lastAverage array.float readDelta(bool printDetails) { float aDelta =readChannel(0, true); if (printDetails) { Serial.print("\t"); } float bDelta =readChannel(1, true); return aDelta + bDelta;}// Read the weight from a channel. Stores the measured value in // the lastAverage array and retuns the delta of the measured value// from the previous lastAverage. This allows us to know if the weight// has changed.// channel 0 =A// channel 1 =Bfloat readChannel(int channel, bool printDetails) { // Gain:// Channel A supports 128 or 64. Default 128 // Channel B supports 32 // Select Channel B by using gain of 32. scales.set_gain(gain[channel]); // HX711 library only has one set of offset/scale factors // which won't work for use as we use both channels and they // have different gains, so each needs to have it's offset/scale set // before reading the value. scales.set_offset(offset[channel]); scales.set_scale(scaleFactor[channel]); // force read to switch to gain. scales.read(); scales.read(); float singleRead =scales.get_units(); float average =scales.get_units(10); float delta =average - lastAverage[channel]; if (printDetails) { Serial.print(singleRead, 1); Serial.print("\t"); Serial.print(average, 1); Serial.print("\t"); Serial.print(delta, 1); Serial.print("\t"); } lastAverage[channel] =average; return delta;}// print the header for the debug data pushed out when measuring.void printHeader() { Serial.print("BME280\t\t\t\t\t"); Serial.print("Channel A\t\t\t"); Serial.print("Channel B\t\t\t"); Serial.print("\t\t"); Serial.print("Totals \t\t\t"); Serial.println(""); Serial.print("Temp\t"); Serial.print("Pressure\t"); Serial.print("Humidity\t"); Serial.print("read\t"); Serial.print("average\t"); Serial.print("delta\t"); Serial.print("\t"); Serial.print("read\t"); Serial.print("average\t"); Serial.print("delta\t"); Serial.print("\t"); Serial.print("sum\t"); Serial.print("\t"); Serial.print("weight\t"); Serial.print("items\t"); Serial.print("change\t"); Serial.print("items added"); Serial.println("");}// Calibration - reads/prints selected channel values.void calibrate() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) scales.set_gain(gain[calibrate_channel]); scales.set_offset(offset[calibrate_channel]); scales.set_scale(scaleFactor[calibrate_channel]); // force read to switch to gain Serial.print("\t|CH:\t"); Serial.print(calibrate_channel,1); Serial.print("\traw:\t"); Serial.print(scales.read(),1); Serial.print("\t| raw:\t"); Serial.print(scales.read(),1); Serial.print("\t| units:\t"); Serial.print(scales.get_units(), 1); Serial.print("\t| gain:\t"); Serial.print(gain[calibrate_channel], 1); Serial.print("\t| factor:\t"); Serial.println(scaleFactor[calibrate_channel], 1); digitalWrite(LED_BUILTIN, LOW);}// check the serial port for input from a console to allow us to alter // the device mode etc.void checkSerial() { if(Serial.available()) { char instruction =Serial.read(); switch (instruction) { case '0':calibrate_channel =0; Serial.println("Channel 0 (A) Selected"); merusak; case '1':calibrate_channel =1; Serial.println("Channel 1 (B) Selected"); merusak; case 'm':// Measurement mode mode =0; Serial.println("Measurement Mode"); printHeader(); merusak; case 'c':// Calibration mode mode =1; Serial.println("Calibration Mode"); merusak; case 't':// Tare. Teset the scale to 0 Serial.println("Taring"); scales.power_up(); penundaan (500); scales.tare(5); // Need to do this for each channel // and update our stored offset. Serial.println("Not properly Tared!"); merusak; case 'h':printHeader(); merusak; case 'z':zeroScales(); merusak; case 's':printSigfoxModelDetails(); merusak; default:Serial.println("Unknown instruction. Select:0, 1, m, c, t, h, z, or s"); Serial.println("m - measurement mode"); Serial.println("c - Calibration mode"); Serial.println("0 - Channel 0 (A) Calibration"); Serial.println("1 - Channel 1 (B) Calibration"); Serial.println("t - Tare (scale)"); Serial.println("z - Zero (Weight)"); Serial.println("h - print Header"); Serial.println("s - print Sigfox model details"); merusak; } }}// Measure (and record) the temperature and humidity levels// Sets alarms if out of rage (we can't use limits on Internet service side// as the messages may only be sent a few times a day and a brief (maybe hours)// out of range temperature/humidity could easily be missed between// message publishing.void measureTemperatureAndHumidity() { if (!bmeOk) { return; } currentTemperature =bme.readTemperature(); if (currentTemperature  maxTemperature) { temperatureAlarm =true; } currentHumidity =bme.readHumidity(); if (currentHumidity  maxHumidity) { humidityAlarm =true; }}// Print the values read from the BME280 sensorvoid printBmeValues() { //Serial.print("Temperature ="); Serial.print(bme.readTemperature(), 1); Serial.print("\t"); Serial.print(bme.readPressure() / 100.0F, 0); Serial.print("\t\t"); Serial.print(bme.readHumidity(),1); Serial.print("\t\t ");}// =============================================================// Sigfox handing// =============================================================// Determine if we should publish the Sigfox message.// We may also wish to publish if the stock level has// changed (or a significant weight level has changed)// but we would need to be careful of exceeding the // 140 messages per day for a noisy system.bool shouldPublish() { // Publish every 15 minutes // this doesn't really need to be this often // but whilst developing it helps keep an eye on the system. int messageIntervalMinutes =15; // On first run after reset // allow a 2 minute delay for the platform to be placed into // the box and stabalise before doing first publish // which is also expected to include a check for zeroing the platform. if (isFirstCycle) { messageIntervalMinutes =2; Serial.println("First cycle"); } // How long ago we last publish a Sigfox message long millisAgo =millis() - lastPublish; return millisAgo> (messageIntervalMinutes * 60 * 1000);}// Publish our measurements (weight, temperature, humidity etc)// to Sigfox.void publishMeasurements() { Serial.println("Sending via Sigfox..."); bool useDownlink =shouldUseDownlink(); if (useDownlink) { Serial.println("Using Sigfox downlink..."); } // stub for message which will be sent SigfoxMessage msg =buildMessage(); SigFox.begin(); SigFox.debug(); // Wait at least 30mS after first configuration (100mS before) delay(100); // Clears all pending interrupts SigFox.status(); penundaan (1); SigFox.beginPacket(); SigFox.write((uint8_t*)&msg, 12); // endPacket actually sends the data. uint8_t statusCode =SigFox.endPacket(useDownlink); printSigfoxStatus(statusCode); // Status =0 for a successful send, otherwise indicates // a failure. // Store when we last published a Sigfox message // to allow for timed message sending. if (statusCode ==0) { resetAlarms(); } // Update the last publish/downlink times // even if an error resonse was received to prevent // repeated publishing lastPublish =millis(); isFirstCycle =false; if (useDownlink) { parseDownlinkData(statusCode); lastDownlink =lastPublish; } // Store the status value lastSigfoxStatus =statusCode; SigFox.end();}void printSigfoxStatus(uint8_t statusCode) { Serial.print("Response status code :0x"); Serial.println(statusCode, HEX); if (statusCode !=0) { Serial.print("Sigfox Status:"); Serial1.println(SigFox.status(SIGFOX)); Serial1.println(); Serial.print("Atmel Status:"); Serial1.println(SigFox.status(ATMEL)); Serial1.println(); }}// Create the message to be publish to Sigfox.SigfoxMessage buildMessage() { SigfoxMessage message; message.status =getStatusFlags(); message.humidity =(int8_t )currentHumidity; message.temperature =(int8_t)currentTemperature; message.zeroWeight =(int16_t)zeroWeight; message.weight =(int16_t)currentWeight; message.itemCount =(int16_t)(stockLevel * 100); message.driftCorrection =0; // TODO message.filler =0; message.lastStatus =lastSigfoxStatus; return message;}// Get the status flags for the Sigfox message.byte getStatusFlags() { byte status =0; // B7 - First run, // B6 - HX711 fault // B5 - BME280 fault // B4 - Temperature alarm // B3 - Humidity alarm // B2 - weight alarm // B1 - Low stock // B0 - spare // Upper Nibble (Charging/Battery) // Battery flat if (isFirstCycle) { status |=0x80; // 1000 0000 } // HX711 fault. // we don't have a way to check this yet. if (!hx711Ok) { status |=0x40; // 0100 0000 } // BME280 fault if (!bmeOk) { status |=0x20; // 0010 0000 } // Over/Under temperature alarm if (temperatureAlarm> 0) { status |=0x10; // 0001 0000 } // Over/Under humidity alarm if (humidityAlarm) { status |=0x08; // 0000 1000 } // Over/under? weight alarm if (weightAlarm) { status |=0x04; // 0000 0100 } // if computed stock level low. if (lowStock) { status |=0x02; // 0000 0010 } return status;}// Determine if we are requesting a downlink message.bool shouldUseDownlink() { // When debugging uncomment this so as to not keep requesting // downlink //return false; // On first run we want to request a downlink // message to help with zero'ing and setup. if (isFirstCycle) { return true; } // How long ago we last did a downlink message. long millisAgo =millis() - lastDownlink; // try every 12 hours, this keeps us under the // maximum 4 per day. return millisAgo> (12 * 60 * 60 * 1000);}// Parse downlinked data.void parseDownlinkData(uint8_t statusMessage) { if (statusMessage> 0) { Serial.println("No transmission. Status:" + String(statusMessage)); kembali; } // Max response size is 8 bytes // set-up a empty buffer to store this. (0x00 ==no action for us.) uint8_t response[] ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Expect... // Byte 0:Flags // B7:Zero scales // B6:Set Temperature range (ignore min/max temp if 0) // B5:Set Humidity range (ignore min/max humidity if 0) // B4:Set tolerance? // B3:Set ??? // B2:Update unit weight (ignore update if 0) // B1:// B0:// Byte 1:Min T // Byte 2:Max T // Byte 3:Min Humidity // byte 4:Max Humidity // byte 5:Read tolerence??? (+/- x) // byte 6 &7:Unit weight // Parse the response packet from Sigfox if (SigFox.parsePacket()) { Serial.println("Response from server:"); // Move the response into local buffer. int i =0; while (SigFox.available()) { Serial.print("0x"); int readValue =SigFox.read(); Serial.println(readValue, HEX); response[i] =(uint8_t)readValue; i++; } // byte 0 - flags. // 0b 1000 0000 if (response[0] &0x80 ==0x80) { zeroScales(); } // 0b 0100 0000 if (response[0] &0x40 ==0x40) { updateTemperatureAlarm(response[1], response[2]); } // 0b 0010 0000 if (response[0] &0x20 ==0x20) { updateHumidityAlarm(response[3], response[4]); } // 0b 0000 0100 if (response[0] &0x04 ==0x04) { // Little Endian format. (ff dd -> 0xddff uint16_t weight =response[7] <<8 &response[6]; updateUnitWeight(weight); } } else { Serial.println("No response from server"); } Serial.println();}void printSigfoxModelDetails() { if (!SigFox.begin()) { Serial.println("Shield error or not present!"); return; } // Output the ID and PAC needed to register the // device at the Sigfox backend. String version =SigFox.SigVersion(); String ID =SigFox.ID(); String PAC =SigFox.PAC(); // Display module informations Serial.println("MKRFox1200 Sigfox configuration"); Serial.println("SigFox FW version " + version); Serial.println("ID =" + ID); Serial.println("PAC =" + PAC); Serial.println(""); Serial.print("Module temperature:"); Serial.println(SigFox.internalTemperature()); Serial.println("Register your board on https://backend.sigfox.com/activate with provided ID and PAC"); delay(100); // Send the module to the deepest sleep SigFox.end();}// =============================================================// General helper methods// =============================================================// Reset the alarms after they have been published.void resetAlarms() { temperatureAlarm =false; humidityAlarm =false; weightAlarm =false;}void zeroScales() { zeroWeight =lastAverage[0] + lastAverage[1]; Serial.print("Zero'd:"); Serial.print(zeroWeight, 1); Serial.println();}void updateTemperatureAlarm(int8_t lower, int8_t upper) { Serial.print("Setting temperature alarm. Min:"); Serial.print(lower); Serial.print(", Max:"); Serial.println(upper); minTemperature =lower; maxTemperature =upper;}void updateHumidityAlarm(int8_t lower, int8_t upper) { Serial.print("Setting humidity alarm. Min:"); Serial.print(lower); Serial.print(", Max:"); Serial.println(upper); minHumidity =lower; maxHumidity =upper;}void updateUnitWeight(uint16_t weight) { Serial.print("Setting unit weight:"); Serial.println(weight); unitWeight =weight;}
Really Smart Box Github Repository
https://github.com/Tinamous/ReallySmartBox

Suku cadang dan penutup khusus

Use this to cut the top and bottom acrylic sheets. cuttingguide_e7GNHf980M.svgThis sits between the lower acrylic sheet and load cell to raise it up a little and provide a edge to the platformsPrint 4 of these for each corner of the lower sheet if needed

Skema

Nothing to complex.

Proses manufaktur

  1. Jus Box
  2. Kotak Hitam
  3. Sel Surya
  4. Bartender Cerdas
  5. Lampu Lalu Lintas Cerdas
  6. Tempat Sampah Pintar
  7. Robot Kotak CD Raspberry Pi
  8. UVC Box Sterilizer UV DIY
  9. Smart Plant IoT
  10. Smart Blinds