Funpack第十期: kitronik Arcade
硬件介绍
ARCADE是kitronik出品的一款开发板,或者说是可以用微软makecode自行编程的游戏机。板子有一个1.77寸的全彩的LCD屏幕,有蜂鸣器、振动马达、6个操作按钮,一个bootlader自带的menu界面按钮,一个硬件复位按钮,一个电源开关,并通过3节5号电池供电,可以提供20小时续航(当游戏机用可能差了点意思)。
板载的单片机核心是Atmel SAMD51J19A,是一款工作在 120MHz下的ARM Cotex-M4的单片机。按照命名型号,该单片机为64pin QFN封装,512KB Flash,192K的S-RAM。总的来说,性能并不强,但用来学习编程却能带来不错的体验。
在手柄板子的背面,只有三个电池座,没有其他元件,也就是说,开发板元件基本采用单面铺贴,正面来看,板上元件极其简介,除了必要的电源芯片,滤波电容外,连电阻都很少用到。
可以通过U盘方式下载,貌似u盘方式已经成为入门开发板的一种主流方案了。
在这里简要介绍下[Microsoft MakeCode Arcade](https://arcade.makecode.com/)
makecode是由微软运营的一个开源的教育平台,旨在构建一套廉价、基础、有趣味性的编程学习平台:
首先,提供了交互式的模拟器界面,虽然界面和实际硬件来说有一些区别,也不乏存在诸多bug,但却是极大的方便了学生学习编程的热情。
对于较为初级、或者想感受计算机学习的用户,提供了轻松易懂的块编程,易于上手。
对于中高级用户,则提供了更为灵活的javascript及python等编程界面。基本能覆盖语言初学者及创客的需求。主页上有很多游戏开发、编程的教程和例程,宝藏众多,论坛我一直没登陆进去,据说论坛有很多大神设计的游戏。
尽管makecode支持的板卡众多,(大多数都是adafruit出品的),但国内其实能低价买到的并不多,其中最为出名的就是掌控板(microBit)了,但掌控板(本体)可没有该款arcade如此丰富的外设。另外树莓派zero,也可以通过刷写bootloader支持makecode,树莓派相对其他的板子,真可谓降维打击,和掌控板差不多的价格,确是桌面级架构。
接下来进入正题。
任务
本次选择的是任务二:设计一个摩斯密码练习器,选择两个按键为点与横,或者一个按键的长短按。LCD屏幕上随机出现一个字符,敲出相应组合,正确时,蜂鸣器响,错误时,电机振动。
这个题目用python代码实现的,makecode自带的库里用来做文本显示差点意思,有个扩展库名为Text Sprite能够很好的解决文本显示问题,这个库需要加载下才能跑通代码。
代码的主体就一个init(),里面只跑了一个生成摩斯码 gen_morse()函数,其他功能则通过按键中断调用函数的方式来实现。具体来说,开始时从摩斯码表中随机选出字符,并生成相应的摩斯码序列。接下来通过按按键AB,调用中断函数生成的输入摩斯码key_ram序列,与生成的正确摩斯码序key_ram_list序列做比较,如果相同,则正确,得分score +1 ,如果错误,不得分。界面则通过text sprite在每次按键时更新一次显示文本的方式实现。另外,左键为删除字符,右键为确认输出,上键则是显示正确字符。在右键调用的确认函数中,调用确定正确错误的函数,正确则通过 music.ba_ding.play_until_done(),调用蜂鸣器播放音乐,同时得分加一。错误则调用scene.camera_shake(),使屏幕抖动、调用pins.pin_by_cfg(101).digital_write(True)控制输出IO,使震动马达工作,并在100毫秒后关闭马达,表现为马达短时震动。
本来想做个多码的摩斯序列, 因此加入了当输出长串时,缩小显示,换行等操作,后来没用上,就当个乐子吧。
在模拟器上,鼠标点按键很容易出现连点(导致程序出错),硬件则没有这个现象,代码中应当加入按键中断的防抖功能,防止短时间多次调用中断,这部分后续可以加入一个判断函数实现。
具体的代码见后续代码及附件,视频中进行了演示。
仿真实现的效果,以及实际上机效果。
心得体会
这是第二次参加funpack的活动,之前在第四期的时候,玩过蓝牙传感器开发板,当时觉得,板子集成了很多传感器,非常实用,能用在很多项目中。这次提供的是一款可以当作游戏机玩的编程板,简直爱不释手,尝试了makecode上的一些作品后,也自己上手做了些简单的玩了下。
板卡本身其实性价比并不高,重要的在于参与活动,提升自我,接触一些有趣的开发板。电子森林、硬禾学堂、得捷电子组织起的这个活动,为创客们带来了一个新的舞台,国外创客混迹hackaday,国内缺少一个能够供创客们展示的平台,funpack的活动是一个好的开始,希望电子森林能够办的越来越好,达到甚至超过hackaday平台。
附件
附代码:直接粘贴到makecode的python界面使用,注意需要手工点击添加textSprite模块,以供正常编译。
# 生成摩斯码
def gen_morse():
global char_ram_list,key_ram_list
char_num= 1
for index in range(char_num):
rand= randint(0,38)
char_ram_list= char_ram_list + char_tab[rand]+ " "
key_ram_list = key_ram_list + key_tab[rand] + ""
char_disp.set_text(char_ram_list)
# 显示摩斯码
def disp_key(key_ramtemp: str):
if len(key_ramtemp) > 20:
key_disp.set_max_font_height(6)
key_disp.set_text(key_ramtemp.slice(0, 16))
key_disp2.set_max_font_height(6)
key_disp2.set_text(key_ramtemp.slice(16))
else:
key_disp.set_text(key_ramtemp)
# 键A行为
controller.A.on_event(ControllerButtonEvent.PRESSED, press_keyA)
def press_keyA():
global key_ram
key_ram= key_ram + "."+""
disp_key(key_ram)
# 键B行为
controller.B.on_event(ControllerButtonEvent.PRESSED, press_keyB)
def press_keyB():
global key_ram
key_ram= key_ram + "_"+ ""
disp_key(key_ram)
# 键左行为
controller.left.on_event(ControllerButtonEvent.PRESSED, press_keyleft)
def press_keyleft():
global key_ram
if len(key_ram)>=1:
key_ram=key_ram[:-1]
disp_key(key_ram)
# 键右行为
controller.right.on_event(ControllerButtonEvent.RELEASED, press_keyright)
def press_keyright():
if check_char_vs_key():
key_test_disp.set_text("correct")
music.ba_ding.play_until_done()
score= score+1
info.change_score_by(1)
score_disp.set_text("score:")
else:
key_test_disp.set_text("fault")
scene.camera_shake()
pins.pin_by_cfg(101).digital_write(True)
pause(100)
pins.pin_by_cfg(101).digital_write(False)
key_disp2.set_text(key_ram_list)
pause(3000)
init()
# 显示答案
controller.up.on_event(ControllerButtonEvent.PRESSED, press_keyup)
def press_keyup():
key_test_disp.set_text(key_ram_list)
# 校验对比
def check_char_vs_key():
if len(key_ram) !=len(key_ram_list):
return False
i=0
while i <= len(key_ram) - 1:
if not (((key_ram[i] == '.') and (key_ram_list[i] == '.')) or
((key_ram[i] == '_') and (key_ram_list[i] == '_'))):
return False
i +=1
return True
#disp 显示信息
def init():
global char_ram,char_ram_list,key_ram,key_ram_list
global char_num,score
char_ram= ""
key_ram= ""
char_ram_list= ""
key_ram_list= ""
char_num=0
key_disp.set_text("")
key_disp2.set_text("")
key_test_disp.set_text("")
score_disp.set_text("score:")
scene.set_background_color(9)
gen_morse()
# char对应 字符 key 对应_.键值,tab=table
char_tab= [
"A","B","C","D","E","F","G",
"H","I","J","K","L","M","N",
"O","P","Q","R","S","T",
"U","V","W","X","Y","Z",
"1","2","3","4","5","6","7","8","9","0",
"?","/","-"
]
key_tab= [
"._","_...","_._.","_..",".",".._.","__.",
"....","..",".___","_._","._..","__","_.",
"___",".__.","__._","._.","...","_",
".._","..._",".__","_.._","_.__","__..",
".____","..___","...__","...._",".....","_....","__...","___..","____.","_____",
"..__..","_.._.","_...._"
]
info.set_score(0)
score= 0
char_ram_list= ""
key_ram_list= ""
char_num= 0
char_ram= ""
key_ram= ""
char_disp= textsprite.create("")
char_disp.set_max_font_height(30)
char_disp.set_outline(2,6)
char_disp.set_position(0,16)
key_disp= textsprite.create("")
key_disp.set_outline(1,8)
key_disp.set_max_font_height(10)
key_disp.set_position(15,50)
key_disp2= textsprite.create("")
key_disp2.set_outline(1,8)
key_disp2.set_max_font_height(10)
key_disp2.set_position(15,60)
key_test_disp=textsprite.create("")
key_test_disp.set_outline(1,8)
key_test_disp.set_max_font_height(8)
key_test_disp.set_position(10,100)
score_disp=textsprite.create("")
score_disp.set_outline(1,8)
score_disp.set_max_font_height(8)
score_disp.set_position(110,8)
init()