recordcount-1问题解决方法

本文介绍了解决VB中recordcount-1问题的方法。该问题是由于VB默认将游标定位到服务器导致的。解决办法是在conn.open之前设置conn.CursorLocation=3或rst.CursorLocation=3。

recordcount-1问题解决方法
这是由于vb默认把游标定位到服务器了。
解决方法是在conn.open之前加上:
conn.CursorLocation = 3

rst.CursorLocation = 3

/* * 气轨光电门系统 - SD卡存储版本 * 使用SD卡存储所有实验数据:时间、速度、加速度、时间差和时间戳 * 硬件连接: * - 光电门1: 数字引脚 2 * - 光电门2: 数字引脚 3 * - 蜂鸣器: 数字引脚 8 * - LCD显示屏: I2C接口 (16×2) * - SD卡模块: SPI接口(CS-4, MOSI-11, MISO-12, SCK-13) */ #include <SD.h> // 添加SD卡库 #include <SPI.h> // SPI通信库 #include <Wire.h> #include <LiquidCrystal_I2C.h> // 光电门和蜂鸣器引脚 const int GATE1_PIN = 2; const int GATE2_PIN = 3; const int BUZZER_PIN = 8; const int STATUS_LED = 13; const int SD_CS = 4; // SD卡片选引脚 // LCD配置 (16列, 2行) LiquidCrystal_I2C lcd(0x27, 16, 2); // SD卡配置 #define FILENAME "DATA.CSV" // 数据文件名 #define MAX_RECORDS 1000 // SD卡可存储更多记录 // 实验参数 const float WIDTH = 0.1; // 挡光片宽度(米) float gateDistance = 0.36; // 光电门间距(米) // 实验数据结构(增加时间差字段) struct ExperimentData { unsigned long time1; // 光电门1时间(μs) unsigned long time2; // 光电门2时间(μs) unsigned long timeDiff; // 新增:两次挡光中间时刻的时间差(μs) float velocity1; // 门1速度(m/s) float velocity2; // 门2速度(m/s) float acceleration; // 计算加速度(m/s²) unsigned long timestamp; // 实验时间戳(ms) }; // 计时变量 volatile unsigned long gate1Start = 0; volatile unsigned long gate1End = 0; volatile unsigned long gate2Start = 0; volatile unsigned long gate2End = 0; // 状态标志 volatile bool gate1Active = false; volatile bool gate2Active = false; volatile bool experimentComplete = false; // 显示控制 int displayState = 0; // 0:状态 1:测量中 2:结果 3:历史 ExperimentData currentData; // 当前实验数据 // 系统启动时间(用于相对时间戳) const unsigned long SYSTEM_START_TIME = millis(); // 全局变量 int recordCount = 0; // 记录计数器 ExperimentData lastRecord; // 最后一条记录缓存 void setup() { Serial.begin(115200); // 初始化LCD lcd.init(); lcd.backlight(); lcd.clear(); lcd.setCursor(0, 0); lcd.print("SD Card System"); lcd.setCursor(0, 1); lcd.print("Version 3.0"); // 更新版本号 delay(2000); // 初始化SD卡 if (!SD.begin(SD_CS)) { Serial.println("SD卡初始化失败!"); lcd.clear(); lcd.print("SD Card Error"); while (1) { // 闪烁LED提示错误 digitalWrite(STATUS_LED, HIGH); delay(200); digitalWrite(STATUS_LED, LOW); delay(200); } } Serial.println("SD卡初始化成功"); // 创建数据文件头(如果文件不存在) if (!SD.exists(FILENAME)) { File dataFile = SD.open(FILENAME, FILE_WRITE); if (dataFile) { dataFile.println("Timestamp(ms),Time1(us),Time2(us),TimeDiff(us),Velocity1(m/s),Velocity2(m/s),Acceleration(m/s2)"); dataFile.close(); Serial.println("创建CSV文件头"); } } // 初始化引脚 pinMode(GATE1_PIN, INPUT); pinMode(GATE2_PIN, INPUT); pinMode(BUZZER_PIN, OUTPUT); pinMode(STATUS_LED, OUTPUT); pinMode(SD_CS, OUTPUT); // 配置中断 attachInterrupt(digitalPinToInterrupt(GATE1_PIN), gate1ISR, CHANGE); attachInterrupt(digitalPinToInterrupt(GATE2_PIN), gate2ISR, CHANGE); // 加载记录计数 recordCount = getRecordCount(); Serial.println("系统就绪"); Serial.println("命令: R-读取数据 | C-清除数据 | E-导出数据 | T-设置时间"); Serial.println("--------------------------------------"); } void loop() { // 处理实验完成 if (experimentComplete) { calculateAndStoreResults(); resetExperiment(); } // 处理串口命令 if (Serial.available() > 0) { processSerialCommand(); } // 更新LCD显示 updateLCD(); // 自动状态切换 static unsigned long lastStateChange = 0; if (millis() - lastStateChange > 10000 && displayState == 0) { displayState = 3; // 切换到历史记录 lastStateChange = millis(); } else if (millis() - lastStateChange > 5000 && displayState == 3) { displayState = 0; // 返回状态显示 lastStateChange = millis(); } } // 光电门中断服务程序 void gate1ISR() { if (digitalRead(GATE1_PIN) == HIGH) { gate1Start = micros(); gate1Active = true; digitalWrite(STATUS_LED, HIGH); displayState = 1; // 记录实验开始时间戳 currentData.timestamp = millis() - SYSTEM_START_TIME; } else { gate1End = micros(); gate1Active = false; digitalWrite(STATUS_LED, LOW); // 记录时间1 currentData.time1 = gate1End - gate1Start; // 计算速度1 currentData.velocity1 = WIDTH / (currentData.time1 / 1000000.0); } } void gate2ISR() { if (digitalRead(GATE2_PIN) == HIGH) { gate2Start = micros(); gate2Active = true; displayState = 1; } else { gate2End = micros(); gate2Active = false; experimentComplete = true; displayState = 2; // 记录时间2 currentData.time2 = gate2End - gate2Start; // 计算速度2 currentData.velocity2 = WIDTH / (currentData.time2 / 1000000.0); } } // 计算并存储结果(增加时间差计算) void calculateAndStoreResults() { // 计算两个光电门中间时刻的时间差 unsigned long midTime1 = gate1Start + currentData.time1/2; unsigned long midTime2 = gate2Start + currentData.time2/2; currentData.timeDiff = midTime2 - midTime1; // 存储时间差(微秒) // 计算加速度 float timeInterval = currentData.timeDiff / 1000000.0; currentData.acceleration = (currentData.velocity2 - currentData.velocity1) / timeInterval; // 串口打印完整数据(增加时间差输出) Serial.println("\n===== 实验数据 ====="); Serial.print("时间戳: "); Serial.print(currentData.timestamp); Serial.println(" ms"); Serial.print("时间1: "); Serial.print(currentData.time1); Serial.println(" μs"); Serial.print("时间2: "); Serial.print(currentData.time2); Serial.println(" μs"); Serial.print("时间差: "); Serial.print(currentData.timeDiff); Serial.println(" μs"); Serial.print("速度1: "); Serial.print(currentData.velocity1, 4); Serial.println(" m/s"); Serial.print("速度2: "); Serial.print(currentData.velocity2, 4); Serial.println(" m/s"); Serial.print("加速度: "); Serial.print(currentData.acceleration, 4); Serial.println(" m/s²"); // 蜂鸣器提示 beep(3, 100); // 存储到SD卡 saveToSD(); // 循环显示3遍,每遍10秒 for (int cycle = 0; cycle < 3; cycle++) { // 显示结果10秒 unsigned long startTime = millis(); while (millis() - startTime < 10000) { // 10秒显示 showResultsScreen(); // 在第二行显示剩余时间和循环次数 int remaining = 10 - (millis() - startTime) / 1000; if (remaining < 0) remaining = 0; lcd.setCursor(12, 1); if (remaining < 10) lcd.print(" "); // 对齐 lcd.print(remaining); lcd.print("s "); lcd.print(cycle+1); lcd.print("/3"); delay(100); } // 短暂返回初始状态(0.5秒) displayState = 0; showStatusScreen(); delay(500); } // 最终返回初始状态 displayState = 0; } // 更新LCD显示 void updateLCD() { static unsigned long lastUpdate = 0; if (millis() - lastUpdate < 300) return; lastUpdate = millis(); switch(displayState) { case 0: showStatusScreen(); break; case 1: showMeasurementScreen(); break; case 2: showResultsScreen(); break; case 3: showHistorySummary(); break; } } // 显示状态屏幕 void showStatusScreen() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Ready"); lcd.setCursor(0, 1); lcd.print("Records:"); lcd.print(recordCount); } // 显示测量屏幕 void showMeasurementScreen() { lcd.clear(); if (gate1Active) { lcd.setCursor(0, 0); lcd.print("Door1:"); unsigned long elapsed = micros() - gate1Start; lcd.print(elapsed); lcd.print("μs"); lcd.setCursor(0, 1); lcd.print("V1:"); lcd.print(WIDTH / (elapsed / 1000000.0), 2); lcd.print("m/s"); } else if (gate2Active) { lcd.setCursor(0, 0); lcd.print("Door2:"); unsigned long elapsed = micros() - gate2Start; lcd.print(elapsed); lcd.print("μs"); lcd.setCursor(0, 1); lcd.print("V2:"); lcd.print(WIDTH / (elapsed / 1000000.0), 2); lcd.print("m/s"); } } // 显示结果屏幕 void showResultsScreen() { lcd.clear(); // 第一行: 时间戳和加速度 lcd.setCursor(0, 0); lcd.print("Time:"); lcd.print(currentData.timestamp / 1000); // 转换为秒 lcd.print("s a:"); lcd.print(currentData.acceleration, 2); // 第二行: 存储状态和时间差 lcd.setCursor(0, 1); lcd.print("Time diff:"); lcd.print(currentData.timeDiff / 1000.0, 1); // 转换为毫秒显示 lcd.print("ms"); // 在有限空间内显示存储信息 lcd.setCursor(10, 1); lcd.print("#"); lcd.print(recordCount + 1); } // 保存完整数据到SD卡 void saveToSD() { File dataFile = SD.open(FILENAME, FILE_WRITE); if (dataFile) { // 以CSV格式写入数据 dataFile.print(currentData.timestamp); dataFile.print(","); dataFile.print(currentData.time1); dataFile.print(","); dataFile.print(currentData.time2); dataFile.print(","); dataFile.print(currentData.timeDiff); dataFile.print(","); dataFile.print(currentData.velocity1, 4); dataFile.print(","); dataFile.print(currentData.velocity2, 4); dataFile.print(","); dataFile.println(currentData.acceleration, 4); dataFile.close(); Serial.println("数据已存SD卡"); // 更新记录计数和最后记录 recordCount++; lastRecord = currentData; } else { Serial.println("写入SD卡失败!"); } } // 显示历史摘要 void showHistorySummary() { lcd.clear(); if (recordCount == 0) { lcd.setCursor(0, 0); lcd.print("No data"); return; } // 第一行: 记录数 lcd.setCursor(0, 0); lcd.print("Records:"); lcd.print(recordCount); // 第二行: 最后记录的加速度和时间差 lcd.setCursor(0, 1); lcd.print("A:"); lcd.print(lastRecord.acceleration, 2); lcd.print(" Δt:"); lcd.print(lastRecord.timeDiff / 1000.0, 1); // 转换为毫秒显示 lcd.print("ms"); } // 获取记录数量 int getRecordCount() { File dataFile = SD.open(FILENAME, FILE_READ); int count = 0; if (dataFile) { // 跳过标题行 dataFile.readStringUntil('\n'); // 计算行数 while (dataFile.available()) { if (dataFile.read() == '\n') count++; } dataFile.close(); } // 加载最后一条记录 if (count > 0) { loadLastRecord(); } return count; } // 加载最后一条记录 void loadLastRecord() { File dataFile = SD.open(FILENAME, FILE_READ); if (!dataFile) return; // 定位到文件末尾 dataFile.seek(dataFile.size()); // 向前查找最后一行 int linesToRead = 2; // 最后一行和可能的空行 while (dataFile.position() > 0 && linesToRead > 0) { dataFile.seek(dataFile.position() - 1); char c = dataFile.read(); if (c == '\n') { linesToRead--; if (linesToRead == 0) break; } if (dataFile.position() <= 1) break; dataFile.seek(dataFile.position() - 2); } // 读取最后一行 String lastLine = dataFile.readStringUntil('\n'); parseCSVLine(lastLine, lastRecord); dataFile.close(); } // 解析CSV行到数据结构 void parseCSVLine(String line, ExperimentData &data) { int index = 0; int lastIndex = 0; // 时间戳 index = line.indexOf(',', lastIndex); data.timestamp = line.substring(lastIndex, index).toInt(); lastIndex = index + 1; // time1 index = line.indexOf(',', lastIndex); data.time1 = line.substring(lastIndex, index).toInt(); lastIndex = index + 1; // time2 index = line.indexOf(',', lastIndex); data.time2 = line.substring(lastIndex, index).toInt(); lastIndex = index + 1; // timeDiff index = line.indexOf(',', lastIndex); data.timeDiff = line.substring(lastIndex, index).toInt(); lastIndex = index + 1; // velocity1 index = line.indexOf(',', lastIndex); data.velocity1 = line.substring(lastIndex, index).toFloat(); lastIndex = index + 1; // velocity2 index = line.indexOf(',', lastIndex); data.velocity2 = line.substring(lastIndex, index).toFloat(); lastIndex = index + 1; // acceleration data.acceleration = line.substring(lastIndex).toFloat(); } // 导出所有实验数据(增加时间差列) void exportAllData() { File dataFile = SD.open(FILENAME, FILE_READ); if (!dataFile) { Serial.println("无数据可导出"); return; } Serial.println("\n===== 所有实验数据 ====="); // 输出所有数据 while (dataFile.available()) { Serial.write(dataFile.read()); } dataFile.close(); Serial.println("===== 导出完成 ====="); } // 从SD卡读取数据(增加时间差显示) void readFromSD() { File dataFile = SD.open(FILENAME, FILE_READ); if (!dataFile) { Serial.println("SD卡中无数据"); lcd.clear(); lcd.print("No Data"); delay(2000); return; } Serial.println("\n===== 历史数据 ====="); // 跳过标题行 dataFile.readStringUntil('\n'); int recordNum = 0; while (dataFile.available()) { String line = dataFile.readStringUntil('\n'); if (line.length() == 0) continue; recordNum++; ExperimentData data; parseCSVLine(line, data); // 串口输出(增加时间差) Serial.print("记录 #"); Serial.print(recordNum); Serial.print(" 时间戳: "); Serial.print(data.timestamp); Serial.println(" ms"); Serial.print("时间1: "); Serial.print(data.time1); Serial.println(" μs"); Serial.print("时间2: "); Serial.print(data.time2); Serial.println(" μs"); Serial.print("时间差: "); Serial.print(data.timeDiff); Serial.println(" μs"); Serial.print("速度1: "); Serial.print(data.velocity1, 4); Serial.println(" m/s"); Serial.print("速度2: "); Serial.print(data.velocity2, 4); Serial.println(" m/s"); Serial.print("加速度: "); Serial.print(data.acceleration, 4); Serial.println(" m/s²"); Serial.println("----------------------"); // LCD显示当前记录摘要(增加时间差) lcd.clear(); lcd.setCursor(0, 0); lcd.print("Record "); lcd.print(recordNum); lcd.setCursor(0, 1); lcd.print("Δt:"); lcd.print(data.timeDiff / 1000.0, 1); // 转换为毫秒显示 lcd.print("ms A:"); lcd.print(data.acceleration, 2); delay(10000); // 每条记录显示10秒 } Serial.println("--------------------------------------"); dataFile.close(); displayState = 0; beep(1, 100); } // 清除SD卡数据 void clearSD() { if (SD.remove(FILENAME)) { // 重新创建文件头 File dataFile = SD.open(FILENAME, FILE_WRITE); if (dataFile) { dataFile.println("Timestamp(ms),Time1(us),Time2(us),TimeDiff(us),Velocity1(m/s),Velocity2(m/s),Acceleration(m/s2)"); dataFile.close(); } recordCount = 0; Serial.println("所有数据已清除"); lcd.clear(); lcd.print("Data cleared"); delay(1000); } else { Serial.println("清除数据失败"); } beep(2, 50); displayState = 0; } // 处理串口命令 void processSerialCommand() { char command = Serial.read(); switch(command) { case 'R': case 'r': readFromSD(); // 改为从SD卡读取 break; case 'C': case 'c': clearSD(); // 改为清除SD卡数据 break; case 'E': case 'e': exportAllData(); // 导出所有数据 break; case 'T': // 设置时间偏移 if (Serial.available() >= 4) { unsigned long timeOffset; Serial.readBytes((char*)&timeOffset, sizeof(timeOffset)); Serial.println("时间戳调整功能在SD卡版本中不可用"); } break; default: Serial.println("未知命令"); Serial.println("可用命令: R-读取, C-清除, E-导出, T-设置时间"); } } // 蜂鸣器控制(音量提高) void beep(int times, int duration) { for (int i = 0; i < times; i++) { // 使用高频音调(3000Hz)提高音量 tone(BUZZER_PIN, 3000); // 持续发声 delay(duration); // 持续时间 noTone(BUZZER_PIN); // 停止发声 if (i < times - 1) delay(duration); // 间隔 } } // 重置实验状态 void resetExperiment() { gate1Active = false; gate2Active = false; experimentComplete = false; gate1Start = 0; gate1End = 0; gate2Start = 0; gate2End = 0; displayState = 0; // 重置当前数据结构 memset(&currentData, 0, sizeof(currentData)); } 此代码报错为Sketch uses 25076 bytes (77%) of program storage space. Maximum is 32256 bytes. Global variables use 2105 bytes (102%) of dynamic memory, leaving -57 bytes for local variables. Maximum is 2048 bytes. Not enough memory; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing your footprint. data section exceeds available space in board Compilation error: data section exceeds available space in board请你修改
最新发布
12-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值