当前位置: 首页 > news >正文

Mind+积木编程控制小水泵给宠物喂水

          前期用scratch,带着小朋友做了大鱼吃小鱼、桌面弹球、小学生计算器3个作品,小朋友收获不小。关键是小家伙感兴趣,做出来后给家人炫耀了一圈后,兴趣大增,嚷嚷着要做更好玩的。

         最近,娃妈从抖音上买了个小猫喝水的容器,一通电,水龙头就自动出水,猫咪就跑过来了。小朋友又发现了新大陆,摆弄起了开关,逗着猫咪。看到这,我心想这玩意能搞成自动化,跟scratch结合起来,正好又卡着小朋友的兴趣点,连玩带学,一箭双雕。

以上为背景。


因为上学的时候折腾过单片机,初步判定这个功能用单片机控制肯定是可行的,大概搜了下scratch这类少儿编程软件也支持单片机,所以整体方案可行,初步制定了功能如下:

  • 基础功能:图形化编程,用积木控制,角色可以是小猫,运动来触发单片机
  • 增强功能:如果孩子感兴趣,继续增加灯光控制,与水龙头联动
  • 增强功能:如果孩子感兴趣,继续增加光电控制,用红外线或者声音触发水龙头开关

功能定义清楚后,然后就是寻找资料,分析技术可行性:

编程软件选型

上文提及了,孩子之前用的是Scratch,因为一些原因,Scratch在国内逐步被替换,可选的有如下:

  • Kittenblock
  • ClipCC
  • Mind+
  • PictoBlox

大概看了下,功能都差不多,基本与Scratch旗鼓相当,因为要连单片机,我主要关注扩展性,就选了Mind+,其实Kittenblock也差不多,先入为主就选了Mind+

官方网站:Mind+官网传送门

选择Mind+的另一个原因是,Mind+的开发者网站有大量电子积木的教程,与我的诉求匹配,无脑选了它了,

开发者网站:https://mindplus.dfrobot.com.cn/

扩展库选型

之所以要讨论这个,主要原因看Mind+教程,如果要控制单片机,无非就是usb口转串口,那么不得不用有线的方式连接单片机和控制设备。目前给小朋友编程用的是华为的平板,如果再连个usb线,恐怕小朋友会丧失玩下去的乐趣,所以要考虑无线连接,硬件方面(下个章节讨论)应该没问题,软件层面要支持无线连接的,从Mind+网站上看可以有python和nodejs两种,对应python和js两种语言,小朋友还没上小学,代码编程自然是不考虑的,所以要把上述两种语言“封装”到积木中,把涉及TCP数据包收发的逻辑的嵌入到积木中。显然js和python都可以胜任TCP收发任务。

在Mind+中,python扩展是包含在“Python”模式中的,每个积木对应着一段python代码,通过搭积木的方式组织代码。对于学龄前小朋友,这个可视化功能还是有点太深奥了,暂不考虑。另外,Python模式下,角色功能也不可用(猜测是python模式更偏代码逻辑,弱化了角色),而我家小朋友还处于启蒙阶段,没有了角色,兴趣也会大大减弱。

在Mind+中,nodejs扩展是集成到“实时”模式中的,实时模式就是普通的模式,包含了场景和角色,和我的诉求很贴合。从官方的说明,nodejs类里面可以扩展实时模式用户库,库里面可以构造一个或者多个block,可以自定义block的外观,以及自定义block的运行逻辑。

Mind+从V1.6.5开始开放 实时模式用户库,内部兼容 Scratch扩展语法,,本文档将介绍如何开发Mind+实时模式用户库,阅读此文档需要你掌握 JavaScript的基础知识以及了解一些ES6的新特性。
如果你在阅读过程中产生疑惑, 请加入官方交流群(671877416)。
在开发之前, 你需要知道 能做出什么东西.
添加不依赖硬件的模块 可以很方便的使用第三方JS库
为mind+中已有的主板/套件增加硬件小模块
添加自己的硬件套件并通信

从上述官方教程引用看,实时模式用户库完全符合我的诉求,就选它了。

硬件选型

因为喝水的容器已经小水泵已经有了,如下图:

那么剩下的就是买单片机、电机驱动板、LED灯,以及必要的连接线了,Mind+官方支持Arduino,ESP32,ESP8266,这些都是市面上很常见的,

从节约成本的角度,就选ESP32了,其他的随便买。

元件列表


以下开始教程:


硬件连接

马云家买的元件,购买链接怎么连硬件基本说的很清楚了,需要注意的就是注意电压及正负极,别烧板子了。

如下 图:

ESP32固件:

基于Arduino的示例代码,简单改下即可,注释不多,凑合看,不复杂。

定义了3个gpio口

5 --输出口,连电机驱动板,用于控制小水泵的启动/停止

17 --输出口,直接连一个小LED灯

16 --输入口,连红外传感器,用于控制电机的启动/停止

代码运行逻辑为:水泵受两个管脚的控制,一个是来自上位机(Mind+)的指令,一个是红外传感器,红外传感器的优先级高于上位机指令,实现的效果就是小猫靠近,水龙头打开;小猫离开,水龙头由上位机控制。

/*WiFi Web Server LED/Motor Control*/#include <WiFi.h>const char* ssid     = "xxxxx";
const char* password = "xxxxx";
const int MOTOR = 5;
const int LIGHT = 17;
const int NEAR = 16;WiFiServer server(80);void setup()
{Serial.begin(115200);pinMode(MOTOR, OUTPUT); pinMode(LIGHT, OUTPUT); pinMode(NEAR, INPUT); delay(10);// We start by connecting to a WiFi networkSerial.println();Serial.println();Serial.print("Connecting to ");Serial.println(ssid);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}Serial.println("");Serial.println("WiFi connected.");Serial.println("IP address: ");Serial.println(WiFi.localIP());server.begin();}int lastValue = LOW;void loop(){int state = digitalRead(NEAR);if (state != lastValue ) {lastValue = state;if (state == HIGH){Serial.println("receive near signal: HIGH");digitalWrite(MOTOR, HIGH);return;} else {Serial.println("receive near signal: LOW");digitalWrite(MOTOR, LOW);}}sleep(1);WiFiClient client = server.available();   // listen for incoming clientsSerial.println("server created, wating ...");  if (client) {                             // if you get a client,Serial.println("New Client.");           // print a message out the serial portString currentLine = "";                // make a String to hold incoming data from the clientwhile (client.connected()) {            // loop while the client's connectedif (client.available()) {             // if there's bytes to read from the client,char c = client.read();             // read a byte, then//Serial.write(c);                    // print it out the serial monitorif (c == '\n') {                    // if the byte is a newline characterif (currentLine.startsWith("motoron")) {digitalWrite(MOTOR, HIGH);               // GET /H turns the LED on}if (currentLine.startsWith("motoroff")) {digitalWrite(MOTOR, LOW);                // GET /L turns the LED off}if (currentLine.startsWith("lightoff")) {digitalWrite(LIGHT, LOW);                // GET /L turns the LED off}if (currentLine.startsWith("lighton")) {digitalWrite(LIGHT, HIGH);                // GET /L turns the LED off}Serial.println("receive msg:" + currentLine);  currentLine = "";break;} else if (c != '\r') {  // if you got anything else but a carriage return character,currentLine += c;      // add it to the end of the currentLine}// Check to see if the client request was "GET /H" or "GET /L":}}// close the connection:client.stop();Serial.println("Client Disconnected.");}
}

代码写完后,上传到ESP32中(教程很多,不展开说明了),可以通过网络调试助手这类工具,发送“motoron”等指令,确保ESP工作正常。

Nodejs Block定义

Nodejs中定义两个Block,分别控制LED灯和水泵的开关,并且定义两个控制函数(motor和light),分别控制LED和水泵的运行逻辑,不复杂,直接上代码了。

import ArgumentType from './extension-support/argument-type';
import BlockType from './extension-support/block-type';
import blockIconURI from './image/icon.svg';class YourExtension{constructor(runtime) {this.runtime = runtime;}getInfo () {const operator_values = [["打开","1"],["关闭","0"]];return {name: '小猫喝水',blockIconURI: blockIconURI,blocks: [{  opcode: 'motor',blockType: BlockType.COMMAND,text: ' [OPERATOR] 小猫喝水的龙头 ',arguments: {OPERATOR: {type: ArgumentType.STRING,onlyField: true,options: operator_values,defaultValue: operator_values[1][1]}}},{  opcode: 'light',blockType: BlockType.COMMAND,text: ' [OPERATOR] 水龙头的灯泡 ',arguments: {OPERATOR: {type: ArgumentType.STRING,onlyField: true,options: operator_values,defaultValue: operator_values[1][1]}}},],}}// block运行函数, 与opcode同名motor (args) {// NUM1与NUM2参数都是'ArgumentType.STRING'类型, 所以要parseInt解析成numbervar msg = '';switch (args.OPERATOR){case "1":msg = "motoron\n";break;case "0":msg = "motoroff\n";break;default:msg = "motoroff\n";break;}const net = require("net");const HOST = "192.168.5.130";const PORT = 80;const client = new net.Socket();client.connect(PORT, HOST, function() {//客户端向服务端socket发送数据client.write(msg);});}light (args) {// NUM1与NUM2参数都是'ArgumentType.STRING'类型, 所以要parseInt解析成numbervar msg = '';switch (args.OPERATOR){case "1":msg = "lighton\n";break;case "0":msg = "lightoff\n";break;default:msg = "lightoff\n";break;}const net = require("net");const HOST = "192.168.5.130";const PORT = 80;const client = new net.Socket();client.connect(PORT, HOST, function() {//客户端向服务端socket发送数据client.write(msg);});}
}
module.exports = YourExtension;

其中:

const HOST="192.168.5.130";要改成ESP在局域网下的真实IP地址,可以通过ESP上电后控制台打印的log查看。

ESP log

在代码目录下执行npm run build,确保编译成功

npm build

Mind+操作步骤

在上述nodejs编译成功后,在Mind+中添加用户库,具体教程参考,也不展开讲了。

https://mindplus.dfrobot.com.cn/ext-js

注意,官方教程有个坑,nodejs的版本不能用最新的,建议用14.16.0版本,配套的Mind+版本是1.7.3,笔者用这两个版本配合没有问题,用最新的nodejs就出怪异问题。

按官方教程操作,编译,添加扩展后,最终,在Mind+实时模式下,可以看到如下两个用户自定义Block

写了两份示例代码,当然,这个大家就可以发挥想象力了,没有固定的模板。

案例一:用空格键切换水泵的开启/关闭状态

案例2:用角色移动,控制水泵的开启/关闭

硬件也简单整理下,看上去像是一个具有实用价值的工具兼玩具。

运行效果视频

积木运行效果

教程结束,enjoy!

相关文章:

Mind+积木编程控制小水泵给宠物喂水

前期用scratch&#xff0c;带着小朋友做了大鱼吃小鱼、桌面弹球、小学生计算器3个作品&#xff0c;小朋友收获不小。关键是小家伙感兴趣&#xff0c;做出来后给家人炫耀了一圈后&#xff0c;兴趣大增&#xff0c;嚷嚷着要做更好玩的。 最近&#xff0c;娃妈从抖音上买了个小猫喝…...

【Linux从入门到精通】进程的控制(进程替换)

本篇文章会对进程替换进行讲解。希望本篇文章会对你有所帮助 文章目录 一、进程替换概念 二、进程替换函数 2、1 execl 2、2 execlp 2、3 execv 2、3 execle 2、4 execve 三、总结 &#x1f64b;‍♂️ 作者&#xff1a;Ggggggtm &#x1f64b;‍♂️ &#x1f440; 专栏&…...

rancher平台上强制删除pod服务操作

背景&#xff1a; 在日常paas平台运维工作中需要对rancher平台进行巡检的工作&#xff0c;在巡检时发现在rancher管理界面无法删除异常的pod服务&#xff0c; 处理&#xff1a; 像这样的情况就是k8s集群的pod无法通过默认的方式去删除掉pod服务&#xff0c;这时候只能是手工强制…...

【Docker】Docker的通信安全

Docker的通信安全 前言一、Docker 容器与虚拟机的区别1. 隔离与共享2. 性能与损耗 二、Docker 存在的安全问题1. Docker 自身漏洞2. Docker 源码问题 三、Docker 架构缺陷与安全机制1. 容器之间的局域网攻击2. DDoS 攻击耗尽资源3. 有漏洞的系统调用4. 共享 root 用户权限 四、…...

c# 函数中可选参数太多,想设置最后一个参数,又不想修改前面默认参数

C#中&#xff0c;你可以使用命名参数来指定你想要设置的可选参数&#xff0c;而保留其他参数的默认值不变。通过使用命名参数&#xff0c;你可以根据需要选择要为哪些参数提供值&#xff0c;而无需按照它们在函数签名中的顺序提供参数值。 以下是一个示例&#xff0c;演示如何…...

openvino资料(1)

1、c++ - OpenVino model outputs zeroes - Stack Overflow 2、https://chinait-intel.oss-cn-beijing.aliyuncs.com/OpenVINO/Ubuntu20.04%E7%8E%AF%E5%A2%83%E4%B8%8B%E4%BD%BF%E7%94%A8OpenVINO%E9%83%A8%E7%BD%B2BiSeNetV2%E6%A8%A1%E5%9E%8B.pdf 3、c++ - How to cre...

第71篇:某银行外网打点到内网核心区红队评估复盘

Part1 前言 大家好&#xff0c;我是ABC_123。本期分享一篇ABC_123曾经做的针对一家银行的红队评估项目&#xff0c;持续时间两周&#xff0c;难度非常大&#xff0c;但是最终打到了银行核心业务区&#xff0c;今天就复盘一下全过程&#xff0c;希望红蓝双方都能得到一些启示&a…...

网络安全 Day21-数据库知识

数据库知识 1. 什么是数据库2. 为什么需要数据库&#xff08;分类不清晰&#xff09;3. 数据库的种类3.1 关系型数据库3.2 NOSQL 数据库3.3 new sql &#xff08;国产数据库&#xff09;分布式数据库3.4 云数据库 4. mysql 关系型数据库5. 安装mariadb6. 为mariadb设置密码7. M…...

python测试开发面试常考题:装饰器

目录 简介 应用 第一类对象 装饰器 描述器descriptor 资料获取方法 简介 Python 装饰器是一个可调用的(函数、方法或类)&#xff0c;它获得一个函数对象 func_in 作为输入&#xff0c;并返回另一函数对象 func_out。它用于扩展函数、方法或类的行为。 装饰器模式通常用…...

语音同声翻译软件让你不再为语言障碍困扰

从前有一个叫黄俊的小伙子&#xff0c;他有一个大梦想&#xff1a;环游世界&#xff01;但是&#xff0c;他只会说中文&#xff0c;而去到外国又怎么跟当地人交流呢&#xff1f;为了实现自己的梦想&#xff0c;黄俊开始了寻找能帮他解决问题的捷径。这时&#xff0c;方娜向他介…...

又有一个手艺人震惊了B站用户

飞瓜数据&#xff08;B站版&#xff09;【热门视频榜】周榜显示&#xff0c;霸占全站视频流量第一的是来自UP主爱捣鼓的邢志磊发布的作品《我花了半年时间给猫做了个房子》。 视频在一周时间内新增播放1232.2万&#xff0c;新增点赞139.4万。 根据视频详细数据显示&#xff0c…...

HDFS的设计目标和重要特性

HDFS的设计目标和重要特性 设计目标HDFS重要特性主从架构分块存储机制副本机制namespace元数据管理数据块存储 设计目标 硬件故障(Hardware Failure)是常态&#xff0c;HDFS可能有成百上千的服务器组成&#xff0c;每一个组件都有可能出现故障。因此古见检测和自动快速恢复的H…...

【JMeter】JMeter添加插件

目录 一、前言 二、插件管理器 三、推荐插件 1.Custom Thread Groups &#xff08;1&#xff09;Ultmate Thread Group &#xff08;2&#xff09;Stepping Thread Group 2.3 Basic Graph 资料获取方法 一、前言 ​ 在我们的工作中&#xff0c;我们可以利用一些插件来帮…...

测牛学堂:车载测试面试总结之语音助手相关

车载语音助手的工作原理&#xff1f; 语音助手的工作原理总结下来可以分为4个步骤&#xff1a; 1 通过麦克风采集驾驶员的语音指令 2将语音信号转换为数字信号 3过语音识别技术将语音指令转换为计算机可以理解的指令 4 通过语音合成技术将计算机的回应转换为语音输出 车载…...

Android开发之Fragment动态添加与管理

文章目录 主界面布局资源两个工具Fragment主程序 主界面布局资源 在activity_main.xml中&#xff0c;声明两个按钮备用&#xff0c;再加入一个帧布局&#xff0c;待会儿用来展示Fragment。 <?xml version"1.0" encoding"utf-8"?> <LinearLayo…...

Python爬虫+数据可视化:分析唯品会商品数据

目录 前言数据来源分析1. 明确需求2. 抓包分析&#xff1a;通过浏览器自带工具: 开发者工具 代码实现步骤: 发送请求 -> 获取数据 -> 解析数据 -> 保存数据发送请求解析数据保存数据 数据可视化先读取数据泳衣商品性别占比商品品牌分布占比各大品牌商品售价平均价格各…...

el-tree数据渲染超出省略

el-tree数据渲染超出省略 问题 <el-tree:data"deptOptions":props"defaultProps":expand-on-click-node"false":filter-node-method"filterNode"ref"tree"default-expand-allhighlight-currentnode-click"handleNo…...

若依vue -【 44】

44 服务监控讲解 1 需求 显示CPU、内存、服务器信息、Java虚拟机信息、磁盘状态的信息 2 前端 RuoYi-Vue\ruoyi-ui\src\views\monitor\server\index.vue <script> import { getServer } from "/api/monitor/server";export default {name: "Server&quo…...

React 基础篇(一)

&#x1f4bb; React 基础篇&#xff08;一&#xff09;&#x1f3e0;专栏&#xff1a;React &#x1f440;个人主页&#xff1a;繁星学编程&#x1f341; &#x1f9d1;个人简介&#xff1a;一个不断提高自我的平凡人&#x1f680; &#x1f50a;分享方向&#xff1a;目前主攻…...

Bean 的作用域和生命周期

目录 什么是 Bean 的作用域 ?Bean 的六种作用域Spring 的执行流程Bean 的生命周期 什么是 Bean 的作用域 ? Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式&#xff0c;⽐如 singleton 单例作⽤域&#xff0c;就表示 Bean 在整个 Spring 中只有⼀份&#xff0c…...

App Inventor蓝牙调试避坑指南:从连接失败到数据乱码,一次讲清所有常见问题

App Inventor蓝牙调试避坑指南&#xff1a;从连接失败到数据乱码的实战解决方案在移动应用开发领域&#xff0c;蓝牙通信一直是实现设备间短距离数据交换的核心技术之一。对于使用App Inventor的开发者而言&#xff0c;蓝牙模块提供了无需复杂编码即可实现无线通信的便捷途径。…...

自制BLE112串口编程器:基于Bootloader的免调试器烧录方案

1. 项目概述&#xff1a;为BLE112模块打造一款免调试器的RS232编程器在嵌入式开发&#xff0c;特别是早期的蓝牙低功耗&#xff08;BLE&#xff09;模块应用中&#xff0c;我们常常会遇到一个棘手的问题&#xff1a;官方开发工具链的依赖和限制。以Silicon Labs&#xff08;当时…...

光轮智能 谢晨 访谈总结机器人仿真数据产业

光轮智能 谢晨 访谈总结机器人仿真关于创始人关于数据数据金字塔数据痛点仿真数据的重要性仿真数据的质量b站链接地址公司官网关于创始人 清华物理&#xff1b;哥伦比亚金融&#xff1b;英伟达智驾仿真&#xff1b;小鹏智驾仿真&#xff1b;现为光轮智能CEO 关于数据 数据的…...

DragonBones与Godot集成:骨骼动画的可编程化实践

1. 为什么在Godot里用DragonBones不是“锦上添花”&#xff0c;而是“绕不开的刚需” 去年上线一个横版动作手游Demo时&#xff0c;美术团队交来一套20个角色、每个角色含8套动画&#xff08;待机/跑动/跳跃/攻击/受击/死亡/闪避/必杀&#xff09;的Spine资源。我兴冲冲导入God…...

LPCM框架:大模型驱动的计算机架构设计革命

1. LPCM框架&#xff1a;计算机系统架构设计的范式革命计算机系统架构设计正站在历史性的转折点上。过去八十年来&#xff0c;从ENIAC的真空管到现代7纳米制程的异构计算芯片&#xff0c;架构设计始终遵循着"专家经验EDA工具"的传统范式。但随着摩尔定律逼近物理极限…...

Git Bash 中无法启动 Claude Code ?

最近需要在 git bash 中跑 Claude Code 。git bash 是随 git for windows 套件安装的&#xff0c;很久没更新了&#xff0c;结果启动 Claude Code 报错&#xff1a;Warning: no stdin data received in 3s, proceeding without it. If piping from a slow command, redirect st…...

AhMyth位置跟踪:GPS定位与地理围栏技术深度解析

AhMyth位置跟踪&#xff1a;GPS定位与地理围栏技术深度解析 【免费下载链接】AhMyth Cross-Platform Android Remote Administration Tool | The only maintained version of AhMyth on github | A revival of the original repository at https://GitHub.com/AhMyth/AhMyth-An…...

鸿蒙HarmonyOS 5与Unity跨运行时通信实战指南

1. 这不是“调个API”那么简单&#xff1a;为什么鸿蒙Unity通信总在临门一脚卡住我第一次把Unity打包的AR模块塞进HarmonyOS 5 App里时&#xff0c;信心满满——毕竟文档里写着“支持JS/ArkTS调用Native能力”&#xff0c;Unity也标榜“跨平台通用”。结果呢&#xff1f;App一启…...

为什么你的DeepSeek总漏检重构后代码?4步反混淆预处理法(附LLM辅助去装饰器Python脚本)

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;DeepSeek代码重复检测 DeepSeek-R1 模型在训练过程中引入了严格的代码去重机制&#xff0c;其核心目标是消除训练语料中语义等价或高度相似的代码片段&#xff0c;从而提升模型对真实编程模式的学习能力与泛化…...

Safe Exam Browser虚拟机绕过实战:深度解析与安全研究指南

Safe Exam Browser虚拟机绕过实战&#xff1a;深度解析与安全研究指南 【免费下载链接】safe-exam-browser-bypass A VM and display detection bypass for SEB. 项目地址: https://gitcode.com/gh_mirrors/sa/safe-exam-browser-bypass 在数字化教育快速发展的今天&…...