+2 голосов
Делаю прибор, который будет запускать исполнительное устройство по времени(плата arduino nano). При задании значения переменной h > 9 часы выводят бред(типа 22 часа 15 минут). код прилагаю. При h < 9 все в порядке

#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
const int ledPin = 13;

const int h = 10; //значение часов (проблема здесь!)
const int m = 16; //значение минут

bool Button1WasUp = true;
bool action1 = true;

bool Button2WasUp = true;
bool action2 = false;

bool Button3WasUp = true;
bool action3 = false;

void setup()   {                
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  Serial.begin(9600);
}

void btn1act() {
  bool isbutton1up = !digitalRead(2); //состояние кнопки(инвертиованная логика в силу подтяжки к 5 вольтам в выкл. состоянии
  if (Button1WasUp == true && isbutton1up == true)
  {
    delay(20);    
    if (isbutton1up == true)
    {
      action1 = !action1;
    }
  }
  Button1WasUp == isbutton1up;
}

void btn2act() {
  bool isbutton2up = !digitalRead(3); //состояние кнопки(инвертиованная логика в силу подтяжки к 5 вольтам в выкл. состоянии
  if (Button2WasUp == true && isbutton2up == true)
  {
    delay(20);    
    if (isbutton2up == true)
    {
      action2 = !action2;
    }
  }
  Button2WasUp == isbutton2up;
}

void loop() {
  btn1act();
  btn2act();
  unsigned long sect = millis() / 1000+3600*h + 60*m;
  int hour = (sect / 3600)%24 ;
  int sec = sect  % 60;
  int minute = (sect  / 60)%60 ;
  
    
  display.setTextSize(2);
  if (action1 == true) {
    display.setTextColor(WHITE);
  }
  else {
    display.setTextColor(BLACK);
  }
  display.setCursor(20,10);
  display.print(hour);display.print(":");display.print(minute);display.print(":");display.print(sec);
  display.display();
  delay(500);
  display.clearDisplay();
}
(7 баллов) 1 3

1 Ответ

+3 голосов
 
Лучший ответ

Скорее всего проблема в переполнении типов.

unsigned long sect = millis() / 1000+3600*h + 60*m;
//2^(8*4) unsigned long
  int hour = (sect / 3600)%24 ;
//2^16 int 

1+3600*10+60*16=36961

это больше чем 32768 =2^15 т.к. в типе int крайний левый бит отвечает за знак. Из-за этого у вас были неправильные значения. Попробуйте использовать 

unsigned long sect = millis() / 1000+3600*h + 60*m;
  int hour = int((long)(sect / 3600)%24 );
  long sec = sect  % 60;
  int minute = int((long)(sect  / 60)%60 );
  

Секунды лучше считать в long т.к. при 24часа * 3600с = 86400.

(3.1 тыс. баллов) 15 20 41
выбран
Спасибо! Уже разобрался сам, проблема была именно в переполнении
Добро пожаловать на Бредборд! Сайт вопросов и ответов на тему Arduino, Raspberry Pi и хоббийной электроники в целом. Цель Бредборда — быть максимально полезным. Поэтому мы строго следим за соблюдением правил, боремся с холиворами и оффтопиком.

    За этот месяц ещё никого.

    ...