Timer Arduino P10显示和时间计数
各位,我正在使用,Timer Arduino P10显示和时间计数,timer,arduino,dot-matrix,Timer,Arduino,Dot Matrix,各位,我正在使用,P10点阵显示和Arduino Uno。我正在从这个链接使用P10库。我需要在显示模块上显示一小时倒计时。给定的库使用库。所以对于倒计时,我使用的是使用arduino定时器2的库 当我单独运行这两个库时,我在显示器上的滚动是完美的,我的计时器库也会产生一个纯1秒的中断。现在我所做的是在我的项目中添加库,我正在倒计时。但是现在我的MsTimer2突然不能产生纯1秒 这是代码 #include <MsTimer2.h> #include <TimerOne.h&g
P10点阵显示
和Arduino Uno
。我正在从这个链接使用P10库。我需要在显示模块上显示一小时倒计时。给定的库使用库。所以对于倒计时,我使用的是使用arduino定时器2的库
当我单独运行这两个库时,我在显示器上的滚动是完美的,我的计时器库也会产生一个纯1秒的中断。现在我所做的是在我的项目中添加库,我正在倒计时。但是现在我的MsTimer2
突然不能产生纯1秒
这是代码
#include <MsTimer2.h>
#include <TimerOne.h>
#include"SPI.h"
#include <ledP10.h>
LedP10 myled;
uint8_t minute = 0, second = 0, hour = 1;
volatile bool xIsCountDone = false;
volatile bool xIsInterruptOcuured = false;
char time_buff[100];
void setup()
{
Serial.begin(9600);
myled.init(3,4,8,9 ,3);
sprintf((char*)time_buff, " %d%d:%d%d:%d%d", (hour/10), (hour%10),(minute/10), (minute%10),(second/10), (second%10));
Serial.println((char*)time_buff);
myled.showmsg_single_static((char*)time_buff, 0);
xIsInterruptOcuured = false;
//myled.showmsg_single_scroll("this is single led test",2,8,0);
MsTimer2::set(1000, count);
MsTimer2::start();
}
void loop() {
if (xIsInterruptOcuured == true)
{
sprintf((char*)time_buff, " %d%d:%d%d:%d%d", (hour/10), (hour%10),(minute/10), (minute%10),(second/10), (second%10));
Serial.println((char*)time_buff);
myled.showmsg_single_static((char*)time_buff, 0);
xIsInterruptOcuured = false;
}
}
void count(){
second--;
if (second <= 0 || second > 59)
{
second = 59;
minute--;
if (minute <= 0 || minute > 59)
{
minute = 59;
hour--;
if (hour <= 0 || hour > 12)
{
xIsCountDone =true;
}
}
}
Serial.println(millis());
xIsInterruptOcuured = true;
}
在Arduino世界中,一些库正在禁用中断 所有WS2812 LED和您的LED都会出现这种情况。如果不禁用中断,外部设备将出现计时问题 所以,如果您使用另一个将禁用中断的库,则永远不要使用中断或带中断的库 您想使用P10库吗?可以,但不要在代码中使用中断。不要添加其他库,如IR_remote,因为它将无法正常工作 回到你的问题,只需更新循环中的计时器。不要等到一秒钟结束后才更新你的时间1秒钟!这将始终超过1秒 例如,您可以将毫秒转换为秒
seconds=millis()/1000代码>。
您的循环可能是这样的:
void循环(){
currentSeconds=millis()/1000;//获取当前“时间”(实际上是程序启动后的毫秒数)
if(currentSeconds!=savedSeconds)//测试周期是否已过
{
savedSeconds=当前秒数;
Serial.println(millis());
第二--;
如果(第二个59){
秒=59;
分钟--;
若有(第59分钟){
分钟=59;
小时--;
若有(第12小时){
小时=0;
}
}
}
sprintf((char*)time_buff,“%d%d:%d%d:%d%d”,(小时/10),(小时%10),(分钟/10),(分钟%10),(秒/10),(秒%10));
myled.showmsg\u single\u static((char*)time\u buff,0);
}
}
此答案针对您的示例,使用millis()
。通过不设置相对于当前时间的下一次更新,可以避免随着时间的推移累积错误。而是每次增加一秒。这样,主循环是否被中断阻塞了几毫秒并不重要
还请注意,您不必分别节省小时、分钟和秒,您只需计算它们:
unsigned long nextMillis = 1000;
unsigned long targetTime = 1 * 60 * 60 * 1000; // 1 hour in milliseconds
void setup(){
myled.init(3,4,8,9,3);
Serial.begin(9600);
updateMyLed(0);
}
void updateMyLed( unsigned long elapsedTime ){
char buffer[100];
unsigned long timeLeftInSeconds = (targetTime - elapsedTime) / 1000;
uint8_t hour = timeLeftInSeconds / 3600;
timeLeftInSeconds -= hour * 3600;
uint8_t minute = timeLeftInSeconds / 60;
uint8_t second = timeLeftInSeconds - (minute * 60);
sprintf((char*)buffer, " %d%d:%d%d:%d%d", (hour/10), (hour%10), (minute/10), (minute%10), (second/10), (second%10));
myled.showmsg_single_static((char*)buffer, 0);
}
void loop() {
if( millis() >= nextMillis ){
updateMyLed(nextMillis);
nextMillis += 1000;
}
}
我没有时间深入研究你的密码。我懒惰的程序员的建议:买一个实时时钟,这样你就不必担心计时器中断:)更简单的解决方案是使用millis()
函数,因为一小时倒计时不需要实时。@Fitzi使用millis()也不能给出准确的倒计时。12分钟左右有很大的差别。我用秒表测量。@Pigget是的,我有一个备用ds3231,但我想用计时器试试。但是如果什么都没有发生,那将是我唯一的选择。你能举个例子说明你是如何使用米利斯的吗?因为在一个小时的倒计时中休息12分钟很可能是其他问题的结果,这不是不准确的。谢谢你的回答。您使用的逻辑很好,我取消了对它的访问,但为了检查它是否给出了正确的时间,我只使用了Serial.println(millis())在循环中的if语句中,我发现有11.81秒的精确差异。此外,我对ledp10初始化进行了注释,并再次检查,它给出了精确的时间。现在我想我应该更改p10显示的库。所有的问题都发生在这个库中。p10库很可能在内部使用计时器,这会把事情搞砸。但是如果它真的把millis()
函数也弄糟了,那么您应该更改它,是的。您熟悉我正在使用的显示模块的库吗?图书馆不干扰millis()的可能性有多大?我最好切换到ds3231从rtc获取时间。你有什么建议?谢谢你提供的信息。是的,我必须使用p10显示和库,但它可以是p10的任何库,而不是这个库,只要我可以滚动和显示字符串。说到代码,我完全不理解逻辑。您使用了currentSeconds=millis()/1000代码>然后您已选中currentSeconds!=节省的秒数。有很多次我保存的秒数将不等于当前秒数,大多数情况下,条件将为真,显示将更新多次是,抱歉。我更新了代码。您必须保存已保存的秒数。禁用中断的库的主要问题是,您的中断不会每次都执行。在脚本的循环中,您只需检查是否经过了1秒的时间以将时间减少1。但当1.2秒过去时,这也可能是真的。同样在我的例子中,一旦时间超过1秒,就会发生这种情况,但是使用这种方法不会损失任何毫秒。
unsigned long nextMillis = 1000;
unsigned long targetTime = 1 * 60 * 60 * 1000; // 1 hour in milliseconds
void setup(){
myled.init(3,4,8,9,3);
Serial.begin(9600);
updateMyLed(0);
}
void updateMyLed( unsigned long elapsedTime ){
char buffer[100];
unsigned long timeLeftInSeconds = (targetTime - elapsedTime) / 1000;
uint8_t hour = timeLeftInSeconds / 3600;
timeLeftInSeconds -= hour * 3600;
uint8_t minute = timeLeftInSeconds / 60;
uint8_t second = timeLeftInSeconds - (minute * 60);
sprintf((char*)buffer, " %d%d:%d%d:%d%d", (hour/10), (hour%10), (minute/10), (minute%10), (second/10), (second%10));
myled.showmsg_single_static((char*)buffer, 0);
}
void loop() {
if( millis() >= nextMillis ){
updateMyLed(nextMillis);
nextMillis += 1000;
}
}