一小时入门Scratch机器学习

一说到人工智能和机器学习,人们总会觉得很高深。除了相关从业者,其他人可能就望而却步了。别说让孩子学,自己都很少看一眼。

其实除了那些涉及算法的专项研究和底层嵌入式开发,还有很多上层应用需要人们开发,去运用。

比如今天我要讲的,一个用Scratch机器学习完成智能化教室控制的演示。

在这个项目中,我们将使用 MachinelearningforKids.co.uk 的在线服务来制作一个智能教室助理,让它对我们所输入的内容作出反应。

首先,我们将创建一个使用规则列表来理解命令的助手。但这种方法比较单调,不是很智能。

而我们这次的重点是让计算机能读懂我们的“弦外之意”。

具体是怎么操作的呢?

首先找一台能联网的计算机,且能正常浏览网页。

在浏览器中打开 machinelearningforkids.co.uk ,然后点击“Get Started”,如果你是中文环境,应该是“开始使用”。

点击“立即尝试”后,+ Add a new project 创建一个项目。

这里先说明一下,该平台是支持中文识别的。但为了方便大家入门,我这里用他们的英文版本做讲解了。

建好之后, 再点击“smart classroom”会看到三个选项,选最后一个 “Make”。

这个时候Scratch要出场了。

选择“ Scratch 3”,然后再点“Open in Scratch 3”。不想自己从零开始,就从“ Project templates”里面选择“智能教室”。

点击箭头处的classroom,然后在代码区输入以下内容:

然后点击“小绿旗”测试一下程序是否正常工作。

挨个输入以下命令,并查看程序的反应:

  • Turn on the lamp
  • Turn off the lamp
  • Turn on the fan
  • Turn off the fan

输入“ Turn on the lamp”的时候,看看画面中的灯是不是真的亮了。

如果你上面的操作都没错的话,你现在已经做好了一个传统的教室电器控制系统。接下来就是我们今天的重头戏了。让计算机经过训练之后,不再呆板的钉是钉,铆是铆。要举一反三,像人类一样理解话语中的含义。

比如有时候我们不一定会说“打开这个电扇!”,而是会感叹“天好热啊。”

那如果是一个聪明的助理,肯定就默默的把电扇打开了,并不需要你一字不差的发号施令。

这个是怎么做的呢?

收集训练样本

首先,你要收集足够多的样本。

回到项目首页,点击第一个“Train”。

然后“ + Add new label ”,添加四个新标签。分别在四个池子里输入要训练的词,这一步相当关键。

在“fan on”这个标签里面,你可以表示房间里太热了。

在“fan off”,你可以抱怨房间里太凉了。

在“lamp on”,你可以表示你看不见。

在“lamp off”,你可以抱怨灯太亮了。

如果还不太理解,就照着图做吧。

样本输入的要点:

1、表达一定要准确,不要在冷的要命的时候还说要更多风。

2、词汇尽量多一些,这样计算机可以理解的也更多。

训练和测试一个机器学习模型

再次返回项目首页, 点击“Learn & Test”, 我们要开始让计算机学习,并测试它的学习效果。

如果你的样本数量比较多,可能要在这个环节多等一会儿。如果就几个,基本上一分钟内就可以测试了。

在箭头处输入你想表达的冷热明暗相关意思,看看计算机是不是都认对了。如果觉得满意,就可以继续下一步了。

在Scratch中使用机器学习

再次回到“Make”,点击“Open in Scratch 3”。

你会发现左下角多了一个块积木,那就是我们刚才让计算机辛勤努力后的成果。用它来改造我们前面的程序。

再次单击绿色小旗,看看程序是不是比之前聪明多了?人性多了?

到现在为止,你的“智能教室助理”基本雏形已经完成,如果有兴趣,可以把电视机、音乐播放机什么的都加上。

小结:

一般情况下,真正智能助理都是可以语音控制的。以后如果想实战相关的内容,可以进行更高阶段的研究,比如和IoT的硬件结合等等。

目前已经有人根据亚马逊的Alexa语音识别功能制作了自己的智能助手。国内也有相关厂商提供类似服务,你也可以试试。

素材:Raspberrypi.org

作者:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

创客妹子教你做《偷天陷阱》激光警报系统

喜欢电影的朋友可能看过凯瑟琳.泽塔琼斯和肖恩.康纳利演的《偷天陷阱》。

片中,女主角绕过激光警报系统的过程让人印象深刻。

1999年上映的《偷天陷阱》

那这个激光警报系统实现起来难不难呢?

答案可能比你想象的要简单。

对于那些想要尝试自己构建防盗系统的人,创客妹子 Estefannie 提供了一个制作指南。

示例目标:

建立激光警报系统,保护饼干不被窃取。

工作流程:

激光阵列发现入侵者,摄像头拍照并把照片通过Twitter短消息发给主人,同时蜂鸣器警报响起。

配件清单:

10个激光头

10个光敏电阻

10个电容器

1个树莓派Zero W

1个蜂鸣器

1个树莓派相机模块

12英尺PVC管+ 4个角

1个丙烯酸面板

1个电池组

8根扎带

一罐饼干

Estefannie 并联焊接了10个激光头,又把十个光敏电阻连接到它们自己的GPIO引脚。由于灵敏度的原因,她没有将它们串联起来,这样可以简化调试。

选框架需要几次尝试。Estefannie 从一个木头架子开始试,最后意识到更好的解决方案是PVC管。所有的导线都可以放置在管道内部,然后从管道顶部的一个小窗口出来,连到树莓派Zero W。使用PVC管还可以降低制作成本,因为12英尺的管道大约只需要3美元。

管道内部的布线非常棘手,为完成电路, Estefannie 不得不将一些导线先置入管道内再进行焊接。

Estefannie 尝试将激光头粘合到PVC框架上,但是激光使胶水融化导致失焦。她又尝试使用胶带,后来发现腻子比较完美。成型后可以作为激光器的底座,并可在需要时重新校准。此外,无论激光的温度有多高,它们都能保持不移位。

虽然激光不是很强,但在长时间的校准后, Estefannie 还是会紧张她的眼睛。所以大家在调试的时候,可以戴上太阳镜。

Estefannie 最终在自家厨房里把这个装置搞定了。如果你认真观看影片,会发现她最后还皮了一下。希望大家能和她一样,在创作的过程中收获快乐。

相关视频地址:https://v.qq.com/x/page/l3014nzcgx0.html

相关代码: https://github.com/IoToutpost/Lasers/

素材:Raspberrypi.org

编译:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

创客妹子教你做“一键发Twitter眼镜”

关注“IoT前哨站”的朋友可能记得之前我们发过一篇“让相机根据GPS定位自动拍照”的文章。

是的,那位名叫“Estefannie” 的创客妹子又出现了,这次她给大家带来的是一个可以自动发Twitter的眼镜,而且是“侏罗纪公园模式”。

什么叫侏罗纪公园模式呢?

看看这个眼镜发的Twitter内容就知道了。

发现梁龙一只
发现雷龙一只

准确的说, Estefannie 做的这个装置应该叫“侏罗纪恐龙抓拍系统”。因为她这个发的每张照片都会标一个恐龙的名字,比如:“发现梁龙”,“发现雷龙”……她在眼镜上装了一个按钮。按下就能把照片发到Twitter上。

制作流程:

Estefannie 先是找了一个像护目镜一样的眼镜模型。

用3D打印机把眼镜的原型做出来以后,对其进行打磨、喷漆、抛光。然后在上面接好树莓派Zero W,LED和按钮,加上可调节部分、软垫以及绿色镜片……

大量的涂胶、焊接和布线工作之后,她最终得到了一副漂亮的眼镜。

紧接着,她写了一个Python脚本来拍照、与Twitter交互,并通过LED环来提供眼镜当前的状态信息。树莓派系统启动时,会先连到她手机的无线热点。然后,眼镜上的红色LED亮起,表示程序正常运行。

然后,就可以戴着这个眼镜去抓拍有意思的景物了。

背景:

原本这是她被邀请去“Coolest Projects”青少年创客大会演讲而制作的道具,但你可以根据她的代码自己改改,做一个发微博或者抖音的版本。

关于详细流程,建议大家看视频。

相关视频:https://v.qq.com/x/page/c3010lo613b.html

3D模型文件: https://www.thingiverse.com/thing:3732889

代码下载: https://github.com/IoToutpost/JurassicGoggles

素材:Raspberrypi.org

编译:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

解析Python开发的一款迷你跑步游戏

之前“IoT前哨站”上发了一些用Python写文本游戏的文章。不管对于Python开发者来说还是对于游戏爱好者来说,都非常适合打基础。

这次我们迈入图形时代,来看看国外开发者“Rik Cross”制作的一款迷你跑步游戏。

他用了不到一百行代码,就写出了值得一玩的2D动作游戏,怎么做到的?

在此之前,先向大家介绍一个游戏框架:pgzero。

该框架全名Pygame Zero,是一个基于Pygame的游戏编程框架。它可以更容易地编辑游戏,无需模板、不用编写事件循环,也无需学习复杂的Pygame API,而且支持树莓派。

安装
pip install pgzero

需求:
通过键盘的左右键操作,让运动员向前奔跑,每过25米有路标提醒,最后看谁在百米跑步中耗时最少。

代码下载地址:
https://github.com/IoToutpost/Python_game/tree/master/Sprint

素材(地址同上):
Images文件夹中有21张图,包括运动员的动作分解、跑道等。

其中的关键代码,是一个叫做Sprinter()的类。

class Sprinter(Actor):
     def init(self, **kwargs):
         super().init(image='idle', pos=(200,220), **kwargs)
         self.startTime = time()
         self.finishTime = time()
         self.runFrames = ['run' + str(i) for i in range(1,16)]
         self.timeOnCurrentFrame = 0
         self.speed = 0
         self.lastPressed = None
         self.keyPressed = False
         self.distance = 0
# 将运动员推进到下一帧
def nextFrame(self):
    # 如果当前空闲,则启动正在运行的动画。 
    if self.image == 'idle':
        self.image = self.runFrames[0]
    else:
        # 在列表中找到下一个图像,然后返回到第一个图像 
        # 当列表已经到末尾的时候
        nextImageIndex = (self.runFrames.index(self.image) + 1) % len(self.runFrames)
        self.image = self.runFrames[nextImageIndex]

# 检查左右方向键是否正确
# 被交替按下
def isNextKeyPressed(self):
    if keyboard.left and self.lastPressed is not 'left' and not keyboard.right:
        self.lastPressed = 'left'
        return True
    if keyboard.right and self.lastPressed is not 'right' and not keyboard.left:
        self.lastPressed = 'right'
        return True
    return False

def update(self):
    # 更新运动员的速度
    # 交替按键加速
    if self.isNextKeyPressed() and self.distance < 100:
        self.speed = min(self.speed + ACCELERATION, 0.15)
    # 如果没有按键,减速
    else:
        self.speed = max(0, self.speed-DECELERATION)
    # 根据运动员的速度更新距离 
    self.distance += self.speed
    # 根据运动员的速度对其进行动画 
    self.timeOnCurrentFrame += 1
    if self.speed > 0 and self.timeOnCurrentFrame > 10 - (self.speed * 75):
        self.timeOnCurrentFrame = 0
        self.nextFrame()
    # 如果不移动,则设置为空闲
    if self.speed <= 0:
        self.image = 'idle'

里面有一些变量用来跟踪运动员的速度和距离,以及全局的常量(ACCELERATION和DECELERATION的值)。这样可以确定玩家的速度变化。这些数字很小,因为它们代表了玩家加速和减速时,每一帧对应的米数。

玩家通过交替按左右键来增加运动员的速度。这个输入由Sprinter类中的isNextKeyPressed()方法处理,如果按下正确的键,该方法将返回True。

lastPressed变量用于确保左右键被交替按压。如果未按下任何键,玩家会减速,并且该减速程度应小于加速度,以免让玩家突然停下。

在游戏设计中,作者用了gameart2d.com上一个名为“The Boy”的免费形象来作为运动员,里面有15张跑步动作分解图构成的循环。他将从空闲状态开始,只要速度大于0,就切换到跑步动作循环。

这是通过index()在runFrames列表中查找当前运动员图像的名称来实现的,程序会将当前图像设置为列表中的下一个图像(并且在到达列表的末尾时返回第一个图像)。

我们还需要让运动员在跑步动作循环中以成比例的速度向前移动,通过跟踪当前图像显示的帧数来实现(在那个名为timeOnCurrentFrame的变量中)。

为了给玩家一种移动的错觉,作者添加了一些经过玩家的物品:一条终点线和三个显示跑动距离的标记。

这些物品出现的时机是根据运动员在屏幕上的x位置和运动距离计算出来的。

​然而,这意味着每个物品距离玩家最多只有100像素的距离,似乎移动的有点缓慢。我们可以通过SCALE因子来解决,它对应的是运动员跑过的米数和屏幕上像素之间的关系。比如设成1:75。

这些物品最初被绘制在屏幕看不见的右侧,然后向左移动并更快地经过运动员。

最后,startTime和finishTime变量用于计算比赛时间。这两个值最初都设置为比赛开始的时间,只要跑动的距离小于100,finishTime就会更新。使用time模块,比赛时间可以简单地计算为finishTime – startTime。

附注:该游戏在树莓派和Windows PC上都能跑,如果要试玩,记得在Python文件前面加pgzrun命令。

Have fun.

素材:Wireframe #23

编译:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

Python图形界面开发入门之Guizero

不管是手机电脑,还是带触摸屏的终端设备,简单易用的图形界面,总是很受欢迎。

而提起Python下的图形界面开发,大家一定都会想到 PyQt 和 wxPython、Kivy 等经典模块。

不过我们这次要介绍的“guizero”,是一个非常易用的GUI库,能让初学者快速、轻松地为他们的程序创建图形界面。

安装很简单:

pip3 install guizero

这里先来个基础的例子。

from guizero import App, Text, PushButton
app = App(title="IoT前哨站")
intro = Text(app, text="试着用guizeo开发图形界面")
ok = PushButton(app, text="Ok")
app.display()

这个例子应该很容易懂,先设置窗体、标题,然后放入一个文本框和一个按钮。

由于文本框没有设置内容,所以不太看得出来,整个窗体只能发现一个按钮孤零零的杵那儿。

下面我们试着给按钮加功能,让它做一个显示字符的操作(准备让文本框发挥作用了)。

from guizero import App, Text, PushButton

def say_hello():
    text.value = "欢迎关注IoT前哨站"

from guizero import App, Text, PushButton
app = App()
text = Text(app)
button = PushButton(app, command=say_hello)
app.display() 

当你单击 Button 按钮时,原本空着的文本框会显示“欢迎关注IoT前哨站”。

如果你的程序功能比较复杂,需要另外一个窗体展示内容的时候……

from guizero import App, Window, Text
app = App(title="主窗体")
window = Window(app, title="第二窗体")
text = Text(window, text="这段文字将在第二窗体显示")
app.display()

默认情况下,guizero是自动布局,或者通过修改窗体内各部件的align属性,来调整它们的基本方位,但那肯定不够。

更细致一点的布局方式 —— 网格。

from guizero import App, PushButton
app = App(title="IoT前哨站",layout="grid")
button1 = PushButton(app, text="1", grid=[0,0])
button2 = PushButton(app, text="2", grid=[1,0])
button3  = PushButton(app, text="3", grid=[2,0])
button4  = PushButton(app, text="4", grid=[0,1])
button5  = PushButton(app, text="5", grid=[1,1])
button6  = PushButton(app, text="6", grid=[2,1])
button7  = PushButton(app, text="7", grid=[0,2])
button8  = PushButton(app, text="8", grid=[1,2])
button9  = PushButton(app, text="9", grid=[2,2])
button0  = PushButton(app, text="0", grid=[1,3])
app.display()

通过grid参数来修改各部件的[x,y]坐标,以此改变它们在窗体中出现的位置。

你也可以通过在网格参数中指定范围,使部件跨越多个列或行。这些都是可选的,但必须用[x,y,xspan,yspan]这样的格式来指定它们。

比如下面这个图片摆放的例子。

from guizero import App, Picture
app = App(title="IoT前哨站",layout="grid")
picture1 = Picture(app, image="Debian.jpg", grid=[0,0])
picture2 = Picture(app, image="IotOutpost.jpg", grid=[1,0])
picture3 = Picture(app, image="wide.jpg", grid=[0,1,2,1])
picture4 = Picture(app, image="tall.jpg", grid=[2,0,2,2])
app.display()

弹出框大家也经常在用,一般经典的就是询问、提示和警告。

from guizero import App
app = App(title="月饼提问")
build_a_snowman = app.yesno("问题", "你喜欢吃蛋黄月饼吗?")
if build_a_snowman == True:
    app.info("月饼", "这就给你拿一块过来。")
else:
    app.error("月饼", "好吧,那就不吃了。")
app.display()

再看一个经典的滑动条,假设要调整空调的温度。

from guizero import App, PushButton, Slider
app = App(title="空调操作")
button = PushButton(app, text="开/关",width=30, height=5)
slider = Slider(app, width=200, height=30)
app.display() 

下面来一个读取传感器数值并每秒钟刷新的例子。当然,为了方便演示,里面用的是随机数。

from guizero import *
import random
def read_sensor():
    return random.randrange(3200, 5310, 10) / 100
def update_label():
    text.value = read_sensor()
    # recursive call
    text.after(1000, update_label)

if name == 'main':
    app = App(title='Sensor Display!',
              height=100,
              width=200,
              layout='grid')

title = Text(app, 'Sensor value:', grid=[0, 0]) 
text = Text(app, "xx", grid=[1, 0]) 
text.after(1000, update_label) 
app.display()

最后,来一个带菜单选项的例子。

 from guizero import *

 def switch_screen(switch_to):
     hide_all()
     switch_to.show()

 def hide_all():
     for screen in all_screens:
         screen.hide()

 app = App("多选择框运用", layout="grid")
 all_screens = []

 创建一个菜单区域
 menu = Box(app, grid=[0,0], layout="grid")
 menu.tk.width = 900
 menu.bg = "gray"

 选项1
 option1 = Box(app, grid=[1,0])
 text1 = Text(option1, text="这是列表区的内容")
 combo = Combo(option1, options=["树莓派","小熊派","香橙派"])
 all_screens.append(option1)

 选项2
 option2 = Box(app, grid=[1,0])
 text2 = Text(option2, text="这是滑动框")
 slider = Slider(option2)
 all_screens.append(option2)
 
 option1_button = PushButton(menu, text="列表区", \
 command=switch_screen, args=[option1], grid=[0,0], align="left")
 option2_button = PushButton(menu, text="滑动框", \
 command=switch_screen, args=[option2], grid=[0,1], align="left")
 hide_all()
 all_screens[0].show()
 app.display()

左侧灰色的两个菜单选项,分别是“列表区”和“滑动框”,单击任意一个按钮后会出现相应内容,列表区中有个下拉式清单,而滑动框点进去是与其对应的部件。

其他的用法大家可以继续挖掘,不管你的系统是 Windows 还是 Mac、Raspbian Linux,Guizero均可支持。

虽然看着似乎有一点糙,但好在上手快。哪怕你是一个刚开始研究图形界面的 Python 开发者,也能轻松掌握。

作者:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

月黑风高无遁逃 —— 用树莓派自制夜视仪

小时候,我花了很多时间玩“细胞分裂”。这个游戏经常要在阴影中徘徊,光线和声音是完成各种任务的重要因素。

游戏中最让人印象深刻的就是情报员 Sam Fisher 戴的夜视仪。因此我一直对能在黑暗中看清事物而着迷,并有了打造便携式夜视设备的想法。

功能要求:

能在黑暗中观察事物(2米到5米)
有图形界面可操作
10个不同功能的按钮
方便的手柄
可调整到最佳视角。
可保存实时视频
可拍照

主要思路:

这个夜视仪核心是红外摄像头(红外线可让你在黑暗中拍摄照片和视频),我买了一个旧的手持式相机闪光灯作为夜视仪的基础。

树莓派Zero小巧,放在这个闪光灯壳子里很完美,有足够的空间支持HyperPixel屏幕和摄像头。而且它还有一个倾斜手柄,这意味着你可以调整夜视角度并且随身携带。

所需硬件:

1、树莓派 Zero W

2、树莓派摄像头 NoIR Camera V2

3、触摸屏 HyperPixel 4.0

代码地址:

https://github.com/IoToutpost/Night-Vision

把程序部署完成之后,可以在桌面放置一个快捷方式,以便随时启动。

十个按钮的功能:

预览 10秒

预览 30秒

预览60秒

预览5分钟

预览10分钟

预览15分钟

拍照

捕捉一个10秒视频

保持预览(没有时间限制)

离开/关闭

因为默认的灰色在黑暗中太亮了,于是作者把按钮改为黑色背景和绿色字体。

编者按:这里用到的HyperPixel 4.0触摸屏似乎与2019年8月发布的Raspbian Buster不太兼容,建议使用Raspbian Stretch。

原先的手持式相机闪光灯没地方展示触摸屏,作者用小刀将其顶部塑料一点一点切掉,这才有了一个不规则的显示区。DIY真是锻炼人啊……

相关视频地址:

https://v.qq.com/x/page/w0917ae6ohs.html

素材:Tecoed.co.uk

作者:TeCoEd

编译:王文文,前51CTO安全频道主编,RedHat认证工程师,华为HCIP-IoT认证工程师。

在树莓派上安装Scratch 3桌面版

Scratch 3于2019年1月发布后,树莓派和Scratch的团队就在努力为 Raspbian这个系统开发桌面版本。

与以前的版本相比,新版Scratch界面和功能都有了显著的改进。但这些改进需要更高配置的硬件和更先进的系统来支持。

随着树莓派4代的性能升级以及 Raspbian Buster 这款系统的发布,业界知名的积木编程工具Scratch 3,终于可以跑在树莓派上了。

哪些树莓派才能装Scratch 3呢?

理论上1G内存的树莓派3B就能跑起来。

但树莓派官方推荐2G或以上内存的树莓派4B,否则你的Scratch 3可能会因为内存不足而出现问题。

注意,Scratch 3只能装在Raspbian Buster以及后续版本上,老系统就别尝试了。

如果你还没有升级到Raspbian Buster,建议你在SD卡上安装一个新的Buster版本,而不是升级当前的Raspbian Stretch。

如果你已经在使用Raspbian Buster,但你不确定你是否在运行最新的版本,请执行:

sudo apt-get update
sudo apt-get install scratch3

或者在桌面进入菜单,然后Preferences > Recommended Software,选中Scratch 3并单击OK。

Scratch 3在树莓派上有哪些特别应用?

Scratch 3为Raspbian提供了新的扩展,允许你用Scratch代码控制GPIO针脚和Sense HAT。

GPIO扩展

GPIO扩展是Scratch 2时代出现的,这里对其做了强化,可以让你更便捷的连接和控制整个电子设备。

Simple Electronics扩展

如果你希望添加一些简单的电子模块,比如游戏用到的的LED或按钮控制器。你应该会发现新的Simple Electronics扩展比GPIO扩展更易于使用。

Simple Electronics扩展是对初学者非常友好的模块,也可以用来和树莓派GPIO引脚做交互。

在本例中,连接到GPIO引脚17的LED由引脚2和GND之间的按钮控制。

Sense HAT扩展

我们改进了Sense HAT扩展让其支持Scratch 3的新功能,另外还引入了许多新的积木块以便于:

感应设备的倾斜,摇晃和方向
使用操纵杆
测量温度,压力和湿度
在LED矩阵上显示文本,字符和图案

Micro:bit和LEGO扩展

Micro:bit和LEGO扩展已经在Scratch 3 Desktop的Windows版和Mac版上提供。这是因为两个系统上都已支持Scratch Link蓝牙通信软件。而目前Raspbian这样的Linux系统还不支持。

Raspbian的Scratch Link版本是我们计划的一部分,但到目前为止,我们还没有正式的发布日期。大家可能要等一段时间。

一轮感谢

长期以来,Scratch和 Raspberry Pi 团队都有一个共同目标,那就是在Raspberry Pi上运行Scratch 3。如今能看到它发布,真是太棒了!

非常感谢 Raspberry Pi 工程师 Simon Long 为Scratch 3的构建和打包,也非常感谢Scratch团队给予的支持。

来自:Raspberrypi.org

作者: Martin O’Hanlon 

译者:王文文,前51CTO安全频道主编,Redhat认证工程师,华为HCIP-IoT认证工程师。

把站台上的电子提示牌建到桌边

一般轻轨和火车的站台上都会有电子提示牌,提醒乘客当前时间、下一班车还要等多久以及该班车的始发站和终点站等等。

那类似的电子提示牌用到了哪些东西?我们能不能自己做一个?

用树莓派Zero、OLED显示器和3D打印的小盒子就可以搞定。它会涉及一些软件,一点焊接工作,还有一些3D打印材料。

引言

不久前,我看到克里斯·哈钦森(Chris Hutchinson)发布的帖子。

Pretty hyped about my most recent @Raspberry_Pi project — a realistic, real-time, train departure board

I’ve open sourced the software over at: 
https://t.co/vGQzagsSpi

Next step: find a case and make it a permanent fixture! 
pic.twitter.com/HEXgzdH8TS— Chris Hutchinson (@chrishutchinson) June 6, 2019

他从交通网站的API中提取数据,并在一个小型OLED上实时显示列车发车信息,以模仿英国列车站台上的那些电子提示牌。

我很欣赏他的项目,所以决定自己也做一个。主要是打算改变软件工作的方式,使其在 balendCloud 上运行,这样部署和配置会更加容易。

此外,我重新设计了显示布局,以实现字体的1:1像素映射。避免任何缩放,以便看起来更像真正的点阵显示。

至此,我已大功告成,并对结果感到满意。你可以按照本教程做一个类似的版本。

列车信息来源

https://www.transportapi.com/

硬件需求

这个项目的硬件需求不多,主要就是下面这几项。

·树莓派Zero W
·8G容量的SD卡
·USB电缆(用于电源)
·SSD1322 OLED显示器

如果你想自己做外壳,那还需要一台3D打印机或3D打印服务。

软件需求

该项目构建在 balenaCloud 上的 Docker 容器中运行,这意味着你只需几步就可以部署项目,从而节省任何耗时的手动包安装或配置。

所以你需要:

• 从GitHub下载项目

https://github.com/IoToutpost/UK-Train-Departure-Display

• 准备好刷系统的工具
• 一个免费的 balenaCloud 账户,用于设置和管理Pi下载并安装balena CLI工具——安装在你的计算机上,允许你在树莓派上安装项目代码。

组合在一起

第一个任务是将显示器连接到树莓派的GPIO头。

我用的是树莓派Zero W,它没有引脚针。虽然可以把它放在一个小得多的空间,但这意味着我必须自己焊接跳线。

我已经在下面列出了2.8英寸显示器(从AliExpress买来的)的引脚分配。

其他基于 SSD1322 的显示器应该也是可以的,你只需要留意一下引脚,并在上电前仔细检查它们是否连接正确。

无论你是否把线焊接到Raspberry Pi,都肯定要将线焊接到显示器上。

设置软件

用 balenaCloud & Docker 大大简化了软件的设置过程。

这意味着你不必手动安装或配置软件包,只需设置应用程序,添加设备并刷写SD卡,然后用 balena CLI 工具从计算机推送代码。我不会在这里详细介绍这个过程,你可以访问以下链接查看相关文档。

https://www.balena.io/docs/learn/deploy/deployment/

• 设置balenaCloud应用程序

首先你要有一个balenaCloud账户。然后添加一个新的应用程序,确保为正在使用的设备选择匹配的硬件类型。

接下来,向应用程序添加一个新设备,配置网络并下载balenaOS映像。

• 给设备刷写SD卡并接通电源

用Etcher或其他工具把下载好的操作系统刷入SD卡。
将SD卡插入树莓派并启动设备。几分钟内,它应该会出现在balenaCloud仪表板上。

• 推送App代码

这一步是将代码推送到balenaCloud,之后它会将其分发到你刚才添加的树莓派。具体步骤:

从GitHub下载代码(本文前面提到的链接),然后在你的计算机上安装 balena CLI 工具,进入项目目录,执行 balena push <appName> ,其中 <appName> 是你之前在 balenaCloud 仪表板中创建的应用程序的名称。例如:balena push TrainDepartureDisplay。

如果一切顺利,你将看到balena 独角兽吉祥物,并且你刚刚推送的代码将自动分发到设备上。

准备好硬件并部署代码后,下一步是配置运行应用程序所需的环境变量。

添加配置信息

不需要手动编辑配置文件,你可以用 balloud 仪表板来设置并随时更改任何变量。如果需要的话,你可以看看如何设置环境变量的文档。

https://github.com/balena-io-playground/UK-Train-Departure-Display#configuration

在获得传输API的密钥和应用ID之前,你需要在 Transport API 上注册一个帐户。这样你才能知道列车目的地和到站时间等信息。

一个基础帐户是免费的,每天只能有1000个请求,但是对于这个项目来说已经足够了。

如果前面工作都没问题,整个系统应该可以运行了,你第一眼看到的画面应该是这样。

做个外壳

接下来要把这个电子提示牌做的更真实一些,至少在外观方面。

我设计了一个外壳来装显示器和树莓派。这样可以把所有的东西紧密地放在一起,不会浪费太多的空间。

然后用Autodesk Fusion 360和Creality Ender 3(通过Cura)将其打印出来。这个外壳的模型可以在balena Thingiverse页面上找到。

将 Raspberry Pi Zero 放进壳中,然后熔化少许卡槽以便将其固定。

然后,用四个2.6毫米螺丝封住后盖。

我的电脑显示屏背面有USB接口,所以我剪了一条旧的USB电缆来供电。用细电线做这样的连接时,两根导线外侧可以加上热收缩管。给它们加热后,会形成一个坚固的接头。

供电线通过外壳顶部引出,以获得清爽的外观,然后用双面胶将我们的成品固定在电脑显示屏的下面。

后记

非常感谢Chris Hutchinson,是他最初启动这个项目,并促使我做进一步的开发。Blake也做了一些改进,这个项目就是他那里 fork 出来的。

Blake的项目地址:
https://github.com/ghostseven/UK-Train-Departure-Display

本项目用到的字体:
https://github.com/DanielHartUK/Dot-Matrix-Typeface

来自:Balena.io

作者:Chris Crocker-White

译者:王文文,前51CTO安全频道主编,Redhat认证工程师,华为HCIP-IoT认证工程师。

请君入瓮 —— 智能捕鼠器DIY

住处闹鼠患怎么办?

老鼠药、粘鼠胶不环保,捕鼠夹又容易误伤别的小动物。

来看看一个叫 Alain Mauer 的国外创客用树莓派和红外光栅做的智能捕鼠器。

视频地址:

https://v.qq.com/x/page/l0884rzglyt.html

他的捕鼠器名叫RaspiTrap,原理说起来也很简单:

当有东西进入捕鼠器被红外线探测到,马上放下闸门,并拍照向管理员告警。

1、 捕鼠器结构

长方体中空装置,主要分为陷阱区和控制区,闸门平时呈开放状态。

盒内控制区主要由一个带摄像头的树莓派和一个控制板,红外光栅外加一个舵机组成。


2、外壳制作

一般用PVC板拼接,当然你也可以选用其他强度比较好的板材。这里用的是5mm厚的PVC板,面积约350毫米×110毫米大小。

将这些PVC板有序的拼接,卡紧。

长方体的前端要开一个拱形门,以便老鼠进来。

两侧也要开口,装上丙烯酸玻璃板,方便肉眼看到捕鼠器内部的情况。

3、红外光栅

为了检测老鼠是否在里面,这里要用到红外光栅。你可以先在面包板上进行测试。如果你喜欢深度DIY,可以自己制作PCB。当然网上有现成的可以订购。该板可以使用树莓派的5V电路供电。

控制板电路图

实际电路板

4、盒内重要部件摆放

为了固定陷阱内的TEMIC K153P(红外),作者又钻了两个凹槽。它们被安置在3毫米丙烯酸玻璃板后面。

装好9GR伺服电机。

把一个鱼眼镜头放置在树莓派相机前面。

把所有配件都装起来,检查一下镜头是否正常工作。

一般手机有自动对焦功能,但树莓派相机只有一个固定的焦点,所以照片是模糊的。

有兴趣的朋友可以想想怎么改进。

4、盒内主要结构

打开后盖,你可以看到树莓派,伺服电机和红外光栅连接的PCB板。镜头下方还有一个白色的LED灯,它能提示捕鼠器状态,也能用作拍照​的光源。

左边的机械释放装置是一块薄薄的PVC板。它通过一根细金属线与伺服电机连接。发现老鼠进入后,伺服电机拉下门栓。

最后,是捕鼠器的源代码。

地址:

https://github.com/IoToutpost/Raspitrap

这些脚本是用python写的。trapmain.py 相当于入口程序。

在本例中,入口程序先检查物体是否被红外线监测到,然后跳转到拍照并发送即时消息的脚本。最后,发送邮件。

对于即时消息推送,作者使用的是Instapush的服务 (https://instapush.im/)。

提前在手机或智能手表上装好App,配置好用户信息之后,就可以收到实时消息了。

当然,如果你想用微博或微信来接收推送也是可以的,具体根据自己需求开发即可。

注:作者在这个例子中用的系统是Archlinux,当然这看个人喜好。你用Raspbian或Fedora都是可以的。

素材: instructables

编译:IoT前哨站

Python文本游戏之根据提示猜词

之前IoT前哨站上发布了“Python写文本冒险游戏的要点”和“在文本冒险游戏中加入道具”,讲的都是冒险类游戏。

那猜谜类型的文本游戏大家知道怎么做吗?

比如经常被用来练习的猜数字:

这确实是一个经典的入门。不过我们这次要加点难度。让大家来猜词语。

要求:

每次随机给出一部分残缺的字符,让大家回忆并输入完整的词语。

答对输出正确,答错提示错误,并告知正确答案。

思路:

1、创建一个小的词库,这里我们将一部分词语放入数组,命名为:questions。

import random

questions = [“As you like it”, “The Tempest”, “Measure for Measure”, “Much Ado About Nothing”, “The Comedy of Errors”, “King Lear”, “Cymbeline”, “Hamlet”, “Coriolanus”, “Othello”, “Love’s Labour’s Lost”, “King John”, “Julius Caesar”, “Edward III”]

2、随机选择一个短语,并将其转换为大写。

chosen_phrase = random.choice(questions)
chosen_phrase = chosen_phrase.upper()

3、去掉元音、空格和单引号。把删选后的字符拼接起来,赋值给变量puzzle。

vowels = [“A”, “E”, “I”, “O”, “U”, ” “, “‘”]
puzzle = “”
for letter in chosen_phrase:
if not letter in vowels:
puzzle += letter

4、随机插入空格

puzzle_with_spaces = “”

while len(puzzle) > 0:
group_length = random.randint(1,5)
puzzle_with_spaces += puzzle[:group_length] + ” “
puzzle = puzzle[group_length:]

5、最后加入答案检测,如果输入和答案一致,就告知“That’s correct!”,如果答案错误,提示:No,并给出正确答案。

guess = input(“What is your guess? “)
guess = guess.upper()

if guess == chosen_phrase:
print(“That’s correct!”)
else:
print(“No. The answer is “, chosen_phrase)

好了,一个根据提示信息猜短语的文本游戏就写完了。

完整代码可访问:

https://github.com/IoToutpost/Python_game/tree/master/Puzzles

在把这个游戏给别人玩的时候,记得先让玩家看一看你的词库。不然就是瞎猜了。

有能力的朋友可以试着扩展一下,说不定你可以把它改成一个英语学习程序。

注:文中猜词代码来自MagPi 82《Code a quiz game with Python》。