479 lines
16 KiB
Python
479 lines
16 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
SMiTSense足部压力传感器DLL测试程序
|
||
测试SMiTSenseUsb-F3.0.dll的Python接口调用
|
||
"""
|
||
|
||
import ctypes
|
||
import os
|
||
import sys
|
||
import time
|
||
from ctypes import Structure, c_int, c_float, c_char_p, c_void_p, c_uint32, POINTER, byref
|
||
import logging
|
||
|
||
# 设置日志
|
||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||
logger = logging.getLogger(__name__)
|
||
|
||
class SMiTSensePressureSensor:
|
||
"""
|
||
SMiTSense足部压力传感器Python接口类
|
||
"""
|
||
|
||
def __init__(self, dll_path=None):
|
||
"""
|
||
初始化SMiTSense压力传感器
|
||
|
||
Args:
|
||
dll_path: DLL文件路径,如果为None则使用默认路径
|
||
"""
|
||
self.dll = None
|
||
self.device_handle = None
|
||
self.is_connected = False
|
||
|
||
# 设置DLL路径
|
||
if dll_path is None:
|
||
dll_path = os.path.join(os.path.dirname(__file__), 'SMiTSenseUsb-F3.0.dll')
|
||
|
||
self.dll_path = dll_path
|
||
self._load_dll()
|
||
|
||
def _load_dll(self):
|
||
"""
|
||
加载SMiTSense DLL并设置函数签名
|
||
"""
|
||
try:
|
||
if not os.path.exists(self.dll_path):
|
||
raise FileNotFoundError(f"DLL文件未找到: {self.dll_path}")
|
||
|
||
# 加载DLL
|
||
self.dll = ctypes.WinDLL(self.dll_path)
|
||
logger.info(f"成功加载DLL: {self.dll_path}")
|
||
|
||
# 设置函数签名
|
||
self._setup_function_signatures()
|
||
|
||
except Exception as e:
|
||
logger.error(f"加载DLL失败: {e}")
|
||
raise
|
||
|
||
def _setup_function_signatures(self):
|
||
"""
|
||
设置DLL函数的参数类型和返回类型
|
||
"""
|
||
try:
|
||
# fpms_usb_init - 初始化USB连接
|
||
self.dll.fpms_usb_init.argtypes = []
|
||
self.dll.fpms_usb_init.restype = c_int
|
||
|
||
# fpms_usb_get_device_list - 获取设备列表
|
||
self.dll.fpms_usb_get_device_list.argtypes = [POINTER(c_int)]
|
||
self.dll.fpms_usb_get_device_list.restype = c_int
|
||
|
||
# fpms_usb_open - 打开设备
|
||
self.dll.fpms_usb_open.argtypes = [c_int]
|
||
self.dll.fpms_usb_open.restype = c_void_p
|
||
|
||
# fpms_usb_close - 关闭设备
|
||
self.dll.fpms_usb_close.argtypes = [c_void_p]
|
||
self.dll.fpms_usb_close.restype = c_int
|
||
|
||
# fpms_usb_read_frame - 读取压力数据帧
|
||
self.dll.fpms_usb_read_frame.argtypes = [c_void_p, POINTER(c_float), c_int]
|
||
self.dll.fpms_usb_read_frame.restype = c_int
|
||
|
||
# fpms_usb_get_sensitivity - 获取灵敏度
|
||
self.dll.fpms_usb_get_sensitivity.argtypes = [c_void_p, POINTER(c_float)]
|
||
self.dll.fpms_usb_get_sensitivity.restype = c_int
|
||
|
||
# fpms_usb_config_sensitivity - 配置灵敏度
|
||
self.dll.fpms_usb_config_sensitivity.argtypes = [c_void_p, c_float]
|
||
self.dll.fpms_usb_config_sensitivity.restype = c_int
|
||
|
||
logger.info("DLL函数签名设置完成")
|
||
|
||
except AttributeError as e:
|
||
logger.error(f"设置函数签名失败,可能是函数名不匹配: {e}")
|
||
raise
|
||
|
||
def initialize(self):
|
||
"""
|
||
初始化USB连接
|
||
|
||
Returns:
|
||
bool: 初始化是否成功
|
||
"""
|
||
try:
|
||
result = self.dll.fpms_usb_init()
|
||
if result == 0:
|
||
logger.info("USB连接初始化成功")
|
||
return True
|
||
else:
|
||
logger.error(f"USB连接初始化失败,错误码: {result}")
|
||
return False
|
||
except Exception as e:
|
||
logger.error(f"初始化异常: {e}")
|
||
return False
|
||
|
||
def get_device_list(self):
|
||
"""
|
||
获取可用设备列表
|
||
|
||
Returns:
|
||
list: 设备ID列表
|
||
"""
|
||
try:
|
||
device_count = c_int()
|
||
result = self.dll.fpms_usb_get_device_list(byref(device_count))
|
||
|
||
if result == 0:
|
||
count = device_count.value
|
||
logger.info(f"发现 {count} 个SMiTSense设备")
|
||
return list(range(count))
|
||
else:
|
||
logger.error(f"获取设备列表失败,错误码: {result}")
|
||
return []
|
||
except Exception as e:
|
||
logger.error(f"获取设备列表异常: {e}")
|
||
return []
|
||
|
||
def connect(self, device_id=0):
|
||
"""
|
||
连接到指定设备
|
||
|
||
Args:
|
||
device_id: 设备ID,默认为0
|
||
|
||
Returns:
|
||
bool: 连接是否成功
|
||
"""
|
||
try:
|
||
self.device_handle = self.dll.fpms_usb_open(device_id)
|
||
|
||
if self.device_handle:
|
||
self.is_connected = True
|
||
logger.info(f"成功连接到设备 {device_id}")
|
||
return True
|
||
else:
|
||
logger.error(f"连接设备 {device_id} 失败")
|
||
return False
|
||
except Exception as e:
|
||
logger.error(f"连接设备异常: {e}")
|
||
return False
|
||
|
||
def disconnect(self):
|
||
"""
|
||
断开设备连接
|
||
|
||
Returns:
|
||
bool: 断开是否成功
|
||
"""
|
||
try:
|
||
if self.device_handle and self.is_connected:
|
||
result = self.dll.fpms_usb_close(self.device_handle)
|
||
|
||
if result == 0:
|
||
self.is_connected = False
|
||
self.device_handle = None
|
||
logger.info("设备连接已断开")
|
||
return True
|
||
else:
|
||
logger.error(f"断开连接失败,错误码: {result}")
|
||
return False
|
||
else:
|
||
logger.warning("设备未连接,无需断开")
|
||
return True
|
||
except Exception as e:
|
||
logger.error(f"断开连接异常: {e}")
|
||
return False
|
||
|
||
def read_pressure_data(self, sensor_count=16):
|
||
"""
|
||
读取压力传感器数据
|
||
|
||
Args:
|
||
sensor_count: 传感器数量,默认16个
|
||
|
||
Returns:
|
||
list: 压力值列表,如果失败返回None
|
||
"""
|
||
try:
|
||
if not self.is_connected or not self.device_handle:
|
||
logger.error("设备未连接")
|
||
return None
|
||
|
||
# 创建压力数据缓冲区
|
||
pressure_data = (c_float * sensor_count)()
|
||
|
||
result = self.dll.fpms_usb_read_frame(
|
||
self.device_handle,
|
||
pressure_data,
|
||
sensor_count
|
||
)
|
||
|
||
if result == 0:
|
||
# 转换为Python列表
|
||
data_list = [pressure_data[i] for i in range(sensor_count)]
|
||
logger.debug(f"读取压力数据成功: {data_list}")
|
||
return data_list
|
||
else:
|
||
logger.error(f"读取压力数据失败,错误码: {result}")
|
||
return None
|
||
|
||
except Exception as e:
|
||
logger.error(f"读取压力数据异常: {e}")
|
||
return None
|
||
|
||
def get_sensitivity(self):
|
||
"""
|
||
获取传感器灵敏度
|
||
|
||
Returns:
|
||
float: 灵敏度值,如果失败返回None
|
||
"""
|
||
try:
|
||
if not self.is_connected or not self.device_handle:
|
||
logger.error("设备未连接")
|
||
return None
|
||
|
||
sensitivity = c_float()
|
||
result = self.dll.fpms_usb_get_sensitivity(self.device_handle, byref(sensitivity))
|
||
|
||
if result == 0:
|
||
value = sensitivity.value
|
||
logger.info(f"当前灵敏度: {value}")
|
||
return value
|
||
else:
|
||
logger.error(f"获取灵敏度失败,错误码: {result}")
|
||
return None
|
||
|
||
except Exception as e:
|
||
logger.error(f"获取灵敏度异常: {e}")
|
||
return None
|
||
|
||
def set_sensitivity(self, sensitivity_value):
|
||
"""
|
||
设置传感器灵敏度
|
||
|
||
Args:
|
||
sensitivity_value: 灵敏度值
|
||
|
||
Returns:
|
||
bool: 设置是否成功
|
||
"""
|
||
try:
|
||
if not self.is_connected or not self.device_handle:
|
||
logger.error("设备未连接")
|
||
return False
|
||
|
||
result = self.dll.fpms_usb_config_sensitivity(
|
||
self.device_handle,
|
||
c_float(sensitivity_value)
|
||
)
|
||
|
||
if result == 0:
|
||
logger.info(f"灵敏度设置成功: {sensitivity_value}")
|
||
return True
|
||
else:
|
||
logger.error(f"设置灵敏度失败,错误码: {result}")
|
||
return False
|
||
|
||
except Exception as e:
|
||
logger.error(f"设置灵敏度异常: {e}")
|
||
return False
|
||
|
||
def get_foot_pressure_zones(self, pressure_data):
|
||
"""
|
||
将原始压力数据转换为足部区域压力
|
||
|
||
Args:
|
||
pressure_data: 原始压力数据列表
|
||
|
||
Returns:
|
||
dict: 足部各区域压力数据
|
||
"""
|
||
if not pressure_data or len(pressure_data) < 16:
|
||
return None
|
||
|
||
try:
|
||
# 假设16个传感器的布局(可根据实际传感器布局调整)
|
||
# 左脚前部: 传感器 0-3
|
||
# 左脚后部: 传感器 4-7
|
||
# 右脚前部: 传感器 8-11
|
||
# 右脚后部: 传感器 12-15
|
||
|
||
left_front = sum(pressure_data[0:4])
|
||
left_rear = sum(pressure_data[4:8])
|
||
right_front = sum(pressure_data[8:12])
|
||
right_rear = sum(pressure_data[12:16])
|
||
|
||
left_total = left_front + left_rear
|
||
right_total = right_front + right_rear
|
||
total_pressure = left_total + right_total
|
||
|
||
return {
|
||
'left_front': left_front,
|
||
'left_rear': left_rear,
|
||
'right_front': right_front,
|
||
'right_rear': right_rear,
|
||
'left_total': left_total,
|
||
'right_total': right_total,
|
||
'total_pressure': total_pressure,
|
||
'raw_data': pressure_data
|
||
}
|
||
|
||
except Exception as e:
|
||
logger.error(f"处理足部压力区域数据异常: {e}")
|
||
return None
|
||
|
||
|
||
def test_smitsense_sensor():
|
||
"""
|
||
测试SMiTSense压力传感器的主要功能
|
||
"""
|
||
logger.info("开始SMiTSense压力传感器测试")
|
||
|
||
# 创建传感器实例
|
||
sensor = SMiTSensePressureSensor()
|
||
|
||
try:
|
||
# 1. 初始化
|
||
logger.info("1. 初始化USB连接...")
|
||
if not sensor.initialize():
|
||
logger.error("初始化失败,测试终止")
|
||
return False
|
||
|
||
# 2. 获取设备列表
|
||
logger.info("2. 获取设备列表...")
|
||
devices = sensor.get_device_list()
|
||
if not devices:
|
||
logger.warning("未发现SMiTSense设备")
|
||
return False
|
||
|
||
logger.info(f"发现设备: {devices}")
|
||
|
||
# 3. 连接第一个设备
|
||
logger.info("3. 连接设备...")
|
||
if not sensor.connect(devices[0]):
|
||
logger.error("连接设备失败")
|
||
return False
|
||
|
||
# 4. 获取当前灵敏度
|
||
logger.info("4. 获取传感器灵敏度...")
|
||
sensitivity = sensor.get_sensitivity()
|
||
if sensitivity is not None:
|
||
logger.info(f"当前灵敏度: {sensitivity}")
|
||
|
||
# 5. 设置新的灵敏度(可选)
|
||
logger.info("5. 设置传感器灵敏度...")
|
||
if sensor.set_sensitivity(1.0):
|
||
logger.info("灵敏度设置成功")
|
||
|
||
# 6. 读取压力数据
|
||
logger.info("6. 开始读取压力数据...")
|
||
for i in range(10): # 读取10次数据
|
||
pressure_data = sensor.read_pressure_data()
|
||
|
||
if pressure_data:
|
||
# 转换为足部区域数据
|
||
foot_zones = sensor.get_foot_pressure_zones(pressure_data)
|
||
|
||
if foot_zones:
|
||
logger.info(f"第{i+1}次读取:")
|
||
logger.info(f" 左脚前部: {foot_zones['left_front']:.2f}")
|
||
logger.info(f" 左脚后部: {foot_zones['left_rear']:.2f}")
|
||
logger.info(f" 右脚前部: {foot_zones['right_front']:.2f}")
|
||
logger.info(f" 右脚后部: {foot_zones['right_rear']:.2f}")
|
||
logger.info(f" 总压力: {foot_zones['total_pressure']:.2f}")
|
||
else:
|
||
logger.warning(f"第{i+1}次读取: 数据处理失败")
|
||
else:
|
||
logger.warning(f"第{i+1}次读取: 无数据")
|
||
|
||
time.sleep(0.1) # 等待100ms
|
||
|
||
logger.info("压力数据读取测试完成")
|
||
return True
|
||
|
||
except Exception as e:
|
||
logger.error(f"测试过程中发生异常: {e}")
|
||
return False
|
||
|
||
finally:
|
||
# 7. 断开连接
|
||
logger.info("7. 断开设备连接...")
|
||
sensor.disconnect()
|
||
logger.info("SMiTSense压力传感器测试结束")
|
||
|
||
|
||
def test_dll_functions():
|
||
"""
|
||
测试DLL函数的基本调用(不需要实际硬件)
|
||
"""
|
||
logger.info("开始DLL函数基本调用测试")
|
||
|
||
try:
|
||
sensor = SMiTSensePressureSensor()
|
||
logger.info("DLL加载成功")
|
||
|
||
# 测试初始化函数
|
||
logger.info("测试初始化函数...")
|
||
result = sensor.initialize()
|
||
logger.info(f"初始化结果: {result}")
|
||
|
||
# 测试获取设备列表
|
||
logger.info("测试获取设备列表...")
|
||
devices = sensor.get_device_list()
|
||
logger.info(f"设备列表: {devices}")
|
||
|
||
logger.info("DLL函数基本调用测试完成")
|
||
return True
|
||
|
||
except Exception as e:
|
||
logger.error(f"DLL函数测试失败: {e}")
|
||
return False
|
||
|
||
|
||
if __name__ == "__main__":
|
||
print("SMiTSense足部压力传感器DLL测试程序")
|
||
print("=" * 50)
|
||
|
||
# 检查DLL文件是否存在
|
||
dll_path = os.path.join(os.path.dirname(__file__), 'SMiTSenseUsb-F3.0.dll')
|
||
if not os.path.exists(dll_path):
|
||
print(f"错误: DLL文件不存在 - {dll_path}")
|
||
print("请确保SMiTSenseUsb-F3.0.dll文件在当前目录中")
|
||
sys.exit(1)
|
||
|
||
print(f"DLL文件路径: {dll_path}")
|
||
print()
|
||
|
||
# 运行测试
|
||
try:
|
||
# 首先测试DLL基本功能
|
||
print("1. DLL基本功能测试")
|
||
print("-" * 30)
|
||
if test_dll_functions():
|
||
print("✅ DLL基本功能测试通过")
|
||
else:
|
||
print("❌ DLL基本功能测试失败")
|
||
|
||
print()
|
||
|
||
# 然后测试完整的传感器功能(需要硬件)
|
||
print("2. 完整传感器功能测试(需要硬件连接)")
|
||
print("-" * 30)
|
||
if test_smitsense_sensor():
|
||
print("✅ 传感器功能测试通过")
|
||
else:
|
||
print("❌ 传感器功能测试失败(可能是硬件未连接)")
|
||
|
||
except KeyboardInterrupt:
|
||
print("\n用户中断测试")
|
||
except Exception as e:
|
||
print(f"\n测试过程中发生未处理的异常: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
print("\n测试程序结束") |