99浏览
查看: 99|回复: 0

[K10项目分享] K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...

[复制链接]
本帖最后由 湘里人 于 2025-1-14 16:26 编辑

一、刷micropython_unihiker_k10官方库
具体方法见官方介绍:烧录固件


二、百度千帆大模型:
https://qianfan.cloud.baidu.com/ ... fa8684dc35f119d4f3f
登陆界面
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图1
登陆成功后,点击页面上方的“大模型服务与开发平台ModelBuilder”
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图2
在右侧找到“应用接入”
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图3
创建应用:输入应用名称和应用描述,选择全部服务,点击“确定”创建应用。
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图4
应用创建完后,复制 API Key和 Secret Key用于“获取AccessToken”。

K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图5

二、语音识别和语音合成应用
网址:https://console.bce.baidu.com/ai/#/ai/speech/app/create
1、创建应用。
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图6
2、应用创建完后,复制 API Key和 Secret Key用于“获取AccessToken”。
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图7


3、领取语音应用的免费额度
进入https://console.bce.baidu.com/ai-engine/speech/overview/index,领取免费资源
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图8


三、api调用
进入示例代码中心:https://console.bce.baidu.com/support/?u=dhead#/api
在“全部产品”中选择“千帆ModelBuilder”或“语音技术”
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图9
1.获取AccessToken
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图10K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图11K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图12


2、示例代码的获取,以语音识别为例。
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图13

四、界面美化   unihiker_k10官方库集成了LVGL(轻量级和多功能图形库),为创建美观的视觉效果提供了可能,但官方固件对中文支持不是很好。
1、建立中文字库,实现中文显示
具体操作见我以前的帖子:K10官方micropython_unihiker_k10固件支持中文显示的方法
2、机器人的动态表情,命名为change_eyes.py
  1. from unihiker_k10 import screen, acce
  2. import time, gc
  3. import lvgl as lv
  4. import fs_driver, math
  5. # 初始化LVGL和屏幕
  6. screen.init(dir=2)
  7. scrn = lv.screen_active()
  8. scrn.set_style_bg_color(lv.color_hex(0x000000), 0)
  9. # 初始化文件系统驱动
  10. fs_drv = lv.fs_drv_t()
  11. fs_driver.fs_register(fs_drv, 'S')
  12. # 创建开口向上的弧线
  13. arc3 = lv.arc(scrn)
  14. arc3.set_size(200, 100)  # 设置弧线的大小
  15. arc3.set_bg_angles(90, 100)  # 设置背景角度为0到180度,表示开口向上
  16. arc3.set_angles(0, 180)  # 设置显示角度为0到180度
  17. arc3.align(lv.ALIGN.BOTTOM_MID, 50, -60)  # 将弧线放置在屏幕底部中间位置,稍微向上移动
  18. # 创建第一个蓝色实心球(眼球)
  19. eye1 = lv.led(scrn)
  20. eye1.set_size(60, 30)  # 设置大小为32x20像素
  21. eye1.set_color(lv.color_hex(0x0000FF))  # 设置颜色为蓝色
  22. eye1.align(lv.ALIGN.TOP_LEFT, 50, 90)  # 将眼球放置在第一个圆球的中间
  23. # 创建第二个蓝色实心球(眼球)
  24. eye2 = lv.led(scrn)
  25. eye2.set_size(60, 30)  # 设置大小为32x20像素
  26. eye2.set_color(lv.color_hex(0x0000FF))  # 设置颜色为蓝色
  27. eye2.align(lv.ALIGN.TOP_RIGHT, -50, 90)  # 将眼球放置在第二个圆球的中间
  28. def animate_mouth():
  29.     for angle in range(360, 300, -10):
  30.         arc3.set_angles(angle, angle + 180)  # 设置显示角度为0到180度
  31. #         time.sleep(2)  # 持续2秒
  32.         time.sleep(0.1)
  33.     for angle in range(300, 360, 10):
  34.         arc3.set_angles(angle, angle + 180)  # 设置显示角度为0到180度
  35. #         time.sleep(2)  # 持续2秒
  36.         time.sleep(0.1)
  37. # 动态改变眼球的水平位置以模拟表情变化
  38. def change_eyes():
  39. #   # 向左看
  40.     eye1.align(lv.ALIGN.TOP_LEFT, 40, 90)
  41.     eye2.align(lv.ALIGN.TOP_RIGHT, -60, 90)
  42.     time.sleep(0.2)  # 持续1秒
  43.    
  44.     # 向右看
  45.     eye1.align(lv.ALIGN.TOP_LEFT, 60, 90)
  46.     eye2.align(lv.ALIGN.TOP_RIGHT, -40, 90)
  47.     time.sleep(0.2)  # 持续1秒
  48.    
  49.     # 回到中间
  50.     eye1.align(lv.ALIGN.TOP_LEFT, 50, 90)
  51.     eye2.align(lv.ALIGN.TOP_RIGHT, -50, 90)
  52.     time.sleep(0.2)  # 持续1秒
  53.     animate_mouth()
  54. # 启动眼球变化
  55. change_eyes()
  56. # 启动表情变化
  57. # change_expression()
复制代码
3、上传字库和机器人表情文件
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图15K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图14


五、主脚本
  1. from unihiker_k10 import screen, mic, button, wifi,speaker
  2. import ubinascii
  3. import json
  4. import time
  5. import urequests as requests
  6. import lvgl as lv
  7. import fs_driver, math
  8. from change_eyes import change_eyes
  9. from machine import Timer
  10. # 全局变量
  11. scrn = None
  12. font_cn = None
  13. token= None
  14. AItoken=None
  15. text = ""
  16. label_title = None
  17. # 连接WiFi
  18. def connect_wifi(ssid, password):
  19.     wifi.connect(ssid=ssid, psd=password, timeout=50000)
  20.     while not wifi.status():
  21.         time.sleep(0.1)
  22.     print("WiFi connected:", wifi.info())
  23.    
  24.    
  25. # 初始化屏幕和字体
  26. def init_screen():
  27.     global scrn, font_cn, label_title
  28.     screen.init(dir=2)
  29.     scrn = lv.screen_active()
  30.     scrn.set_style_bg_color(lv.color_hex(0x000000), 0)
  31.     fs_drv = lv.fs_drv_t()
  32.     fs_driver.fs_register(fs_drv, 'S')
  33.     font_cn = lv.binfont_create("S:my_font_16.bin")
  34.     if font_cn is None:
  35.         print("字体加载失败")
  36.     else:
  37.         print("字体加载成功")
  38.    
  39.     # 创建一个新的标签
  40.     label_title = lv.label(scrn)
  41.     label_title.set_text("字体加载成功")
  42.     label_title.set_width(200)
  43.     label_title.align(lv.ALIGN.TOP_LEFT, 20, 20)
  44.     if font_cn:
  45.         label_title.set_style_text_font(font_cn, 0)  # 设置中文字体
  46.     scrn.set_style_bg_color(lv.color_hex(0x000000), 0)
  47. # 更新标签的回调函数
  48. def update_label():
  49.     global text
  50.     print("text:",text, time.localtime())
  51.     label_title.set_text(text)
  52. # 百度语音识别
  53. def baidu_speech_recognize(audio_file, token):
  54.     print("token:",token)
  55.     url = "https://vop.baidu.com/server_api"
  56.     with open(audio_file, "rb") as f:
  57.         audio_data = f.read()
  58.     base64_data = ubinascii.b2a_base64(audio_data)[:-1].decode('utf-8')
  59.     payload = json.dumps({
  60.         "format": "wav",
  61.         "rate": 16000,
  62.         "channel": 1,
  63.         "cuid": "UNIHIKER_K10",
  64.         "speech": base64_data,
  65.         "len": len(audio_data),
  66.         "token": token
  67.     })
  68.     headers = {
  69.         'Content-Type': 'application/json',
  70.         'Accept': 'application/json'
  71.     }
  72.     response = requests.post(url, headers=headers, data=payload)
  73.     print(response.text)
  74.     data = json.loads(response.text)
  75.     return ''.join(data['result'])
  76. def Baidu_TTS(filename,text, token):
  77.     # 设置请求参数
  78.     params = {
  79.         'tok': token,
  80.         'tex': text,  # 直接使用text,不需要quote_plus
  81.         'per': 5,#基础音库:度小宇=1,度小美=0,度逍遥(基础)=3,度丫丫=4,精品音库:度逍遥(精品)=5003,度小鹿=5118,度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5
  82.         'spd': 5,#中语速
  83.         'pit': 5,#中语调
  84.         'vol': 9,#中音量
  85.         'aue': 6,#wav,3为mp3格式(默认); 4为pcm-16k;5为pcm-8k;6为wav(内容同pcm-16k);
  86.         'cuid': "ZZloekkfqvZFKhpVtFXGlAopgnHnHCgQ",#用户唯一标识
  87.         'lan': 'zh',
  88.         'ctp': 1  #客户端类型选择,web端填写固定值1
  89.     }
  90.     headers = {
  91.         'Content-Type': 'application/x-www-form-urlencoded',
  92.         'Accept': '*/*'
  93.     }
  94.     # 将参数编码,然后放入body,生成Request对象
  95.     data = urlencode(params).encode('utf-8')
  96.     # 发送POST请求
  97.     response = requests.post("http://tsn.baidu.com/text2audio", headers=headers,data=data)
  98.     # 检查响应状态码
  99.     if response.status_code == 200:
  100.         # 将返回的音频数据写入文件
  101.         print("开始生成合成音频")
  102.         
  103.         gc.collect()  # 写入前收集垃圾
  104.         with open(filename, "wb") as f:
  105.             f.write(response.content)
  106.         gc.collect()  # 写入后收集垃圾
  107.         print("完成生成合成音频")
  108.     else:
  109.         print("无法获取音频文件")
  110.    
  111. def Baidu_Big_Model(text,AItoken):#大模型对话函数
  112.     url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie_speed?access_token="+AItoken
  113.    
  114.     payload = json.dumps({
  115.         "messages": [
  116.             {
  117.                 "role": "user",
  118.                 "content": text
  119.             }
  120.         ],
  121.         "temperature": 0.95,
  122.         "top_p": 0.8,
  123.         "penalty_score": 1,
  124.         "enable_system_memory": False,
  125.         "disable_search": False,
  126.         "enable_citation": False,
  127.         "system": "请将回答控制在30字,最后加个‘完’字结束对话",
  128.         "response_format": "text"
  129.     })
  130.     headers = {
  131.         'Content-Type': 'application/json'
  132.     }
  133.     response = requests.post(url, headers=headers, data=payload.encode('utf-8'))
  134.     if response.status_code == 200:
  135.         print(response.text)
  136.         data = json.loads(response.text)
  137.         decoded_str= data['result']   
  138.         return(decoded_str)
  139. def urlencode(params):#编码成 URL 编码格式的字符串
  140.     encoded_pairs = []
  141.     for key, value in params.items():
  142.         # 确保键和值都是字符串
  143.         key_str = str(key)
  144.         value_str = str(value)
  145.         # 手动实现简单的URL编码
  146.         encoded_key = key_str.replace(" ", "%20")
  147.         encoded_value = value_str.replace(" ", "%20")
  148.         encoded_pairs.append(f"{encoded_key}={encoded_value}")
  149.     return "&".join(encoded_pairs)
  150. #获取token
  151. def get_access_token(API_KEY,SECRET_KEY):
  152.    
  153.     url = "https://aip.baidubce.com/oauth/2.0/token"
  154.     params = {
  155.         'grant_type': 'client_credentials',
  156.         'client_id': API_KEY,
  157.         'client_secret': SECRET_KEY
  158.     }
  159.     data = urlencode(params).encode('utf-8')
  160.     response = requests.post(url, data=data)
  161.     access_token=json.loads(response.text)['access_token']
  162.     print(access_token)
  163.     return access_token
  164. # 开始录音
  165. def start_recording():
  166.     global scrn, font_cn,label_title,token,AItoken,text
  167.    
  168.     print("开始录音")
  169.     text ="开始对话"
  170.     mic.recode_sys(name="sound.wav", time=5)
  171. #     label_title.set_text("开始录音……")
  172. # 上传录音并识别
  173.     print("音频上传,进行百度识别")
  174.     text ="音频上传,进行百度识别"
  175.     time.sleep(0.1)
  176.     label_title.set_text(text)
  177.     time.sleep(0.1)
  178.     text = baidu_speech_recognize("sound.wav", token)
  179.     print("百度语音识别结果:", text)
  180.     text = Baidu_Big_Model(text,AItoken)
  181.     time.sleep(0.1)
  182.     label_title.set_text(text)
  183.     time.sleep(0.1)
  184.     audio_file = "audio2.wav"
  185.     Baidu_TTS(audio_file,text, token)#语音合成
  186.     time.sleep(0.1)
  187.     #播放音频
  188.     print("播放音频")
  189.     speaker.play_sys_music(audio_file)
  190. def up_recording():
  191.     global scrn, font_cn,label_title,token,AItoken
  192.     label_title.set_text("功能暂未开发")
  193. # 初始化板载按键传感器 A 和 B
  194. def init_buttons():
  195.     bt_a = button(button.a)
  196.     bt_b = button(button.b)
  197.     bt_a.event_pressed = start_recording
  198.     bt_b.event_pressed = up_recording
  199. # 主函数
  200. def main():
  201.     global scrn, font_cn,label_title,token,AItoken,text
  202.     connect_wifi("r……", "wi……")
  203.     init_screen()
  204.     init_buttons()
  205.     API_KEY = "sexS8Y……"
  206.     SECRET_KEY = "nS2qMT……yjhTKrsWQ"
  207.     token = get_access_token(API_KEY,SECRET_KEY)#语音识别和语音合成的token
  208.       
  209.     print(token)
  210.     API_KEY = "ShZO7VeT……lmnF"
  211.     SECRET_KEY = "b5bxt……xV"   
  212. #     AItoken ="24.1bd84e812aa……………………"   
  213.     AItoken = get_access_token(API_KEY,SECRET_KEY)#大模型的token
  214.    
  215.     text ="按A键开始与大模型对话"
  216.     label_title.set_text(text)
  217. #     tim1 = Timer(1)
  218. #     tim1.init(period=100, mode=Timer.PERIODIC, callback=lambda t:update_label())
  219.     while True:
  220. #         #     # 启动眼球变化
  221.         change_eyes()
  222.         time.sleep(0.1)
  223. if __name__ == "__main__":
  224.     main()
  225.    
  226.    
复制代码
需修改部分
K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图17

文件打包【字库,change_eyes.py,main.py下载附件baiduK10.zip

效果图K10AI机器人【基于官方micropython_unihiker_k10固件和百度千...图16

六、待完善之处
1、语音识别和合成调用所需时间太长
2、机器人的表情和文字显示会因其它程序的运行而中断
多次尝试,没有解决。







您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail