V1.1 正式版本提交

主要新增功能:
1. 添加 Debian 打包脚本 (pack_deb.sh),支持一键打包部署
2. 新增机顶辐照度使用说明书 (README.md),记录系统配置和使用方法
3. 添加 SD 卡配置更新功能 (configdatairis 文件夹),便于现场配置
4. 新增光谱仪打开失败检测,两灯同时闪烁提示异常
5. 添加说明书自动拷贝到 SD 卡功能

详细修改:
- main.cpp:
  * 添加 SD 卡 configdatairis 配置更新逻辑
  * 添加说明书自动拷贝到 /home/data/
  * 优化 stopwait.txt 判断逻辑

- Source/Capture/MainGrabber.cpp:
  * 添加光谱仪初始化失败检测,失败时两灯同时闪烁

- Source/Logger/Logger.h:
  * 添加日志功能支持

- pack_deb.sh:
  * 新增完整的 Debian 打包脚本
  * 支持自动构建、复制文件、生成 postinst/prerm

- root/start.sh:
  * 添加 mkdir 确保 /home/data 目录存在

- root/DCTable.txt:
  * 添加默认暗电流校准表文件

- README.md:
  * 编写完整的中文使用说明书
  * 包含硬件连接、目录结构、配置说明、GPIO 指示灯含义等

依赖文件:
- /root/DeviceSettings.ini (需另行配置)
- /root/机顶辐照度使用说明书.md (打包时自动复制)
This commit is contained in:
xin
2026-03-23 14:32:12 +08:00
parent fb9e85734b
commit 60559291f2
7 changed files with 363 additions and 54 deletions

120
README.md
View File

@ -0,0 +1,120 @@
# 机顶辐照度使用说明书
## 1. 系统概述
机顶辐照度使用说明书 支持 GPS 北斗双模定位、实时暗背景扣除等功能。
## 2. 硬件连接
光谱仪 |USB(下)
GPS (内置)
## 3. 目录结构
**SD 卡根目录** (挂载到 /home/data/)
```
SD卡根目录/
├── configdatairis/ # 配置更新文件夹(可选)
│ ├── DeviceSettings.ini # 设备配置文件
│ └── DCTable.txt # 暗电流校准表
├── Setting/
│ └── DeviceSettings.ini # 设备配置文件
├── Data/
│ ├── DCTable.txt # 暗电流校准表
│ └── WavelengthInfo.txt # 波长校准信息(程序生成)
├── Log/ # 日志目录
└── stopwait.txt # 启动等待文件(可选)
```
## 4. 配置文件
### DeviceSettings.ini
```ini
[FS]
Model=IS1 # 光谱仪型号IS1, IS11, FLAME
Port=/dev/ttyUSB0 # 串口路径
UID=FLMS15814 # 设备序列号
Depth=65535 # 积分深度
AEMax=0.85 # 自动曝光最大值
AEMin=0.60 # 自动曝光最小值
MinSI=1000 # 最小光谱强度
[GPS]
Port=/dev/ttyS1 # GPS 串口
Baud=9600 # GPS 波特率
```
### 支持的光谱仪型号
- `IS1` - Iris S1
- `IS11` - Iris S11
- `FLAME` - Ocean Optics FLAME
## 5. 输入输出文件
| 文件 | 类型 | 说明 |
|------|------|------|
| DeviceSettings.ini | 输入 | 设备参数配置 |
| DCTable.txt | 输入 | 暗电流校准表 |
| WavelengthInfo.txt | 输出 | 波长校准信息(程序生成) |
| *.dat | 输出 | 采集的光谱数据文件 |
## 6. 配置更新流程
如果在 SD 卡上放置 `configdatairis` 文件夹,程序启动时会自动拷贝其中的配置文件到 `/root` 并删除该文件夹。
```
1. 在 SD 卡根目录创建目录configdatairis/
2. 放入配置文件:
- DeviceSettings.ini
- DCTable.txt
3. 启动程序,配置文件会自动复制到系统 /root/ 目录
4. configdatairis 文件夹会被自动删除
```
## 7. 使用流程
### 首次部署
1. 格式化 SD 卡FAT32
2. 创建必要目录结构:
```
SD卡根目录/
├── Setting/
├── Data/
└── Log/
```
3. 部署 deb 包或手动复制可执行文件到 `/home/pi/bin/`
4. 配置文件会随程序从系统 /root/ 复制到 SD 卡
### 正常启动
1. 系统上电TF 卡自动挂载到 /home/data/
2. 启动程序:`/home/pi/bin/IRIS_FODIS &`
### 启动等待
如果 **不存在** SD 卡根目录下的 `stopwait.txt` 文件,程序会等待 30 秒再继续(用于调试时等待调试器附加)。
### 采集数据
程序自动采集光谱数据,保存到 SD 卡根目录 `/Data/` 目录,文件名格式为时间戳。
## 8. GPIO 指示灯
| 灯状态 | 含义 |
|--------|------|
| 灯1与灯2交替闪烁各亮200ms | TF 卡检测失败(卡未挂载),程序等待中 |
| 灯1与灯2同时闪烁各亮200ms | 光谱仪打开失败,程序异常 |
| 灯1亮灯2灭 | GPS 时间同步中 |
| 灯1灭灯2闪烁亮200ms | 数据采集中(光谱采集→写卡) |
| 灯1灭灯2常亮 | 采集完成/待机 |
## 9. 版本信息
- 当前版本1.1
- 版本号文件SD卡根目录 `/version`

View File

@ -113,7 +113,23 @@ int CMainGrabber::InitializeWorkers()
} }
m_pctrlFS->SetContext(m_struFSRunParams); m_pctrlFS->SetContext(m_struFSRunParams);
m_pctrlFS->Initialize(); int iFSInitResult = m_pctrlFS->Initialize();
if (iFSInitResult != 0)
{
// Sensor 打开失败,两灯同时闪烁
while (1)
{
system("gpio write 4 1");
system("gpio write 5 1");
QEventLoop qeLoop;
QTimer::singleShot(200, &qeLoop, SLOT(quit()));
qeLoop.exec();
system("gpio write 4 0");
system("gpio write 5 0");
QTimer::singleShot(200, &qeLoop, SLOT(quit()));
qeLoop.exec();
}
}
while (!m_pctrlFS->m_iFlagInit) while (!m_pctrlFS->m_iFlagInit)
{ {
Delay_MSec(1000); Delay_MSec(1000);
@ -214,7 +230,7 @@ int CMainGrabber::CheckExposureTime(DataFrame dfTemp)
int CMainGrabber::RemoveBackground(DataFrame& dfTemp) int CMainGrabber::RemoveBackground(DataFrame& dfTemp)
{ {
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD>۰<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> //<2F><><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD>۰<EFBFBD><DBB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (m_struFSRunParams.ucDeviceModel==DeviceModel::FLAME) if (m_struFSRunParams.ucDeviceModel==DeviceModel::FLAME)
{ {
double dBackground = 0; double dBackground = 0;

View File

@ -49,6 +49,7 @@ namespace QT_LOG
outFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); outFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
QTextStream ts(&outFile); QTextStream ts(&outFile);
ts << log_info << endl; ts << log_info << endl;
std::cout<< log_info.toStdString() << std::endl;
outFile.close(); outFile.close();
m_LogMutex.unlock(); m_LogMutex.unlock();

108
main.cpp
View File

@ -46,7 +46,7 @@ int main(int argc, char* argv[])
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
//ָʾ<D6B8>ƿ<EFBFBD><C6BF><EFBFBD> //ָʾ<D6B8>ƿ<EFBFBD><C6BF><EFBFBD>
//system("sudo mount / dev / mmcblk1p1 / home / data"); //system("sudo mount / dev / mmcblk1p1 / home / data");
system("gpio mode 4 out"); system("gpio mode 4 out");
system("gpio mode 5 out"); system("gpio mode 5 out");
@ -55,7 +55,7 @@ int main(int argc, char* argv[])
qDebug() << "system(gpio mode 5 out)"; qDebug() << "system(gpio mode 5 out)";
///check tf card ///check tf card
//<2F><><EFBFBD><EFBFBD>sd<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>еƾͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸ //<2F><><EFBFBD>sd<73><64><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>أ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>еƾͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸
std::string device = "/dev/mmcblk1p1"; std::string device = "/dev/mmcblk1p1";
std::string mount_point = "/home/data"; std::string mount_point = "/home/data";
if (!is_mounted(device, mount_point)/*1*/) if (!is_mounted(device, mount_point)/*1*/)
@ -75,21 +75,60 @@ int main(int argc, char* argv[])
} }
} }
// 拷贝说明书到 SD 卡
if (!QFile::exists("/home/data/机顶辐照度使用说明书.md")) {
if (QFile::exists("/root/机顶辐照度使用说明书.md")) {
QFile::copy("/root/机顶辐照度使用说明书.md", "/home/data/机顶辐照度使用说明书.md");
}
}
QEventLoop qeLoop; //////////////////////////////////////////////////////////////////////////Check configdatairis folder
QTimer::singleShot(30000, &qeLoop, SLOT(quit())); QDir qdirConfigDataIris("/home/data/configdatairis");
//QTimer::singleShot(10000, &qeLoop, SLOT(quit())); if (qdirConfigDataIris.exists())
qeLoop.exec(); {
printf("configdatairis folder found. Copying config files...\n");
QFileInfo fiSettings("/home/data/configdatairis/DeviceSettings.ini");
if (fiSettings.isFile() && fiSettings.size() >= 50)
{
QFile::copy("/home/data/configdatairis/DeviceSettings.ini", "/root/DeviceSettings.ini");
printf(" DeviceSettings.ini copied.\n");
}
QFileInfo fiDCTable("/home/data/configdatairis/DCTable.txt");
if (fiDCTable.isFile())
{
QFile::copy("/home/data/configdatairis/DCTable.txt", "/root/DCTable.txt");
printf(" DCTable.txt copied.\n");
}
// 删除configdatairis文件夹
qdirConfigDataIris.removeRecursively();
printf("configdatairis folder removed.\n");
}
//////////////////////////////////////////////////////////////////////////Check configdatairis folder
if (!QFile::exists("/home/data/stopwait.txt")) {
QEventLoop qeLoop;
QTimer::singleShot(30000, &qeLoop, SLOT(quit()));
// //QTimer::singleShot(10000, &qeLoop, SLOT(quit()));
qeLoop.exec();
}
// QTimer::singleShot(30000, &qeLoop, SLOT(quit()));
// //QTimer::singleShot(10000, &qeLoop, SLOT(quit()));
// qeLoop.exec();
OneFSContext m_struFSParam;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> OneFSContext m_struFSParam;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
GPSInfo m_struGPSInfo; GPSInfo m_struGPSInfo;
//FodisRP m_struMiscRunParams; //FodisRP m_struMiscRunParams;
ZZ_SysConfigger m_syscfSettings;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ZZ_SysConfigger m_syscfSettings;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
BD357Controller m_ctrlGPS; BD357Controller m_ctrlGPS;
CMainGrabber m_mgMainGrabber;//<2F><><EFBFBD>ɼ<EFBFBD> CMainGrabber m_mgMainGrabber;//<2F><><EFBFBD>ɼ<EFBFBD>
DataFileProcessor m_dfpDataSaver; DataFileProcessor m_dfpDataSaver;
#ifndef WIN32 #ifndef WIN32
@ -108,47 +147,12 @@ int main(int argc, char* argv[])
QFileInfo m_qfiSettingFileInfo("/home/data/Setting/DeviceSettings.ini"); QFileInfo m_qfiSettingFileInfo("/home/data/Setting/DeviceSettings.ini");
if (!m_qfiSettingFileInfo.isFile()) // 如果SD卡上有配置文件拷贝到/root下
if (m_qfiSettingFileInfo.isFile() && m_qfiSettingFileInfo.size() >= 50)
{ {
printf ("DeviceSettings File Missing !!! Will create from default one."); printf("DeviceSettings found on SD card. Copying to /root...");
QFile::copy("/home/data/Setting/DeviceSettings.ini", "/root/DeviceSettings.ini");
QDir qdirPath("/home/data/Setting"); printf("Done.\n");
if (!qdirPath.exists())
{
bool bRes = qdirPath.mkpath("/home/data/Setting");
if (!bRes)
{
qDebug() << "DataFileProcessor mkdir Failed.";
return -1;
}
}
bool bRes = QFile::copy("/root/DeviceSettings.ini", "/home/data/Setting/DeviceSettings.ini");
if (!bRes)
{
qDebug() << " QFile::copy Failed.";
return -2;
}
}
else
{
int iSize = m_qfiSettingFileInfo.size();
if (iSize<50)
{
bool bRes = QFile::remove("/home/data/Setting/DeviceSettings.ini");
if (!bRes)
{
qDebug() << " QFile::remove Failed.";
return -2;
}
bRes = QFile::copy("/root/DeviceSettings.ini", "/home/data/Setting/DeviceSettings.ini");
if (!bRes)
{
qDebug() << " QFile::copy Failed.";
return -2;
}
}
} }
//////////////////////////////////////////////////////////////////////////Check Settings File //////////////////////////////////////////////////////////////////////////Check Settings File
//////////////////////////////////////////////////////////////////////////Load Settings File //////////////////////////////////////////////////////////////////////////Load Settings File
@ -209,19 +213,19 @@ int main(int argc, char* argv[])
//m_test.Initialize_Part(); //m_test.Initialize_Part();
//m_test.LoadTable(); //m_test.LoadTable();
////////////////////////////////test only ////////////////////////////////test only
m_ctrlGPS.SetContext(m_mgMainGrabber);//<2F><>ʼ<EFBFBD><CABC>gps m_ctrlGPS.SetContext(m_mgMainGrabber);//<2F><>ʼ<EFBFBD><CABC>gps
m_ctrlGPS.SetupMessagePipeline(); m_ctrlGPS.SetupMessagePipeline();
m_ctrlGPS.Initialize(m_struGPSInfo); m_ctrlGPS.Initialize(m_struGPSInfo);
QThread* m_pqDataGrabberThreadHolder = new QThread(); QThread* m_pqDataGrabberThreadHolder = new QThread();
m_mgMainGrabber.moveToThread(m_pqDataGrabberThreadHolder); m_mgMainGrabber.moveToThread(m_pqDataGrabberThreadHolder);
m_mgMainGrabber.SetRunParams(m_struFSParam);//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><C9BC>߳<EFBFBD> m_mgMainGrabber.SetRunParams(m_struFSParam);//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD><C9BC>߳<EFBFBD>
m_mgMainGrabber.SetContext(m_ctrlGPS, m_dfpDataSaver); m_mgMainGrabber.SetContext(m_ctrlGPS, m_dfpDataSaver);
m_pqDataGrabberThreadHolder->start(); m_pqDataGrabberThreadHolder->start();
m_mgMainGrabber.Initialize();//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD> m_mgMainGrabber.Initialize();//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
//m_ctrlGPS.VSlot_SkipSyncDateOnce(); //m_ctrlGPS.VSlot_SkipSyncDateOnce();

137
pack_deb.sh Executable file
View File

@ -0,0 +1,137 @@
#!/bin/bash
# IRIS_FODIS 项目打包脚本
# 打包成 Debian 包
VERSION=1.1
PROJECT_NAME="iris-fodis"
PACKAGE_NAME="${PROJECT_NAME}_V${VERSION}.deb"
BUILD_DIR="build"
DEB_DIR="Debpack_iris_fodis"
# 检查是否在正确目录
if [ ! -f "CMakeLists.txt" ]; then
echo "错误:请在项目根目录运行此脚本"
exit 1
fi
echo "========================================="
echo "IRIS_FODIS 打包脚本 v${VERSION}"
echo "========================================="
# 1. 构建项目
echo ""
echo "[1/5] 开始构建项目..."
# 清理旧的 build 目录并重新创建
#rm -rf $BUILD_DIR
mkdir -p $BUILD_DIR
cd $BUILD_DIR
cmake ..
#if [ $? -ne 0 ]; then
# echo "错误cmake 配置失败"
# exit 1
#fi
# 执行 make
make -j$(nproc)
if [ $? -ne 0 ]; then
echo "错误:构建失败"
exit 1
fi
cd ..
# 检查构建产物
if [ ! -f "${BUILD_DIR}/IRIS_FODIS" ]; then
echo "错误:构建产物不存在"
exit 1
fi
echo "构建完成"
# 2. 创建打包目录
echo ""
echo "[2/5] 创建打包目录..."
rm -rf $DEB_DIR
mkdir -p $DEB_DIR
# 3. 复制可执行文件和脚本文件
echo ""
echo "[3/5] 复制文件..."
mkdir -p ${DEB_DIR}/home/pi/bin
cp ${BUILD_DIR}/IRIS_FODIS ${DEB_DIR}/home/pi/bin/
chmod +x ${DEB_DIR}/home/pi/bin/IRIS_FODIS
# 复制启动脚本和配置文件到 /root/
mkdir -p ${DEB_DIR}/root
cp root/start.sh ${DEB_DIR}/root/
cp Settings/DeviceSettings.ini ${DEB_DIR}/root/
cp root/DCTable.txt ${DEB_DIR}/root/
cp README.md ${DEB_DIR}/root/机顶辐照度使用说明书.md
chmod +x ${DEB_DIR}/root/start.sh
# 4. 创建 DEBIAN 目录和配置文件
echo ""
echo "[4/5] 创建 DEBIAN 配置..."
mkdir -p ${DEB_DIR}/DEBIAN
# 创建 control 文件
cat > ${DEB_DIR}/DEBIAN/control <<EOF
Package: iris-fodis
Version: ${VERSION}
Architecture: armhf
Maintainer: iris-fodis Team
Description: IRIS Fiber Optic Spectrometer Data Acquisition System
EOF
# 创建 postinst 脚本(安装后执行)
cat > ${DEB_DIR}/DEBIAN/postinst <<EOF
#!/bin/bash
echo "IRIS_FODIS v${VERSION} installed"
chmod +x /home/pi/bin/IRIS_FODIS
chmod +x /root/start.sh
# 确保 SD 卡挂载后再写入 version
mkdir -p /home/data
if [ -b /dev/mmcblk1p1 ]; then
if ! mount | grep -q "/dev/mmcblk1p1 on /home/data"; then
mount /dev/mmcblk1p1 /home/data
fi
if mount | grep -q "/dev/mmcblk1p1 on /home/data"; then
echo "V${VERSION}" > /home/data/version
fi
fi
exit 0
EOF
# 创建 prerm 脚本(删除前执行)
cat > ${DEB_DIR}/DEBIAN/prerm <<EOF
#!/bin/bash
exit 0
EOF
chmod +x ${DEB_DIR}/DEBIAN/postinst
chmod +x ${DEB_DIR}/DEBIAN/prerm
# 5. 打包
echo ""
echo "[5/5] 打包成 deb 文件..."
sudo dpkg -b $DEB_DIR $PACKAGE_NAME
if [ $? -eq 0 ]; then
echo ""
echo "========================================="
echo "打包成功: ${PACKAGE_NAME}"
echo "========================================="
# 移动到 DEB 目录
mkdir -p DEB
mv $PACKAGE_NAME DEB/
echo "已移动到: DEB/${PACKAGE_NAME}"
# 清理临时目录
rm -rf $DEB_DIR
else
echo "错误:打包失败"
exit 1
fi

28
root/DCTable.txt Normal file

File diff suppressed because one or more lines are too long

3
root/start.sh Normal file
View File

@ -0,0 +1,3 @@
mkdir -p /home/data
mount /dev/mmcblk1p1 /home/data
/home/pi/bin/IRIS_FODIS &