金华网站建设设计,网站怎么添加百度地图,国家工商企业注册查询系统官网,香河县住房和城乡建设部网站前期用scratch#xff0c;带着小朋友做了大鱼吃小鱼、桌面弹球、小学生计算器3个作品#xff0c;小朋友收获不小。关键是小家伙感兴趣#xff0c;做出来后给家人炫耀了一圈后#xff0c;兴趣大增#xff0c;嚷嚷着要做更好玩的。 最近#xff0c;娃妈从抖音上买了个小猫喝… 前期用scratch带着小朋友做了大鱼吃小鱼、桌面弹球、小学生计算器3个作品小朋友收获不小。关键是小家伙感兴趣做出来后给家人炫耀了一圈后兴趣大增嚷嚷着要做更好玩的。 最近娃妈从抖音上买了个小猫喝水的容器一通电水龙头就自动出水猫咪就跑过来了。小朋友又发现了新大陆摆弄起了开关逗着猫咪。看到这我心想这玩意能搞成自动化跟scratch结合起来正好又卡着小朋友的兴趣点连玩带学一箭双雕。 以上为背景。 因为上学的时候折腾过单片机初步判定这个功能用单片机控制肯定是可行的大概搜了下scratch这类少儿编程软件也支持单片机所以整体方案可行初步制定了功能如下
基础功能图形化编程用积木控制角色可以是小猫运动来触发单片机增强功能如果孩子感兴趣继续增加灯光控制与水龙头联动增强功能如果孩子感兴趣继续增加光电控制用红外线或者声音触发水龙头开关 功能定义清楚后然后就是寻找资料分析技术可行性
编程软件选型
上文提及了孩子之前用的是Scratch因为一些原因Scratch在国内逐步被替换可选的有如下
KittenblockClipCCMindPictoBlox
大概看了下功能都差不多基本与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官方支持ArduinoESP32ESP8266这些都是市面上很常见的 从节约成本的角度就选ESP32了其他的随便买。 元件列表 以下开始教程 硬件连接
马云家买的元件购买链接怎么连硬件基本说的很清楚了需要注意的就是注意电压及正负极别烧板子了。
如下 图 ESP32固件
基于Arduino的示例代码简单改下即可注释不多凑合看不复杂。
定义了3个gpio口
5 --输出口连电机驱动板用于控制小水泵的启动/停止
17 --输出口直接连一个小LED灯
16 --输入口连红外传感器用于控制电机的启动/停止
代码运行逻辑为水泵受两个管脚的控制一个是来自上位机Mind的指令一个是红外传感器红外传感器的优先级高于上位机指令实现的效果就是小猫靠近水龙头打开小猫离开水龙头由上位机控制。
/*WiFi Web Server LED/Motor Control*/#include WiFi.hconst 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 clients connectedif (client.available()) { // if theres 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 HOST192.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