diff --git a/.gitbook/assets/food-irradiation/apache.png b/.gitbook/assets/food-irradiation/apache.png new file mode 100644 index 00000000..b94fa3e6 Binary files /dev/null and b/.gitbook/assets/food-irradiation/apache.png differ diff --git a/.gitbook/assets/food-irradiation/assembly_1.jpg b/.gitbook/assets/food-irradiation/assembly_1.jpg new file mode 100644 index 00000000..50df54ba Binary files /dev/null and b/.gitbook/assets/food-irradiation/assembly_1.jpg differ diff --git a/.gitbook/assets/food-irradiation/assembly_2.jpg b/.gitbook/assets/food-irradiation/assembly_2.jpg new file mode 100644 index 00000000..d4a19d8c Binary files /dev/null and b/.gitbook/assets/food-irradiation/assembly_2.jpg differ diff --git a/.gitbook/assets/food-irradiation/assembly_3.jpg b/.gitbook/assets/food-irradiation/assembly_3.jpg new file mode 100644 index 00000000..80622437 Binary files /dev/null and b/.gitbook/assets/food-irradiation/assembly_3.jpg differ diff --git a/.gitbook/assets/food-irradiation/assembly_4.jpg b/.gitbook/assets/food-irradiation/assembly_4.jpg new file mode 100644 index 00000000..639e7089 Binary files /dev/null and b/.gitbook/assets/food-irradiation/assembly_4.jpg differ diff --git a/.gitbook/assets/food-irradiation/assembly_5.jpg b/.gitbook/assets/food-irradiation/assembly_5.jpg new file mode 100644 index 00000000..8463a5f8 Binary files /dev/null and b/.gitbook/assets/food-irradiation/assembly_5.jpg differ diff --git a/.gitbook/assets/food-irradiation/assembly_6.jpg b/.gitbook/assets/food-irradiation/assembly_6.jpg new file mode 100644 index 00000000..2940ef8b Binary files /dev/null and b/.gitbook/assets/food-irradiation/assembly_6.jpg differ diff --git a/.gitbook/assets/food-irradiation/code_app_1.PNG b/.gitbook/assets/food-irradiation/code_app_1.PNG new file mode 100644 index 00000000..9c0240c3 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_app_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_app_2.PNG b/.gitbook/assets/food-irradiation/code_app_2.PNG new file mode 100644 index 00000000..7363325b Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_app_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_app_3.PNG b/.gitbook/assets/food-irradiation/code_app_3.PNG new file mode 100644 index 00000000..a42f8f0b Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_app_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_app_4.PNG b/.gitbook/assets/food-irradiation/code_app_4.PNG new file mode 100644 index 00000000..913c2cc7 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_app_4.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_app_5.PNG b/.gitbook/assets/food-irradiation/code_app_5.PNG new file mode 100644 index 00000000..2d3466c8 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_app_5.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_app_6.PNG b/.gitbook/assets/food-irradiation/code_app_6.PNG new file mode 100644 index 00000000..104aa13a Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_app_6.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_collect_1.PNG b/.gitbook/assets/food-irradiation/code_collect_1.PNG new file mode 100644 index 00000000..d87c9580 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_collect_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_collect_2.PNG b/.gitbook/assets/food-irradiation/code_collect_2.PNG new file mode 100644 index 00000000..61509c91 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_collect_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_collect_3.PNG b/.gitbook/assets/food-irradiation/code_collect_3.PNG new file mode 100644 index 00000000..42b73a97 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_collect_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_collect_4.PNG b/.gitbook/assets/food-irradiation/code_collect_4.PNG new file mode 100644 index 00000000..6768dff0 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_collect_4.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_collect_5.PNG b/.gitbook/assets/food-irradiation/code_collect_5.PNG new file mode 100644 index 00000000..f59a7109 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_collect_5.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_run_1.PNG b/.gitbook/assets/food-irradiation/code_run_1.PNG new file mode 100644 index 00000000..fa168f70 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_run_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_run_2.PNG b/.gitbook/assets/food-irradiation/code_run_2.PNG new file mode 100644 index 00000000..fc117d64 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_run_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_run_3.PNG b/.gitbook/assets/food-irradiation/code_run_3.PNG new file mode 100644 index 00000000..1a7b66f3 Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_run_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_run_4.PNG b/.gitbook/assets/food-irradiation/code_run_4.PNG new file mode 100644 index 00000000..fa235eda Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_run_4.PNG differ diff --git a/.gitbook/assets/food-irradiation/code_run_5.PNG b/.gitbook/assets/food-irradiation/code_run_5.PNG new file mode 100644 index 00000000..1c6ea93c Binary files /dev/null and b/.gitbook/assets/food-irradiation/code_run_5.PNG differ diff --git a/.gitbook/assets/food-irradiation/collect_0.jpg b/.gitbook/assets/food-irradiation/collect_0.jpg new file mode 100644 index 00000000..3b0ed554 Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_0.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_1.jpg b/.gitbook/assets/food-irradiation/collect_1.jpg new file mode 100644 index 00000000..a71def27 Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_1.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_10.jpg b/.gitbook/assets/food-irradiation/collect_10.jpg new file mode 100644 index 00000000..9709b786 Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_10.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_11.jpg b/.gitbook/assets/food-irradiation/collect_11.jpg new file mode 100644 index 00000000..19662f8b Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_11.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_12.jpg b/.gitbook/assets/food-irradiation/collect_12.jpg new file mode 100644 index 00000000..db47db17 Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_12.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_2.jpg b/.gitbook/assets/food-irradiation/collect_2.jpg new file mode 100644 index 00000000..e9c0482a Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_2.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_3.jpg b/.gitbook/assets/food-irradiation/collect_3.jpg new file mode 100644 index 00000000..533b9faf Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_3.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_4.jpg b/.gitbook/assets/food-irradiation/collect_4.jpg new file mode 100644 index 00000000..0ce8a40f Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_4.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_5.jpg b/.gitbook/assets/food-irradiation/collect_5.jpg new file mode 100644 index 00000000..987a9a53 Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_5.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_6.jpg b/.gitbook/assets/food-irradiation/collect_6.jpg new file mode 100644 index 00000000..2a55f1cd Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_6.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_7.jpg b/.gitbook/assets/food-irradiation/collect_7.jpg new file mode 100644 index 00000000..b3da7a53 Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_7.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_8.jpg b/.gitbook/assets/food-irradiation/collect_8.jpg new file mode 100644 index 00000000..257522d9 Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_8.jpg differ diff --git a/.gitbook/assets/food-irradiation/collect_9.jpg b/.gitbook/assets/food-irradiation/collect_9.jpg new file mode 100644 index 00000000..70522230 Binary files /dev/null and b/.gitbook/assets/food-irradiation/collect_9.jpg differ diff --git a/.gitbook/assets/food-irradiation/connections_1.jpg b/.gitbook/assets/food-irradiation/connections_1.jpg new file mode 100644 index 00000000..b6ea96a9 Binary files /dev/null and b/.gitbook/assets/food-irradiation/connections_1.jpg differ diff --git a/.gitbook/assets/food-irradiation/connections_2.jpg b/.gitbook/assets/food-irradiation/connections_2.jpg new file mode 100644 index 00000000..690c19cf Binary files /dev/null and b/.gitbook/assets/food-irradiation/connections_2.jpg differ diff --git a/.gitbook/assets/food-irradiation/connections_3.jpg b/.gitbook/assets/food-irradiation/connections_3.jpg new file mode 100644 index 00000000..3ab67e9b Binary files /dev/null and b/.gitbook/assets/food-irradiation/connections_3.jpg differ diff --git a/.gitbook/assets/food-irradiation/connections_4.jpg b/.gitbook/assets/food-irradiation/connections_4.jpg new file mode 100644 index 00000000..4c678e5b Binary files /dev/null and b/.gitbook/assets/food-irradiation/connections_4.jpg differ diff --git a/.gitbook/assets/food-irradiation/connections_5.jpg b/.gitbook/assets/food-irradiation/connections_5.jpg new file mode 100644 index 00000000..274afe1e Binary files /dev/null and b/.gitbook/assets/food-irradiation/connections_5.jpg differ diff --git a/.gitbook/assets/food-irradiation/connections_6.jpg b/.gitbook/assets/food-irradiation/connections_6.jpg new file mode 100644 index 00000000..2b91945b Binary files /dev/null and b/.gitbook/assets/food-irradiation/connections_6.jpg differ diff --git a/.gitbook/assets/food-irradiation/connections_7.jpg b/.gitbook/assets/food-irradiation/connections_7.jpg new file mode 100644 index 00000000..c444a86d Binary files /dev/null and b/.gitbook/assets/food-irradiation/connections_7.jpg differ diff --git a/.gitbook/assets/food-irradiation/connections_8.jpg b/.gitbook/assets/food-irradiation/connections_8.jpg new file mode 100644 index 00000000..3a34ec02 Binary files /dev/null and b/.gitbook/assets/food-irradiation/connections_8.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_1.jpg b/.gitbook/assets/food-irradiation/cr_200b_set_1.jpg new file mode 100644 index 00000000..31698313 Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_1.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_2.jpg b/.gitbook/assets/food-irradiation/cr_200b_set_2.jpg new file mode 100644 index 00000000..02cfc383 Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_2.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_3.jpg b/.gitbook/assets/food-irradiation/cr_200b_set_3.jpg new file mode 100644 index 00000000..b134c922 Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_3.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_4.jpg b/.gitbook/assets/food-irradiation/cr_200b_set_4.jpg new file mode 100644 index 00000000..df3c6412 Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_4.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_5.jpg b/.gitbook/assets/food-irradiation/cr_200b_set_5.jpg new file mode 100644 index 00000000..a55f21e1 Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_5.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_6.jpg b/.gitbook/assets/food-irradiation/cr_200b_set_6.jpg new file mode 100644 index 00000000..20cfed98 Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_6.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_7.jpg b/.gitbook/assets/food-irradiation/cr_200b_set_7.jpg new file mode 100644 index 00000000..1fdd8814 Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_7.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_8.jpg b/.gitbook/assets/food-irradiation/cr_200b_set_8.jpg new file mode 100644 index 00000000..585b344a Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_8.jpg differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_cura_1.PNG b/.gitbook/assets/food-irradiation/cr_200b_set_cura_1.PNG new file mode 100644 index 00000000..065de0c5 Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_cura_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/cr_200b_set_cura_2.PNG b/.gitbook/assets/food-irradiation/cr_200b_set_cura_2.PNG new file mode 100644 index 00000000..bb72106c Binary files /dev/null and b/.gitbook/assets/food-irradiation/cr_200b_set_cura_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/data_create_1.PNG b/.gitbook/assets/food-irradiation/data_create_1.PNG new file mode 100644 index 00000000..a239a74b Binary files /dev/null and b/.gitbook/assets/food-irradiation/data_create_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/data_create_2.PNG b/.gitbook/assets/food-irradiation/data_create_2.PNG new file mode 100644 index 00000000..122f2268 Binary files /dev/null and b/.gitbook/assets/food-irradiation/data_create_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/data_create_3.PNG b/.gitbook/assets/food-irradiation/data_create_3.PNG new file mode 100644 index 00000000..5b255f33 Binary files /dev/null and b/.gitbook/assets/food-irradiation/data_create_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/data_create_4.PNG b/.gitbook/assets/food-irradiation/data_create_4.PNG new file mode 100644 index 00000000..fabb85c1 Binary files /dev/null and b/.gitbook/assets/food-irradiation/data_create_4.PNG differ diff --git a/.gitbook/assets/food-irradiation/data_create_5.PNG b/.gitbook/assets/food-irradiation/data_create_5.PNG new file mode 100644 index 00000000..f4fa3747 Binary files /dev/null and b/.gitbook/assets/food-irradiation/data_create_5.PNG differ diff --git a/.gitbook/assets/food-irradiation/database_settings.png b/.gitbook/assets/food-irradiation/database_settings.png new file mode 100644 index 00000000..09a5c8d4 Binary files /dev/null and b/.gitbook/assets/food-irradiation/database_settings.png differ diff --git a/.gitbook/assets/food-irradiation/dataset_1.PNG b/.gitbook/assets/food-irradiation/dataset_1.PNG new file mode 100644 index 00000000..2d9b4d8d Binary files /dev/null and b/.gitbook/assets/food-irradiation/dataset_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/dataset_2.PNG b/.gitbook/assets/food-irradiation/dataset_2.PNG new file mode 100644 index 00000000..796877c9 Binary files /dev/null and b/.gitbook/assets/food-irradiation/dataset_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/dataset_3.PNG b/.gitbook/assets/food-irradiation/dataset_3.PNG new file mode 100644 index 00000000..955a53f7 Binary files /dev/null and b/.gitbook/assets/food-irradiation/dataset_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/dataset_4.PNG b/.gitbook/assets/food-irradiation/dataset_4.PNG new file mode 100644 index 00000000..7b8af294 Binary files /dev/null and b/.gitbook/assets/food-irradiation/dataset_4.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_deploy_1.PNG b/.gitbook/assets/food-irradiation/edge_deploy_1.PNG new file mode 100644 index 00000000..a8186ed3 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_deploy_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_deploy_2.PNG b/.gitbook/assets/food-irradiation/edge_deploy_2.PNG new file mode 100644 index 00000000..9c79e3fb Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_deploy_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_deploy_3.PNG b/.gitbook/assets/food-irradiation/edge_deploy_3.PNG new file mode 100644 index 00000000..81b655c0 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_deploy_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_set_1.PNG b/.gitbook/assets/food-irradiation/edge_set_1.PNG new file mode 100644 index 00000000..fba2985a Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_set_2.png b/.gitbook/assets/food-irradiation/edge_set_2.png new file mode 100644 index 00000000..ea7ec0a8 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_2.png differ diff --git a/.gitbook/assets/food-irradiation/edge_set_3.png b/.gitbook/assets/food-irradiation/edge_set_3.png new file mode 100644 index 00000000..d0fbaff8 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_3.png differ diff --git a/.gitbook/assets/food-irradiation/edge_set_4.PNG b/.gitbook/assets/food-irradiation/edge_set_4.PNG new file mode 100644 index 00000000..188e1295 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_4.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_set_5.PNG b/.gitbook/assets/food-irradiation/edge_set_5.PNG new file mode 100644 index 00000000..20c80059 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_5.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_set_6.PNG b/.gitbook/assets/food-irradiation/edge_set_6.PNG new file mode 100644 index 00000000..7aa3ec20 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_6.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_set_7.PNG b/.gitbook/assets/food-irradiation/edge_set_7.PNG new file mode 100644 index 00000000..a9fb2098 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_7.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_set_8.PNG b/.gitbook/assets/food-irradiation/edge_set_8.PNG new file mode 100644 index 00000000..41244e57 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_8.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_set_9.PNG b/.gitbook/assets/food-irradiation/edge_set_9.PNG new file mode 100644 index 00000000..60b4f6a4 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_set_9.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_test_1.PNG b/.gitbook/assets/food-irradiation/edge_test_1.PNG new file mode 100644 index 00000000..318d0614 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_test_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_test_2.PNG b/.gitbook/assets/food-irradiation/edge_test_2.PNG new file mode 100644 index 00000000..3dd202aa Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_test_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_test_3.PNG b/.gitbook/assets/food-irradiation/edge_test_3.PNG new file mode 100644 index 00000000..be8f12f3 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_test_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_train_1.PNG b/.gitbook/assets/food-irradiation/edge_train_1.PNG new file mode 100644 index 00000000..46d78859 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_train_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_train_2.PNG b/.gitbook/assets/food-irradiation/edge_train_2.PNG new file mode 100644 index 00000000..aae8934e Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_train_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_train_3.PNG b/.gitbook/assets/food-irradiation/edge_train_3.PNG new file mode 100644 index 00000000..db1d68d5 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_train_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_train_4.PNG b/.gitbook/assets/food-irradiation/edge_train_4.PNG new file mode 100644 index 00000000..3ea68665 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_train_4.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_train_5.PNG b/.gitbook/assets/food-irradiation/edge_train_5.PNG new file mode 100644 index 00000000..6e921cea Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_train_5.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_train_6.PNG b/.gitbook/assets/food-irradiation/edge_train_6.PNG new file mode 100644 index 00000000..d41b711a Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_train_6.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_train_7.PNG b/.gitbook/assets/food-irradiation/edge_train_7.PNG new file mode 100644 index 00000000..faa991e1 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_train_7.PNG differ diff --git a/.gitbook/assets/food-irradiation/edge_train_8.PNG b/.gitbook/assets/food-irradiation/edge_train_8.PNG new file mode 100644 index 00000000..37b46fd2 Binary files /dev/null and b/.gitbook/assets/food-irradiation/edge_train_8.PNG differ diff --git a/.gitbook/assets/food-irradiation/espC3_set_1.png b/.gitbook/assets/food-irradiation/espC3_set_1.png new file mode 100644 index 00000000..b63b541c Binary files /dev/null and b/.gitbook/assets/food-irradiation/espC3_set_1.png differ diff --git a/.gitbook/assets/food-irradiation/espC3_set_2.png b/.gitbook/assets/food-irradiation/espC3_set_2.png new file mode 100644 index 00000000..35218840 Binary files /dev/null and b/.gitbook/assets/food-irradiation/espC3_set_2.png differ diff --git a/.gitbook/assets/food-irradiation/espC3_set_3.png b/.gitbook/assets/food-irradiation/espC3_set_3.png new file mode 100644 index 00000000..6c447556 Binary files /dev/null and b/.gitbook/assets/food-irradiation/espC3_set_3.png differ diff --git a/.gitbook/assets/food-irradiation/espC3_set_4.png b/.gitbook/assets/food-irradiation/espC3_set_4.png new file mode 100644 index 00000000..a08ba610 Binary files /dev/null and b/.gitbook/assets/food-irradiation/espC3_set_4.png differ diff --git a/.gitbook/assets/food-irradiation/espC3_set_5.png b/.gitbook/assets/food-irradiation/espC3_set_5.png new file mode 100644 index 00000000..1c2e2ffe Binary files /dev/null and b/.gitbook/assets/food-irradiation/espC3_set_5.png differ diff --git a/.gitbook/assets/food-irradiation/espC3_set_6.png b/.gitbook/assets/food-irradiation/espC3_set_6.png new file mode 100644 index 00000000..29494412 Binary files /dev/null and b/.gitbook/assets/food-irradiation/espC3_set_6.png differ diff --git a/.gitbook/assets/food-irradiation/finished_1.jpg b/.gitbook/assets/food-irradiation/finished_1.jpg new file mode 100644 index 00000000..432801c2 Binary files /dev/null and b/.gitbook/assets/food-irradiation/finished_1.jpg differ diff --git a/.gitbook/assets/food-irradiation/finished_2.jpg b/.gitbook/assets/food-irradiation/finished_2.jpg new file mode 100644 index 00000000..b6d155d6 Binary files /dev/null and b/.gitbook/assets/food-irradiation/finished_2.jpg differ diff --git a/.gitbook/assets/food-irradiation/gif_data_collect.gif b/.gitbook/assets/food-irradiation/gif_data_collect.gif new file mode 100644 index 00000000..229098ea Binary files /dev/null and b/.gitbook/assets/food-irradiation/gif_data_collect.gif differ diff --git a/.gitbook/assets/food-irradiation/gif_run_model.gif b/.gitbook/assets/food-irradiation/gif_run_model.gif new file mode 100644 index 00000000..7f9c8c00 Binary files /dev/null and b/.gitbook/assets/food-irradiation/gif_run_model.gif differ diff --git a/.gitbook/assets/food-irradiation/home.gif b/.gitbook/assets/food-irradiation/home.gif new file mode 100644 index 00000000..6591f2a0 Binary files /dev/null and b/.gitbook/assets/food-irradiation/home.gif differ diff --git a/.gitbook/assets/food-irradiation/home_1.jpg b/.gitbook/assets/food-irradiation/home_1.jpg new file mode 100644 index 00000000..68a09bb9 Binary files /dev/null and b/.gitbook/assets/food-irradiation/home_1.jpg differ diff --git a/.gitbook/assets/food-irradiation/home_2.jpg b/.gitbook/assets/food-irradiation/home_2.jpg new file mode 100644 index 00000000..3ea73c14 Binary files /dev/null and b/.gitbook/assets/food-irradiation/home_2.jpg differ diff --git a/.gitbook/assets/food-irradiation/hostname.png b/.gitbook/assets/food-irradiation/hostname.png new file mode 100644 index 00000000..089b1dc9 Binary files /dev/null and b/.gitbook/assets/food-irradiation/hostname.png differ diff --git a/.gitbook/assets/food-irradiation/img_convert_1.png b/.gitbook/assets/food-irradiation/img_convert_1.png new file mode 100644 index 00000000..fda64d63 Binary files /dev/null and b/.gitbook/assets/food-irradiation/img_convert_1.png differ diff --git a/.gitbook/assets/food-irradiation/img_convert_2.png b/.gitbook/assets/food-irradiation/img_convert_2.png new file mode 100644 index 00000000..dfc6905d Binary files /dev/null and b/.gitbook/assets/food-irradiation/img_convert_2.png differ diff --git a/.gitbook/assets/food-irradiation/img_convert_3.png b/.gitbook/assets/food-irradiation/img_convert_3.png new file mode 100644 index 00000000..d61e4f89 Binary files /dev/null and b/.gitbook/assets/food-irradiation/img_convert_3.png differ diff --git a/.gitbook/assets/food-irradiation/img_convert_4.png b/.gitbook/assets/food-irradiation/img_convert_4.png new file mode 100644 index 00000000..93098399 Binary files /dev/null and b/.gitbook/assets/food-irradiation/img_convert_4.png differ diff --git a/.gitbook/assets/food-irradiation/img_convert_5.png b/.gitbook/assets/food-irradiation/img_convert_5.png new file mode 100644 index 00000000..4b36236a Binary files /dev/null and b/.gitbook/assets/food-irradiation/img_convert_5.png differ diff --git a/.gitbook/assets/food-irradiation/img_convert_6.png b/.gitbook/assets/food-irradiation/img_convert_6.png new file mode 100644 index 00000000..0b5cb161 Binary files /dev/null and b/.gitbook/assets/food-irradiation/img_convert_6.png differ diff --git a/.gitbook/assets/food-irradiation/localhost.png b/.gitbook/assets/food-irradiation/localhost.png new file mode 100644 index 00000000..1cf73bfc Binary files /dev/null and b/.gitbook/assets/food-irradiation/localhost.png differ diff --git a/.gitbook/assets/food-irradiation/model_1.PNG b/.gitbook/assets/food-irradiation/model_1.PNG new file mode 100644 index 00000000..40a6b58a Binary files /dev/null and b/.gitbook/assets/food-irradiation/model_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/model_2.PNG b/.gitbook/assets/food-irradiation/model_2.PNG new file mode 100644 index 00000000..c19cc8e7 Binary files /dev/null and b/.gitbook/assets/food-irradiation/model_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/model_3.PNG b/.gitbook/assets/food-irradiation/model_3.PNG new file mode 100644 index 00000000..a05caa50 Binary files /dev/null and b/.gitbook/assets/food-irradiation/model_3.PNG differ diff --git a/.gitbook/assets/food-irradiation/model_4.PNG b/.gitbook/assets/food-irradiation/model_4.PNG new file mode 100644 index 00000000..bdb44365 Binary files /dev/null and b/.gitbook/assets/food-irradiation/model_4.PNG differ diff --git a/.gitbook/assets/food-irradiation/model_5.PNG b/.gitbook/assets/food-irradiation/model_5.PNG new file mode 100644 index 00000000..ca9e394f Binary files /dev/null and b/.gitbook/assets/food-irradiation/model_5.PNG differ diff --git a/.gitbook/assets/food-irradiation/model_6.PNG b/.gitbook/assets/food-irradiation/model_6.PNG new file mode 100644 index 00000000..145e7827 Binary files /dev/null and b/.gitbook/assets/food-irradiation/model_6.PNG differ diff --git a/.gitbook/assets/food-irradiation/model_7.PNG b/.gitbook/assets/food-irradiation/model_7.PNG new file mode 100644 index 00000000..1ef401a0 Binary files /dev/null and b/.gitbook/assets/food-irradiation/model_7.PNG differ diff --git a/.gitbook/assets/food-irradiation/model_8.PNG b/.gitbook/assets/food-irradiation/model_8.PNG new file mode 100644 index 00000000..2df789d3 Binary files /dev/null and b/.gitbook/assets/food-irradiation/model_8.PNG differ diff --git a/.gitbook/assets/food-irradiation/mysql.png b/.gitbook/assets/food-irradiation/mysql.png new file mode 100644 index 00000000..b7c3ca61 Binary files /dev/null and b/.gitbook/assets/food-irradiation/mysql.png differ diff --git a/.gitbook/assets/food-irradiation/php.png b/.gitbook/assets/food-irradiation/php.png new file mode 100644 index 00000000..db421086 Binary files /dev/null and b/.gitbook/assets/food-irradiation/php.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_set_1.png b/.gitbook/assets/food-irradiation/rasp_app_set_1.png new file mode 100644 index 00000000..ae1fb997 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_set_1.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_set_2.png b/.gitbook/assets/food-irradiation/rasp_app_set_2.png new file mode 100644 index 00000000..ee1e6fce Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_set_2.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_set_3.png b/.gitbook/assets/food-irradiation/rasp_app_set_3.png new file mode 100644 index 00000000..9780b589 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_set_3.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_1.png b/.gitbook/assets/food-irradiation/rasp_app_work_1.png new file mode 100644 index 00000000..a133ab22 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_1.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_10.png b/.gitbook/assets/food-irradiation/rasp_app_work_10.png new file mode 100644 index 00000000..3ee3a3c9 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_10.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_2.png b/.gitbook/assets/food-irradiation/rasp_app_work_2.png new file mode 100644 index 00000000..f0144855 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_2.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_3.png b/.gitbook/assets/food-irradiation/rasp_app_work_3.png new file mode 100644 index 00000000..6b0a06b1 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_3.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_4.png b/.gitbook/assets/food-irradiation/rasp_app_work_4.png new file mode 100644 index 00000000..8f8f2076 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_4.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_5.png b/.gitbook/assets/food-irradiation/rasp_app_work_5.png new file mode 100644 index 00000000..0b8a2ffb Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_5.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_6.png b/.gitbook/assets/food-irradiation/rasp_app_work_6.png new file mode 100644 index 00000000..897d3209 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_6.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_7.png b/.gitbook/assets/food-irradiation/rasp_app_work_7.png new file mode 100644 index 00000000..a93a1d73 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_7.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_8.png b/.gitbook/assets/food-irradiation/rasp_app_work_8.png new file mode 100644 index 00000000..a24410d1 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_8.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_app_work_9.png b/.gitbook/assets/food-irradiation/rasp_app_work_9.png new file mode 100644 index 00000000..3289910f Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_app_work_9.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_database.png b/.gitbook/assets/food-irradiation/rasp_database.png new file mode 100644 index 00000000..cef8d7b3 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_database.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_php_ini.png b/.gitbook/assets/food-irradiation/rasp_php_ini.png new file mode 100644 index 00000000..c5d7e61e Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_php_ini.png differ diff --git a/.gitbook/assets/food-irradiation/rasp_zip_lib.png b/.gitbook/assets/food-irradiation/rasp_zip_lib.png new file mode 100644 index 00000000..6303d3c0 Binary files /dev/null and b/.gitbook/assets/food-irradiation/rasp_zip_lib.png differ diff --git a/.gitbook/assets/food-irradiation/run_model_1.jpg b/.gitbook/assets/food-irradiation/run_model_1.jpg new file mode 100644 index 00000000..b3b290b0 Binary files /dev/null and b/.gitbook/assets/food-irradiation/run_model_1.jpg differ diff --git a/.gitbook/assets/food-irradiation/run_model_2.jpg b/.gitbook/assets/food-irradiation/run_model_2.jpg new file mode 100644 index 00000000..923e75b8 Binary files /dev/null and b/.gitbook/assets/food-irradiation/run_model_2.jpg differ diff --git a/.gitbook/assets/food-irradiation/run_model_3.jpg b/.gitbook/assets/food-irradiation/run_model_3.jpg new file mode 100644 index 00000000..f5d2896b Binary files /dev/null and b/.gitbook/assets/food-irradiation/run_model_3.jpg differ diff --git a/.gitbook/assets/food-irradiation/run_model_4.jpg b/.gitbook/assets/food-irradiation/run_model_4.jpg new file mode 100644 index 00000000..d2bd827f Binary files /dev/null and b/.gitbook/assets/food-irradiation/run_model_4.jpg differ diff --git a/.gitbook/assets/food-irradiation/run_model_5.jpg b/.gitbook/assets/food-irradiation/run_model_5.jpg new file mode 100644 index 00000000..3069a475 Binary files /dev/null and b/.gitbook/assets/food-irradiation/run_model_5.jpg differ diff --git a/.gitbook/assets/food-irradiation/serial_collect_1.PNG b/.gitbook/assets/food-irradiation/serial_collect_1.PNG new file mode 100644 index 00000000..16dfcda6 Binary files /dev/null and b/.gitbook/assets/food-irradiation/serial_collect_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/serial_collect_2.PNG b/.gitbook/assets/food-irradiation/serial_collect_2.PNG new file mode 100644 index 00000000..1d12699f Binary files /dev/null and b/.gitbook/assets/food-irradiation/serial_collect_2.PNG differ diff --git a/.gitbook/assets/food-irradiation/serial_error.PNG b/.gitbook/assets/food-irradiation/serial_error.PNG new file mode 100644 index 00000000..14ccbf92 Binary files /dev/null and b/.gitbook/assets/food-irradiation/serial_error.PNG differ diff --git a/.gitbook/assets/food-irradiation/serial_run_1.PNG b/.gitbook/assets/food-irradiation/serial_run_1.PNG new file mode 100644 index 00000000..d3f527ee Binary files /dev/null and b/.gitbook/assets/food-irradiation/serial_run_1.PNG differ diff --git a/.gitbook/assets/food-irradiation/serial_run_2.PNG b/.gitbook/assets/food-irradiation/serial_run_2.PNG new file mode 100644 index 00000000..334865f4 Binary files /dev/null and b/.gitbook/assets/food-irradiation/serial_run_2.PNG differ diff --git a/README.md b/README.md index 9e530358..0a15afd5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ # Welcome -This is the landing page for [docs.edgeimpulse.com/experts/](https://app.gitbook.com/o/sFuY9TdTT07QHwgM7yVS/s/EJB5OaeYjM5VSFEKLEFz/) +These Docs contain all of the Projects built by the Edge Impulse Expert Network. + +There are computer vision, audio classification, anomaly detection, gesture recognition, robotics, environmental and spacial awareness and more, covering a wide variety of hardware, sensors, and devices. + +As you browse the projects, be sure to make note that many of them could be adapted to use other hardware targets, sensors, or add-ons. If you have any questions, simply let us know over on the [Forums](https://forum.edgeimpulse.com/) + diff --git a/SUMMARY.md b/SUMMARY.md index 23c29870..f644b521 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -4,6 +4,7 @@ * [Workplace Organizer with NVIDIA Jetson Nano](workplace-organizer.md) * [Recyclable Materials Sorter with NVIDIA Jetson Nano](recyclable-materials-sorter.md) +* [Predictive Maintenance with Nordic Thingy:91](predictive-maintenance-with-nordic-thingy-91.md) * [Cyclist Blind Spot Detection](cyclist-blind-spot-detection.md) * [Shield Bot Autonomous Security Robot](shieldbot.md) * [ROS2 + Edge Impulse, Part 1: Pub/Sub Node in Python](ros2-part1-pubsub-node.md) @@ -16,3 +17,4 @@ * [8x8 ToF Gesture Classification](tof-gesture-classification.md) * [Detecting Worker Accidents with Audio Classification](detecting-worker-accidents-with-ai.md) * [IV Drip Fluid-Level Monitoring](iv-drip-fluid-level-monitoring.md) +* [Food Irradiation Dose Detection](food-irradiation-detection.md) diff --git a/food-irradiation-detection.md b/food-irradiation-detection.md new file mode 100644 index 00000000..ce46777e --- /dev/null +++ b/food-irradiation-detection.md @@ -0,0 +1,1588 @@ +--- +description: Building a Food Irradiation detection device using a DFRobot ESP32, Geiger Counter, and Visible Light sensor. +--- + +# Food Irradiation Dose Detection with a DFRobot Beetle C3 + +Created By: +Kutluhan Aktar + +Public Project Link: +[https://studio.edgeimpulse.com/public/109647/latest](https://studio.edgeimpulse.com/public/109647/latest) + +![](.gitbook/assets/food-irradiation/collect_2.jpg) + +## Description + +Even though food irradiation improves food hygiene, spoilage reduction, and extension of shelf-life, it should be regulated strictly to avoid any health risks and nutritional value drops. However, small businesses in the food industry lack a budget-friendly and simple way to detect food irradiation doses after treating food with ionizing energy, especially for animal (livestock) feed. Therefore, I decided to build an AI-driven IoT device predicting food irradiation doses based on weight, color (visible light), and emitted ionizing radiation. + +Ionizing radiation is a nonthermal process utilized to achieve the preservation of food. At a maximum commercial irradiation dose of 10 kGy, irradiation does not impart heat to the food, and the nutritional quality of the food is generally unaffected. The irradiation process can reduce the microbial contamination of food, resulting in improved microbial safety as well as the extended shelf-life of the food[^1]. Irradiation also benefits the consumer by reducing the risk of severe health issues caused by foodborne illnesses. Food irradiation has three categories: low-dose (radurization), medium-dose (radicidation), and high-dose (radappertization). Low dose irradiation (under 1 kGy) inhibits the sprouting of produce (onion, potato, and garlic); retards the ripening and fungi deterioration of fruits and vegetables (strawberry, tomato, etc.), and promotes insect disinfestations in cereals and vegetables. Medium dose irradiation (between 1 and 10 kGy) controls the presence of pathogenic organisms, especially in fruit juices; retards the deterioration of fish and fresh meat; and reduces Salmonella in poultry products, similar to pasteurization. High dose irradiation (over 10 kGy) is rather significant to the sterilization of health and personal hygiene products[^2]. + +Since foods treated with ionizing radiation should be adequately labeled under the general labeling requirements, consumers can make their own free choice between irradiated and non-irradiated food. However, unfortunately, some countries do not apply strict regulations for irradiated foods, especially for animal feed. Therefore, detecting proper irradiation doses can be arduous for small businesses in the food industry due to governments not incentivizing strictly regulated food irradiation processes. Since irradiation can engender certain alterations that can modify the chemical composition and nutritive values of food, depending on the factors such as irradiation dose, food composition, packaging, and processing conditions such as temperature and atmospheric oxygen saturation[^2], unsupervised food irradiation portends health issues. + +After scrutinizing recent research papers on food irradiation, I decided to utilize ionizing radiation, weight, and visible light (color) measurements denoting the applied irradiation dose so as to create a budget-friendly and accessible device to predict food irradiation dose levels in the hope of assisting small businesses in checking compliance with existing regulations on food irradiation. + +Although ionizing radiation, weight, and visible light (color) measurements provide insight into detecting food irradiation doses, it is not possible to conclude and interpret food irradiation doses precisely by merely employing limited data without applying complex algorithms since food irradiation dose levels fluctuate depending on processing techniques, food characteristics, and equipment. Therefore, I decided to build and train an artificial neural network model by utilizing the theoretically assigned food irradiation dose classes to predict food irradiation dose levels based on ionizing radiation, weight, and visible light (color) measurements. Since I could not apply ionizing radiation directly to foods by emitting Gamma rays, X-rays, or electron beams, I exposed foods to sun rays as a natural source of radiation for estimated periods. + +Since Beetle ESP32-C3 is an ultra-small size development board intended for IoT applications, that can easily collect data and run my neural network model after being trained to predict food irradiation doses, I decided to employ Beetle ESP32-C3 in this project. To obtain the required measurements to train my model, I utilized a Geiger counter module (Gravity), an I2C weight sensor (Gravity), and an AS7341 11-channel visible light sensor (Gravity). Since Beetle ESP32-C3 is equipped with an expansion board providing the GDI display interface, I connected an SSD1309 OLED transparent screen (Fermion) to display the collected data. + +After collecting data successfully, I developed a PHP web application that obtains the transmitted data from Beetle ESP32-C3 via HTTP GET requests, logs the received measurements in a given MySQL database table, and lets the user create appropriately formatted samples for Edge Impulse. + +After completing my data set and creating samples, I built my artificial neural network model (ANN) with Edge Impulse to make predictions on food irradiation dose levels (classes) based on ionizing radiation, weight, and visible light (color) measurements. Since Edge Impulse is nearly compatible with all microcontrollers and development boards, I had not encountered any issues while uploading and running my model on Beetle ESP32-C3. As labels, I employed the theoretically assigned food irradiation dose classes for each data record while collecting and logging data: + +- Regulated +- Unsafe +- Hazardous + +After training and testing my neural network model, I deployed and uploaded the model on Beetle ESP32-C3. Therefore, the device is capable of detecting precise food irradiation dose levels (classes) by running the model independently without any additional procedures. + +Lastly, to make the device as robust and compact as possible while experimenting with a motley collection of foods, I designed a Hulk-inspired structure with a moveable visible light sensor handle (3D printable). + +So, this is my project in a nutshell 😃 + +In the following steps, you can find more detailed information on coding, logging data via a web application, building a neural network model with Edge Impulse, and running it on Beetle ESP32-C3. + +:gift::art: Huge thanks to [DFRobot](https://www.dfrobot.com/?tracking=60f546f8002be) for sponsoring these products: + +:star: Beetle ESP32-C3 | [Inspect](https://www.dfrobot.com/product-2566.html?tracking=60f546f8002be) + +:star: Gravity: Geiger Counter Module | [Inspect](https://www.dfrobot.com/product-2547.html?tracking=60f546f8002be) + +:star: Gravity: I2C 1Kg Weight Sensor Kit | [Inspect](https://www.dfrobot.com/product-2289.html?tracking=60f546f8002be) + +:star: Gravity: AS7341 11-Channel Visible Light Sensor | [Inspect](https://www.dfrobot.com/product-2131.html?tracking=60f546f8002be) + +:star: Fermion: 1.51” OLED Transparent Display | [Inspect](https://www.dfrobot.com/product-2521.html?tracking=60f546f8002be) + +:gift::art: If you want to purchase products from DFRobot, you can use [my $5 discount coupon](https://www.dfrobot.com/coupon-117.html). + +:gift::art: Also, huge thanks to [Creality](https://store.creality.com/) for sending me a [Creality CR-200B 3D Printer](https://www.creality.com/products/cr-200b-3d-printer). + +![image](.gitbook/assets/food-irradiation/home_1.jpg) + +![image](.gitbook/assets/food-irradiation/collect_2.jpg) + +![image](.gitbook/assets/food-irradiation/collect_4.jpg) + +![image](.gitbook/assets/food-irradiation/gif_data_collect.gif) + +![image](.gitbook/assets/food-irradiation/run_model_4.jpg) + +![image](.gitbook/assets/food-irradiation/gif_run_model.gif) + +![image](.gitbook/assets/food-irradiation/data_create_4.PNG) + +## Step 1: Designing and printing a Hulk-inspired structure + +Since this project is for detecting irradiation doses of foods treated with ionizing radiation, I got inspired by the most prominent fictional Gamma radiation expert, Bruce Banner (aka, The Incredible Hulk), to design a unique structure so as to create a robust and compact device flawlessly operating while collecting data from foods. To collect data with the visible light sensor at different angles, I added a moveable handle to the structure, including a slot and a hook for hanging the sensor. + +I designed the structure and its moveable handle in Autodesk Fusion 360. You can download their STL files below. + +![image](.gitbook/assets/food-irradiation/model_1.PNG) + +![image](.gitbook/assets/food-irradiation/model_2.PNG) + +![image](.gitbook/assets/food-irradiation/model_3.PNG) + +![image](.gitbook/assets/food-irradiation/model_4.PNG) + +![image](.gitbook/assets/food-irradiation/model_5.PNG) + +For the Hulk replica affixed to the top of the structure, I utilized this model from Thingiverse: + +- [Hulk](https://www.thingiverse.com/thing:993933) + +Then, I sliced all 3D models (STL files) in Ultimaker Cura. + +![image](.gitbook/assets/food-irradiation/model_6.PNG) + +![image](.gitbook/assets/food-irradiation/model_7.PNG) + +![image](.gitbook/assets/food-irradiation/model_8.PNG) + +Since I wanted to create a solid structure for this device with a moveable handle and complement the Hulk theme gloriously, I utilized these PLA filaments: + +- eMarble Natural +- Peak Green + +Finally, I printed all parts (models) with my Creality CR-200B 3D Printer. It is my first fully-enclosed FDM 3D printer, and I must say that I got excellent prints effortlessly with the CR-200B :) + +If you are a maker planning to print your 3D models to create more complex projects, I highly recommend the CR-200B. Since the CR-200B is fully-enclosed, you can print high-resolution 3D models with PLA and ABS filaments. Also, it has a smart filament runout sensor and the resume printing option for power failures. + +According to my experience, there are only two downsides of the CR-200B: relatively small build size (200 x 200 x 200 mm) and manual leveling. Conversely, thanks to the large leveling nuts and assisted leveling, I was able to level the bed and start printing my first model in less than 30 minutes. + +:hash: Before the first use, remove unnecessary cable ties and apply grease to the rails. + +![image](.gitbook/assets/food-irradiation/cr_200b_set_1.jpg) + +![image](.gitbook/assets/food-irradiation/cr_200b_set_2.jpg) + +:hash: Test the nozzle and hot bed temperatures. + +![image](.gitbook/assets/food-irradiation/cr_200b_set_3.jpg) + +:hash: Go to *Settings ➡ Leveling* and adjust four predefined points by utilizing the leveling nuts. + +![image](.gitbook/assets/food-irradiation/cr_200b_set_4.jpg) + +![image](.gitbook/assets/food-irradiation/cr_200b_set_5.jpg) + +![image](.gitbook/assets/food-irradiation/cr_200b_set_6.jpg) + +![image](.gitbook/assets/food-irradiation/cr_200b_set_7.jpg) + +:hash: Finally, attach the spool holder and feed the extruder with the filament. + +![image](.gitbook/assets/food-irradiation/cr_200b_set_8.jpg) + +:hash: Since the CR-200B is not officially supported by Cura, select the Ender-3 profile and change the build size to 200 x 200 x 200 mm. Also, to compensate for the nozzle placement, set the *Nozzle offset X* and *Y* values to -10 mm on the *Extruder 1* tab. + +![image](.gitbook/assets/food-irradiation/cr_200b_set_cura_1.PNG) + +![image](.gitbook/assets/food-irradiation/cr_200b_set_cura_2.PNG) + +## Step 1.1: Assembling the structure and making connections & adjustments + +``` +// Connections +// Beetle ESP32-C3 : +// Gravity: Geiger Counter Module +// D5 --------------------------- D +// VCC --------------------------- + +// GND --------------------------- - +// Gravity: I2C 1Kg Weight Sensor Kit - HX711 +// VCC --------------------------- VCC +// GND --------------------------- GND +// D9 --------------------------- SCL +// D8 --------------------------- SDA +// Fermion: 1.51” SSD1309 OLED Transparent Display +// D4 --------------------------- SCLK +// D6 --------------------------- MOSI +// D7 --------------------------- CS +// D2 --------------------------- RES +// D1 --------------------------- DC +// AS7341 11-Channel Spectral Color Sensor +// VCC --------------------------- + +// GND --------------------------- - +// D9 --------------------------- C +// D8 --------------------------- D +// Control Button (A) +// D0 --------------------------- + +// Control Button (B) +// D20 --------------------------- + +// Control Button (C) +// D21 --------------------------- + +``` + +First of all, I soldered male pin headers to [Beetle ESP32-C3](https://wiki.dfrobot.com/SKU_DFR0868_Beetle_ESP32_C3) and its expansion board. + +![image](.gitbook/assets/food-irradiation/assembly_1.jpg) + +Then, to collect ionizing radiation, weight, and color (visible light) measurements, I connected a Geiger counter module (Gravity), an I2C HX711 weight sensor (Gravity), and an AS7341 11-channel visible light sensor (Gravity) to Beetle ESP32-C3. Since the expansion board provides the GDI display interface for DFRobot screens, I was able to connect [the SSD1309 OLED transparent screen (Fermion)](https://wiki.dfrobot.com/SKU_DFR0934_Fermion_1.51Inch_128%C3%9764_OLED_Transparent_Display_with_Converter_Breakout) to Beetle ESP32-C3 via the expansion board. + +![image](.gitbook/assets/food-irradiation/assembly_2.jpg) + +After assembling [the weight sensor kit](https://wiki.dfrobot.com/HX711_Weight_Sensor_Kit_SKU_KIT0176), to calibrate the weight sensor in order to get accurate measurements, press the *cal* button on the adapter board. Then, wait for the indicator LED to turn on and place a 100 g (default value) object on the scale within 5 seconds. When the adapter board completes calibration, the indicator LED blinks three times. + +![image](.gitbook/assets/food-irradiation/assembly_3.jpg) + +![image](.gitbook/assets/food-irradiation/assembly_4.jpg) + +Since Beetle ESP32-C3 cannot power [the Geiger counter module](https://wiki.dfrobot.com/SKU_SEN0463_Gravity_Geiger_Counter_Module) and the weight sensor simultaneously due to its working current, I connected a USB buck-boost converter board to my Xiaomi power bank to elicit stable 3.3V to supply the sensors. + +Since the Geiger counter library needs to use an external interrupt pin for counting, the Geiger counter module can only be connected to external interrupt pins. Plausibly, Beetle ESP32-C3 allows the user to define any pin as an external interrupt. + +To assign labels while transmitting the collected data and run my neural network model effortlessly, I added three control buttons (6x6), as shown in the schematic below. + +After completing sensor connections and adjustments on breadboards successfully, I made the breadboard connection points rigid by utilizing a hot glue gun. + +![image](.gitbook/assets/food-irradiation/assembly_5.jpg) + +![image](.gitbook/assets/food-irradiation/assembly_6.jpg) + +After printing all parts (models), I fastened all components except the visible light sensor to their corresponding slots on the structure via the hot glue gun. + +Then, I attached the visible light sensor to the moveable handle and hung it via its slot in the structure. + +![image](.gitbook/assets/food-irradiation/connections_1.jpg) + +![image](.gitbook/assets/food-irradiation/connections_2.jpg) + +![image](.gitbook/assets/food-irradiation/connections_3.jpg) + +![image](.gitbook/assets/food-irradiation/connections_4.jpg) + +![image](.gitbook/assets/food-irradiation/connections_5.jpg) + +![image](.gitbook/assets/food-irradiation/connections_6.jpg) + +![image](.gitbook/assets/food-irradiation/connections_7.jpg) + +![image](.gitbook/assets/food-irradiation/connections_8.jpg) + +Finally, I affixed the Hulk replica to the top of the structure via the hot glue gun. + +![image](.gitbook/assets/food-irradiation/finished_1.jpg) + +![image](.gitbook/assets/food-irradiation/finished_2.jpg) + +## Step 2: Developing a web application in PHP to collate data on food irradiation doses + +To be able to log and process data packets transmitted by Beetle ESP32-C3, I decided to develop a web application in PHP named *food_irradiation_data_logger*. + +As shown below, the web application consists of two folders and five files: + +- /assets +- - class.php +- - icon.png +- - index.css +- /data +- get_data.php +- index.php + +I also employed the web application to scale (normalize) and preprocess my data set so as to create appropriately formatted samples for Edge Impulse. + +If the data type is not time series, Edge Impulse requires a CSV file with a header indicating data fields per sample to upload data with CSV files. Since Edge Impulse can infer the uploaded sample's label from its file name, the application reads the given data set in the MySQL database and generate a CSV file (sample) for each data record, named according to the assigned food irradiation dose class. Also, the application utilizes the unique row number under the *id* data field as the sample number to identify each generated CSV file: + +- Regulated.training.sample_101.csv +- Unsafe.training.sample_542.csv +- Hazardous.training.sample_152.csv + +You can download and inspect the web application in the ZIP file format below. + +📁 *class.php* + +In the *class.php* file, in order to run all functions successfully, I created two classes named *_main* and *sample*: the latter inherits from the former. + +:star: Define the *_main* class and its functions: + +:star: In the *__init__* function, define the required variables for the MySQL database. + +``` + public function __init__($conn, $table){ + $this->conn = $conn; + $this->table = $table; + } +``` + +:star: In the *insert_new_data* function, append the given measurements and food irradiation dose class to the given database table. + +``` + public function insert_new_data($d1, $d2, $d3, $d4, $d5, $d6, $d7, $d8, $d9, $d10, $d11, $d12, $c){ + $sql = "INSERT INTO `$this->table`(`weight`, `f1`, `f2`, `f3`, `f4`, `f5`, `f6`, `f7`, `f8`, `cpm`, `nsv`, `usv`, `class`) VALUES ('$d1', '$d2', '$d3', '$d4', '$d5', '$d6', '$d7', '$d8', '$d9', '$d10', '$d11', '$d12', '$c')"; + if(mysqli_query($this->conn, $sql)){ return true; }else { return false; } + } +``` + +:star: In the *database_create_table* function, create the required database table. + +``` + public function database_create_table(){ + // Create a new database table. + $sql_create = "CREATE TABLE `$this->table`( + id int AUTO_INCREMENT PRIMARY KEY NOT NULL, + weight varchar(255) NOT NULL, + f1 varchar(255) NOT NULL, + f2 varchar(255) NOT NULL, + f3 varchar(255) NOT NULL, + f4 varchar(255) NOT NULL, + f5 varchar(255) NOT NULL, + f6 varchar(255) NOT NULL, + f7 varchar(255) NOT NULL, + f8 varchar(255) NOT NULL, + cpm varchar(255) NOT NULL, + nsv varchar(255) NOT NULL, + usv varchar(255) NOT NULL, + `class` varchar(255) NOT NULL + );"; + if(mysqli_query($this->conn, $sql_create)) echo("<br><br>Database Table Created Successfully!"); + } +``` + +:star: Define the *sample* class, extending the *_main* class, and its functions: + +:star: Define the food irradiation dose class (label) names. + +:star: In the *count_samples* function, count the registered data records (samples) in the given database table. + +``` + public $class_names = ["Regulated", "Unsafe", "Hazardous"]; + + // Count the registered data records (samples) in the given database table. + public function count_samples(){ + $count = [ + "total" => mysqli_num_rows(mysqli_query($this->conn, "SELECT * FROM `$this->table`")), + "regulated" => mysqli_num_rows(mysqli_query($this->conn, "SELECT * FROM `$this->table` WHERE class='0'")), + "unsafe" => mysqli_num_rows(mysqli_query($this->conn, "SELECT * FROM `$this->table` WHERE class='1'")), + "hazardous" => mysqli_num_rows(mysqli_query($this->conn, "SELECT * FROM `$this->table` WHERE class='2'")), + ]; + return $count; + } +``` + +:star: In the *create_sample_files* function: + +:star: Obtain the registered data records from the given database table. + +:star: Scale (normalize) data items to define appropriately formatted inputs in the range of 0-1. + +:star: Define the header indicating data elements. + +:star: Create an array with the scaled data items. + +:star: For each data record, create a CSV file (sample) named with the assigned irradiation dose class and identified with the unique row number under the *id* data field. + +:star: Each sample includes twelve data items [shape=(12,)]: + +*[15.877, 0.25, 0.76, 0.57, 0.8, 1.89, 2.85, 4.65, 3.63, 0.8, 5.31, 0.53]* + +``` + public function create_sample_files($type){ + // Obtain the registered data records (samples) from the given database table. + $sql = "SELECT * FROM `$this->table`"; + $result = mysqli_query($this->conn, $sql); + $check = mysqli_num_rows($result); + if($check > 0){ + while($row = mysqli_fetch_assoc($result)){ + // Scale (normalize) data items to define appropriately formatted inputs (samples). + $scaled = [ + "weight" => $row["weight"] / 10, + "f1" => $row["f1"] / 100, + "f2" => $row["f2"] / 100, + "f3" => $row["f3"] / 100, + "f4" => $row["f4"] / 100, + "f5" => $row["f5"] / 100, + "f6" => $row["f6"] / 100, + "f7" => $row["f7"] / 100, + "f8" => $row["f8"] / 100, + "cpm" => $row["cpm"] / 100, + "nsv" => $row["nsv"] / 100, + "usv" => $row["usv"] + ]; + // Add the header as the first row. + $processed_data = [ + ['weight','f1','f2','f3','f4','f5','f6','f7','f8','cpm','nsv','usv'], + [$scaled["weight"],$scaled["f1"],$scaled["f2"],$scaled["f3"],$scaled["f4"],$scaled["f5"],$scaled["f6"],$scaled["f7"],$scaled["f8"],$scaled["cpm"],$scaled["nsv"],$scaled["usv"]] + ]; + $filename = "data/".$this->class_names[$row["class"]].".".$type.".sample_".$row["id"].".csv"; + $f = fopen($filename, "w"); + foreach($processed_data as $r){ + fputcsv($f, $r); + } + fclose($f); + } + } + } +``` + +:star: In the *download_samples* function, download all generated CSV files (samples) in the ZIP file format. + +``` + public function download_samples($zipname){ + if(count(scandir("data")) > 2){ + $zip = new ZipArchive; + $zip->open($zipname, ZipArchive::CREATE); + foreach(glob("data/*.csv") as $sample){ + $zip->addFile($sample); + } + $zip->close(); + + header('Content-Type: application/zip'); + header("Content-Disposition: attachment; filename='$zipname'"); + header('Content-Length: ' . filesize($zipname)); + header("Location: $zipname"); + }else{ + header("Location: ."); + exit(); + } + } +``` + +:star: Define the required MySQL database connection settings for Raspberry Pi. + +``` +$server = array( + "name" => "localhost", + "username" => "root", + "password" => "bot", + "database" => "foodirradiation", + "table" => "entries" + +); + +$conn = mysqli_connect($server["name"], $server["username"], $server["password"], $server["database"]); +``` + +📁 *get_data.php* + +:star: Include the *class.php* file. + +:star: Define the *food* object of the *_main* class with its required parameters. + +``` +include_once "assets/class.php"; + +// Define the new 'food' object: +$food = new _main(); +$food->__init__($conn, $server["table"]); +``` + +:star: Obtain the transferred information from Beetle ESP32-C3. + +:star: Then, insert the received measurements into the given database table. + +``` +if(isset($_GET["weight"]) && isset($_GET["F1"]) && isset($_GET["F2"]) && isset($_GET["F3"]) && isset($_GET["F4"]) && isset($_GET["F5"]) && isset($_GET["F6"]) && isset($_GET["F7"]) && isset($_GET["F8"]) && isset($_GET["CPM"]) && isset($_GET["nSv"]) && isset($_GET["uSv"]) && isset($_GET["class"])){ + if($food->insert_new_data($_GET["weight"], $_GET["F1"], $_GET["F2"], $_GET["F3"], $_GET["F4"], $_GET["F5"], $_GET["F6"], $_GET["F7"], $_GET["F8"], $_GET["CPM"], $_GET["nSv"], $_GET["uSv"], $_GET["class"])){ + echo("Data received and saved successfully!"); + }else{ + echo("Database error!"); + } +}else{ + echo("Waiting Data..."); +} +``` + +:star: If requested, create the required database table *(entries)*. + +``` +if(isset($_GET["create_table"]) && $_GET["create_table"] == "OK") $food->database_create_table(); +``` + +📁 *index.php* + +:star: Include the *class.php* file. + +:star: Define the *sample* object of the *sample* class with its required parameters. + +``` + include_once "assets/class.php"; + + // Define the new 'sample' object: + $sample = new sample(); + $sample->__init__($conn, $server["table"]); +``` +:star: Elicit the total number of data records (samples) for classes (labels) in the given database table. + +``` +$count = $sample->count_samples(); +``` + +:star: If the user requests via the HTML form, create a CSV file (sample) for each data record in the given database table, depending on the selected data type: training or testing. + +``` + if(isset($_POST["data"]) && $_POST["data"] != ""){ + $sample->create_sample_files($_POST["data"]); + } +``` + +:star: If the *Download* button is clicked, download all generated CSV files (samples) in the ZIP file format. + +``` + if(isset($_GET["download"])){ + $sample->download_samples("data.zip"); + } +``` + +![image](.gitbook/assets/food-irradiation/code_app_1.PNG) + +![image](.gitbook/assets/food-irradiation/code_app_2.PNG) + +![image](.gitbook/assets/food-irradiation/code_app_3.PNG) + +![image](.gitbook/assets/food-irradiation/code_app_4.PNG) + +![image](.gitbook/assets/food-irradiation/code_app_5.PNG) + +![image](.gitbook/assets/food-irradiation/code_app_6.PNG) + +## Step 3: Setting up a LAMP web server on Raspberry Pi + +Since I decided to host my web application on a Raspberry Pi 3, I needed to set up a LAMP web server. + +:hash: First of all, open a terminal window by selecting *Accessories ➡ Terminal* from the menu. + +:hash: Then, install the *apache2* package by typing the following command into the terminal and pressing Enter: + +*sudo apt-get install apache2 -y* + +![image](.gitbook/assets/food-irradiation/apache.png) + +:hash: After installing the *apache2* package successfully, open Chromium Web Browser and navigate to *localhost* so as to test the web server. + +:hash: Then, enter the command below to the terminal to obtain the Raspberry Pi's IP address: + +*hostname -I* + +![image](.gitbook/assets/food-irradiation/localhost.png) + +![image](.gitbook/assets/food-irradiation/hostname.png) + +:hash: To install the latest package versions successfully, update the Pi. Then, download the *PHP* package by entering these commands below to the terminal: + +*sudo apt-get update* + +*sudo apt-get install php -y* + +![image](.gitbook/assets/food-irradiation/php.png) + +:hash: To be able to create files in the ZIP file format with the web application, install the *php-zip* package: + +*sudo apt install php7.3-zip* + +![image](.gitbook/assets/food-irradiation/rasp_zip_lib.png) + +:hash: Since the web application creates a large ZIP file with the generated CSV files (samples), open the *php.ini* file in order to modify these configurations: + +- upload_max_filesize +- max_file_uploads + +:hash: Then, restart the *apache* server to activate the installed packages on the web server: + +*sudo service apache2 restart* + +![image](.gitbook/assets/food-irradiation/rasp_php_ini.png) + +## Step 3.1: Creating a MySQL database in MariaDB + +Since I needed to log measurements transmitted by Beetle ESP32-C3 so as to create appropriately formatted samples for Edge Impulse, I also set up a MariaDB server on Raspberry Pi 3. + +:hash: First of all, install the MariaDB (MySQL) server and *PHP-MySQL* packages by entering the following command into the terminal: + +*sudo apt-get install mariadb-server php-mysql -y* + +![image](.gitbook/assets/food-irradiation/mysql.png) + +:hash: To create a new user, run the MySQL secure installation command in the terminal window: + +*sudo mysql_secure_installation* + +:hash: When requested, type the current password for the root user (enter for none). Then, press Enter. + +:hash: Type in Y and press Enter to set the root password. + +:hash: Type in *bot* at the *New password:* prompt, and press Enter. + +:hash: Type in Y to remove anonymous users. + +:hash: Type in Y to disallow root login remotely. + +:hash: Type in Y to remove the test database and its access permissions. + +:hash: Type in Y to reload privilege tables. + +:hash: After successfully setting the MariaDB server, the terminal prints: *All done! Thanks for using MariaDB!* + +![image](.gitbook/assets/food-irradiation/database_settings.png) + +:hash: Finally, to create a new database in the MariaDB server, run the MySQL interface in the terminal: + +*sudo mysql -uroot -p* + +:hash: Then, enter the recently changed root password - *bot*. + +:hash: When the terminal shows the *MariaDB [(none)]>* prompt, create the new database *(foodirradiation)* by utilizing these commands below: + +``` +create database foodirradiation; + +GRANT ALL PRIVILEGES ON foodirradiation.* TO 'root'@'localhost' IDENTIFIED BY 'bot'; + +FLUSH PRIVILEGES; +``` + +:hash: Press Ctrl + D to exit the *MariaDB [(none)]>* prompt. + +![image](.gitbook/assets/food-irradiation/rasp_database.png) + +## Step 3.2: Setting and running the web application on Raspberry Pi + +As discussed above, I set up a LAMP web server on my Raspberry Pi 3 to run the web application, but you can run it on any server as long as it is a PHP server. + +:hash: First of all, install and extract the *food_irradiation_data_logger.zip* folder. + +![image](.gitbook/assets/food-irradiation/rasp_app_set_1.png) + +:hash: Then, move the application folder *(food_irradiation_data_logger)* to the Apache server *(/var/www/html)* by using the terminal since the Apache server is a protected location. + +*sudo mv /home/pi/Downloads/food_irradiation_data_logger /var/www/html/* + +![image](.gitbook/assets/food-irradiation/rasp_app_set_2.png) + +:hash: Since the Apache server is a protected location, it throws an error while attempting to modify the files and folders in it. Therefore, before utilizing the web application to create CSV files (samples) and download them in the ZIP file format, change the web application's folder permission by using the terminal: + +*sudo chmod -R 777 /var/www/html/food_irradiation_data_logger* + +![image](.gitbook/assets/food-irradiation/rasp_app_set_3.png) + +💻 On the *get_data.php* file: + +:star: If the web application did not receive measurements from Beetle ESP32-C3 via an HTTP GET request, it prints: *Waiting Data...* + +:star: Otherwise, the web application prints: *Data received and saved successfully!* + +*localhost/food_irradiation_data_logger/get_data.php* + +![image](.gitbook/assets/food-irradiation/rasp_app_work_1.png) + +![image](.gitbook/assets/food-irradiation/rasp_app_work_2.png) + +:star: If the *create_table* parameter is set as OK, the web application creates the requested database table *(entries)* and prints: *Database Table Created Successfully!* + +![image](.gitbook/assets/food-irradiation/rasp_app_work_3.png) + +💻 On the *index.php* file: + +:star: The application interface shows created sample names and data record numbers for each class in the MySQL database. + +:star: If the user clicks the *Create Samples* submit button on the HTML form, the web application generates CSV files (samples) for Edge Impulse, depending on the selected data type (training or testing). + +![image](.gitbook/assets/food-irradiation/rasp_app_work_4.png) + +![image](.gitbook/assets/food-irradiation/rasp_app_work_5.png) + +![image](.gitbook/assets/food-irradiation/rasp_app_work_6.png) + +![image](.gitbook/assets/food-irradiation/rasp_app_work_7.png) + +![image](.gitbook/assets/food-irradiation/rasp_app_work_8.png) + +:star: If the user clicks the *Download* button, the application downloads all generated CSV files (samples) in the ZIP file format *(data.zip)*. + +![image](.gitbook/assets/food-irradiation/rasp_app_work_9.png) + +![image](.gitbook/assets/food-irradiation/rasp_app_work_10.png) + +## Step 4: Setting up Beetle ESP32-C3 on the Arduino IDE + +Before proceeding with the following steps, I needed to set up Beetle ESP32-C3 on the Arduino IDE and install the required libraries for this project. + +If your computer cannot recognize Beetle ESP32-C3 when plugged in via a USB cable, connect Pin 9 to GND (pull-down) and try again. + +:hash: To add the ESP32-C3 board package to the Arduino IDE, navigate to *File ➡ Preferences* and paste the URL below under *Additional Boards Manager URLs*. + +*https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json* + +![image](.gitbook/assets/food-irradiation/espC3_set_1.png) + +![image](.gitbook/assets/food-irradiation/espC3_set_2.png) + +:hash: Then, to install the required core, navigate to *Tools ➡ Board ➡ Boards Manager* and search for *esp32*. + +![image](.gitbook/assets/food-irradiation/espC3_set_3.png) + +![image](.gitbook/assets/food-irradiation/espC3_set_4.png) + +:hash: After installing the core, navigate to *Tools > Board > ESP32 Arduino* and select *ESP32C3 Dev Module*. + +![image](.gitbook/assets/food-irradiation/espC3_set_5.png) + +:hash: To print data on the serial monitor, enable *USB CDC On Boot* after setting Beetle ESP32-C3. + +![image](.gitbook/assets/food-irradiation/espC3_set_6.png) + +:hash: Finally, download the required libraries for the Geiger counter module, the I2C HX711 weight sensor, the AS7341 visible light sensor, and the SSD1309 OLED transparent screen: + +DFRobot_Geiger | [Download](https://github.com/cdjq/DFRobot_Geiger) +DFRobot_HX711_I2C | [Download](https://github.com/DFRobot/DFRobot_HX711_I2C) +DFRobot_AS7341 | [Download](https://github.com/DFRobot/DFRobot_AS7341) +U8g2_Arduino | [Download](https://github.com/DFRobot/U8g2_Arduino) + +## Step 4.1: Displaying images on the SSD1309 transparent OLED screen + +To display images (monochrome) on the SSD1309 transparent OLED screen successfully, I needed to convert PNG or JPG files into the XBM (X Bitmap Graphic) file format. + +:hash: First of all, download [GIMP](https://www.gimp.org/). + +:hash: Then, upload an image (black and white) and go to *Image ➡ Scale Image...* to resize the uploaded image. + +![image](.gitbook/assets/food-irradiation/img_convert_1.png) + +:hash: Go to *Image ➡ Mode* and select *Grayscale*. + +![image](.gitbook/assets/food-irradiation/img_convert_2.png) + +:hash: Finally, export the image as an XBM file. + +![image](.gitbook/assets/food-irradiation/img_convert_3.png) + +![image](.gitbook/assets/food-irradiation/img_convert_4.png) + +:hash: After exporting the image, add the generated data array to the code and print it on the screen. + +``` + u8g2.firstPage(); + do{ + //u8g2.setBitmapMode(true /* transparent*/); + u8g2.drawXBMP( /* x=*/36 , /* y=*/0 , /* width=*/50 , /* height=*/50 , data_colllect_bits); + }while(u8g2.nextPage()); +``` + +![image](.gitbook/assets/food-irradiation/img_convert_5.png) + +![image](.gitbook/assets/food-irradiation/img_convert_6.png) + +## Step 5: Collecting and storing food irradiation data w/ Beetle ESP32-C3 + +After setting up Beetle ESP32-C3 and installing the required libraries, I programmed Beetle ESP32-C3 to collect ionizing radiation, weight, and visible light (color) measurements in order to store them on the MySQL database and create appropriately formatted samples for Edge Impulse. + +- CPM (Counts per Minute) +- nSv/h (nanoSieverts per hour) +- μSv/h (microSieverts per hour) +- Weight (g) +- F1 (405 - 425 nm) +- F2 (435 - 455 nm) +- F3 (470 - 490 nm) +- F4 (505 - 525 nm) +- F5 (545 - 565 nm) +- F6 (580 - 600 nm) +- F7 (620 - 640 nm) +- F8 (670 - 690 nm) + +Since I needed to assign food irradiation dose levels (classes) theoretically as labels for each data record while collecting data from foods to create a valid data set, I utilized the control buttons attached to Beetle ESP32-C3 so as to choose among irradiation dose classes. After selecting an irradiation dose class, Beetle ESP32-C3 appends the selected class to the collected data and then transmits that data packet to the web application. + +- Control Button (A) ➡ Regulated +- Control Button (B) ➡ Unsafe +- Control Button (C) ➡ Hazardous + +You can download the *IoT_food_irradiation_data_collect.ino* file to try and inspect the code for collecting ionizing radiation, weight, and visible light (color) measurements and for transferring information to a given web application. + +:star: Include the required libraries. + +``` +#include <WiFi.h> +#include <DFRobot_Geiger.h> +#include <DFRobot_HX711_I2C.h> +#include <U8g2lib.h> +#include <SPI.h> +#include "DFRobot_AS7341.h" +``` + +:star: Define the Wi-Fi network settings and use the *WiFiClient* class to create TCP connections. + +``` +char ssid[] = "<_SSID_>"; // your network SSID (name) +char pass[] = "<_PASSWORD_>"; // your network password (use for WPA, or use as key for WEP) +int keyIndex = 0; // your network key Index number (needed only for WEP) + +// Define the server (Raspberry Pi). +char server[] = "192.168.1.20"; +// Define the web application path. +String application = "/food_irradiation_data_logger/get_data.php"; + +// Initialize the WiFi client library. +WiFiClient client; /* WiFiSSLClient client; */ +``` +:star: Define the Geiger counter module. + +:star: Define the I2C HX711 weight sensor. + +:star: Define the AS7341 visible light sensor settings and objects. + +``` +DFRobot_Geiger geiger(5); + +// Define the HX711 weight sensor. +DFRobot_HX711_I2C MyScale; + +// Define the AS7341 object. +DFRobot_AS7341 as7341; +// Define AS7341 data objects: +DFRobot_AS7341::sModeOneData_t data1; +DFRobot_AS7341::sModeTwoData_t data2; +``` + +:star: Define the 1.51” SSD1309 OLED transparent display settings. + +``` +#define OLED_DC 1 +#define OLED_CS 7 +#define OLED_RST 2 + +U8G2_SSD1309_128X64_NONAME2_1_4W_HW_SPI u8g2(/* rotation=*/U8G2_R0, /* cs=*/ OLED_CS, /* dc=*/ OLED_DC,/* reset=*/OLED_RST); +``` +:star: Define monochrome graphics. +:star: Initialize the SSD1309 OLED transparent display. +``` + u8g2.begin(); + u8g2.setFontPosTop(); + //u8g2.setDrawColor(0); +``` + +:star: In the *err_msg* function, display the error message on the SSD1309 OLED transparent screen. + +``` +void err_msg(){ + // Show the error message on the SSD1309 transparent display. + u8g2.firstPage(); + do{ + //u8g2.setBitmapMode(true /* transparent*/); + u8g2.drawXBMP( /* x=*/44 , /* y=*/0 , /* width=*/40 , /* height=*/40 , error_bits); + u8g2.setFont(u8g2_font_4x6_tr); + u8g2.drawStr(0, 47, "Check the serial monitor to see"); + u8g2.drawStr(40, 55, "the error!"); + }while(u8g2.nextPage()); +} + +``` + +:star: Check the connection status between the weight (HX711) sensor and Beetle ESP32-C3. + +``` + while (!MyScale.begin()) { + Serial.println("HX711 initialization is failed!"); + err_msg(); + delay(1000); + } + Serial.println("HX711 initialization is successful!"); +``` + +:star: Set the calibration weight (g) and threshold (g) to calibrate the weight sensor automatically. + +:star: Display the current calibration value on the serial monitor. + +``` + MyScale.setCalWeight(100); + // Set the calibration threshold (g). + MyScale.setThreshold(30); + // Display the current calibration value. + Serial.print("\nCalibration Value: "); Serial.println(MyScale.getCalibration()); + MyScale.setCalibration(MyScale.getCalibration()); + delay(1000); +``` + +:star: Check the connection status between the AS7341 visible light sensor and Beetle ESP32-C3. Then, enable the built-in LED on the AS7341 sensor. + +``` + while (as7341.begin() != 0) { + Serial.println("AS7341 initialization is failed!"); + err_msg(); + delay(1000); + } + Serial.println("AS7341 initialization is successful!"); + + // Enable the built-in LED on the AS7341 sensor. + as7341.enableLed(true); +``` + +:star: Initialize the Wi-Fi module. + +:star: Attempt to connect to the given Wi-Fi network. + +``` + WiFi.begin(ssid, pass); + // Attempt to connect to the WiFi network: + while(WiFi.status() != WL_CONNECTED){ + // Wait for the connection: + delay(500); + Serial.print("."); + } + // If connected to the network successfully: + Serial.println("Connected to the WiFi network successfully!"); + u8g2.firstPage(); + do{ + u8g2.setFont(u8g2_font_open_iconic_all_8x_t); + u8g2.drawGlyph(/* x=*/32, /* y=*/0, /* encoding=*/247); + }while(u8g2.nextPage()); + delay(2000); +``` + +:star: In the *get_Weight* function, obtain the weight (g) measurement generated by the I2C HX711 weight sensor. + +``` +void get_Weight(){ + weight = MyScale.readWeight(); + if(weight < 0.5) weight = 0; + Serial.print("\nWeight: "); Serial.print(weight); Serial.println(" g"); + delay(1000); +} +``` + +:star: In the *get_Visual_Light* function, start spectrum measurement with the AS7341 sensor and read the value of sensor data channel 0~5 under these channel mapping modes: + +- eF1F4ClearNIR +- eF5F8ClearNIR + +``` +void get_Visual_Light(){ + // Start spectrum measurement: + // Channel mapping mode: 1.eF1F4ClearNIR + as7341.startMeasure(as7341.eF1F4ClearNIR); + // Read the value of sensor data channel 0~5, under eF1F4ClearNIR + data1 = as7341.readSpectralDataOne(); + // Channel mapping mode: 2.eF5F8ClearNIR + as7341.startMeasure(as7341.eF5F8ClearNIR); + // Read the value of sensor data channel 0~5, under eF5F8ClearNIR + data2 = as7341.readSpectralDataTwo(); + // Print data: + Serial.print("\nF1(405-425nm): "); Serial.println(data1.ADF1); + Serial.print("F2(435-455nm): "); Serial.println(data1.ADF2); + Serial.print("F3(470-490nm): "); Serial.println(data1.ADF3); + Serial.print("F4(505-525nm): "); Serial.println(data1.ADF4); + Serial.print("F5(545-565nm): "); Serial.println(data2.ADF5); + Serial.print("F6(580-600nm): "); Serial.println(data2.ADF6); + Serial.print("F7(620-640nm): "); Serial.println(data2.ADF7); + Serial.print("F8(670-690nm): "); Serial.println(data2.ADF8); + // CLEAR and NIR: + Serial.print("Clear_1: "); Serial.println(data1.ADCLEAR); + Serial.print("NIR_1: "); Serial.println(data1.ADNIR); + Serial.print("Clear_2: "); Serial.println(data2.ADCLEAR); + Serial.print("NIR_2: "); Serial.println(data2.ADNIR); + delay(1000); +} +``` + +:star: In the *activate_Geiger_counter* function: + +:star: Initialize the Geiger counter module and enable the external interrupt. + +:star: Every three seconds, pause the count to turn off the external interrupt trigger. + +:star: Evaluate the current CPM (Counts per Minute) by dropping the edge pulse within three seconds: the error is ±3CPM. + +:star: Obtain the current nSv/h (nanoSieverts per hour). + +:star: Obtain the current μSv/h (microSieverts per hour). + +``` +void activate_Geiger_counter(){ + // Initialize the Geiger counter module and enable the external interrupt. + geiger.start(); + delay(3000); + // If necessary, pause the count and turn off the external interrupt trigger. + geiger.pause(); + + // Evaluate the current CPM (Counts per Minute) by dropping the edge pulse within 3 seconds: the error is ±3CPM. + Serial.print("\nCPM: "); Serial.println(geiger.getCPM()); + // Get the current nSv/h (nanoSieverts per hour). + Serial.print("nSv/h: "); Serial.println(geiger.getnSvh()); + // Get the current μSv/h (microSieverts per hour). + Serial.print("μSv/h: "); Serial.println(geiger.getuSvh()); +} +``` + +:star: In the *drawNumber* function, convert numbers to char arrays with the *itoa* function so as to display them on the SSD1309 OLED transparent screen. + +``` +void drawNumber(int x, int y, int __){ + char buf[7]; + u8g2.drawStr(x, y, itoa(__, buf, 10)); +} +``` + +:star: In the *home_screen* function, display the collected data on the SSD1309 OLED transparent screen. + +``` +void home_screen(int y, int x, int s){ + u8g2.firstPage(); + do{ + u8g2.setFont(u8g2_font_open_iconic_all_2x_t); + u8g2.drawGlyph(/* x=*/0, /* y=*/y-3, /* encoding=*/142); + u8g2.drawGlyph(/* x=*/0, /* y=*/y+s-3, /* encoding=*/259); + u8g2.drawGlyph(/* x=*/0, /* y=*/y+(2*s)-3, /* encoding=*/280); + u8g2.setFont(u8g2_font_freedoomr10_mu); + u8g2.drawStr(25, y, "WEIGHT:"); drawNumber(x, y, weight); + u8g2.drawStr(25, y+s, "F1:"); drawNumber(x, y+s, data1.ADF1); + u8g2.drawStr(25, y+(2*s), "CPM:"); drawNumber(x, y+(2*s), geiger.getCPM()); + }while(u8g2.nextPage()); +} +``` + +:star: In the *make_a_get_request* function: + +:star: Connect to the web application named *food_irradiation_data_logger*. + +:star: Create the query string with the collected data. + +:star: Make an HTTP GET request with the data parameters to the web application. + +:star: Wait until the client is available, then fetch the response from the web application. + +:star: If there is a response from the server and the web application appends the transferred data packet to the MySQL database successfully, print *Data registered successfully!* on the serial monitor and the SSD1309 screen. + +``` +void make_a_get_request(String _class){ + // Connect to the web application named food_irradiation_data_logger. Change '80' with '443' if you are using SSL connection. + if (client.connect(server, 80)){ + // If successful: + Serial.println("\nConnected to the web application successfully!"); + // Create the query string: + String query = application+"?weight="+String(weight)+"&F1="+data1.ADF1+"&F2="+data1.ADF2+"&F3="+data1.ADF3+"&F4="+data1.ADF4+"&F5="+data2.ADF5+"&F6="+data2.ADF6+"&F7="+data2.ADF7+"&F8="+data2.ADF8; + query += "&CPM="+String(geiger.getCPM())+"&nSv="+String(geiger.getnSvh())+"&uSv="+String(geiger.getuSvh()); + query += "&class="+_class; + // Make an HTTP Get request: + client.println("GET " + query + " HTTP/1.1"); + client.println("Host: 192.168.1.20"); + client.println("Connection: close"); + client.println(); + }else{ + Serial.println("\nConnection failed to the web application!"); + err_msg(); + } + delay(2000); // Wait 2 seconds after connecting... + // If there are incoming bytes available, get the response from the web application. + String response = ""; + while (client.available()) { char c = client.read(); response += c; } + if(response != "" && response.indexOf("Data received and saved successfully!") > 0){ + Serial.println("Data registered successfully!"); + u8g2.firstPage(); + do{ + //u8g2.setBitmapMode(true /* transparent*/); + u8g2.drawXBMP( /* x=*/36 , /* y=*/0 , /* width=*/50 , /* height=*/50 , data_colllect_bits); + u8g2.setFont(u8g2_font_4x6_tr); + u8g2.drawStr(6, 55, "Data registered successfully!"); + }while(u8g2.nextPage()); + } +} +``` + +:star: According to the pressed control button (A, B, or C), transmit the data packet to the given web application, including the selected food irradiation dose class. + +``` + if(!digitalRead(button_A)) make_a_get_request("0"); + if(!digitalRead(button_B)) make_a_get_request("1"); + if(!digitalRead(button_C)) make_a_get_request("2"); +``` +![image](.gitbook/assets/food-irradiation/code_collect_1.PNG) + +![image](.gitbook/assets/food-irradiation/code_collect_2.PNG) + +![image](.gitbook/assets/food-irradiation/code_collect_3.PNG) + +![image](.gitbook/assets/food-irradiation/code_collect_4.PNG) + +![image](.gitbook/assets/food-irradiation/code_collect_5.PNG) + +## Step 5.1: Logging the collected data into the MySQL database + +After uploading and running the code for collecting data and transmitting data packets to the web application on Beetle ESP32-C3: + +☢:bento: The device waits for the Wi-Fi module to connect to the given Wi-Fi network. + +![image](.gitbook/assets/food-irradiation/collect_0.jpg) + +☢:bento: Then, the device displays a modicum of the collected data on the SSD1309 OLED transparent screen. + +- WEIGHT (g) +- F1 (405 - 425 nm) +- CPM (Counts per Minute) + +☢:bento: The device allows the user to collect visible light (color) data at different angles with the moveable handle. + +![image](.gitbook/assets/food-irradiation/collect_1.jpg) + +![image](.gitbook/assets/food-irradiation/collect_2.jpg) + +![image](.gitbook/assets/food-irradiation/collect_3.jpg) + +☢:bento: If one of the control buttons (A, B, or C) is pressed, the device transmits the recently collected data by adding the selected food irradiation dose class to the given web application. + +- Control Button (A) ➡ Regulated [0] +- Control Button (B) ➡ Unsafe [1] +- Control Button (C) ➡ Hazardous [2] + +☢:bento: Then, if the web application appends the transferred data packet to the MySQL database successfully, the device shows this message on the SSD1309 OLED transparent screen: *Data registered successfully!* + +![image](.gitbook/assets/food-irradiation/collect_4.jpg) + +☢:bento: If Beetle ESP32-C3 throws an error while operating, the device shows the error message on the SSD1309 OLED transparent screen and prints the error details on the serial monitor. + +![image](.gitbook/assets/food-irradiation/collect_12.jpg) + +![image](.gitbook/assets/food-irradiation/serial_error.PNG) + +☢:bento: Also, the device prints notifications and sensor measurements on the serial monitor for debugging. + +![image](.gitbook/assets/food-irradiation/serial_collect_1.PNG) + +![image](.gitbook/assets/food-irradiation/serial_collect_2.PNG) + +As far as my experiments go, the device operates impeccably while collecting measurements and transmitting data packets to a given web application :) + +![image](.gitbook/assets/food-irradiation/gif_data_collect.gif) + +## Step 5.2: Creating samples from data records with the web application + +After logging ionizing radiation, weight, and visible light (color) measurements in the MySQL database from a motley collection of foods, exposed to sun rays as a natural source of radiation for estimated periods, I elicited my data set with eminent validity. + +📌Foods: + +- Pasta +- Corn kernel +- Herb +- Apple +- Wheat +- Animal (livestock) feed + +![image](.gitbook/assets/food-irradiation/collect_5.jpg) + +![image](.gitbook/assets/food-irradiation/collect_6.jpg) + +![image](.gitbook/assets/food-irradiation/collect_7.jpg) + +![image](.gitbook/assets/food-irradiation/collect_8.jpg) + +![image](.gitbook/assets/food-irradiation/collect_9.jpg) + +![image](.gitbook/assets/food-irradiation/collect_10.jpg) + +![image](.gitbook/assets/food-irradiation/collect_11.jpg) + +As explained in Step 2, I generated a CSV file (sample) for each data record in the MySQL database by utilizing the web application. + +☢:bento: The web application shows the total number of data records for classes (labels) in the database. + +![image](.gitbook/assets/food-irradiation/data_create_1.PNG) + +☢:bento: If the user clicks the *Create Samples* button, the web application scales data items and generates a CSV file (sample) for each data record, depending on the selected data type (training or testing). + +![image](.gitbook/assets/food-irradiation/data_create_2.PNG) + +![image](.gitbook/assets/food-irradiation/data_create_3.PNG) + +![image](.gitbook/assets/food-irradiation/data_create_4.PNG) + +![image](.gitbook/assets/food-irradiation/data_create_5.PNG) + +☢:bento: If the user clicks the *Download* button, the web application downloads all generated CSV files (samples) in the ZIP file format. + +📌 Training samples: + +![image](.gitbook/assets/food-irradiation/dataset_1.PNG) + +![image](.gitbook/assets/food-irradiation/dataset_2.PNG) + +📌 Testing samples: + +![image](.gitbook/assets/food-irradiation/dataset_3.PNG) + +![image](.gitbook/assets/food-irradiation/dataset_4.PNG) + +## Step 6: Building a neural network model with Edge Impulse + +When I completed collating my food irradiation dose data set and assigning labels, I had started to work on my artificial neural network model (ANN) to make predictions on food irradiation dose levels (classes) based on ionizing radiation, weight, and visible light (color) measurements. + +Since Edge Impulse supports almost every microcontroller and development board due to its model deployment options, I decided to utilize Edge Impulse to build my artificial neural network model. Also, Edge Impulse makes scaling embedded ML applications easier and faster for edge devices such as Beetle ESP32-C3. + +Even though Edge Impulse supports CSV files to upload samples, the data type should be time series to upload all data records in a single file. Therefore, I needed to follow the steps below to format my data set so as to train my model accurately: + +- Data Scaling (Normalizing) +- Data Preprocessing + +As explained in the previous steps, I utilized the web application to scale (normalize) and preprocess data records to create CSV files (samples) for Edge Impulse. + +Since the assigned classes are stored under the *class* data field in the MySQL database, I preprocessed my data set effortlessly to obtain labels for each data record while generating samples: + +- 0 — Regulated +- 1 — Unsafe +- 2 — Hazardous + +Plausibly, Edge Impulse allows building predictive models optimized in size and accuracy automatically and deploying the trained model as an Arduino library. Therefore, after scaling (normalizing) and preprocessing my data set to create samples, I was able to build an accurate neural network model to forecast food irradiation dose levels and run it on Beetle ESP32-C3 effortlessly. + +You can inspect [my neural network model on Edge Impulse](https://studio.edgeimpulse.com/public/109647/latest) as a public project. + +## Step 6.1: Uploading samples to Edge Impulse + +After generating training and testing samples successfully, I uploaded them to my project on Edge Impulse. + +:hash: First of all, sign up for [Edge Impulse](https://www.edgeimpulse.com/) and create a new project. + +![image](.gitbook/assets/food-irradiation/edge_set_1.PNG) + +:hash: Navigate to the *Data acquisition* page and click the *Upload existing data* button. + +![image](.gitbook/assets/food-irradiation/edge_set_2.png) + +![image](.gitbook/assets/food-irradiation/edge_set_3.PNG) + +:hash: Then, choose the data category (training or testing) and select *Infer from filename* under *Label* to deduce labels from file names automatically. + +:hash: Finally, select files and click the *Begin upload* button. + +![image](.gitbook/assets/food-irradiation/edge_set_4.PNG) + +![image](.gitbook/assets/food-irradiation/edge_set_5.PNG) + +![image](.gitbook/assets/food-irradiation/edge_set_6.PNG) + +![image](.gitbook/assets/food-irradiation/edge_set_7.PNG) + +![image](.gitbook/assets/food-irradiation/edge_set_8.PNG) + +![image](.gitbook/assets/food-irradiation/edge_set_9.PNG) + +## Step 6.2: Training the model on food irradiation dose levels + +After uploading my training and testing samples successfully, I designed an impulse and trained it on food irradiation dose levels (classes). + +An impulse is a custom neural network model in Edge Impulse. I created my impulse by employing the *Raw Data* block and the *Classification* learning block. + +The *Raw Data* block generate windows from data samples without any specific signal processing. + +The *Classification* learning block represents a Keras neural network model. Also, it lets the user change the model settings, architecture, and layers. + +:hash: Go to the *Create impulse* page. Then, select the *Raw Data* block and the *Classification* learning block. Finally, click *Save Impulse*. + +![image](.gitbook/assets/food-irradiation/edge_train_1.PNG) + +:hash: Before generating features for the model, go to the *Raw data* page and click *Save parameters*. + +![image](.gitbook/assets/food-irradiation/edge_train_2.PNG) + +:hash: After saving parameters, click *Generate features* to apply the *Raw Data* block to training samples. + +![image](.gitbook/assets/food-irradiation/edge_train_3.PNG) + +![image](.gitbook/assets/food-irradiation/edge_train_4.PNG) + +:hash: Finally, navigate to the *NN Classifier* page and click *Start training*. + +![image](.gitbook/assets/food-irradiation/edge_train_5.PNG) + +![image](.gitbook/assets/food-irradiation/edge_train_6.PNG) + +According to my experiments with my neural network model, I modified classification model settings, architecture, and layers to build a neural network model with high accuracy and validity: + +📌 Neural network settings: + +- Number of training cycles ➡ 50 +- Learning level ➡ 0.0006 +- Validation set size ➡ 10 + +📌 Extra layers: + +- Dense layer (64 neurons) +- Dense layer (32 neurons) + +After generating features and training my model with training samples, Edge Impulse evaluated the precision score (accuracy) as *100%*. + +The precision score is approximately *100%* due to the volume and variety of training samples. In technical terms, the model overfits the training data set. Therefore, I am still collecting data to improve my training data set. + +![image](.gitbook/assets/food-irradiation/edge_train_7.PNG) + +![image](.gitbook/assets/food-irradiation/edge_train_8.PNG) + +## Step 6.3: Evaluating the model accuracy and deploying the model + +After building and training my neural network model, I tested its accuracy and validity by utilizing testing samples. + +The evaluated accuracy of the model is *96.30%*. + +:hash: To validate the trained model, go to the *Model testing* page and click *Classify all*. + +![image](.gitbook/assets/food-irradiation/edge_test_1.PNG) + +![image](.gitbook/assets/food-irradiation/edge_test_2.PNG) + +![image](.gitbook/assets/food-irradiation/edge_test_3.PNG) + +After validating my neural network model, I deployed it as a fully optimized and customizable Arduino library. + +:hash: To deploy the validated model as an Arduino library, navigate to the *Deployment* page and select *Arduino library*. + +:hash: Then, choose the *Quantized (int8)* optimization option to get the best performance possible while running the deployed model. + +:hash: Finally, click *Build* to download the model as an Arduino library. + +![image](.gitbook/assets/food-irradiation/edge_deploy_1.PNG) + +![image](.gitbook/assets/food-irradiation/edge_deploy_2.PNG) + +![image](.gitbook/assets/food-irradiation/edge_deploy_3.PNG) + +## Step 7: Setting up the Edge Impulse model on Beetle ESP32-C3 + +After building, training, and deploying my model as an Arduino library on Edge Impulse, I needed to upload and run the Arduino library on Beetle ESP32-C3 directly so as to create an easy-to-use and capable device operating with minimal latency and power consumption. + +Since Edge Impulse optimizes and formats signal processing, configuration, and learning blocks into a single package while deploying models as Arduino libraries, I was able to import my model effortlessly to run inferences. + +:hash: After downloading the model as an Arduino library in the ZIP file format, go to *Sketch > Include Library > Add .ZIP Library...* + +:hash: Then, include the *IoT_AI-driven_Food_Irradiation_Classifier_inferencing.h* file to import the Edge Impulse neural network model. + +``` +#include <IoT_AI-driven_Food_Irradiation_Classifier_inferencing.h> +``` +After importing my model successfully to the Arduino IDE, I employed the control button (B) attached to Beetle ESP32-C3 to run inferences so as to predict food irradiation dose levels: + +- Press ➡ Run Inference + +You can download the *IoT_food_irradiation_run_model.ino* file to try and inspect the code for running Edge Impulse neural network models on Beetle ESP32-C3. + +You can inspect the corresponding functions and settings in Step 5. + +:star: Include the required libraries. + +``` +#include <DFRobot_Geiger.h> +#include <DFRobot_HX711_I2C.h> +#include <U8g2lib.h> +#include <SPI.h> +#include "DFRobot_AS7341.h" + +// Include the Edge Impulse model converted to an Arduino library: +#include <IoT_AI-driven_Food_Irradiation_Classifier_inferencing.h> +``` +:star: Define the required parameters to run an inference with the Edge Impulse model. +:star: Define the features array (buffer) to classify one frame of data. +``` +#define FREQUENCY_HZ EI_CLASSIFIER_FREQUENCY +#define INTERVAL_MS (1000 / (FREQUENCY_HZ + 1)) + +// Define the features array to classify one frame of data. +float features[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE]; +size_t feature_ix = 0; +``` +:star: Define the threshold value (0.60) for the model outputs (predictions). + +:star: Define the food irradiation dose class names: + +- Regulated +- Unsafe +- Hazardous + +``` +float threshold = 0.60; + +// Define the food irradiation dose (class) names: +String classes[] = {"Hazardous", "Regulated", "Unsafe"}; +``` + +:star: Define monochrome graphics. + +:star: Create an array including icons for each food irradiation dose class. + +``` +static const unsigned char *class_icons[] U8X8_PROGMEM = {hazardous_bits, regulated_bits, unsafe_bits}; +``` +:star: In the *run_inference_to_make_predictions* function: + +:star: Scale (normalize) the collected data depending on the given model and copy the scaled data items to the features array (buffer). + +:star: If required, multiply the scaled data items while copying them to the features array (buffer). + +:star: Display the progress of copying data to the features buffer on the serial monitor. + +:star: If the features buffer is full, create a signal object from the features buffer (frame). + +:star: Then, run the classifier. + +:star: Print the inference timings on the serial monitor. + +:star: Read the prediction (detection) result for each food irradiation dose class (label). + +:star: Print the prediction results on the serial monitor. + +:star: Obtain the detection result greater than the given threshold (0.60). It represents the most accurate label (food irradiation dose class) predicted by the model. + +:star: Print the detected anomalies on the serial monitor, if any. + +:star: Finally, clear the features buffer (frame). + +``` +void run_inference_to_make_predictions(int multiply){ + // Scale (normalize) data items depending on the given model: + float scaled_weight = weight / 10; + float scaled_F1 = data1.ADF1 / 100; + float scaled_F2 = data1.ADF2 / 100; + float scaled_F3 = data1.ADF3 / 100; + float scaled_F4 = data1.ADF4 / 100; + float scaled_F5 = data2.ADF5 / 100; + float scaled_F6 = data2.ADF6 / 100; + float scaled_F7 = data2.ADF7 / 100; + float scaled_F8 = data2.ADF8 / 100; + float scaled_CPM = geiger.getCPM() / 100; + float scaled_nSv = geiger.getnSvh() / 100; + float scaled_uSv = geiger.getuSvh(); + + // Copy the scaled data items to the features buffer. + // If required, multiply the scaled data items while copying them to the features buffer. + for(int i=0; i<multiply; i++){ + features[feature_ix++] = scaled_weight; + features[feature_ix++] = scaled_F1; + features[feature_ix++] = scaled_F2; + features[feature_ix++] = scaled_F3; + features[feature_ix++] = scaled_F4; + features[feature_ix++] = scaled_F5; + features[feature_ix++] = scaled_F6; + features[feature_ix++] = scaled_F7; + features[feature_ix++] = scaled_F8; + features[feature_ix++] = scaled_CPM; + features[feature_ix++] = scaled_nSv; + features[feature_ix++] = scaled_uSv; + } + + // Display the progress of copying data to the features buffer. + Serial.print("\nFeatures Buffer Progress: "); Serial.print(feature_ix); Serial.print(" / "); Serial.println(EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE); + + // Run inference: + if(feature_ix == EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE){ + ei_impulse_result_t result; + // Create a signal object from the features buffer (frame). + signal_t signal; + numpy::signal_from_buffer(features, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal); + // Run the classifier: + EI_IMPULSE_ERROR res = run_classifier(&signal, &result, false); + ei_printf("\nrun_classifier returned: %d\n", res); + if(res != 0) return; + + // Print the inference timings on the serial monitor. + ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n", + result.timing.dsp, result.timing.classification, result.timing.anomaly); + + // Obtain the prediction results for each label (class). + for(size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++){ + // Print the prediction results on the serial monitor. + ei_printf("%s:\t%.5f\n", result.classification[ix].label, result.classification[ix].value); + // Get the predicted label (class). + if(result.classification[ix].value >= threshold) predicted_class = ix; + } + Serial.print("\nPredicted Class: "); Serial.println(predicted_class); + + // Detect anomalies, if any: + #if EI_CLASSIFIER_HAS_ANOMALY == 1 + ei_printf("Anomaly : \t%.3f\n", result.anomaly); + #endif + + // Clear the features buffer (frame): + feature_ix = 0; + } +} +``` + +:star: If the control button (B) is pressed, start running inference with the Edge Impulse model to predict the food irradiation dose level. + +:star: Wait until the Edge Impulse model predicts a food irradiation dose level (label) successfully. + +:star: Then, display the prediction (detection) result (class) on the SSD1309 OLED transparent screen with its assigned monochrome icon. + +:star: Clear the predicted label (class). + +:star: Finally, stop the running inference and return to the home screen. + +``` + if(!digitalRead(button_B)){ + model_activation = true; + u8g2.firstPage(); + do{ + u8g2.setFont(u8g2_font_open_iconic_all_8x_t); + u8g2.drawGlyph(/* x=*/32, /* y=*/0, /* encoding=*/233); + }while(u8g2.nextPage()); + } + while(model_activation){ + get_Weight(); + get_Visual_Light(); + activate_Geiger_counter(); + + // Run inference: + run_inference_to_make_predictions(1); + + // If the Edge Impulse model predicted a label (class) successfully: + if(predicted_class != -1){ + // Display the predicted class: + String c = "Class: " + classes[predicted_class]; + int str_x = c.length() * 4; + u8g2.firstPage(); + do{ + //u8g2.setBitmapMode(true /* transparent*/); + u8g2.drawXBMP( /* x=*/(u8g2.getDisplayWidth()-50)/2 , /* y=*/0 , /* width=*/50 , /* height=*/50 , class_icons[predicted_class]); + u8g2.setFont(u8g2_font_4x6_tr); + u8g2.drawStr((u8g2.getDisplayWidth()-str_x)/2, 55, c.c_str()); + }while(u8g2.nextPage()); + + // Clear the predicted class (label). + predicted_class = -1; + + // Stop the running inference and return to the home screen. + model_activation = false; + } + } +``` + +![image](.gitbook/assets/food-irradiation/code_run_1.PNG) + +![image](.gitbook/assets/food-irradiation/code_run_2.PNG) + +![image](.gitbook/assets/food-irradiation/code_run_3.PNG) + +![image](.gitbook/assets/food-irradiation/code_run_4.PNG) + +![image](.gitbook/assets/food-irradiation/code_run_5.PNG) + +## Step 8: Running the model on Beetle ESP32-C3 to make predictions on food irradiation doses + +When the features array (buffer) is full with data items, my Edge Impulse neural network model predicts possibilities of labels (food irradiation dose classes) for the given features buffer as an array of 3 numbers. They represent the model's *"confidence"* that the given features buffer corresponds to each of the three different food irradiation dose levels (classes) based on ionizing radiation, weight, and visible light (color) measurements [0 - 2], as shown in Step 6: + +- 0 — Regulated +- 1 — Unsafe +- 2 — Hazardous + +After executing the *IoT_food_irradiation_run_model.ino* file on Beetle ESP32-C3: + +☢:bento: The device displays a modicum of the collected data on the SSD1309 OLED transparent screen. + +- WEIGHT (g) +- F1 (405 - 425 nm) +- CPM (Counts per Minute) + +![image](.gitbook/assets/food-irradiation/run_model_1.jpg) + +☢:bento: If the control button (B) is pressed, the device runs an inference with the Edge Impulse model by filling the features buffer with the recently collected ionizing radiation, weight, and visible light (color) measurements. + +☢:bento: When the device starts filling the features buffer with data items, it shows: + +![image](.gitbook/assets/food-irradiation/run_model_2.jpg) + +☢:bento: Then, the device displays the detection result, which represents the most accurate label (food irradiation dose class) predicted by the model. + +☢:bento: Each food irradiation dose level (class) has a unique monochrome icon to be shown on the SSD1309 OLED transparent screen when being predicted (detected) by the model: + +- Regulated +- Unsafe +- Hazardous + +![image](.gitbook/assets/food-irradiation/run_model_3.jpg) + +![image](.gitbook/assets/food-irradiation/run_model_4.jpg) + +![image](.gitbook/assets/food-irradiation/run_model_5.jpg) + +☢:bento: Also, the device prints notifications and sensor measurements on the serial monitor for debugging. + +![image](.gitbook/assets/food-irradiation/serial_run_1.PNG) + +![image](.gitbook/assets/food-irradiation/serial_run_2.PNG) + +As far as my experiments go, the device predicts food irradiation dose levels (classes) accurately by employing the collected measurements :) + +![image](.gitbook/assets/food-irradiation/gif_run_model.gif) + +## Videos and Conclusion +[Data Collection | IoT AI-driven Food Irradiation Dose Detector w/ Edge Impulse](https://www.youtube.com/embed/CEl3ukSI1EA) + +[Experimenting with the model | IoT AI-driven Food Irradiation Dose Detector w/ Edge Impulse](https://www.youtube.com/embed/LAanlabmYJA) + +After completing all steps above and experimenting, I have employed the device to predict and detect food irradiation dose levels of various foods and food packaging so as to check whether they conform to health and safety standards regarding food irradiation. + +![image](.gitbook/assets/food-irradiation/home_1.jpg) + +## Further Discussions + +By applying neural network models trained on ionizing radiation, weight, and visible light (color) measurements in detecting food irradiation dose levels, we can achieve to[^3]: + +☢:bento: prevent changes to the packaging that might affect integrity as a barrier to microbial contamination, + +☢:bento: avert producing radiolysis products that could migrate into food, affecting odor, taste, and possibly the safety of the food, + +☢:bento: preclude inadvertent radiation effects on polymers in food packaging due to competing crosslinking or chain scission reactions. + +![image](.gitbook/assets/food-irradiation/home_2.jpg) + +## References + +[^1] Vanee Komolprasert. "CHAPTER 6: PACKAGING FOR FOODS TREATED BY IONIZING RADIATION." *Packaging for Nonthermal Processing of Food*. Blackwell Publishing, First edition, 2007. 87 - 88. + +[^2] Ana Paula Dionísio, Renata Takassugui Gomes, and Marília Oetterer. *Ionizing Radiation Effects on Food Vitamins – A Review*. Braz. Arch. Biol. Technol. v.52 n.5: pp. 1267-1278, Sept/Oct 2009 + +[^3] Kim M. Morehouse and Vanee Komolprasert. *Overview of Irradiation of Food and Packaging*. ACS Symposium Series 875, Irradiation of Food and Packaging, 2004, Chapter 1, Pages 1-11. *https://www.fda.gov/food/irradiation-food-packaging/overview-irradiation-food-and-packaging*. + diff --git a/predictive-maintenance-with-nordic-thingy-91.md b/predictive-maintenance-with-nordic-thingy-91.md new file mode 100644 index 00000000..67f2a079 --- /dev/null +++ b/predictive-maintenance-with-nordic-thingy-91.md @@ -0,0 +1,334 @@ +--- +description: Running anomaly detection on a Nordic Thingy:91 for predictive maintenance of machinery. +--- + +# Predictive Maintenance with the Nordic Thingy:91 + +Created By: +[Zalmotek](https://zalmotek.com) + +Public Project Link: +[https://studio.edgeimpulse.com/public/96183/latest](https://studio.edgeimpulse.com/public/96183/latest) + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/intro.jpg) + +## Intro + +Untimely critical machinery failure is one of the biggest troubles a plant manager must deal with when running a production facility. Because heavy machinery parts are expensive and lead times for replacement are getting longer and longer due to the supply crisis, employing preventive measures like equipping machinery with a predictive maintenance solution greatly improves the Overall Equipment Effectiveness (OEE). + +Such a solution measures key health indicators of machinery like vibration, temperature, and noise, analyzes them using AI algorithms and sends alerts way before machinery breaks down, allowing the facility to reduce operating costs and increase production capacity. + +## Our Solution + +To show you a real world use-case of predictive maintenance we have decided to use the Nordic Thingy:91, an easy-to-use prototyping dev kit for IoT projects, packed with a multitude of sensors relevant for our application: Low-power accelerometer, temperature, and pressure sensors. + +The on-board nRF9160 System-in-Package (SiP) supports LTE-M, NB-IoT and GNSS if you wish to send the data in the cloud and the nRF52840 allows the development of Bluetooth LE applications. + +The 64 MHz Arm® Cortex®-M33 CPU is great for running a TinyML model on the edge used to detect anomalies while the machinery is running. + +Our approach to building a predictive maintenance solution based on the Nordic Semi Thingy:91 is to attach it mechanically to a machine and collect accelerometer data during normal functioning. After a proper data set is acquired, we will train a TinyML model based on an **Anomaly Detection Neural Network** using Edge Impulse that will detect anomalies. + +### Hardware requirements + - Nordic Semi Thingy:91 + - Micro-USB cable for Thingy:91 + - J-link debugging probe + +### Software requirements + - Edge Impulse account + - nRF Connect for Desktop v3.7.1 + - [Edge Impulse CLI](https://docs.edgeimpulse.com/docs/cli-installation) + - A working Zephyr RTOS build environment achieved by installing nRF Connect SDK + - GNU ARM Embedded Toolchain (version 9-2019-q4-major) + +## Hardware Setup + +The Thingy:91 comes equipped with all the required sensors for this use-case so there is not much wiring to do. Plugging a micro-USB cable in the prototyping board is enough to do the data acquisition and to deploy the model back on the edge. If you wish to run it completely wireless, the 1359 mAh Li-Po battery is big enough to run the inference on the target for a while, varying based on the sensor reading frequency and the communication protocol used. + +Our aim is to detect faulty operation or an approaching critical machinery failure in an extruding-based machine. For this, we have attached the Nordic Semi Thingy:91 to a 3D printer in order to better schedule our maintenance operations like unclogging the nozzle, oiling the linear bearings, dusting the fan etc. Using the same principles the use case can be adapted to other much larger extruders or machines that involve any type of motors that are vibrating when functioning. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/hardware.jpg) + +## Software Setup + +First thing first, to collect our dataset, we must upload the Thingy:91 firmware provided by Edge Impulse on the dev kit. + +1. Install the latest version of [nRF Connect for Desktop](https://www.nordicsemi.com/Products/Development-tools/nrf-connect-for-desktop) from the official source on your OS of choice. +1. Install [Edge Impulse CLI](https://docs.edgeimpulse.com/docs/edge-impulse-cli/cli-installation). This is a suite of tools that is used to control local devices, act as a proxy to synchronize data for devices that are not connected to the internet and to facilitate uploading and converting local files. +1. Afterwards, [download the latest Edge Impulse firmware](https://cdn.edgeimpulse.com/firmware/nordic-thingy91.zip) and extract the archive somewhere convenient. +1. Turn on the Thingy:91 while pressing on the multi-function button placed in the middle of the board. Release the button, connect it to the PC, launch nRF Connect for Desktop and open the Programmer. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/flash.jpg) + +1. Click on Select Device, select Thingy:91 and once returned to the programmer screen, make sure that Enable MCUboot is checked. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/programmer.jpg) + +1. In the Programmer navigation bar, click Select device. +1. In the menu on the right, click **Add HEX file > Browse**, and select the firmware.hex file from the firmware previously downloaded at step 3. +Scroll down in the menu on the right to Device and click **Write**: + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/firmware-1.jpg) + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/firmware-2.jpg) + +Right now, we have everything we need to connect the dev kit to our Edge Impulse project, collect the data and train the model. Next up, we must install all the prerequisites necessary for the Deployment Phase of this project. Take note that these are necessary only if you wish to build your own custom application. + +1. Install the [nRF Connect SDK](https://www.nordicsemi.com/Software-and-tools/Software/nRF-Connect-SDK). Follow the steps in the [official documentation](https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/gs_installing.html) and instead of installing a build IDE, set up the command-line build environment. +1. Download and extract the GNU ARM Embedded Toolchain (version 9-2019-q4-major) and extract it in /home/USER/gnuarmemb +1. Install the [nRF command line tools](https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download) and [Segger J-Link tools](https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack) that will enable us to flash the board using the west command line interface. + +### Creating an Edge Impulse Project + +The first step towards building your TinyML Model is creating a new Edge Impulse Project. + +Once logged in to your Edge Impulse account, you will be greeted by the Project Creation screen. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/dashboard.jpg) + +Click on **Create new project**, give it a meaningful name, select **Developer** as your desired project type and press **Create new project**. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/new-project.jpg) + +Afterward, select **Accelerometer** data as the type of data you wish to use. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/accelerometer.jpg) + +### Connecting the device + +With the project created, it’s time to connect a device to it. Power up the Thingy:91 and connect it via a USB cable to the PC. Open up a terminal and run: + +``` +edge-impulse-daemon --clean +``` + +You will be prompted with a message to insert your username and password and then you will be asked to select which device you would like to connect to. + +``` +Edge Impulse serial daemon v1.14.10 +? What is your user name or e-mail address (edgeimpulse.com)? +? What is your password? [hidden] +``` + +You may notice that the Thingy:91 exposes multiple UARTs. Select the first one and press ENTER. + +``` +? Which device do you want to connect to? (Use arrow keys) +> /dev/ttyACM0 (Nordic Semiconductor) + /dev/ttyACM1 (Nordic Semiconductor) +``` + +Next up, select the project you wish to connect the device to, press Enter and give it a recognisable name. + +If you head back to Edge Impulse Studio, you will notice that the device shows up in the **Devices** Tab. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/devices.jpg) + +### Collecting the dataset + +When monitoring an industrial system, purposefully running it in a faulty manner to collect data dedicated to training a model for failure detection is not possible since breaking would be out of the question. Instead, our approach is collecting data in a time where the machine operates nominally / is idling / is powered off and create an anomaly detection algorithm that will detect when something is out of order. + +With the device connected, head over to the Data acquisition tab. Before acquiring data we must set a Sample Length and a Reading Frequency. + +When sensors or other devices take measurements of some physical quantity, the process of converting this analogue signal into a digital representation is known as sampling. In order for the resulting digital signal to be an accurate representation of the original, it is important to respect the Nyquist–Shannon sampling theorem when carrying out this process. The Nyquist frequency is twice the highest frequency present in the signal being sampled, and Nyquist's theorem states that if the sampling frequency is not equal to or higher than the Nyquist frequency, then aliasing will occur. This means that high-frequency components in the signal will be misrepresented in the digital version, leading to errors in the measurements.This being said, we will pick the highest frequency available, to avoid the aliasing phenomenon. + +When building the dataset, keep in mind that machine learning leverages data, so when creating a new class, try to record at least 3 minutes of data. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/dataset.jpg) + +Also, remember to gather some samples for the testing data set, as to achieve a distribution of at least 85-15% between training and testing set sizes. + +### Designing an impulse + +Once the data acquisition phase is over, the next step is designing an **Impulse**. What an Impulse does is take raw data from your dataset, split it up in manageable bites, called **“windows”**, extract features using signal processing blocks and then, classify new data by employing the learning block. + +For this example, we will make use of the **Spectral analysis** signal processing block and the **Classification** and **Anomaly Detection** learning blocks. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/impulse.jpg) + +### Configuring the Digital processing block + +Once the setup is done, clock on **Save impulse** and move over to the **Spectral features** tab that appeared under the **Impulse Design** menu. In this screen you can observe the raw data being displayed on the top side of the window and the results of the signal processing block on the right side. + +Digital signal processing theory is convoluted at times so we are not going to dwell too deep in this subject. Tweak the parameters with the target of obtaining similar results from similar data. + +In our case, we have noticed huge improvements in the mode’s accuracy when switching from Low-pass filter to a High-pass filter and increasing the **Scale axis** factor to 30. + +Once done configuring the DSP block, move forward to the **Feature generation** screen. Make sure that **Calculate feature importance** is checked and click on **Generate Features**. + +The Feature explorer is one of the most powerful tools put at your disposal by Edge Impulse. It allows intuitive data exploration in a visual manner. It allows you to quickly validate whether your data separates nicely before moving over to training the model. It color-codes similar data and allows you to trace it back to the sample it came from by just clicking on the data item, making it a great perk if you are trying to find the outsiders in your dataset. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/feature-explorer.jpg) + +When you are working on a classification-based application, what you aim to see in the Feature explorer is clearly defined clusters of data points. In our use-case, this is not the case, and the small overlap of the data clusters does not inconvenience us as we are trying to detect when the system is running outside of those nominal parameters. + +### Configure the Classifier(NN) + +Once we are happy with the collected data, we will be moving forward to training a neural network. + +Neural networks are computer algorithms that are designed to recognize patterns in large amounts of raw data. Similar in many ways to the human brain, a neural network is made up of interconnected layers of highly specialized neurons. Each neuron examines a particular aspect of the raw data, such as specific frequency patterns, and then passes this information on to the next layer through weighted connections. This process allows the network to learn how to identify different types of patterns over time, adjusting its weights accordingly based on what it has learned from past experience. Thus, neural networks have the ability to accurately recognize complex and nuanced patterns in virtually any type of data. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/training.jpg) + +In the **NN Classifier** tab, under the **Impulse Design** menu, leave the parameters on the default settings and click on the **Start Training** button and wait for the NN to be trained. Once done, you will be presented with some training performance indices like the Accuracy and Loss. In a classification-based project we would be aiming for at least 95% Accuracy but in our case, it is not required. + +### Configure the Anomaly Detector + +The Anomaly detector is a secondary Neural Network that we will employ to differentiate when data does not fit in any of the categories we have defined in the previous step. + +When we were designing the impulse for this use-case, a very important step was to check the **Generate Feature Importance** before clicking on **Generate Features**. What this does is determine what are the most relevant features in the collected data, as to increase the “resolution” of our model and to reduce the amount of processing power needed. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/anomaly-detector.jpg) + +As you can see, the predominant features in our dataset are the accY RMS and accZ RMS. + +Click on the **Anomaly detection** under the Impulse Design menu. Click on **Select suggested axes**, leave the number of clusters set on 32, and click on **Start Training**. Once the training is done, you will be prompted with the training results. You can observe that the Anomaly Explorer plots the 2 most important features against each other, and defines areas around the collected data. When new data is gathered, it is placed on the same coordinate system and if it is situated around the defined clusters, it is flagged as an anomaly. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/anomaly-explorer.jpg) + +### Model testing + +Even though we said earlier in this guide that purposefully running the machinery in a faulty manner is out of discussion, we have induced a small clog for 10 seconds in our machine to gather authentic data. + +To test out the model, head over to the **Live Classification** tab and press the **Start Sampling** button. + +Under the Summary tab you can see the number of samples that were placed in each category, and in the right side of the screen, you can see the Raw Data, Spectral Features and the Anomaly Explorer. Head over to the **Anomaly detection** under the **Impulse Design** menu and load your newly gathered sample in the Anomaly Explorer to analyze it even further. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/testing.jpg) + +## Deploying the model on the edge + +There are 2 ways going about running the Impulse we have just designed on the edge: Either deploying a pre-built binary or exporting the Impulse as a C++ library and building the binary locally. Let’s explore both in our use case and see the benefits for each: + +### 1. Deploying a pre-built binary + +Deploying the newly created model on the Nordic Thingy:91 implies running it without an internet connection, optimizing the power consumption of the device and minimizing latency between measurements and analyzing them. + +Because the Thingy:91 board is fully supported by Edge Impulse, you can navigate to the **Deployment** tab, select the board and download a ready-to-go binary for it that includes the Impulse we have just built. + +Deploying the model in this manner is a great way of evaluating the on-board performance of the Impulse with the smallest time investment possible. It allows you to go back and tweak the model until it reaches the desired performance for your application. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/deployment.jpg) + +Follow the same steps you did when uploading the custom Edge Impulse firmware on the board, only this time upload the downloaded binary file. + +Restart the board, connect it to your PC, launch a terminal and run: + +``` +edge-impulse-run-impulse +``` + +The Thingy:91 will start reading accelerometer data, run it through the previously configured DSP block and then classify it. + +``` +? Which device do you want to connect to? /dev/ttyACM0 (Nordic Semiconductor) +[SER] Connecting to /dev/ttyACM0 +[SER] Serial is connected, trying to read config... +[SER] Retrieved configuration +[SER] Device is running AT command version 1.3.0 +[SER] Started inferencing, press CTRL+C to stop... +LSE +> Inferencing settings: + Interval: 10ms. + Frame size: 600 + Sample length: 2000ms. + No. of classes: 2 + Starting inferencing, press 'b' to break + Starting inferencing in 2 seconds... + Predictions (DSP: 26 ms., Classification: 0 ms., Anomaly: 2 ms.): + Extruding: 0.26171 + Idling: 0.73828 + anomaly score: 11.67579 +``` + +Notice that we are running the edge in a 2 seconds interval. If you wish to change this parameter, navigate to the **Impulse Design** tab, select the desired window size and re-train your model. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/retrain.jpg) + +### 2. Exporting the Impulse as a C++ library and building the binary locally + +When you are done testing the model and you are happy with the results you can use this method to fully integrate with other code required to make your device functioning fully stand-alone at the edge (this could include direct control of other devices, triggering alarms, logging data or sending it remotely if needed based on your demands). Choosing this method of deploying, what you get is a library that contains all the signal processing blocks, learning blocks, configurations and SDK needed to integrate the ML model in your own custom application. + +You can find a great guide about how you can [Build an application locally for a Zephyr-based Nordic Semiconductor development board](https://docs.edgeimpulse.com/docs/deployment/running-your-impulse-locally/running-your-impulse-locally-zephyr) in the official Edge Impulse Documentation. + +If you are curious, our main.cpp file looks like this: + +``` +#include +#include "edge-impulse-sdk/classifier/ei_run_classifier.h" +#include "edge-impulse-sdk/dsp/numpy.hpp" +#include + +static const float features[] = { +1.4318, -1.8338, -12.7388, -1.7260, 1.0885, -7.9532, -1.9417, 1.9809, -7.2471, -0.8630, 0.9414, -8.3749, -0.4707, -0.1569, -8.7966, -1.2454, 0.0686, -8.8064, -0.7845, 0.1961, -9.1300, 0.2550, -0.3432, -10.4637, 0.4805, -0.7845, -10.8854, 0.1569, 0.1373, -9.2379, -0.6472, 0.1765, -9.1300, 0.9512, -1.4220, -11.7189, 2.2948, -0.9512, -10.4735, 6.6195, 1.0885, -9.9439, 16.6027, 4.9622, -9.7576, 20.0742, 11.7778, -9.6301, 9.0712, 10.6304, -9.3163, 1.5593, 10.4931, -9.4732, -8.8946, 6.9823, -10.5716, -20.0840, 2.5399, -8.6495, -20.0840, -4.0796, -8.0709, -9.8851, 0.5198, -8.5024, -3.3539, 2.4517, -7.8257, 1.0787, 0.4511, -8.2180, 4.1286, 0.2844, -8.3749, 0.2059, -0.6374, -10.6206, 0.4217, -0.9316, -10.0714, -0.8434, 0.0981, -9.0221, -1.5691, 0.9120, -10.0420, -1.9613, 1.4612, -7.1981, -2.0692, -0.8630, -9.3163, -2.5301, 0.1275, -8.5808, -2.0300, 0.2059, -8.6789, -2.3438, 0.3236, -8.3749, -1.7750, -0.5982, -8.1787, -2.5007, 0.0294, -9.5811, -1.7456, 0.7649, -7.6982, -1.5691, 0.8826, -8.3945, -1.8338, 0.0981, -9.9439, -1.6867, -0.2157, -9.0025, -1.4710, 0.8336, -8.2768, -1.5593, 0.5198, -8.5024, -0.2157, 1.0395, -8.7868, 0.3334, 0.7257, -9.2084, -0.9709, -0.1569, -9.9930, -3.0891, 1.4023, -7.7374, -0.6472, 0.0000, -10.0518, 0.8238, -1.5396, -11.5130, 0.0000, 1.1964, -8.4533, 0.1471, 1.5495, -10.3656, -1.9613, 0.3923, -9.2575, -1.9515, -0.4217, -9.8459, -0.6374, 0.7355, -8.4828, 1.1964, 1.1474, -9.2084, 1.9319, 0.8924, -8.7671, -0.2354, 1.3043, -8.5808, -0.5884, -0.5296, -9.8949, 0.8434, 0.3040, -9.2477, 1.2454, 1.1964, -7.9532, 1.4514, 0.6178, -9.3163, 2.6674, 0.5198, -9.4046, 2.6086, 1.6671, -9.4046, 3.5010, -0.7257, -9.8361, 17.4755, 4.2365, -9.1006, 20.0742, 10.9050, -9.2575, 10.7481, 12.1995, -8.7868, 0.5786, 7.9434, -8.6887, -4.9229, 11.8464, -8.4828, -14.1216, 2.9028, -8.8456, -19.1328, -1.4906, -10.2578, -20.0840, -0.6865, -8.5318, -14.1020, 0.8826, -10.0420, -2.0986, -0.8434, -11.4051, -3.0401, -0.2648, -9.6497, 2.9028, -1.9907, -11.6111, 2.7949, 0.2059, -8.8946, 0.7257, 0.4511, -7.9532, -0.7943, 0.4119, -9.0025, -0.5198, -0.7747, -9.4046, -0.5099, 0.0785, -7.8159, -0.5982, 0.1177, -8.6397, 0.1471, -1.2258, -10.8462, -0.1863, -0.5296, -9.9930, -2.0398, 0.4805, -8.3357, -1.3141, -0.9218, -10.3852, -2.9126, -0.1569, -8.8162, -1.7162, -0.1471, -10.0616, -1.4906, 0.9709, -9.0025, -1.3631, 0.2059, -9.1594, -0.8434, 0.5688, -8.2180, 0.6767, -2.0986, -11.5032, -0.2157, -0.3432, -9.9930, -2.3046, 0.6963, -7.8551, -0.3138, 1.0199, -9.4144, 0.6374, 0.8532, -10.2087, -0.9414, -0.4021, -9.1006, -1.6769, 0.3628, -8.5024, -1.3631, -0.4217, -9.8361, -3.1479, 1.3043, -7.2177, -4.5601, 1.8240, -6.5901, -1.7848, 0.8238, -8.2670, -1.4710, 1.8829, -7.3256, -2.2261, 0.8728, -7.9630, -1.6279, 0.3628, -10.0518, -1.9417, 1.5887, -8.3749, -0.3138, 0.9218, -9.2084, -0.1079, 0.9120, -9.4242, -0.2648, 1.2258, -8.1787, 1.7946, -0.3236, -10.2087, 0.9414, -0.3236, -9.8067, 1.6377, 1.4122, -7.3746, 1.3533, 0.9611, -8.3749, 1.0395, 1.1180, -8.9241, 2.0888, 0.8336, -9.6497, 5.5408, 3.9129, -8.7083, 20.0742, 3.3931, -11.4051, 20.0742, 14.3177, -11.0913, 14.3962, 13.4253, -11.5032, 3.7363, 9.5321, -9.6301, -8.5906, 12.2779, -11.1698, -20.0840, 4.7072, -9.4144, -20.0840, -1.9417, -8.6887, -20.0840, 1.0395, -10.2578, -2.9910, 0.7845, -9.8753, -0.0392, 0.9414, -9.2281 +}; + +int raw_feature_get_data(size_t offset, size_t length, float *out_ptr) { + memcpy(out_ptr, features + offset, length * sizeof(float)); + return 0; +} + +int main() { + k_msleep(7000); + // This is needed so that output of printf is output immediately without buffering + setvbuf(stdout, NULL, _IONBF, 0); + +#ifdef CONFIG_SOC_NRF5340_CPUAPP + // Switch CPU core clock to 128 MHz + nrfx_clock_divider_set(NRF_CLOCK_DOMAIN_HFCLK, NRF_CLOCK_HFCLK_DIV_1); +#endif + + printk("Edge Impulse standalone inferencing (Zephyr)\n"); + + if (sizeof(features) / sizeof(float) != EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE) { + printk("The size of your 'features' array is not correct. Expected %d items, but had %u\n", + EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, sizeof(features) / sizeof(float)); + return 1; + } + + ei_impulse_result_t result = { 0 }; + + while (1) { + // the features are stored into flash, and we don't want to load everything into RAM + signal_t features_signal; + features_signal.total_length = sizeof(features) / sizeof(features[0]); + features_signal.get_data = &raw_feature_get_data; + + // invoke the impulse + EI_IMPULSE_ERROR res = run_classifier(&features_signal, &result, true); + printk("run_classifier returned: %d\n", res); + + if (res != 0) return 1; + + printk("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n", + result.timing.dsp, result.timing.classification, result.timing.anomaly); + + // print the predictions + printk("["); + for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) { + ei_printf_float(result.classification[ix].value); + +#if EI_CLASSIFIER_HAS_ANOMALY == 1 + printk(", "); +#else + if (ix != EI_CLASSIFIER_LABEL_COUNT - 1) { + printk(", "); + } +#endif + } +#if EI_CLASSIFIER_HAS_ANOMALY == 1 + ei_printf_float(result.anomaly); +#endif + printk("]\n"); + + k_msleep(2000); + } +} +``` + +## Conclusion + +While reactive and preventive maintenance require constant effort from the support team, predictive maintenance seems to be, in our opinion, a very good choice not only to minimize their presence on the factory floor but also help factories reduce their inventory costs by identifying spare parts that are likely to be needed in the future. As a result, predictive maintenance is a useful tool for factories that want to minimize disruptions and improve their bottom line. + +![](.gitbook/assets/predictive-maintenance-with-nordic-thingy-91/conclusion.jpg) + +