【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;					//获取分钟信息并且转为小数形式加入小时数中 
}

步骤:

  1. 将网络获取的时间戳减70年得到标准时间戳
  2. 然后用标准时间戳除一年的秒数,就得到距离时间戳开始运行的1970年过去了多少年
  3. 标准时间戳除于一天的秒数,为今年过去了多少天,还要加上没过完的今天,即加1。
  4. 小时数为将时间戳除一小时的秒数,得到至今运行了多少小时,再进行24小时取余,余今天过了多少小时
  5. 小时数在加上分钟数,得到带小数点的精确时间。(方法类似步骤5)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/162714.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LoRaWAN 中国地区文件详细解读

目录 一、LoRaWAN简介 二、CN470-510地区参数分析 1.信道频率 2.支持功率 3.支持空速 4.最大负载大小 5.接受窗口参数 三、CN470_510默认参数 Lora LoraWAN教程 一、LoRaWAN简介 LoraWAN是一种基于LoRa远距离通信技术配套设计的一套通讯协议和系统架构。LoRaWAN网络通…

Java实现拼图游戏

1、了解拼图游戏基本功能&#xff1a; 拼图游戏内容由若干小图像块组成的&#xff0c;通过鼠标点击图像块上下左右移动&#xff0c;完成图像的拼凑。 2、拼图游戏交互界面设计与开发&#xff1a; 通过创建窗体类、菜单、中间面板和左右面板完成设计拼图的交互界面 &#xff…

外贸自建站服务器怎么选?网站搭建的工具?

外贸自建站服务器用哪个好&#xff1f;如何选海洋建站的服务器&#xff1f; 外贸自建站是企业拓展海外市场的重要手段之一。而在这个过程中&#xff0c;选择一个适合的服务器对于网站的稳定运行和优化至关重要。海洋建站将为您介绍如何选择适合的外贸自建站服务器。 外贸自建…

【STM32外设系列】GPS定位模块(ATGM336H)

&#x1f380; 文章作者&#xff1a;二土电子 &#x1f338; 关注公众号获取更多资料&#xff01; &#x1f438; 期待大家一起学习交流&#xff01; 文章目录 一、GPS模块简介二、使用方法2.1 引脚介绍2.2 数据帧介绍2.3 关于不同的启动方式 三、前置知识3.1 strstr函数3.2…

基于H1ve一分钟搭好CTF靶场

写在前面 ◉ ‿ ◉ 上一篇文章给大家详细介绍了基于H1ve搭建CTF靶场&#xff0c;以及过程中可能遇到的报错及解决方法&#xff0c;那么这篇文章&#xff0c;我总结了一下&#xff0c;将不会遇到报错的方法给到大家&#xff0c;但是前提是你的服务器最好是一个全新的哦~~~ 我…

C++基础从0到1入门编程(四)类和对象

系统学习C 方便自己日后复习&#xff0c;错误的地方希望积极指正 往期文章&#xff1a; C基础从0到1入门编程&#xff08;一&#xff09; C基础从0到1入门编程&#xff08;二&#xff09; C基础从0到1入门编程&#xff08;三&#xff09; 参考视频&#xff1a; 1.黑马程序员匠心…

香蕉派BPI-M4 Zero单板计算机采用全志H618,板载2GRAM内存

Banana Pi BPI-M4 Zero 香蕉派 BPI-M4 Zero是BPI-M2 Zero的最新升级版本。它在性能上有很大的提高。主控芯片升级为全志科技H618 四核A53, CPU主频提升25%。内存升级为2G LPDDR4&#xff0c;板载8G eMMC存储。它支持5G WiFi 和蓝牙, USB接口也升级为type-C。 它具有与树莓派 …

23. 深度学习 - 多维向量自动求导

Hi, 你好。我是茶桁。 前面几节课中&#xff0c;我们从最初的理解神经网络&#xff0c;到讲解函数&#xff0c;多层神经网络&#xff0c;拓朴排序以及自动求导。 可以说&#xff0c;最难的部分已经过去了&#xff0c;这节课到了我们来收尾的阶段&#xff0c;没错&#xff0c;生…

算法通关村第十二关-白银挑战字符串经典题目

大家好我是苏麟 , 今天带来字符串相关的题目 . 大纲 反转问题字符串反转K个一组反转仅仅反转字母反转字符串中的单词 反转问题 字符串反转 描述 : 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s的形式给出。 题目 : LeetCode 344. 反转…

webshell之扩展免杀

由于很多企业为了防止源码泄露&#xff0c;都会使用加密扩展将代码进行加密&#xff0c;那么我们就可以就将计就计&#xff0c;将webshell也利用扩展加密&#xff0c;将特征消除&#xff0c;从而达到免杀的效果 1.php-beast 扩展地址 下载dll&#xff0c;并添加至ext中 在php…

MySQL中自增id用完怎么办?

MySQL中自增id用完怎么办&#xff1f; MySQL里有很多自增的id&#xff0c;每个自增id都是定义了初始值&#xff0c;然后不停地往上加步长。虽然自然数是没有上限的&#xff0c;但是在计算机里&#xff0c;只要定义了表示这个数的字节长度&#xff0c;那它就有上限。比如&#…

python数据结构与算法-15_堆与堆排序

堆(heap) 前面我们讲了两种使用分治和递归解决排序问题的归并排序和快速排序&#xff0c;中间又穿插了一把树和二叉树&#xff0c; 本章我们开始介绍另一种有用的数据结构堆(heap)&#xff0c; 以及借助堆来实现的堆排序&#xff0c;相比前两种排序算法要稍难实现一些。 最后我…

Linux开发工具(含gdb调试教程)

文章目录 Linux开发工具&#xff08;含gdb调试教程&#xff09;1、Linux 软件包管理器 yum2、Linux开发工具2.1、Linux编辑器 -- vim的使用2.1.1、vim的基本概念2.1.2、vim的基本操作2.1.3、vim正常模式命令集2.1.4、vim末行模式命令集 2.2、vim简单配置 3、Linux编译器 -- gcc…

redis之cluster集群

1、redis-cluster集群&#xff1a;redis3.0引入的分布式存储方案 2、集群&#xff1a;由多个node节点组成&#xff0c;redis数据分布在这些节点之中 &#xff08;1&#xff09;在集群之中也分主节点和从节点 &#xff08;2&#xff09;自带哨兵模式 3、redis-cluster集群的…

腾讯云 小程序 SDK对象存储 COS使用记录,原生小程序写法。

最近做了一个项目&#xff0c;需求是上传文档&#xff0c;文档类型多种&#xff0c;图片&#xff0c;视频&#xff0c;文件&#xff0c;doc,xls,zip,txt 等等,而且文档类型可能是大文件&#xff0c;可能得上百兆&#xff0c;甚至超过1G。 腾讯云文档地址&#xff1a;https://c…

PC端页面进去先出现加载效果

自定义指令v-loading&#xff0c;只需要绑定Boolean即可 v-loading“loading” <el-table :data"list" border style"width: 100%" v-loading"loading"><el-table-column align"center" label"序号" width"5…

开发板启动进入系统以后再挂载 NFS 文件系统, 这里的NFS文件系统是根据正点原子教程制作的ubuntu_rootfs

如果是想开发板启动进入系统以后再挂载 NFS 文件系统&#xff0c;开发板启动进入文件系统&#xff0c;开发板和 ubuntu 能互相 ping 通&#xff0c;在开发板文件系统下新建一个目录 you&#xff0c;然后执行如下指令进行挂载&#xff1a; mkdir mi mount -t nfs -o nolock,nfsv…

日本it就职培训机构,日本IT行业的三种类型

日本的IT产业一直保持增长趋势&#xff0c;市场规模逐年增加&#xff0c;在日本所有产业中占据很大比例。由于日本老龄化严重&#xff0c;日本国内的IT人才无法满足需求&#xff0c;为缓解这一问题&#xff0c;日本将引进外国优秀IT人才作为一项国策&#xff0c;日本IT行业不仅…

Leetcode1410. HTML 实体解析器

Every day a Leetcode 题目来源&#xff1a;1410. HTML 实体解析器 解法1&#xff1a;模拟 遍历字符串 text&#xff0c;每次遇到 ’&‘&#xff0c;就判断以下情况&#xff1a; 双引号&#xff1a;字符实体为 &quot; &#xff0c;对应的字符是 " 。单引号&a…

振弦式土压力计在岩土工程安全监测应用的方案

振弦式土压力计在岩土工程安全监测应用的方案 振弦式土压力计是一种常见的土压力测量仪器&#xff0c;其原理是利用振弦在土中传播的速度与土的应力状态有关的特点测量土压力。在岩土工程安全监测中&#xff0c;振弦式土压力计可以应用于以下方面&#xff1a; 1. 地下连续墙和…