系统时间最长9小时22分钟,求大神帮我让这个程序在9小时22分后别乱
unsigned long zhongduan1=6000;#include <LiquidCrystal.h>
#include <SD.h>
// CS引脚为pin4,这里也沿用官方默认设置
const int chipSelect = 4;//设定CS接口
int GP2D12 = 0;//把夏普GP2D12红外测距传感器连接在模拟量端口0
int val; //存储从GP2D12红外测距传感器读到的值
float temp;//存储由传感器读取值,通过算式处理后的浮点型距离值
int distance;//存储由传感器读取值,通过算式处理后的整数型距离值
float dataString;
LiquidCrystal lcd(10,6,5,7,3,2);//构造一个LiquidCrystal的类成员。使用数字IO ,12,11,5,4,3,2
void setup()
{
lcd.begin(16,2);//初始化LCD1602
lcd.setCursor(4, 0);
lcd.print("YANG WEN QI ");//液晶显示
lcd.setCursor(3, 1);
lcd.print("IS SO COOl");
delay(5000); //延时5000ms
lcd.clear(); //液晶清屏
Serial.begin(9600);//设置串口通信波特率为9600
Serial.print("Initializing SD card...");//串口输出数据Initializing SD card...
if (!SD.begin(chipSelect)) {//如果从CS口与SD卡通信失败,串口输出信息Card failed, or not present
Serial.println("Card failed, or not present");
return;
}
Serial.println("card initialized.");//与SD卡通信成功,串口输出信息card initialized.
}
void loop()
{
unsigned long nowtime=millis(); //获取当前的系统运行时间长度
if(nowtime>zhongduan1) //检测系统运行时间长度
{
// 读取1个传感器值,写入数组
for (int GP2D12 = 0; GP2D12 < 1; GP2D12++) {
int sensor = analogRead(GP2D12);
dataString = 2547.8/((float)val*0.49-10.41)-0.42;
}
// 打开文件,注意在同一时间只能有一个文件被打开
// 如果你要打开另一个文件,就需要先关闭前一个
File dataFile = SD.open("datalog.txt", FILE_WRITE);
// 打开datalog.txt文件,读写状态,位置在文件末尾。
if (dataFile)
{
dataFile.println(dataString);
dataFile.close();
// 数组dataString输出到串口
Serial.println(dataString);
}
// 如果无法打开文件,串口输出错误信息error opening datalog.txt
else {
Serial.println("error opening datalog.txt");
}
zhongduan1=nowtime+60000;
}
lcd.clear();
//读取GP2D12红外测距传感器模拟量数据
val = analogRead(GP2D12);
//通过以下算式,把传感器读取值处理成浮点型距离值
temp=2547.8/((float)val*0.49-10.41)-0.42;
//lcd.clear();//LCD清屏
// 定位光标在LCD第0行、第0列
//lcd.setCursor(0, 0);
//在LCD第0行第0列开始显示"Distance:"
// lcd.print("Distance:");
// 定位光标在LCD第1行、第7列
//lcd.setCursor(7, 1);
//如果传感器读取值大于80或者小于10,
// if(temp>80||temp<10)
//{
//则在LCD第1行、第7列开始显示"OverRange"
// lcd.print("OverRange");
// }
//如果传感器读取值在10到80之间,
//else
// {
//把浮点型距离值取整
//distance=temp;
//则在LCD第1行、第7列开始显示距离值
// lcd.print(distance);
//在距离值后显示单位"cm"
//lcd.print("cm");
lcd.setCursor(0, 0);
//在LCD第0行第0列开始显示"Distance:"
lcd.print(dataString);
// 定位光标在LCD第1行、第7列
lcd.setCursor(7, 1);
//则在LCD第1行、第7列开始显示距离值
lcd.print(temp);
//在距离值后显示单位"cm"
lcd.print("cm");
delay(1000);
}
问题已解决 99uuuu 发表于 2015-4-4 22:37 static/image/common/back.gif
问题已解决
已解决 ??
Are you sure 没问题 ?
Your code:
unsigned long nowtime=millis(); //获取当前的系统运行时间长度
if(nowtime>zhongduan1) //检测系统运行时间长度
{
...
...
zhongduan1=nowtime+60000;
}
Should be changed to:
unsigned long nowtime=millis(); //获取当前的系统运行时间长度
if(nowtime - zhongduan1 < 60000) //检测系统运行时间长度
{
// do nothing.. or
// return;
}else{
zhongduan1=nowtime;
...
...
}
这当 millis() 溢出(Overflow)归零时没有问题 !!
你的问题出在 nowtime+60000 这个地方,
由於 60000 是正的数,
而 nowtime = millis( ) 虽然是 unsigned long,
但当 millis( ) 达到unsigned long 接近最大数之时其实就是负很少的负数,
这时 millis( ) 或说 nowtime看作signed如为负数且
其绝对值如果小於 60000 则会使 nowtime+ 60000 变成正数就会出问题 !
这使得 millis( ) < zhongduan1 就会立即不成立 !!
(你的 zhongduan1= nowtime+60000; )
P.S.
millis( )要 49.71 天才溢出(Overflow)归零,
不是 9小时22分 !
但 micros( ) 则大约 71.58分钟归零
因为 millis( )是用 unsigned long (32 bits)表示开机到现在为止几个 milli second,
用 32 bit 表示一个无符號整数, 32bit都是 1就是最大数, 等於 2 的 32 次方 -1 = 4294967295
从 0 数到 4294967295 共要 4294967296milli seconds,
等於 4294967296 /1000 /60 /60 小时; 每天有 24小时,
所以等於 4294967296 /1000 /60 /60 / 24 天 = 49.710 天
也就是说, 开机后大约快要 50 天之时 millis( )会归零 !
tsaiwn 发表于 2015-4-5 16:19 static/image/common/back.gif
已解决 ??
Are you sure 没问题 ?
Your code:
为何说原则上millis()溢出归零是没问题,
但是如果程序码没写好则有问题 ! 因为问题並不是出在 millis( ) 归零本身 !
请看以下这 Arduino 的 delay( ) 代码:(正確 )
void delay( unsigned long dtms ){
unsigned long start = millis();
while (millis() - start < dtms);;
} // delay(
以上这程序完全正確, 且即使 millis( ) 溢出归零也不会有问题 !!
但是以下看起来很像的写法则是有问题的: (错误)
void delay( unsigned long dtms ){
unsigned long start = millis();
while (millis() < start + dtms);; // 有问题 !
} // delay(
从数学观点看起来似乎相同,
因为 millis() - start < dtms)
应该就相当於millis() < start + dtms
可是这只在没有 Overflow 之时成立, 因为把左边的 减项移到右边变 加项, 应该对啊 !?
可是,
如果 millis( ) 前进到 Overflow 之时就不相同 !!其实也不是 millis( ) 本身 Overflow 或 RollOver 归零(变成 0)之时出问题!
严格说是当 millis( )前进到 unsigned long 最大数的一半时大约24天半之后就会开始出问题!!
因为它的问题是出在 start + dtms 这运算 !
並不是出在 millis( ) 本身是否 Overflow !!!
先別管为什么 !
直接测试最准啦, 可是如何测试呢?
总不能等到 millis( ) 快要 Overflow 吧,
那要將近 50天ㄟ! (或是等一半 24.8天也受不了!)
其实我们可以在程序中偷改 millis( ),
现在再简单举例说一下如何改:
(a)在你程序最前面写以下这句:
extern unsigned long timer0_millis;
这是宣告说我们要直接存取(访问)纪录 millis( ) 的变量 timer0_millis
(b)想改为接近快要归零或是接近 49.710 天,
这样写:
timer0_millis =-5678;// 就是再过 5.678 秒就会归零
然后你可以立即 Serial.print( millis( ) ); 印出来看看 millis( ) 是多少 !?
(c)想改为接近 unsigned long 的一半或说大约 24.8 天,
阿可以这样:
timer0_millis = 2147483647L -5677;// 再过 5.678 秒就会过一半 !
或是不记得这么长的 2147483647L,
那简单写这样也一样:
timer0_millis = ((unsigned long) -1 ) /2 -5677; //再过 5.678 秒就会过一半 !
如果你不相信,
那就写个简单的 Arduino 程序测试看看吧 :-)
tsaiwn 发表于 2015-4-5 16:30 static/image/common/back.gif
为何说原则上millis()溢出归零是没问题,
但是如果程序码没写好则有问题 ! 因为问题並不是出在...
可否偷改 micros( )的答案呢 ?
答案是当然可以 !
不然要开机后约 71.58 分钟 micros( )才会到很大接近归零也是很久:
4294967296 /1000/1000 /60 分钟 =71.58 分钟
http://arduino.cc/en/Reference/micros
那要如何偷改 micros( )的答案呢 ?
很简单, 只要偷改计算基础的 timer0_overflow_count 即可,
原理就不多说的, 我写了两个函数方便设定为快要溢出或快要到 unsigned long的一半
setMicrosEndBackMs(3250);// 再过大约 3.25秒 micros( )会溢出(相当於71.58分钟)
unsigned long you = micros( ); // 可用 Serial.println(you);看看
setMicrosHalfBackMs(3388); //再过大约3.388 秒 micros( )会过unsigned long的一半(即快要35.79分钟):
unsigned long her = micros( );// 可用 Serial.println(her);看看
两个函数如下, 大家可以直接抄去用即可:
// 71.58分钟倒回 back ms (注意不是 back us)
void setMicrosEndBackMs(unsigned long back) {
extern unsigned long timer0_overflow_count;
back = ( ((unsigned long)(-1))/4/256-2) - back;
cli( ); // 禁止中断
timer0_overflow_count = back;
sei( ); // 允许中断
}
// 35.79分钟倒回 back ms (注意不是 back us)
void setMicrosHalfBackMs(unsigned long back) {
extern unsigned long timer0_overflow_count;
back = ( ((unsigned long)(-1))/4/256-2) / 2 - back;
cli( ); // 禁止中断
timer0_overflow_count = back;
sei( ); // 允许中断
}
页:
[1]