【C语言】计算实时太阳角度(高度角、方位角),以及使用stm32单片机实时获取时间戳
整体计算方法
在编写该代码的过程中寻找了多篇博文和论文,综合所有文章且按网上的以0时的方位角的0°,且随时间累加累加至360度。我修改了博文和论文的一些角度的计算方法。得到一下代码与网站计算的方位角相互验证过,误差不超过1°
验证网站
太阳赤纬角

n为该天在当年的序号
另一种方法没尝试成功:

代码如下读者可以自行尝试,我没尝试成功
int n, n0;double t, theta, delta;// 计算n和n0n = month * 30 + day;n0 = 79.6764 + 0.2422 * (year - 1985) - ((year - 1985) / 4);// 计算tt = n ;// 计算θ(日角)theta = 2 * M_PI * t / 365.2422;// 计算δ(太阳赤纬)delta = 0.3723 + 23.2567 * sin(theta) + 0.1149 * sin(2 * theta) - 0.1712 * sin(3 * theta)- 0.758 * cos(theta) + 0.3656 * cos(2 * theta) + 0.0201 * cos(3 * theta);
太阳时角

时角这里的话中午时时角为0下午时角为负,可以简化为时角=15*(t-12)
不过这里计算的是时区的时间,不是当地时间所以存在误差,我怀疑代码计算的误差大部分都是出自这里
当地时角位于东7区的换算方法: (120度 – 当地经度) * 4,1个小时15度,平均下来,1度4分钟。
既时角=15*(t-12)+(120-经度)
太阳高度角

通过上述两个方程,即可求出高度角的各个参数。
太阳方位角

h为太阳高度角
Φ为纬度数据
σ为太阳的赤纬角
代码部分
C语言三角函数运算
因为角度计算涉及大量三角函数,所以C语言的三角函数计算不可避免需要使用。
C语言的三角函数计算函数
需要包含头文件#include <math.h>
double __cdecl sin(double _X);double __cdecl cos(double _X);double __cdecl tan(double _X);double __cdecl asin(double _X);double __cdecl acos(double _X);double __cdecl atan(double _X);double __cdecl atan2(double _Y,double _X);
其中sin、cos、tan 函数的参数是一个用弧度表示的角度,分别返回这个角度的正弦、余弦、正切值。度和弧度都是衡量角的大小的单位。度用 ° 来表示,弧度用rad表示。
1度=π/180 弧度 ( ≈0.017453弧度 )
asin()、acos、atan 函数分别返回它们的参数的反正弦、反余弦、反正切值。功能刚好和sin、cos、tan 函数相反。
赤纬角计算
通过公式:

/********************************************************************************************************************************************
*@*名称 : Declination_Angle_Calculation
*@*功能 : 计算太阳赤纬角
*@*形参 : YearData年数据 DayData日数据
*@*返回值 : DeclinationAngle太阳赤纬角
*********************************************************************************************************************************************/
static double Declination_Angle_Calculation(double Daydata,short YearData)
{double DeclinationAngle;DeclinationAngle = 23.45 * sin((Daydata-80)/370.0 * 360*PI/180); //赤纬角公式 return DeclinationAngle; //返回赤纬角
}
时角计算
通过公式:
时角=15*(t-12)
/********************************************************************************************************************************************
*@*名称 : Hour_Angle_Calculation
*@*功能 : 计算太阳时角
*@*形参 : HourData小时数据
*@*返回值 : HourAngle太阳时角
*********************************************************************************************************************************************/
static double Hour_Angle_Calculation(double HourData)
{double HourAngle;HourAngle = 15*(HourData-12);return HourAngle;}
太阳高度角计算
通过公式

/********************************************************************************************************************************************
*@*名称 : Height_Angle_Calculation
*@*功能 : 计算太阳高度角
*@*形参 : LatitudeData纬度数据 HourData小时数据 DeclinationAngle赤纬角数据
*@*返回值 : ElevatingAngle太阳高度角
*********************************************************************************************************************************************/
static double Height_Angle_Calculation(double LatitudeData,double HourAngle,double DeclinationAngle)
{double ElevatingAngle; //高度角double ElevatingAngle_sin; //高度角正弦值double DeclinationAngle_sin = sin(DeclinationAngle * PI / 180); //赤纬角的正弦值 double DeclinationAngle_cos = cos(DeclinationAngle * PI / 180); //赤纬角余弦值 double LatitudeData_sin = sin(LatitudeData * PI / 180); //纬度正弦值 double LatitudeData_cos = cos(LatitudeData * PI / 180); //纬度余弦值 double HourAngle_cos = cos(HourAngle * PI/180);ElevatingAngle_sin = (DeclinationAngle_sin*LatitudeData_sin) + (DeclinationAngle_cos*LatitudeData_cos*HourAngle_cos);ElevatingAngle = asin(ElevatingAngle_sin)*180/PI;return ElevatingAngle;
}
太阳方位角计算
通过公式

/********************************************************************************************************************************************
*@*名称 : Azimuth_Angle_Calculation
*@*功能 : 计算太阳方位角
*@*形参 : ElevatingAngle太阳高度角 HourAngle太阳时角 DeclinationAngle赤纬角数据 HourData小时数据 LatitudeData纬度数据
*@*返回值 : 太阳方位角(0点开始360度)
*********************************************************************************************************************************************/
static double Azimuth_Angle_Calculation(double ElevatingAngle,double HourAngle,double DeclinationAngle,double HourData,double LatitudeData)
{double AzimuthAngle,AzimuthAngle_cos;double ElevatingAngle_cos = cos(ElevatingAngle * PI / 180); //高度角余弦值 double ElevatingAngle_sin = sin(ElevatingAngle * PI / 180); //高度角正弦值 double LatitudeData_sin = sin(LatitudeData * PI / 180); //纬度正弦值 double LatitudeData_cos = cos(LatitudeData * PI / 180); //纬度余弦值 double HourAngle_sin = sin(HourAngle * PI / 180); //时角正弦值 double DeclinationAngle_cos = cos(DeclinationAngle * PI / 180); //赤纬角余弦值 double DeclinationAngle_sin = sin(DeclinationAngle * PI / 180); //赤纬角正弦值AzimuthAngle_cos = (ElevatingAngle_sin*LatitudeData_sin-DeclinationAngle_sin)/(ElevatingAngle_cos*LatitudeData_cos); //初步计算太阳方位角弧度值的cos值 AzimuthAngle = acos(AzimuthAngle_cos)*180/PI; //计算方位角的角度 if (HourData > 12) //不判断的话12点为180度最高,然后两边的角度都是180度递减,所以需要一个360度的角度反馈需要将方位角判断一下。 {return AzimuthAngle + 180;}else {return -AzimuthAngle + 180;}}
其中函数尾部的返回时180度加减计算得出的方位角,是为了对齐网页计算得出的方位角,以0时的方位角的0°,且随时间累加累加至360度。
角度计算到此就结束了
时间戳转换
下文内容多数引用自:博客
因为我打算用stm32f103mcu进行太阳方位角以及高度角的计算,所以需要用stm32单片机获取时间戳信息
我采用的方法是使用esp8266-01s模块来通过联网获取时间戳的方式得到时间。
配置 ESP8266 入网
AT+CWMODE=1 // station模式,设置成3也行
AT+RST // 重启模块
AT+CWJAP="ssid","password" // 连接AP
连接授时服务器
AT+CIPMUX=0 // 设置WiFi模块为单路链接
AT+CIPSTART="UDP","1.cn.pool.ntp.org",123
// 链接到 NTP 服务器,时间服务器默认的端口号是 123,协议为UDP.AT+CIPSEND=48
// 发送48byte的数据若ESP8266返回'>'则继续注意,严格遵照以下数据且使用16进制发送
//切勿发送新行E3 0 6 EC 0 0 0 0 0 0 0 0 31 4E 31 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
//用16进制接收数据
E3 0 6 EC 0 0 0 0 0 0 0 0 31 4E 31 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
不知道为什么我好像需要发送两遍下边的16进制数据,然后接收两帧数据
接收数据
- 执行完上面两步,此时如果顺利的话会受到一大堆16进制数据
- 诸如:41 54 2B 43 49 50 53 45 4E 44 3D 34 38 0D 0D 0A 0D 0A 4F 4B 0D 0A 3E 20 0D 0A 52 65 63 76 20 34 38 20 62 79 74 65 73 0D 0A 0D 0A 53 45 4E 44 20 4F 4B 0D 0A 0D 0A 2B 49 50 44 2C 34 38 3A 24 02 06 E9 00 00 00 52 00 00 08 F2 0A 45 02 22 E0 4F 57 31 79 AF 20 82 00 00 00 00 00 00 00 00 E0 4F 59 9C 2F 4A 40 07 E0 4F 59 9C 2F 4C 22 B9
- 此时需要找到数据中的关键帧,也就是服务器返回的48位时间数据,它们通常具有以下格式:(如果找不到的话请重试2中的3、4步)
- ① 它前面的数据为"2B 49 50 44 2C 34 38 3A"(+IPD,48:),他后面没有东西;
- ② 它通常以 24 开头.3.对数据提取后编号,其中[40][41][42][43]为我们需要的时间数据,在本例中为"E0 4F 5C 00".
处理数据
①将”E04F5C00“转为十进制为3763297280,此即为1900距今的秒数。
②把这个时间减去2208988800(70年),得到标准的Unix时间戳。[3763297280-2208988800=1554308480]
③[1554308480/31556736+1970=2019],得到当下年份。
④计算月份和日期需要考虑平年闰年和每月天数,太麻烦我也没搞懂。
⑤[(1554308480/3600)%24+8=24],得到北京时间-时(别忘了满24归零)
⑥[(1554308480/60)%60=21],得到北京时间-分
⑦[1554308480%60=20],得到北京时间-秒,既当下时间是 24:21:20
⑧将时间戳(1554308480)输入 时间戳生成网页 与计算结果进行比较
时间戳解码并加入代码
因为我们计算太阳角度的代码,只需要获取年份,当天在一年中的序号,以及小时分钟信息。
所以有以下计算
/********************************************************************************************************************************************
*@*名称 : Timestamp_Calculation
*@*功能 : 计算时间戳
*@*形参 : Timestamp时间戳数据 Year_data年数据存放的地址 DayData日数据存放的地址 Hour_data小时数据存放的地址
*@*返回值 : 无
*********************************************************************************************************************************************/
static void Timestamp_Calculation(unsigned int Timestamp,short *Year_data,short *DayData,double *Hour_data)
{Timestamp = Timestamp-0x83AA7E80; //将网络获取的时间戳减去70年得到标准时间戳 *Year_data = Timestamp/31556736+1970; //用时间戳获取年份 *DayData = (short)((Timestamp%31556736)/86400)+1; //获取日期 *Hour_data = (Timestamp/3600)%24+8; //获取小时数 if(*Hour_data==24){*Hour_data = 0; //当时间为24点时归零 } *Hour_data += ((Timestamp/60)%60)/60.0; //获取分钟信息并且转为小数形式加入小时数中
}
步骤:
- 将网络获取的时间戳减70年得到标准时间戳
- 然后用标准时间戳除一年的秒数,就得到距离时间戳开始运行的1970年过去了多少年
- 标准时间戳除于一天的秒数,为今年过去了多少天,还要加上没过完的今天,即加1。
- 小时数为将时间戳除一小时的秒数,得到至今运行了多少小时,再进行24小时取余,余今天过了多少小时
- 小时数在加上分钟数,得到带小数点的精确时间。(方法类似步骤5)
相关文章:
【C语言】计算实时太阳角度(高度角、方位角),以及使用stm32单片机实时获取时间戳
整体计算方法 在编写该代码的过程中寻找了多篇博文和论文,综合所有文章且按网上的以0时的方位角的0,且随时间累加累加至360度。我修改了博文和论文的一些角度的计算方法。得到一下代码与网站计算的方位角相互验证过,误差不超过1 验证网站 太…...
创建git仓库
①git init:用于在一个现有的目录中初始化一个新的 Git 仓库。 # 进入你的项目目录,如果你想要在当前目录下初始化 Git 仓库。 git init 这会在当前目录下创建一个名为 .git 的子目录,其中包含 Git 仓库的所有必要文件和目录。(…...
19.悲观锁与乐观锁解析
1.悲观锁 悲观锁比较悲观,它认为如果不锁住这个资源,别的线程就会来争抢,就会造成数据结果错误,所以悲观锁为了确保结果的正确性,会在每次获取并修改数据时,都把数据锁住,让其他线程无法访问该…...
C语言--给出一个点的坐标判断它在单位圆的内部外部还是上面
一.题目描述 给出一个点的坐标判断它在单位圆的内部外部还是上面 例如输入1,0,输出在圆上 二.思路分析 首先,单位圆是以坐标系原点为圆心、半径为1的圆。 给定一个点坐标 (x,y),我们可以使用勾股定理计算该点到坐标系原点的距…...
变频器基础问答集21-50
21.请问电机软起动器是否能节能?软启动节能效果有限,但可以减少启动对电网的冲击,也可以实现平滑启动,保护电机机组。 根据能量守恒理论,由于加入了相对复杂的控制电路,软启动不但不节能,还会加大能量的消耗,但它可以减小电路的启…...
OpenCvSharp从入门到实践-(01)认识OpenCvSharp开发环境搭建
目录 一、OpenCV 二、OpenCvSharp 三、OpenCvSharp开发环境搭建 四、下载 五、其他 一、OpenCV OpenCV是基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习函数库,支持Windows、Linux、Android和Mac OS操作系统。OpenCV由一系…...
OSG文字-渐变文字(4)
渐变文字(osgText::FadeText类)继承自osgText::Text类继承关系图如图9-6所示 图9-6 osgText::FadeText的继承关系图 从继承关系图中可以看出,它继承自osgText::Text类,因此,它具备一般文字属性的设置方法这里不再重复说明。创建渐变文字与一般…...
排查生产环境:MySQLTransactionRollbackException数据库死锁
一. 问题现状 程序直接宕机,并在error.log日志中发现大量的报错日志,如下: ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting trans…...
140.【鸿蒙OS开发-01】
鸿蒙开发 (一)、初识鸿蒙1.初识鸿蒙(1).移动通讯技术的发展(2).完整的鸿蒙开发 (二)、鸿蒙系统介绍1.鸿蒙系统的官方定义(1).鸿蒙操作系统概述(2).鸿蒙的生态 2.鸿蒙系统的特点3.鸿蒙和安卓的对比4.鸿蒙开发的发展前景 (三)、鸿蒙开发准备工作1.鸿蒙OS的完整开发流程2.注册并实…...
npm install 下载不下来依赖解决方案
背景 最近在构建 前端自动化部署 的方案中发现了一个问题,就是我在npm install的时候,有时候成功,有时候不成功,而且什么代码也没发生更改,报错也就是那么几个错,所以在此也整理了一下遇到这种情况…...
接口自动化中cookies的处理技术
一,理论知识 为什么有cookie和session? 因为http协议是一种无状态的协议,即每次服务端接受到客户端的请求时都时一个全新的请求,服务器并不知道客户端的请求记录,session和cookie主要目的就是弥补http的无状态特性 …...
PHP 安装
您需要做什么? 为了开始使用 PHP,您可以: 找一个支持 PHP 和 MySQL 的 Web 主机在您自己的 PC 机上安装 Web 服务器,然后安装 PHP 和 MySQL 使用支持 PHP 的 Web 主机 如果您的服务器支持 PHP,那么您不需要做任何事情…...
小程序常见操作
测试时访问本地http服务器调用报错 微信开发者工具(右上角)-> 详情->本地设置->不校验合法域名、web-view(业务域名)... -> 去除勾选使用npm包 1) 工程目录下创建package.jsonnpm init(手动完成设定) / npm init -y (默认设定) 2) 安装 np…...
STM32F4串口USART发送为00的解决方案
检查接线是否正确检查TX是否为复用推挽输出 3.检查是否将TX和RX引脚重映射为USART功能 在STM32中,每个GPIO引脚可以配置为不同的复用功能,例如UART、SPI、I2C等。具体来说,GPIO_PinAFConfig函数用于配置GPIO引脚的复用功能。它的参数包括GPIO…...
重磅解读 | 阿里云 云网络领域关键技术创新
云布道师 10 月 31 日,杭州云栖大会,阿里云技术主论坛带来了一场关于阿里云主力产品与技术创新的深度解读,阿里云网络产品线负责人祝顺民带来《云智创新,网络随行》的主题发言,针对阿里云飞天洛神云网络(下…...
【蓝桥杯省赛真题45】Scratch九宫格游戏 蓝桥杯scratch图形化编程 中小学生蓝桥杯省赛真题讲解
目录 scratch九宫格游戏 一、题目要求 编程实现 二、案例分析 1、角色分析...
物联网AI MicroPython学习之语法 ADC数模模块
学物联网,来万物简单IoT物联网!! ADC 介绍 模块功能: ADC数模转换模块 ADC功能在ESP32引脚32-39上可用,使用默认配置时,ADC引脚上的输入电压必须介于0.0v和1.0v之间(任何高于1.0v的值都将读为4095&#x…...
详解Python中哈希表的使用。站在开发者角度,与大家一起探究哈希的世界。
文章目录 1. 前言2. 哈希表2.1 哈希函数2.2 哈希算法2.3 常见哈希算法2.4 哈希冲突 3.总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面…...
详解python淘宝秒杀抢购脚本程序实现
文章目录 前言一、官网下载火狐浏览器二、下载geckodriver,并解压到火狐浏览器文件夹根目录三、添加火狐浏览器根目录到系统环境变量四、下载并安装python及pycharm开发工具五、进入淘宝六、使用Pycharm运行脚本,新建python文件,将代码复制到…...
使用ChatGPT创建Makefile构建系统:使用Make运行Docker
使用ChatGPT创建Makefile构建系统:使用Make运行Docker 芯语芯愿(知乎/纷传/CSDN/);小石头的芯语芯愿(微信公众号) 开发高效现代的构建系统对于满足开发周期需求至关重要。原先,嵌入式开发者一…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
leetcode_69.x的平方根
题目如下 : 看到题 ,我们最原始的想法就是暴力解决: for(long long i 0;i<INT_MAX;i){if(i*ix){return i;}else if((i*i>x)&&((i-1)*(i-1)<x)){return i-1;}}我们直接开始遍历,我们是整数的平方根,所以我们分两…...
【java】【服务器】线程上下文丢失 是指什么
目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失? 直观示例说明 为什么上下文如此重要? 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程,代码应该如何实现 推荐方案:使用 ManagedE…...
