update readme
@ -1,59 +0,0 @@
|
|||||||
import sys
|
|
||||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
|
|
||||||
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
|
|
||||||
import vtkmodules.all as vtk
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
super(MainWindow, self).__init__(parent)
|
|
||||||
self.setWindowTitle("VTK with PyQt Example")
|
|
||||||
self.frame = QWidget()
|
|
||||||
self.vl = QVBoxLayout()
|
|
||||||
|
|
||||||
# VTK Renderer
|
|
||||||
self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
|
|
||||||
self.vl.addWidget(self.vtkWidget)
|
|
||||||
|
|
||||||
self.ren = vtk.vtkRenderer()
|
|
||||||
self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
|
|
||||||
self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
|
|
||||||
|
|
||||||
# Load OBJ and MTL files
|
|
||||||
self.load_obj_file("resource/PCB.obj", "resource/PCB.mtl")
|
|
||||||
|
|
||||||
# Add a light to the renderer
|
|
||||||
self.add_light()
|
|
||||||
|
|
||||||
self.frame.setLayout(self.vl)
|
|
||||||
self.setCentralWidget(self.frame)
|
|
||||||
|
|
||||||
self.show()
|
|
||||||
self.iren.Initialize()
|
|
||||||
|
|
||||||
def load_obj_file(self, obj_file_path, mtl_file_path):
|
|
||||||
# Create an OBJ importer
|
|
||||||
importer = vtk.vtkOBJImporter()
|
|
||||||
importer.SetFileName(obj_file_path)
|
|
||||||
importer.SetFileNameMTL(mtl_file_path)
|
|
||||||
importer.SetTexturePath("resource")
|
|
||||||
importer.SetRenderWindow(self.vtkWidget.GetRenderWindow())
|
|
||||||
importer.Update()
|
|
||||||
|
|
||||||
self.ren.ResetCamera()
|
|
||||||
|
|
||||||
def add_light(self):
|
|
||||||
# Create a light
|
|
||||||
light = vtk.vtkLight()
|
|
||||||
light.SetFocalPoint(0, 0, 0)
|
|
||||||
light.SetPosition(1, 1, 1)
|
|
||||||
light.SetIntensity(0.3) # Adjust intensity to make the scene darker
|
|
||||||
|
|
||||||
self.ren.AddLight(light)
|
|
||||||
# Set a darker background color
|
|
||||||
colors = vtk.vtkNamedColors()
|
|
||||||
self.ren.SetBackground(colors.GetColor3d("DarkSlateGray"))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app = QApplication(sys.argv)
|
|
||||||
window = MainWindow()
|
|
||||||
sys.exit(app.exec_())
|
|
||||||
141
README.md
@ -30,7 +30,8 @@
|
|||||||
|
|
||||||
### 电路设计图:
|
### 电路设计图:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
## 软件开发 💻
|
## 软件开发 💻
|
||||||
|
|
||||||
@ -40,7 +41,130 @@
|
|||||||
- **数据读取**:从芯片读取EEG数据。
|
- **数据读取**:从芯片读取EEG数据。
|
||||||
- **数据处理**:初步处理和滤波。
|
- **数据处理**:初步处理和滤波。
|
||||||
|
|
||||||
## 上位机程序 📊
|
### 引脚定义
|
||||||
|
|
||||||
|
| 引脚名称 | 描述 |
|
||||||
|
| --------- | ------------------------------- |
|
||||||
|
| CS_PIN | 片选引脚,低电平有效 |
|
||||||
|
| SCLK_PIN | SPI时钟引脚 |
|
||||||
|
| MOSI_PIN | SPI主设备输出从设备输入引脚 |
|
||||||
|
| MISO_PIN | SPI主设备输入从设备输出引脚 |
|
||||||
|
| DRDY_PIN | 数据就绪引脚,低电平表示数据可读 |
|
||||||
|
| CLKSEL_PIN| 时钟选择引脚 |
|
||||||
|
| START_PIN | 启动转换引脚 |
|
||||||
|
| RESET_PIN | 重置引脚 |
|
||||||
|
| PWDN_PIN | 省电模式引脚 |
|
||||||
|
|
||||||
|
### 命令定义
|
||||||
|
|
||||||
|
| 命令 | 描述 |
|
||||||
|
| ------- | --------------------- |
|
||||||
|
| WAKEUP | 唤醒芯片 |
|
||||||
|
| STANDBY | 进入待机模式 |
|
||||||
|
| RESET | 重置芯片 |
|
||||||
|
| START | 开始数据转换 |
|
||||||
|
| STOP | 停止数据转换 |
|
||||||
|
| RDATAC | 连续读取数据 |
|
||||||
|
| SDATAC | 停止连续读取数据 |
|
||||||
|
| RDATA | 读取数据 |
|
||||||
|
| RREG | 读取寄存器 |
|
||||||
|
| WREG | 写寄存器 |
|
||||||
|
|
||||||
|
### 定时器中断
|
||||||
|
|
||||||
|
代码中使用ESP32的定时器来定时读取数据和导联检测状态:
|
||||||
|
|
||||||
|
- `onDataTimer`: 检查数据是否就绪,如果就绪则设置标志位`startRead`。
|
||||||
|
- `onImpedanceTimer`: 读取导联检测状态。
|
||||||
|
|
||||||
|
### 初始化
|
||||||
|
|
||||||
|
在`setup`函数中:
|
||||||
|
|
||||||
|
- 初始化串口通信。
|
||||||
|
- 初始化引脚模式。
|
||||||
|
- 初始化SPI通信参数。
|
||||||
|
- 调用`initADS1299`函数初始化ADS1299。
|
||||||
|
- 获取并打印设备ID。
|
||||||
|
- 配置ESP32的定时器用于数据读取和导联检测。
|
||||||
|
|
||||||
|
### 主循环
|
||||||
|
|
||||||
|
在`loop`函数中:
|
||||||
|
|
||||||
|
- 检查串口是否有数据输入,用于切换连续读取模式和导联检测模式。
|
||||||
|
- 如果`startRead`标志位被设置,调用`readData`函数读取数据。
|
||||||
|
|
||||||
|
### 启动连续读取模式
|
||||||
|
|
||||||
|
`startContinuousReadMode`函数:
|
||||||
|
|
||||||
|
- 设置必要的标志位。
|
||||||
|
- 重置并初始化ADS1299的寄存器。
|
||||||
|
- 启动连续数据读取模式。
|
||||||
|
- 启动数据读取定时器,停止导联检测定时器。
|
||||||
|
|
||||||
|
### 启动导联检测模式
|
||||||
|
|
||||||
|
`startLeadOffDetectionMode`函数:
|
||||||
|
|
||||||
|
- 设置必要的标志位。
|
||||||
|
- 重置并初始化ADS1299的寄存器用于导联检测。
|
||||||
|
- 启动导联检测定时器,停止数据读取定时器。
|
||||||
|
|
||||||
|
### ADS1299初始化
|
||||||
|
|
||||||
|
`initADS1299`函数:
|
||||||
|
|
||||||
|
- 启动ADS1299的时序。
|
||||||
|
- 重置芯片。
|
||||||
|
- 停止连续数据读取模式。
|
||||||
|
- 配置必要的寄存器。
|
||||||
|
|
||||||
|
### 读取导联检测状态
|
||||||
|
|
||||||
|
`readLeadOffStatus`函数:
|
||||||
|
|
||||||
|
- 读取`LOFF_STATP`和`LOFF_STATN`寄存器。
|
||||||
|
- 打印导联检测状态。
|
||||||
|
|
||||||
|
### 读取数据
|
||||||
|
|
||||||
|
`readData`函数:
|
||||||
|
|
||||||
|
- 从ADS1299读取数据。
|
||||||
|
- 将数据转换为电压并打印。
|
||||||
|
|
||||||
|
### 寄存器读写
|
||||||
|
|
||||||
|
包含`writeRegister`和`readRegister`函数,用于向ADS1299写入和读取寄存器。
|
||||||
|
|
||||||
|
### 数据转换
|
||||||
|
|
||||||
|
`convertData`函数:
|
||||||
|
|
||||||
|
- 将读取的字节数据转换为电压值。
|
||||||
|
|
||||||
|
这个代码框架基本涵盖了ADS1299的初始化、数据读取、导联检测等主要功能。在实际应用中,可能需要根据具体需求调整寄存器配置和定时器的时间间隔。确保ADS1299手册中的寄存器配置正确无误,以实现所需的功能。
|
||||||
|
|
||||||
|
### REF和偏置电压(BIAS)的工作原理及电路连接
|
||||||
|
|
||||||
|
#### 1. 参考电极(REF)
|
||||||
|
|
||||||
|
参考电极是所有测量电极电位的基准点。它的作用是提供一个稳定的参考电压,以确保各个测量电极的电位能够被正确地采集。ADS1299提供了灵活的配置选项,可以将任意电极设置为参考电极。
|
||||||
|
|
||||||
|
#### 2. 偏置电压(BIAS)
|
||||||
|
|
||||||
|
偏置电压用于提供共模电压稳定性和干扰抑制。在EEG测量中,人体容易受到共模干扰,如电源线频率的干扰(50/60Hz)。偏置电压通过向病人施加一个控制的电压,帮助将测量电极的共模电压保持在ADS1299输入范围内。ADS1299的偏置放大器(BIAS amplifier)提供了一个内部的反馈回路,用于减少共模干扰。
|
||||||
|
|
||||||
|
#### 3. SRB引脚
|
||||||
|
|
||||||
|
SRB(Signal Reference Buffer)引脚在ADS1299中用于信号参考电极的配置。
|
||||||
|
|
||||||
|
- **SRB1**:当SRB1引脚用于参考时,所有通道的负输入可以连接到SRB1。设置`MISC1`寄存器的SRB1位可以实现这种配置。
|
||||||
|
- **SRB2**:SRB2引脚可以选择单独的电极作为参考电极,并通过设置`CHnSET`寄存器的SRB2位,将该电极的电位作为其他通道的参考。
|
||||||
|
|
||||||
|
#### 上位机程序 📊
|
||||||
|
|
||||||
### 功能:
|
### 功能:
|
||||||
|
|
||||||
@ -51,11 +175,15 @@
|
|||||||
### 使用技术:
|
### 使用技术:
|
||||||
|
|
||||||
- **编程语言**:Python
|
- **编程语言**:Python
|
||||||
- **图形库**:Matplotlib
|
- **图形库**:pyqt + fluent
|
||||||
|
|
||||||
### 界面截图:
|
### 界面截图:
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
## 使用指南 📚
|
## 使用指南 📚
|
||||||
|
|
||||||
@ -69,8 +197,9 @@
|
|||||||
|
|
||||||
1. 安装所需库:
|
1. 安装所需库:
|
||||||
```bash
|
```bash
|
||||||
pip install pyserial matplotlib
|
|
||||||
pip install pyserial pyqt5
|
pip install pyserial pyqt5
|
||||||
|
pip install pyqtgraph PyQt-Fluent-Widgets
|
||||||
|
pip install vtk scikit-learn
|
||||||
```
|
```
|
||||||
## 项目结构 🗂️
|
## 项目结构 🗂️
|
||||||
```
|
```
|
||||||
@ -78,7 +207,7 @@
|
|||||||
│ ├── schematics
|
│ ├── schematics
|
||||||
│ └── pcb
|
│ └── pcb
|
||||||
├── firmware
|
├── firmware
|
||||||
│ └── ads1299_driver.c
|
│ └── ads1299_driver.ino
|
||||||
├── software
|
├── software
|
||||||
│ └── bci_gui.py
|
│ └── bci_gui.py
|
||||||
└── README.md
|
└── README.md
|
||||||
|
|||||||
@ -1,15 +1,34 @@
|
|||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
|
|
||||||
|
|
||||||
|
// 函数声明
|
||||||
|
void IRAM_ATTR onDataTimer(void* arg);
|
||||||
|
void IRAM_ATTR onImpedanceTimer(void* arg);
|
||||||
|
void setup();
|
||||||
|
void drawSprite();
|
||||||
|
void readButtons();
|
||||||
|
void loop();
|
||||||
|
void startContinuousReadMode();
|
||||||
|
void startImpedanceMeasurementMode();
|
||||||
|
void initADS1299();
|
||||||
|
void measureImpedance();
|
||||||
|
void getDeviceID();
|
||||||
|
void sendCommand(byte cmd);
|
||||||
|
void writeRegister(byte reg, byte value);
|
||||||
|
byte readRegister(byte reg);
|
||||||
|
void readData();
|
||||||
|
void convertData(byte *data, double *channelData);
|
||||||
|
|
||||||
// 定义引脚
|
// 定义引脚
|
||||||
#define CS_PIN 10
|
#define CS_PIN 15
|
||||||
#define SCLK_PIN 12
|
#define SCLK_PIN 14
|
||||||
#define MOSI_PIN 11
|
#define MOSI_PIN 13
|
||||||
#define MISO_PIN 13
|
#define MISO_PIN 12
|
||||||
#define DRDY_PIN 15
|
#define DRDY_PIN 10
|
||||||
#define CLKSEL_PIN 16
|
#define CLKSEL_PIN 11
|
||||||
#define START_PIN 18
|
#define START_PIN 1
|
||||||
#define RESET_PIN 8
|
#define RESET_PIN 2
|
||||||
#define PWDN_PIN 3
|
#define PWDN_PIN 3
|
||||||
|
|
||||||
// 定义命令
|
// 定义命令
|
||||||
@ -25,12 +44,32 @@
|
|||||||
#define WREG 0x40
|
#define WREG 0x40
|
||||||
|
|
||||||
volatile boolean startRead = false;
|
volatile boolean startRead = false;
|
||||||
volatile boolean readLeadOff = false;
|
volatile boolean startImpedanceRead = false;
|
||||||
|
volatile boolean readImpedance = false;
|
||||||
volatile boolean continuousReadMode = true;
|
volatile boolean continuousReadMode = true;
|
||||||
|
|
||||||
esp_timer_handle_t dataTimer;
|
esp_timer_handle_t dataTimer;
|
||||||
esp_timer_handle_t impedanceTimer;
|
esp_timer_handle_t impedanceTimer;
|
||||||
|
|
||||||
|
// TFT_eSPI tft = TFT_eSPI();
|
||||||
|
// TFT_eSprite sprite = TFT_eSprite(&tft);
|
||||||
|
|
||||||
|
// float batteryVoltage;
|
||||||
|
|
||||||
|
// // 颜色定义
|
||||||
|
// #define gray 0x2A0A
|
||||||
|
// #define lines 0x8C71
|
||||||
|
// unsigned short rings[4] = { 0x47DD, 0xFB9F, 0x86BF, 0xFFD0 };
|
||||||
|
|
||||||
|
// // 图表变量
|
||||||
|
// int n = 0;
|
||||||
|
// int fromTop = 30;
|
||||||
|
// int fromLeft = 20;
|
||||||
|
// int w = 480;
|
||||||
|
// int h = 200;
|
||||||
|
// double channelData[9][20] = { 0 };
|
||||||
|
|
||||||
|
// 定义ESP32定时器回调函数
|
||||||
void IRAM_ATTR onDataTimer(void* arg) {
|
void IRAM_ATTR onDataTimer(void* arg) {
|
||||||
if (digitalRead(DRDY_PIN) == LOW) {
|
if (digitalRead(DRDY_PIN) == LOW) {
|
||||||
startRead = true;
|
startRead = true;
|
||||||
@ -38,7 +77,9 @@ void IRAM_ATTR onDataTimer(void* arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR onImpedanceTimer(void* arg) {
|
void IRAM_ATTR onImpedanceTimer(void* arg) {
|
||||||
readLeadOffStatus();
|
if (digitalRead(DRDY_PIN) == LOW) {
|
||||||
|
startImpedanceRead = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
@ -65,7 +106,7 @@ void setup() {
|
|||||||
// 初始化ADS1299
|
// 初始化ADS1299
|
||||||
initADS1299();
|
initADS1299();
|
||||||
getDeviceID();
|
getDeviceID();
|
||||||
Serial.println("ADS1299 初始化完成");
|
Serial.println("ADS1299 initialized");
|
||||||
|
|
||||||
// 配置ESP32定时器
|
// 配置ESP32定时器
|
||||||
const esp_timer_create_args_t dataTimer_args = {
|
const esp_timer_create_args_t dataTimer_args = {
|
||||||
@ -82,13 +123,15 @@ void setup() {
|
|||||||
esp_timer_create(&impedanceTimer_args, &impedanceTimer);
|
esp_timer_create(&impedanceTimer_args, &impedanceTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
// 处理串口输入,切换ADS1299功能
|
||||||
if (Serial.available()) {
|
if (Serial.available()) {
|
||||||
char cmd = Serial.read();
|
char cmd = Serial.read();
|
||||||
if (cmd == '1') {
|
if (cmd == '1') {
|
||||||
startContinuousReadMode();
|
startContinuousReadMode();
|
||||||
} else if (cmd == '2') {
|
} else if (cmd == '2') {
|
||||||
startLeadOffDetectionMode();
|
startImpedanceMeasurementMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,48 +139,50 @@ void loop() {
|
|||||||
startRead = false;
|
startRead = false;
|
||||||
readData();
|
readData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (startImpedanceRead) {
|
||||||
|
startImpedanceRead = false;
|
||||||
|
measureImpedance();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void startContinuousReadMode() {
|
void startContinuousReadMode() {
|
||||||
continuousReadMode = true;
|
continuousReadMode = true;
|
||||||
readLeadOff = false;
|
readImpedance = false;
|
||||||
// 复位芯片
|
|
||||||
sendCommand(RESET);
|
sendCommand(RESET);
|
||||||
delay(100);
|
delay(100);
|
||||||
sendCommand(SDATAC); // 停止数据连续读取
|
sendCommand(SDATAC);
|
||||||
// 配置寄存器
|
writeRegister(0x01, 0x96); // 设置数据速率为1kSPS
|
||||||
writeRegister(0x01, 0x96); // CONFIG1 设置数据速率为1kSPS
|
writeRegister(0x02, 0xD0); // 内部参考电压和偏置电流
|
||||||
writeRegister(0x02, 0xD0); // CONFIG2 内部参考电压和偏置电流
|
writeRegister(0x03, 0xE0); // 启用偏置驱动器
|
||||||
writeRegister(0x03, 0xE0); // CONFIG3 启用偏置驱动器
|
writeRegister(0x04, 0x20); // 设置MISC1寄存器,启用SRB1
|
||||||
for (int i = 0x05; i <= 0x0C; i++) {
|
for (int i = 0x05; i <= 0x0C; i++) {
|
||||||
writeRegister(i, 0x60); // CHxSET 设置PGA增益和输入类型
|
writeRegister(i, 0x60); // 设置PGA增益和输入类型
|
||||||
}
|
}
|
||||||
writeRegister(0x0D, 0xFF); // BIAS_SENSP
|
writeRegister(0x0D, 0xFF); // BIAS_SENSP
|
||||||
writeRegister(0x0E, 0xFF); // BIAS_SENSN
|
writeRegister(0x0E, 0xFF); // BIAS_SENSN
|
||||||
// 启动连续数据读取模式
|
|
||||||
sendCommand(START);
|
sendCommand(START);
|
||||||
sendCommand(RDATAC); // 启动数据连续读取模式
|
sendCommand(RDATAC); // 启动数据连续读取模式
|
||||||
esp_timer_start_periodic(dataTimer, 1000); // 1000微秒 = 1毫秒
|
esp_timer_start_periodic(dataTimer, 1000); // 1ms间隔
|
||||||
esp_timer_stop(impedanceTimer); // 停止阻抗读取定时器
|
esp_timer_stop(impedanceTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startLeadOffDetectionMode() {
|
void startImpedanceMeasurementMode() {
|
||||||
continuousReadMode = false;
|
continuousReadMode = false;
|
||||||
readLeadOff = true;
|
readImpedance = true;
|
||||||
// 复位芯片
|
|
||||||
sendCommand(RESET);
|
sendCommand(RESET);
|
||||||
delay(100);
|
delay(100);
|
||||||
sendCommand(SDATAC); // 停止数据连续读取
|
sendCommand(SDATAC);
|
||||||
// 配置导联脱落检测
|
// 配置导联电流进行阻抗测量
|
||||||
writeRegister(0x0F, 0x02); // LOFF寄存器,设置为6nA
|
writeRegister(0x0F, 0x02); // 设置LOFF寄存器,导联电流为6nA或其他适当值
|
||||||
writeRegister(0x18, 0xFF); // 启用所有通道的正极导联检测
|
writeRegister(0x18, 0xFF); // 启用所有正极通道的导联检测
|
||||||
writeRegister(0x19, 0xFF); // 启用所有通道的负极导联检测
|
writeRegister(0x19, 0xFF); // 启用所有负极通道的导联检测
|
||||||
esp_timer_start_periodic(impedanceTimer, 100000); // 100000微秒 = 100毫秒
|
esp_timer_start_periodic(impedanceTimer, 1000); // 1ms间隔
|
||||||
esp_timer_stop(dataTimer); // 停止数据读取定时器
|
esp_timer_stop(dataTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initADS1299() {
|
void initADS1299() {
|
||||||
// 启动时序
|
|
||||||
digitalWrite(CLKSEL_PIN, HIGH);
|
digitalWrite(CLKSEL_PIN, HIGH);
|
||||||
digitalWrite(CS_PIN, LOW);
|
digitalWrite(CS_PIN, LOW);
|
||||||
digitalWrite(START_PIN, LOW);
|
digitalWrite(START_PIN, LOW);
|
||||||
@ -145,48 +190,23 @@ void initADS1299() {
|
|||||||
digitalWrite(PWDN_PIN, HIGH);
|
digitalWrite(PWDN_PIN, HIGH);
|
||||||
delay(100);
|
delay(100);
|
||||||
|
|
||||||
// 复位芯片
|
|
||||||
sendCommand(RESET);
|
sendCommand(RESET);
|
||||||
delay(100);
|
delay(100);
|
||||||
|
|
||||||
// 停止连续读取模式
|
|
||||||
sendCommand(SDATAC);
|
sendCommand(SDATAC);
|
||||||
|
writeRegister(0x01, 0x96); // 设置数据速率为1kSPS
|
||||||
// 配置寄存器
|
writeRegister(0x02, 0xD0); // 内部参考电压和偏置电流
|
||||||
writeRegister(0x01, 0x96); // CONFIG1 设置数据速率为1kSPS
|
writeRegister(0x03, 0xE0); // 启用偏置驱动器
|
||||||
writeRegister(0x02, 0xD0); // CONFIG2 内部参考电压和偏置电流
|
writeRegister(0x04, 0x20); // 设置MISC1寄存器,启用SRB1
|
||||||
writeRegister(0x03, 0xE0); // CONFIG3 启用偏置驱动器
|
|
||||||
for (int i = 0x05; i <= 0x0C; i++) {
|
for (int i = 0x05; i <= 0x0C; i++) {
|
||||||
writeRegister(i, 0x60); // CHxSET 设置PGA增益和输入类型
|
writeRegister(i, 0x60); // 设置PGA增益和输入类型
|
||||||
}
|
}
|
||||||
writeRegister(0x0D, 0xFF); // BIAS_SENSP
|
writeRegister(0x0D, 0xFF); // BIAS_SENSP
|
||||||
writeRegister(0x0E, 0xFF); // BIAS_SENSN
|
writeRegister(0x0E, 0xFF); // BIAS_SENSN
|
||||||
// 启动连续数据读取模式
|
|
||||||
sendCommand(START);
|
sendCommand(START);
|
||||||
sendCommand(RDATAC);
|
sendCommand(RDATAC); // 启动数据连续读取模式
|
||||||
}
|
}
|
||||||
|
|
||||||
void readLeadOffStatus() {
|
void measureImpedance() {
|
||||||
byte statP = readRegister(0x1C); // 读取LOFF_STATP寄存器
|
|
||||||
byte statN = readRegister(0x1D); // 读取LOFF_STATN寄存器
|
|
||||||
|
|
||||||
Serial.print("Lead-Off Status:");
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
bool pStatus = statP & (1 << i);
|
|
||||||
bool nStatus = statN & (1 << i);
|
|
||||||
Serial.print(pStatus ? "Off" : "On");
|
|
||||||
if (i != 7) {
|
|
||||||
Serial.print(",");
|
|
||||||
} else {
|
|
||||||
Serial.println("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 读取导联检测结果
|
|
||||||
// readLeadOffImpedance();
|
|
||||||
}
|
|
||||||
|
|
||||||
void readLeadOffImpedance() {
|
|
||||||
byte data[27];
|
byte data[27];
|
||||||
digitalWrite(CS_PIN, LOW);
|
digitalWrite(CS_PIN, LOW);
|
||||||
for (int i = 0; i < 27; i++) {
|
for (int i = 0; i < 27; i++) {
|
||||||
@ -194,14 +214,23 @@ void readLeadOffImpedance() {
|
|||||||
}
|
}
|
||||||
digitalWrite(CS_PIN, HIGH);
|
digitalWrite(CS_PIN, HIGH);
|
||||||
|
|
||||||
// 转换数据
|
|
||||||
double channelData[9];
|
double channelData[9];
|
||||||
convertData(data, channelData);
|
convertData(data, channelData);
|
||||||
|
Serial.print("Channel:");
|
||||||
// 输出导联阻抗
|
for (int i = 0; i < 9; i++) {
|
||||||
Serial.print("Lead-Off Impedance:");
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
Serial.print(channelData[i], 6);
|
Serial.print(channelData[i], 6);
|
||||||
|
if (i != 8) {
|
||||||
|
Serial.print(",");
|
||||||
|
} else {
|
||||||
|
Serial.println("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.print("Impedance Measurement:");
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
double voltage = channelData[i];
|
||||||
|
double current = 0.000006; // 假设使用6nA的导联电流
|
||||||
|
double impedance = voltage / current;
|
||||||
|
Serial.print(impedance, 2); // 打印阻抗值
|
||||||
if (i != 7) {
|
if (i != 7) {
|
||||||
Serial.print(",");
|
Serial.print(",");
|
||||||
} else {
|
} else {
|
||||||
@ -211,12 +240,12 @@ void readLeadOffImpedance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getDeviceID() {
|
void getDeviceID() {
|
||||||
digitalWrite(CS_PIN, LOW); // 低电平以进行通信
|
digitalWrite(CS_PIN, LOW);
|
||||||
SPI.transfer(SDATAC); // 停止连续读取数据模式
|
SPI.transfer(SDATAC);
|
||||||
SPI.transfer(RREG | 0x00); // 读取寄存器命令
|
SPI.transfer(RREG | 0x00);
|
||||||
SPI.transfer(0x00); // 请求一个字节
|
SPI.transfer(0x00);
|
||||||
byte data = SPI.transfer(0x00); // 读取字节
|
byte data = SPI.transfer(0x00);
|
||||||
digitalWrite(CS_PIN, HIGH); // 高电平以结束通信
|
digitalWrite(CS_PIN, HIGH);
|
||||||
Serial.print("Device ID: ");
|
Serial.print("Device ID: ");
|
||||||
Serial.println(data, BIN);
|
Serial.println(data, BIN);
|
||||||
}
|
}
|
||||||
@ -230,7 +259,7 @@ void sendCommand(byte cmd) {
|
|||||||
void writeRegister(byte reg, byte value) {
|
void writeRegister(byte reg, byte value) {
|
||||||
digitalWrite(CS_PIN, LOW);
|
digitalWrite(CS_PIN, LOW);
|
||||||
SPI.transfer(WREG | reg);
|
SPI.transfer(WREG | reg);
|
||||||
SPI.transfer(0x00); // 写一个寄存器
|
SPI.transfer(0x00);
|
||||||
SPI.transfer(value);
|
SPI.transfer(value);
|
||||||
digitalWrite(CS_PIN, HIGH);
|
digitalWrite(CS_PIN, HIGH);
|
||||||
}
|
}
|
||||||
@ -238,7 +267,7 @@ void writeRegister(byte reg, byte value) {
|
|||||||
byte readRegister(byte reg) {
|
byte readRegister(byte reg) {
|
||||||
digitalWrite(CS_PIN, LOW);
|
digitalWrite(CS_PIN, LOW);
|
||||||
SPI.transfer(RREG | reg);
|
SPI.transfer(RREG | reg);
|
||||||
SPI.transfer(0x00); // 读取一个寄存器
|
SPI.transfer(0x00);
|
||||||
byte value = SPI.transfer(0x00);
|
byte value = SPI.transfer(0x00);
|
||||||
digitalWrite(CS_PIN, HIGH);
|
digitalWrite(CS_PIN, HIGH);
|
||||||
return value;
|
return value;
|
||||||
@ -252,7 +281,6 @@ void readData() {
|
|||||||
}
|
}
|
||||||
digitalWrite(CS_PIN, HIGH);
|
digitalWrite(CS_PIN, HIGH);
|
||||||
|
|
||||||
// 转换为9通道的double数据
|
|
||||||
double channelData[9];
|
double channelData[9];
|
||||||
convertData(data, channelData);
|
convertData(data, channelData);
|
||||||
Serial.print("Channel:");
|
Serial.print("Channel:");
|
||||||
@ -269,9 +297,9 @@ void readData() {
|
|||||||
void convertData(byte *data, double *channelData) {
|
void convertData(byte *data, double *channelData) {
|
||||||
for (int i = 0; i < 9; i++) {
|
for (int i = 0; i < 9; i++) {
|
||||||
long value = ((long)data[3 * i + 3] << 16) | ((long)data[3 * i + 4] << 8) | data[3 * i + 5];
|
long value = ((long)data[3 * i + 3] << 16) | ((long)data[3 * i + 4] << 8) | data[3 * i + 5];
|
||||||
if (value & 0x800000) { // 如果最高位为1,则为负数
|
if (value & 0x800000) {
|
||||||
value |= 0xFF000000; // 扩展符号位
|
value |= 0xFF000000;
|
||||||
}
|
}
|
||||||
channelData[i] = (double)value * 4.5 / (double)0x7FFFFF; // 将值转换为电压
|
channelData[i] = (double)value * 4.5 / (double)0x7FFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,8 +35,8 @@ class Window(FramelessWindow):
|
|||||||
self.hBoxLayout = QHBoxLayout(self)
|
self.hBoxLayout = QHBoxLayout(self)
|
||||||
self.navigationInterface = NavigationInterface(self, showMenuButton=True)
|
self.navigationInterface = NavigationInterface(self, showMenuButton=True)
|
||||||
self.stackWidget = QStackedWidget(self)
|
self.stackWidget = QStackedWidget(self)
|
||||||
# channels_to_display = [0, 1, 2, 3, 4, 5, 6, 7] # Example control parameter list
|
channels_to_display = [0, 1, 2, 3, 4, 5, 6, 7] # Example control parameter list
|
||||||
channels_to_display = [2]
|
# channels_to_display = [2]
|
||||||
pen_colors = ['r', 'g', 'b', 'c', 'm', 'y', 'k', 'w', 'orange']
|
pen_colors = ['r', 'g', 'b', 'c', 'm', 'y', 'k', 'w', 'orange']
|
||||||
pen_widths = [2, 2, 2, 2, 2, 2, 2, 2, 2]
|
pen_widths = [2, 2, 2, 2, 2, 2, 2, 2, 2]
|
||||||
plot_num = 1000
|
plot_num = 1000
|
||||||
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |