随着近年来新能源汽车的快速发展,电动汽车充电桩的人机界面(HMI)显示需求日益增长,市场对更优质、更便捷的充电桩需求愈发强烈。本充电桩规划方案基于当前市场需求,设计了一套基于二维码的移动支付系统。该系统涉及通过移动应用或小程序扫描二维码、下载并安装应用程序、注册用户名、分配ID、注册车牌号、手机号码等信息,并实现关联认证与授权。
充电完成后,费用可自动从用户移动钱包中扣除,无需重复操作。
基于处理器的图形用户界面(GUI)设计可加速产品上市时间,并帮助客户设计成本效益高的人机界面(HMI)解决方案,例如:电动汽车(EV)充电基础设施及电动汽车电源供应设备(EVSE)基础设施。
本项目展示了开发HMI的总体思路及STONE Designer(图形设计软件)的部分功能。 STONE Designer兼容OS、Windows和Linux系统,支持HMI屏幕,可满足从低端到高端应用的需求。
本文不涵盖充电硬件和充电桩的充电过程,也不详细介绍移动应用、小程序和云服务器的实现。本文重点介绍在STONE HMI显示屏STWI056WT-01的新开发平台上实现充电桩的过程, 包括 ST 文件创建、界面页面添加、按钮参数设置、图像组件参数设置、实时时钟参数及调整说明、标签分配、新开发平台的两种下载方法等。
叙述框架如下:
- 人机界面简介
- 界面控件制作
- 界面下载
- 人机交互指令
- MCU 与 STONE HMI 显示屏之间的通信编程
1. 电动汽车充电HMI显示介绍
充电桩待机界面如图(1)所示。
通过移动应用程序的二维码登录授权或小程序扫描界面,识别并激活长城充电桩设备。收集客户信息后,判断车辆充电接口连接正确,转至充电实时参数监控页面,如图(2)所示。
充电参数显示页面会显示用户名、ID和车牌号,方便用户查看。监控页面还会收集充电模块上传的实时电压,电流(电流将在不同阶段和充电速度下进行控制)也会累积充电时间并动态显示。随着充电过程的进行,屏幕上还会显示充电费用并动态变化。当充电完成(快速充电后将进行涓流补电,这是充电模块的内部工作,不涉及人机编程),手动按下“充满/结束”按钮进入感谢页面,如图(3)所示。
在感谢页面,但充电模块传感器检测到充电枪已复位,界面可自动跳转至充电桩待机界面 – 图 (1) 返回充电桩待机界面。
若扫描二维码,可再次登录进入充电实时参数监控页面 – 图 (2)。



2. HMI显示界面组件制作
首先,在STONE设计师平台中创建一个新项目,填写项目名称、所选串口屏幕分辨率640×480、项目路径等。在此填写的项目名称将在后续调试下载时用于生成编译文件(项目名称作为编译文件夹名称)。参见图 (4)

工作内容包括:
- 添加窗口
- 导入图像
- 添加数字时钟
- 生产界面切换按钮
- 标签布局显示参数
- 添加加法GIF图表
以下将逐一详细说明。
1) 添加窗口
在项目左上角的项目设置部分,右键点击项目名称。此时,在弹出菜单中选择“新建窗口”依次添加Window1、Window2,新建项目时会自动生成首页_Page作为启动页面。右键点击Window1,弹出菜单可选择“复制”、“删除”和“设为首页”。选择“设为首页”以替换启动页面。双击Window1可展开或在Window1中存储控件。
2) 导入图像
本项目以三个页面为起点_在页面、窗口1和窗口2中导入背景图片。此步骤必须首先完成,因为它是背景!在导入背景图片之前,所有创建的控件都会被背景“遮挡”。如果是按钮,你会发现它们无法实现设计功能。因此,请务必先导入背景,再创建其他控件。
在部件列表的菜单栏中长按图像图标,将其拖动到界面中。背景图像当然是640×480像素。无需使用鼠标进行对齐,键盘操作更快更准确。如图(5)所示,在右上角的参数部分填写X、 y、W和h。此外,图(5)底部的图像可选择背景图片。选择前必须先为平台添加背景图片。添加方法为点击左下角图像标签中的“+”,并根据提示依次选择艺术家制作的UI图片(这些图片的副本在后续下载界面时会提及)。

3) 添加数字时钟
在零件列表的菜单栏中长按数字时钟图标,将其拖动至界面设计区域。参考图(6)设置数字时钟的文本颜色、字体大小及格式属性。需注意PC字体库与显示字体库可能不一致。
PC 界面显示的效果与串口显示屏上的显示效果不同。时间和日期在此以两个控件显示,如图 (1)、图 (2) 和图 (3) 所示。若空间允许同时显示,格式设置为 y-mm-dd HH: mm: SS。若不显示秒,可使用格式 HH: mm。电动汽车充电的人机界面显示。

4) 生产界面切换按钮
在窗口1的充电参数监控页面(如图(2)所示),右下角有一个“全屏切换/结束”按钮。点击该按钮将切换至窗口2的感谢页面。同样,在零件列表的菜单栏中长按按钮图标,将其拖动至界面设计区域。其属性如图(7)所示。要切换到窗口2,需在“用户定义”中选择“打开窗口”,然后将目标名称设为“窗口2”。确保按钮在图片中的位置与背景不重叠,并确认按钮已放置在背景中。此外,主页宽度、 返回窗口、设置值等选项均可在用户定义中进行设置。电动汽车充电的HMI显示。

5) 标签布局显示参数
同样,在零件列表的菜单栏中长按标签图标,将其拖动到界面设计区域。在标签属性部分设置文字颜色和字体大小,并根据实时显示的电压(标签7)、电流(标签8)、充电时间(小时——标签10, 分钟 — 标签11,秒 — 标签12)、成本(标签9)和其他背景。这里重要的是名称。每个单元的名称应区分开来。从充电模块上传的数据应根据名称正确显示。不要自以为是。
6) 添加GIF动态图
如图(2)所示,右侧的电池图标是一个GIF动态图,显示正在充电的电池当前状态。同样,在部件列表的菜单栏中长按GIF图标,将其拖动到界面设计区域。GIF图像导入与图片导入类似。同样,在左侧图片标签下方通过“+”添加GIF图像。然后在属性部分的图像中选择 GIF 图像。EV 充电的人机界面显示
3. 界面下载
有两种方法:A 和 B。
- 通过 USB 闪存盘复制;
- 通过 USB 数据线复制。
方法A:
以下是具体步骤:
- 保存人机界面项目文件;
- 点击主菜单中的“调试” – “下载”,选择目标文件夹,系统将在所选文件夹下生成一个与项目同名的子文件夹;
- 将“default”文件夹复制到USB闪存盘的STONE目录下;
- 断开显示屏的电源,并将显示屏背面的拨动开关切换至“主机”位置;
- 将USB闪存盘插入显示屏的USB接口,断开其他不必要的连接后通电;
- 开机稳定后,按下显示屏背面的复位按钮。指示灯再次稳定后,断电并将拨动开关恢复到“设备”位置;
- 检查下载是否成功。否则,重复上述步骤4、5和6直至成功。
方法B:
点击主菜单中的“调试”→“下载”,选择目标文件夹,所选文件将被显示
在该文件夹下会生成一个与项目同名的子文件夹;使用自带的USB通信线缆直接连接电脑与显示屏的USB接口(即方法A中USB驱动器的USB接口),并将项目同名子文件夹下的raw/default/文件夹复制到显示屏存储目录下的“default”文件夹!注意:可先删除“default”文件夹下的其他七个文件夹(除图像文件夹外)。图像文件夹可能被系统占用,写入时会提示错误。可查看图像文件夹内包含标准标签图片。若新增标签和图片,可通过比较图像/XX文件夹中的文件后手动复制。此方法与实际机器调试类似,更便捷快速!
4.电动汽车充电人机界面(HMI)指令
使用的STONE指令包括:
- 数字时钟调整
- 标签值更新
- 页面转换
A. 数字时钟调整
首次通电时通常需要设置时钟。本项目三个界面中共有六个数字时钟控件,名称不同。通电后只需重置clock1,其余将自动同步。注意数字时钟属性的格式设置为y-mm-dd HH:mm:SS,可根据实际显示情况调整。若不需显示秒,格式为:HH:mm。设置指令统一如下:ST<{“cmd_code”:”set_date”,”type”:”digit_clock”,”widget”:”clock1″,”date”:”2022-03-24 12:23:46″}>ET
B. 标签值更新
窗口1页面上显示的实时电压(标签7)、电流(标签8)、充电时间(小时——标签10,分钟——标签11,秒——标签12)和成本(标签9)均为标签组件,由充电模块传输,MCU通过标签相关指令将其发送至串口触摸屏。标签相关指令:
set_text 设置标签显示的文本
set_value 设置标签显示的值
get_text 获取标签显示的文本
get_value 获取标签显示的值(浮点数)
示例:
设置文本:
ST<{“cmd_code”:”set_text”,”type”:”label”,”widget”:”label4″,”text”:”Frank”}>ET
ST<{“cmd_code”:”set_text”,”type”:”label”,”widget”:”label5″,”text”:”123456″}>ET
Set value:
St < {“cmd_code”: “set_value”, “type”: “label”, “widget”: “label9”, “value”: 1.23, “format”: “%. 2F”} > et set fee 1.23
ST<{“cmd_code”:”set_value”,”type”:”label”,”widget”:”label8″,”value”:25,”format”:”%02d”}>ET
Set current 25 A
Get text:
ST<{“cmd_code”:”get_text”,”type”:”label”,”widget”:”label6″}>ET
Format values: %d,%02d,%03d,%04d,%05d,%06d,%f,%.1f,%.2f,%.3f,%.4f,%.5f,%.6f
C. Page conversion
与命令相关的窗口:
open_ win 打开任何窗口(可在后台运行的 Windows 也可通过此命令打开,推荐使用)
close_ win 关闭任何窗口(不推荐使用,请谨慎操作)
back_ win 返回上级窗口并关闭当前窗口(不缓存当前串口数据)
back_ win_ 返回上层任意窗口,其他打开的窗口在后台运行
back_ home 返回主窗口,不关闭之前打开的窗口,其他窗口在后台运行;
示例:
打开 Window1 窗口
ST<{“cmd_code”:”open_win”,”type”:”window”,”widget”:”window1″}>ET
Close label_ Value window
ST<{“cmd_code”:”close_win”,”type”:”window”,”widget”:”label_value”}>ET
Return to the upper window:
ST<{“cmd_code”:”back_win”,”type”:”window”}>ET
The name of the upper layer returned is label_ Value window, which closes all windows above the window. It is generally applicable to multi-level windows
ST<{“cmd_code”:”back_win_to”,”type”:”window”,”widget”:”label_value”}>ET
Return to label_ Value window
ST<{“cmd_code”:”back_win_to”,”type”:”window”,”widget”:”home_page”}>ET
Return to main window
Return to main window
ST<{“cmd_code”:”back_home”,”type”:”window”}>ET
PS:主窗口无法关闭
- Arduino MCU与 STONE HMI 显示屏之间的通信编程
在 Arduino 环境中编程,卸载百度输入法以实现正常英文输入。此外,需在 Arduino 环境中修改上述指令,如下所示:
St < {“cmd_code”: “set_value”, “type”: “label”, “widget”: “label9”, “value”: 1.23, “format”: “%. 2F”} > et 以上设置的费用为 1.23,应在 Arduino 程序中写为:
成本价格是一个浮点变量,传输方式为串口打印(price, 2),保留小数点后2位。Serial.write(price)只能传输0-9的单个数字。由于是变量,需要单独传输。请参见下方程序代码。电动汽车充电的HMI显示。
视频效果的程序代码如下:
/*
frank13
STONE and arduino COMM
Turns on an LED on for one second, then off for one second, repeatedly.
This example code is in the file of frank.
*/
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
unsigned int count_ i=0;
//------charged station use----------2022.03.23------
unsigned int led1s=0;
unsigned int time_ 1s=0;
unsigned int time_ 1m=0;
unsigned int time_ 1h=0;
float price=0.001; // Expenses$
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
Serial. begin(115200); // Turn on the serial communication function and wait for the serial port to open
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
}
// the loop routine runs over and over again forever:
void loop() {
//---Cumulative time + +------
time_ 1s = time_ 1s + 1;
if(time_1s >= 60){
time_ 1s = 0;
time_ 1m = time_ 1m + 1;
if(time_1m >= 60){
time_ 1m = 0;
time_ 1h = time_ 1h + 1;
}
}
//------time display -----
Serial. print("ST<{\"cmd_code\":\"set_value\",\"type\":\"label\",\"widget\":\"label12\",\"value\":"); //sec
Serial. print(time_1s); // Serial. write(time_1s); . The write value is specified as single byte only out 0-9,
Serial. println(",\"format\":\"%02d\"}>ET"); // sec
delay(100);
Serial. print("ST<{\"cmd_code\":\"set_value\",\"type\":\"label\",\"widget\":\"label11\",\"value\":"); //min
Serial. print(time_1m); // Serial. write(time_1s); only out 0-9,
Serial. println(",\"format\":\"%02d\"}>ET"); // min
Serial. print("ST<{\"cmd_code\":\"set_value\",\"type\":\"label\",\"widget\":\"label10\",\"value\":"); //hour
Serial. print(time_1h); // Serial. write(time_1s); only out 0-9,
Serial. println(",\"format\":\"%d\"}>ET"); // hour
delay(100);
price = (time_1h * 120) + (time_1m * 2) + (time_1s * 0.036); // Simple algorithm of charging cost
//Here is the floating point charge price$
Serial. print("ST<{\"cmd_code\":\"set_value\",\"type\":\"label\",\"widget\":\"label9\",\"value\":");
Serial. print(price,2); // 1.2356 --- > 1.23 floating point number takes 2 decimal places
Serial. println(",\"format\":\"%.2f\"}>ET"); // price $
Serial.println(F("ST<{\"cmd_code\":\"set_value\",\"type\":\"label\",\"widget\":\"label8\",\"value\":20.11,\"format\":\"%.2f\"}>ET"));
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
led1s = led1s + 1;
if(led1s >= 2){
led1s = 0;
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
Serial.println(F("ST<{\"cmd_code\":\"set_value\",\"type\":\"label\",\"widget\":\"label8\",\"value\":20.26,\"format\":\"%.2f\"}>ET")); //current out
}
delay(1000); // wait for a second, range:200-2000
}