×

可以喷洒微滴酒精的小型机器人构建

消耗积分:0 | 格式:zip | 大小:0.23 MB | 2022-11-04

张英

分享资料个

描述

抽象的

办公室、餐厅、图书馆有许多共享工作空间。人们来来去去。在这次 COVID-19 大流行中,我们需要确保这些工作空间在其他人来使用它们之前是清洁和消毒的。该项目将应用 AWS IOT 技术和 H/W M5Stack CORE2 for AWS 来控制机器人在人们离开工作区后喷洒酒精并用 UV-C 灯清洁地板。

项目描述

我们计划建造一个小型机器人,它可以喷洒微滴酒精,同时机器人会携带紫外线消毒器,以确保工作空间的清洁和安全。用户通过扫描餐桌上的二维码开始使用工作区,完成后只需按下移动 Web 上的“完成”按钮。AWS IOT 将计算使用持续时间并命令机器人开始使用 UV-C 射线和酒精喷雾进行清洁。同时,此用法将保留在 Dynamo DB 中。如果感染了 COVID-19 的人以前使用过此工作区,此数据库将用于历史跟踪。

(注意***我们计划使用 PIR 传感器来检测人来并使用 Alexa 来获取用户的姓名。但是 PIR 传感器非常不可靠,用户需要一直坐在桌旁,这不实用。对于 Alexa , 没有简单的方法将语音转换为文本。由于时间限制,我们选择将解决方案与建议的解决方案稍微改变一下。)

系统架构

这个项目有两个部分。

1)客户端,使用M5 stack Core 2来控制所有机器人的动作,如前进、后退、左右转、喷酒精和控制紫外线。检查所有传感器以防止与物体碰撞和跌倒检测。当用户使用完工作区后,该机器人将由 AWS IOT 控制。AWS IOT 会将工作区占用标志更新为 false(意味着工作区现在可用) CORE2 将更新使用时间并开始机器人清洁。完成清洁后,机器人将停止工作,工作空间可供下一个人使用。

2)服务器端使用AWS上的一些服务。用户开始扫描桌面上显示的二维码注册姓名。该网站是一个简单的静态网站,存储在 Amazon S3 AWS 上。当用户按下注册按钮时,javascript会将信息传递给存储在API网关上的Restful API。API 网关将调用 AWS lambda 在 AWS IOT 上更新设备或获取设备影子的设备状态。AWS IOT 更新工作区和机器人的状态,并在用户使用完工作区后发布到 Dynamo DB。

我们可以用下图总结所有活动

poYBAGNkfy2ATt-eAAB1riDoDEY541.png
 

先决条件

因为这个项目需要很多技术的基础。通过完成以下教程,您应该熟悉这些技术。

  • AWS 服务(S3、API 网关、Lampda、AWS IOT)您可能需要查看每项服务的教程。这些 AWS 服务的 Google 教程。
  • 熟悉platformIO和Core2forAWS的开发环境。转到https://edukit.workshop.aws/en/getting-started.html以获取教程,按照说明直到主题 3 智能恒温器。这将确保您可以连接到 AWS 服务并通过所有安全检查。我们的项目是从这个项目扩展而来的。
  • 从 S3 -> API-> Lampda->AWS IOT 的应用流程。本教程对于让您了解每个 AWS 服务之间的流程非常有用。https://iot-esp32.workshop.aws/en/module3.html项目实施

硬件实现

对于硬件构建,我们需要添加额外的两个 M5stack 模块(M5Stack DC Motor 和 M5Stack Proto)DC 电机模块带有四个用于乐高电机的连接器,非常适合我们的快速原型。我们使用原型模块将 CORE2 总线连接到 14 针插座。这些模块可以按顺序堆叠,但要注意堆叠的顺序

Core 2 --> Proto --> DC Motor --> M5GO2(自带core2)

 
 
 
pYYBAGNkfzCAe4T3AABqyB9XUSc108.png
 
1 / 3M5Stack core2 总线图
 

************************************使用 < > 查看更多图片 ********* ************************

我们在这个项目中使用的端口是

  • 用于 UV-C LED 的 GPIO32
  • GPIO27 酒精喷雾
  • 用于红外传感器的 GPIO13、GPIO36
  • GPIO 33、26 用于跌倒检测
  • 用于 PIR 的 GPIO 19
  • GPIO3、GPIO1、GPIO35(未使用)
  • 5V引脚
  • 3V引脚
  • 接地引脚

在 Core2 上使用 GPIO 对我来说非常棘手。您需要考虑许多限制。这是我可以从数据表中收集的一些信息。

  • 应避免使用这些端口 GPIO1、GPIO3、GPIO12、GPIO15,因为它们可能用于调试和闪存。
  • 端口 34 - 39 只能用于 I/P,没有上拉/下拉
  • 端口不是 5V 容差,这意味着如果您的传感器是 5V 传感器类型,您需要使用电平转换器。并且某些电平转换器无法正常工作,如果您想避免出现问题,请确保购买优质的。

对于电平转换器,我将它放在一个单独的盒子中,其中包括 PIR 传感器、继电器模块以及传感器和外围设备的所有连接,如图所示。

pYYBAGNkfzaAaXAkAAEf901kjiU886.png
控制箱
 

有两个设备需要两个继电器来打开/关闭。因为我们使用在市场上销售的商业广告。需要进行一些修改。

酒精喷雾

我们使用便携式酒精喷雾,只需 2 美元即可轻松购买。本设备配有内置电池。我们只是从按钮开关并联到我们的插座,如图所示。

 
 
 
poYBAGNkfzmAGaNZAABFQ4jkhUs633.png
 
1 / 2
 

UV-C LED

请注意,并非所有的紫外线都能杀死病毒。您需要使用比普通 UV Led 更昂贵的 UV-C 产品。UV-C 对眼睛和皮肤有危险。请确保您在实验过程中不要暴露在这种光线下。我买了手机UV-C盒子,取出UV-C模块。对于这个模块,我需要连接外部电池(1x 18650 Battery 3.7V)因为电池在盒子里太大了。如图所示,我从启动开关到插座并联接线。

 
 
 
pYYBAGNkfzuAM9NCAABJLEVhNRk614.png
 
1 / 3拆卸前
 

电池盒

核心 2 无法为两个电机提供足够的电力。我们需要一个单独的电池来驱动直流电机。我为 2x 18650 选择电池盒。这将连接到直流电机模块。您必须使用 3.7 V 的电池来驱动 UV-C 模块。我没有这个的照片。您可以选择任何您喜欢的电池盒。

机器人框架

因为我们使用乐高电机,所以我选择使用乐高构建机器人框架。如果你不是乐高迷。您可以根据可用的材料和想象力选择任何电机和框架。这是我使用乐高的机器人框架的图片。

 
 
 
poYBAGNkfz6AaR-CAAD58772ELU226.png
 
1 / 5
 

传感器

在这个项目中使用了四个传感器,两个在前面用于跌倒检测和碰撞检测,另外两个在后面。我使用两种不同类型的红外传感器进行跌倒检测和碰撞。如图所示。

poYBAGNkf0eAWOpxAACUfQ7nX9E900.jpg
 

使其与乐高兼容。我把乐高板贴在传感器的背面。对于这个技巧,您可以使用小塑料盖作为盒子的家用电灯开关。

完成所有接线并安装所有传感器、组件。这是消毒机器人的最终说明。

 
 
 
pYYBAGNkf0qADH4gAADlqvbmuo0328.png
 
1 / 5
 

软件实施

软件实现有很多部分。了解更多概念。您可能需要开始学习这两个教程

  • 了解有关此项目中使用的 AWS IOT 概念和工具的更多信息。

https://iot-esp32.workshop.aws/en/introduction.html

  • 了解有关许多 AWS 服务流程的更多信息。

https://iot-esp32.workshop.aws/en/module3.html

更完整的源码请到github https://github.com/wtos03/HealthySpaces

我将仅提取一些代码片段以进行解释。

网页

该页面将用于注册工作区,如下图所示

poYBAGNkf0yAFOeuAABUSoeS69Q727.png
 

用户开始选择注册地点。此选项菜单将帮助将名称转换为 AWS IOT 中使用的事物名称。

<select name="roomNames" >
            <option value="0123a8024945e75c01">    Binary Roomoption>
            <option value="TT">    Analog Roomoption>
select>

用户输入姓名并按注册按钮后。网页将发布带有 Jason 格式数据的请求(工作空间状态的名称和 wsOccupancy 标志)以预定义 Web API 影子状态(参见 url:下面)

$("#register").click(function(event){
 
            currentvalue = document.getElementById('register').innerHTML;
            yourName = document.getElementById('name').value;
             
            // trying to add the value from text box 
            thingName = document.getElementById("roomNames").value;
            console.log(thingName);
            var mydata={"action":"on","wsOccupancy":true,"userName":yourName, "thingname":thingName};
            console.log(mydata);
            document.getElementById("status").innerHTML= `Workspace Usage : ${yourName}`;
            document.getElementById("status").setAttribute("class","button is-rounded is-large is-fullwidth is-loading");
            $.ajax( {
                type: 'POST',
                url:'https://u2gtqb6j39.execute-api.us-west-2.amazonaws.com/Dev/shadow-state',
                contentType: 'application/json',
                crossDomain: true,
                processData: false,
                dataType: "json",
                data: JSON.stringify(mydata),
                success:function(data) {
                console.log(" on success");
                document.getElementById("status").setAttribute("class","button is-success is-rounded is-large is-fullwidth");
                },
                error:function(data) {
                    console.log(" on fail;");
                    document.getElementById("status").setAttribute("class","button is-success is-rounded is-large is-fullwidth");
                }
            });
        });

如果用户按下 Finished 按钮,wsOccupancy 标志将设置为 false 并发布到与注册过程相同的 API。

如果用户按下 Occupy 按钮来检查 Workspace 的状态,网页将向预定义的 Web API 影子状态发送获取请求。此 API 将返回可用或已占用的工作区状态。

$("#status").click(function(event){
            console.log("Checking Workspace status");
            //check the status of Shadow
            // thingName = "ESP32"
            thingName = document.getElementById("roomNames").value;
            console.log(`thingname=${thingName}`);
            $.ajax( {
              type: 'GET',
               url:'https://u2gtqb6j39.execute-api.us-west-2.amazonaws.com/Dev/shadow-state',
               contentType: 'application/json',
               crossDomain: true,
               processData: false,
               dataType: "json",
               data: `thingname=${thingName}`,
               success:function(data) {
                console.log("success");
                console.log(data.status);
                document.getElementById("status").innerHTML=data.status;
                if (data.status == "Available" )
                {
                  document.getElementById("status").setAttribute("class","button is-success is-rounded is-large is-fullwidth");
                }
                else{
            
                  document.getElementById("status").setAttribute("class","button is-danger is-rounded is-large is-fullwidth");
                }
               },
               error:function(data) {
                 console.log("error");
               }
            });
        });

静态网页的优点是您可以在任何支持Javascript的网络浏览器下在本地网页上运行它。无需 Web 服务器托管此服务。但是要分享这个网页,我们可以上传到 S3 存储桶并将它们标记为静态网页。通过将此文件 (index.html) 上传到 S3 存储桶并启用为静态网站托管。定义公共访问权限或仅特定组的权限。并复制 Bucket 网站端点以在网页上使用。在这个例子中是

http://cleanws.com.s3-website-us-west-2.amazonaws.com

我们可以翻译此 URL 以创建 QR 码或放入 NFC 标签,以供人们来到工作区时访问。

兰普达功能

在创建 API 网关之前,我们需要先创建 Lampda。因为 API 需要 Lampda 函数名指向。

我们需要创建两个 Lampda 函数

  • Shadow_Status_Check 此函数通过获取 wsOccupancy 标志的值来检查 AWS IOT 的状态。如果 true 将返回值“Occupied”以显示在网页上。如果 false 将返回值“可用”。该标志将从报告的影子状态中读取。
  • Shadow_Update 此函数使用 wsOccupancy 和 userName 的值更新 IOT 设备影子的状态。

这些源代码是用 python 3.8 编写的。确保这两个功能有权访问 AWS IOT 服务(在左侧的配置和权限选项卡下

pYYBAGNkf1GAaMa6AABoYw9WUr0401.png
 

所有源代码都位于 LampdaFunctions 目录下

API网关

让网页轻松访问 AWS IOT 服务。我们可以定义连接到 Lampda 函数的 API。Lampda 功能可以连接到 AWS IOT 服务。我们无法创建 Web API 来直接连接到 AWS IOT。(我不知道原因,但我认为这是安全问题)要创建 API,您需要创建资源影子状态和两个方法 get 和 post。

“获取方法”链接到“Shadow_Status_Check”Lampda 函数。

“发布方法”链接到“Shadow_Update Lampda”功能。

pYYBAGNkf1SAb0XeAADm9fjZryQ290.png
 

 

AWS 物联网

我们没有在 AWS IOT 服务器上进行太多配置。大多数在客户端完成的任务都是由 CORE2 模块完成的。确保正确设置所有配置和安全性。在开始这部分工作之前,请在https://edukit.workshop.aws/en/getting-started.html运行这两个教程 Cloud Connected Blinky 和 ​​Smart Thermostat 。

ThingName 将使用每个设备唯一的设备 ID 自动创建。

CORE 2 将开始连接 AWS IOT Shadow 服务并在数据 userName 和 wsOccupancy 标志上注册增量更改

// register delta callback for workSpaceActuator and nameActuator
rc = aws_iot_shadow_register_delta(&iotCoreClient, &nameActuator);
if(SUCCESS != rc) {
ESP_LOGE(TAG, "Shadow Register userName Delta Error");
}
rc = aws_iot_shadow_register_delta(&iotCoreClient, &workSpaceActuator);
if(SUCCESS != rc) {
ESP_LOGE(TAG, "Shadow Register wsOccupancy Delta Error");
}

这两个 Actuator 将注册回调函数,如下面的数据结构。

jsonStruct_t nameActuator;
nameActuator.cb = userName_Callback;
nameActuator.pKey = "userName";
nameActuator.pData = &userName;
nameActuator.type = SHADOW_JSON_STRING;
nameActuator.dataLength =  MAX_NAME_LENGTH;

jsonStruct_t workSpaceActuator;
workSpaceActuator.cb = occupancy_Callback;
workSpaceActuator.pKey = "wsOccupancy";
workSpaceActuator.pData = &wsOccupancy;
workSpaceActuator.type = SHADOW_JSON_BOOL;
workSpaceActuator.dataLength = sizeof(bool);

计算开始和停止使用时间之间的时间差。我们需要先正确设置时间。为了方便设置和方便,我们使用 ntp 协议来设置时间,它在 ntptime.h 中定义并在 ntptime.c 中实现。当 CORE2 将 wsOccupancy 的更新 delta 状态从 false 变为 true 时,CORE2 将在 LED 条上打开红色,获取 startUsagetime 并将 robotStatus 更改为“Stop Clean”

if (*(bool *)(pContext->pData)) //True mean workspace is used
{
Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_LEFT, 0xFF0000);
Core2ForAWS_Sk6812_SetSideColor(SK6812_SIDE_RIGHT, 0xFF0000);
Core2ForAWS_Sk6812_Show();
// Add starttime
getTimeStructure(&startTime);
strftime(startUsageTime, sizeof(startUsageTime), "%c", &startTime);
ESP_LOGI(TAG, "The current date/time in Thailand is: %s", startUsageTime);
strcpy(robotStatus,"Stop Clean");
}

如果用户使用完工作区。wsOccupancy 的 delta 标志将从 true 变为 false,这将触发获取 stopUsageTime,以 HH:MM 格式计算时间差,停止 LED 条并将机器人状态更改为“开始清洁”

else
{
Core2ForAWS_Sk6812_Clear();
Core2ForAWS_Sk6812_Show();
// Add stoptime
getTimeStructure(&stopTime);
strftime(stopUsageTime, sizeof(stopUsageTime), "%c", &stopTime);
ESP_LOGI(TAG, "The current date/time in Thailand is: %s", stopUsageTime);
// Find time difference
diffTimePeriod (stopTime,startTime,&diffTime);
sprintf(durationTime,"%d Hr: %d Min: %d Sec",diffTime.tm_hour,diffTime.tm_min,diffTime.tm_sec);
ESP_LOGI(TAG, "The workspace usage time  is: %s \n", durationTime);
strcpy(robotStatus,"Start Clean");
}

CORE2 将在第 461 行指定的每个特定时间发送报告设备影子

vTaskDelay(pdMS_TO_TICKS(1000));    Line 461

发电机数据库

该数据库将继续使用工作区。一旦用户完成使用工作区并且 CORE2 完成计算使用时间,我们将发布到 DB。您需要为保存的数据创建表,定义主键。有关更多信息,请访问此网站以了解更多如何在 Dynamo DB 中存储设备数据

https://docs.aws.amazon.com/iot/latest/developerguide/iot-ddb-rule.html

要发布到数据库,我们需要在左侧的规则选项卡下定义规则来处理物联网数据。规则查询将使用 SQL 语句开始发布到数据库。这需要改进 SQL 语句以仅在用户完成时发布。

SELECT state.reported.userName, state.reported.temperature, state.reported.startUsageTime, state.reported.stopUsagetime, state.reported.durationHandler FROM '$aws/things/0123a8024945e75c01/shadow/update/accepted'

机器人控制

这是我们从 aws_iot_task 注册单独进程的另一个任务

xTaskCreatePinnedToCore(&robot_task, "robot_task", 2048, NULL, 3, NULL, 1);
xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 4096*2, NULL, 5, NULL, 0);

robotStatus 标志将用于控制机器人的状态。如果用户离开工作区,状态将变为开始清洁,机器人将开始清洁,直到完成或其他用户进入。这部分尚未完全实施。当机器人撞到东西或几乎要​​摔倒时,只需简单的服务,如前进、后退、左转、右转和掉头。实现机器人移动算法需要更多的时间来开发和测试。

使用 i2c 协议的直流电机驱动器在目录组件 /dc-motor/m5-dcmotor.c 中实现

项目测试

因为我的设备在截止日期前三天停止工作。(CORE2 无法重新编程。引导信息显示 PSRAM 读取错误) 屏幕像这样出现垃圾。

pYYBAGNkf1eAC1SMAABeD3xupmI581.png
 

我不能有视频来展示项目的最终工作。但是在开发期间。所有功能(电机运动、传感器。和打开设备的继电器都已经过测试并且运行良好。除了 GPIO 有时会在传感器上读取错误。

AWS 和 CORE2 之间的逻辑已经过测试。当用户按下完成按钮时机器人开始工作,并在发生新注册时停止工作。唯一错过测试的一件事是在打开 UV-C 和酒精喷雾时进行传感器检查。

正如您在此视频中看到的,AWS 部件工作正常。

 

以史为鉴

我从这个项目中学到了一些技巧。对其他人进一步发展而不是再次尝试和错误将是有用的。

  • CORE2 中的许多设备共享相同的 i2C 总线,这有时会导致问题。例如,我的直流电机控制和 MPU6886 协同工作有问题。
  • 在项目快完成时升级开发环境或拉新库是一个坏主意。这导致我的项目完全停止。我无法及时解决问题。
  • 端口 ESP32 不是 5v 容差。不能直接连接 5 V 传感器。
  • FreeRtos 取决于任务计划。这会影响您的实时操作。我在从输入端口读取值以及调整时间延迟或添加更多任务时遇到问题。我从读取端口得到了不同的行为。
  • AWS 中有很多安全设置。这给我带来了很多问题,直到我决定打开所有安全性。这将是一个很大的安全漏洞。黑客可以使用您的 API 来管理 AWS IOT。我希望亚马逊将在安全设置方面进行更多改进,使其集中且易于设置和理解

我希望你觉得这个项目很有用。建议复制并粘贴此项目的某些部分,以帮助您更快地开发项目。我会很高兴听到这个消息。谢谢你。

 


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !