AVR潮汐计算例程数组映射逻辑解析及跨平台移植咨询
潮汐计算核心逻辑解析与移植方案
核心逻辑拆解
原代码采用潮汐谐波合成法,将潮汐运动分解为37个独立的余弦谐波分量,叠加所有分量的贡献得到最终潮高,核心步骤如下:
1. 时间参数计算
YearIndx = 当前年份 - startYear:计算当前年份相对于起始年份(2022)的索引,比如2022对应0、2023对应1,直到2032对应9。currHours:计算从当年1月1日0点(GMT)到当前时刻的总小时数:- 用当前Unix时间戳减去
startSecs[YearIndx](对应当年年初的Unix时间戳)得到总秒数 - 除以3600转换为小时
- 加上
adjustGMT将本地时间转换为GMT时间(比如东8区加8)
- 用当前Unix时间戳减去
2. 数组元素提取规则
四个数组的作用与提取方式:
startSecs:一维数组(长度10),每个元素对应2022-2032某一年1月1日0点的Unix时间戳,用YearIndx直接索引取对应年份的值。Nodefactor/Equilarg:二维数组(10行×37列)- 行:对应2022-2032每一年(索引0→2022,9→2032)
- 列:对应37个潮汐谐波分量的序号(0到36)
- 提取方式:
Nodefactor[YearIndx][harms]、Equilarg[YearIndx][harms],即取当前年份对应行、当前谐波对应列的值。
Amp/Kappa/Speed:一维数组(长度37),每个元素对应一个谐波分量的固定参数(特定海域的潮汐常数,不随年份变化),直接用谐波序号harms索引。
3. 潮高计算
每个谐波分量的贡献公式:
分量潮高 = Nodefactor × Amp × cos( (Speed×currHours + Equilarg - Kappa) × 角度转弧度系数 )
将37个分量的潮高全部累加到基准潮高Datum上,即为最终潮汐高度。
ESP32/8266 移植示例
移除AVR特有的pgm_read_xxx函数,直接用普通数组存储参数,时间处理采用Arduino自带函数:
#define startYear 2022 #define DEG_TO_RAD 0.017453292519943295 float Datum = 3.35; float adjustGMT = 8.0; // 东8区示例 // 替换为你实际的数组数据 uint32_t startSecs[10] = {1640995200, ...}; // 2022-2032年初Unix时间戳 float Nodefactor[10][37] = {{...}, ...}; float Equilarg[10][37] = {{...}, ...}; float Amp[37] = {...}; float Kappa[37] = {...}; float Speed[37] = {...}; float currentTide(time_t nowUnix) { int YearIndx = year(nowUnix) - startYear; time_t yearStart = makeTime(startYear + YearIndx, 1, 1, 0, 0, 0); float currHours = (nowUnix - yearStart) / 3600.0f; currHours += adjustGMT; float tideHeight = Datum; for (int harms = 0; harms < 37; harms++) { float currNodefactor = Nodefactor[YearIndx][harms]; float currAmp = Amp[harms]; float currEquilarg = Equilarg[YearIndx][harms]; float currKappa = Kappa[harms]; float currSpeed = Speed[harms]; tideHeight += currNodefactor * currAmp * cos( (currSpeed * currHours + currEquilarg - currKappa) * DEG_TO_RAD ); } return tideHeight; } // 使用示例:通过NTP获取时间后调用 #include <NTPClient.h> #include <WiFi.h> WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 8*3600, 60000); void setup() { WiFi.begin("你的WiFi名称", "WiFi密码"); while (!WiFi.isConnected()) delay(500); timeClient.begin(); } void loop() { timeClient.update(); time_t now = timeClient.getEpochTime(); float tide = currentTide(now); Serial.print("当前潮高:"); Serial.print(tide); Serial.println(" 英尺"); delay(30000); }
Python 移植示例
采用datetime和math模块实现,直接定义数组参数:
import datetime import math startYear = 2022 DEG_TO_RAD = math.pi / 180 Datum = 3.35 adjustGMT = 8.0 # 东8区示例 # 替换为实际的数组数据 startSecs = [1640995200, ...] # 2022-2032年初Unix时间戳 Nodefactor = [[...], ...] # 10行37列 Equilarg = [[...], ...] # 10行37列 Amp = [...] # 37个元素 Kappa = [...] # 37个元素 Speed = [...] # 37个元素 def current_tide(now): now_utc = now.astimezone(datetime.timezone.utc) year = now_utc.year YearIndx = year - startYear year_start = datetime.datetime(year, 1, 1, tzinfo=datetime.timezone.utc) curr_seconds = (now_utc - year_start).total_seconds() curr_hours = curr_seconds / 3600.0 tide_height = Datum for harms in range(37): curr_nodefactor = Nodefactor[YearIndx][harms] curr_amp = Amp[harms] curr_equilarg = Equilarg[YearIndx][harms] curr_kappa = Kappa[harms] curr_speed = Speed[harms] angle = (curr_speed * curr_hours + curr_equilarg - curr_kappa) * DEG_TO_RAD tide_height += curr_nodefactor * curr_amp * math.cos(angle) return tide_height # 使用示例 now = datetime.datetime.now(datetime.timezone.utc) tide = current_tide(now) print(f"当前潮高:{tide} 英尺")
内容的提问来源于stack exchange,提问作者JNR
相关产品推荐
相关产品推荐

