7- cегментный дисплей для arduino

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, для того, чтобы мигать, их надо для начала к ардуине подключить. Если у Вас два последовательнях, то падения напряжения складываются.

Давайте считать. Падение напряжения на одном диоде - 2.3 (кстати, странно - у синих обычно от 2.5 до 3.7). Значит у двух - 2,3х2 = 4.6. Ардуина выдаёт 5В, значит, если мы хоти ток как у всех - 10мА, на резисторе должно упасть 5-4,6 = 0,4В. Значит резистор нужен 0,4/0,010А = 40 Ом.

Если будете ставить красные, то 1,8Вх2 = 3,6В, на резисторе падает 5-3,6 = 1,4В, резистор нужен 1,4В/0,010А = 140 Ом

Т.е. ставите Катодом на землю, к аноду цепляете резистор, а лругой конец резистора на цфифровой пин. Допусти пин COLON_PIN.

Сделайте пока с делэем, потом обсудим как сделать по уму. Дело в том, что делэи без крайней нужны лучше не задействовать. Обратите внимание, сейча у Вас часы работют с пустым loop (то, что у Вас в loop - чисто для демнострации). так вот лучше, чтобы до последнего так и оставалось. Но пока сделайте с делэем.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Ну, для того, чтобы мигать, их надо для начала к ардуине подключить. Если у Вас два последовательнях, то падения напряжения складываются.

Давайте считать. Падение напряжения на одном диоде - 2.3 (кстати, странно - у синих обычно от 2.5 до 3.7). Значит у двух - 2,3х2 = 4.6. Ардуина выдаёт 5В, значит, если мы хоти ток как у всех - 10мА, на резисторе должно упасть 5-4,6 = 0,4В. Значит резистор нужен 0,4/0,010А = 40 Ом.

Если будете ставить красные, то 1,8Вх2 = 3,6В, на резисторе падает 5-3,6 = 1,4В, резистор нужен 1,4В/0,010А = 140 Ом

Т.е. ставите Катодом на землю, к аноду цепляете резистор, а лругой конец резистора на цфифровой пин. Допусти пин COLON_PIN.

Сделайте пока с делэем, потом обсудим как сделать по уму. Дело в том, что делэи без крайней нужны лучше не задействовать. Обратите внимание, сейча у Вас часы работют с пустым loop (то, что у Вас в loop - чисто для демнострации). так вот лучше, чтобы до последнего так и оставалось. Но пока сделайте с делэем.

да, я уже сделал с делеем.

#define PIN_SVETODIODA 9
void setup() {                
  
  pinMode(PIN_SVETODIODA, OUTPUT);    
}

void loop() {
  digitalWrite(PIN_SVETODIODA, HIGH);   
  delay(1000);              
  digitalWrite(PIN_SVETODIODA, LOW);    
  delay(1000);              
}

 

protone77
Offline
Зарегистрирован: 02.10.2016

вот, я нашел этот скетч, когда гуглил как мигать светодиодом без дилея. 

http://arduino.ru/tutorials/BlinkWithoutDelay



const int ledPin =  13;      // номер выхода, подключенного к светодиоду
// Variables will change:
int ledState = LOW;             // этой переменной устанавливаем состояние светодиода 
long previousMillis = 0;        // храним время последнего переключения светодиода

long interval = 1000;           // интервал между включение/выключением светодиода (1 секунда)

void setup() {
  // задаем режим выхода для порта, подключенного к светодиоду
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  // здесь будет код, который будет работать постоянно
  // и который не должен останавливаться на время между переключениями свето
  unsigned long currentMillis = millis();
 
  //проверяем не прошел ли нужный интервал, если прошел то
  if(currentMillis - previousMillis > interval) {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;  

    // если светодиод не горит, то зажигаем, и наоборот
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // устанавливаем состояния выхода, чтобы включить или выключить светодиод
    digitalWrite(ledPin, ledState);
  }
}

 

protone77
Offline
Зарегистрирован: 02.10.2016

я, кстати, переделал тут немного разводку. Не знаю, какое должно быть расстояние между дорожками и ещё я соеденил некоторые пины(питание и cброс MR ну и землю с OE) регистра дорожками, чтобы было меньше проводов, так можно?

https://drive.google.com/open?id=0Bw68TyJ34XNUUnFxcUV5QVIxTk0

вопрос ещё по контактам, я выставил отверстия диаметром 1мм и 2мм весь контакт, этого хватит?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Расстояние между дорожками пока оставьте не менее 0.2мм, между отверстиями (вернее их контактами) - не менее 0.5, чтобы паять было проще (значит сами контакты вокруг отверстий - не более 2мм. Отвертия 1 мм - очень большие. Для резисторов за глаза хватит 0.7. Для индикатора не знаю, какие у него ножки - возьмите штангельциркуль и померьте. Для микросхемы - там особый случай, ног у неё много, так что как сверлить будете. Если точно и аккуратно, то 0.8 хватит (пинцетиком там по одной ножке подправите - все влезут. если же 0.9, то легче впихнёте. А вообще, Вы ещё смотрите, какие у Вас свёрла есть. Общее правило - чем тоньше дырка, тем труднее пихать, но легче паять. При больших дырках ножки далего от крёв и надо их припоем заливать буквально.

Четрертый справа в верхнем ряду контакт микросхемы у Вас очень близко к дорожке. Дорожку надо сначала пустить вниз, а потом загибать, чтобы она так близко к контакту не подходила.

Вообще, программа умеет сама проверять такие вещи. Там справа вверху есть несколько иконок. Найдите с надписью DRC. зайдите, выставьте параметры (тима минимальное расстояние между дорожками - 0.2 и т.п., а потом запустите проверку. Она будет искать ошибки на плате.

Микросхему лучше нарисовать на верхнем слое с кружочком (он на корпусе есть), чтобы Вы не перепутали как её паять и вверх ногами не запаяли. Да и ножки подписать не помешает. Вот она, Ваша микросхема уже готовая - добавьте в библиотеку и пользуйтесь. Индикатор лучше тоже нарисовать и и подписать ножки также, как микросхему.

Что касется дорожек  - не можно, а нужно. В идеале на плате не должно быть проводов вообще - всё дорожками.

 

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Расстояние между дорожками пока оставьте не менее 0.2мм, между отверстиями (вернее их контактами) - не менее 0.5, чтобы паять было проще (значит сами контакты вокруг отверстий - не более 2мм. Отвертия 1 мм - очень большие. Для резисторов за глаза хватит 0.7. Для индикатора не знаю, какие у него ножки - возьмите штангельциркуль и померьте. Для микросхемы - там особый случай, ног у неё много, так что как сверлить будете. Если точно и аккуратно, то 0.8 хватит (пинцетиком там по одной ножке подправите - все влезут. если же 0.9, то легче впихнёте. А вообще, Вы ещё смотрите, какие у Вас свёрла есть. Общее правило - чем тоньше дырка, тем труднее пихать, но легче паять. При больших дырках ножки далего от крёв и надо их припоем заливать буквально.

Четрертый справа в верхнем ряду контакт микросхемы у Вас очень близко к дорожке. Дорожку надо сначала пустить вниз, а потом загибать, чтобы она так близко к контакту не подходила.

Вообще, программа умеет сама проверять такие вещи. Там справа вверху есть несколько иконок. Найдите с надписью DRC. зайдите, выставьте параметры (тима минимальное расстояние между дорожками - 0.2 и т.п., а потом запустите проверку. Она будет искать ошибки на плате.

Микросхему лучше нарисовать на верхнем слое с кружочком (он на корпусе есть), чтобы Вы не перепутали как её паять и вверх ногами не запаяли. Да и ножки подписать не помешает. Вот она, Ваша микросхема уже готовая - добавьте в библиотеку и пользуйтесь. Индикатор лучше тоже нарисовать и и подписать ножки также, как микросхему.

Что касется дорожек  - не можно, а нужно. В идеале на плате не должно быть проводов вообще - всё дорожками.

 

сверла пока вообще из размеров 1мм-0.7 нету, только большие. 

По поводу микросхемы, закинул её в папку с макросами, открываю библиотеку она её видит, но самой микросхемы нету. Мне впринципе не обязательно обозначать,как паять эту микросхему там всё понятно, врятли перепутаю)

про 4 контакт справа не понял? вроде с ним всё нормально 

вы про этот?

или про самый первый?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, про этот. Во вчерашнем варианте он шёл не вниз, а сразу наискосок.

Не видит нарисованного красным цветом? Значит у Вас выключен слой К1. Слои внизу окна слева. Посмотрите, если зачёркнут, нажмите на букву.

Подписанные контакты всегда хорошо - разводить легче.

Про свёрла ... а чем сверлить собираетесь?

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Да, про этот. Во вчерашнем варианте он шёл не вниз, а сразу наискосок.

Не видит нарисованного красным цветом? Значит у Вас выключен слой К1. Слои внизу окна слева. Посмотрите, если зачёркнут, нажмите на букву.

Подписанные контакты всегда хорошо - разводить легче.

Про свёрла ... а чем сверлить собираетесь?

нет, когда нажимаешь в библиотеке на элемент он появляется в черном окошке и оттуда перетянуть на плату, вот он там не появляется.

Ок подпишу контакты

Про сверла, я собирался вытравить первым делом, а потом докупить их

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Наверное у нас разные версии спринтлэаута.

Ну сами рисуйте библиотечные элементы - это полезно. Я рисую всякий раз, когда использую новую деталь

protone77
Offline
Зарегистрирован: 02.10.2016

вот я тут немного подправил свою схему, все отверстия сделал 0.7 и просто разьемы в них вставлю, а в них уже регистр и т.д

https://drive.google.com/open?id=0Bw68TyJ34XNUM0hPWGlGbHoybWs

и сейчас запустил часы и у меня интересная проблема появилась, они спешат на 2 часа 10 минут, чтобы я ни делал. Запускал их отдельным скетчем без сегментов и тд. Всеравно спешат.

В мониторе порта тоже время неправильное, не знаю даже из-за чего

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Разъёмы? Тогда может 0.8 надо. У меня в 0.7 с трудом лезут :(

Поясните толком, что значит "спешат на 2 часа 10 минут"? Вы их устанавливаете и они уже сразу же спешат? Или через сутки? Или как это выглядит?

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Разъёмы? Тогда может 0.8 надо. У меня в 0.7 с трудом лезут :(

Поясните толком, что значит "спешат на 2 часа 10 минут"? Вы их устанавливаете и они уже сразу же спешат? Или через сутки? Или как это выглядит?

ок, будет 0.8

Да,сразу как гаружаю скетч в плату спешат на 2ч 10 минут

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, нет. Вы попробуйте их установить правильно и посмотрите как быстро "ухлдят". так чего, ну спеаши и спешат себе.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Да, нет. Вы попробуйте их установить правильно и посмотрите как быстро "ухлдят". так чего, ну спеаши и спешат себе.

что значит установить их правильно? вручную?

я в сетап 2 строчки добавил 

Clock.setHour(19);
Clock.setMinute(10);
завтра скажу, отстают они или нет
protone77
Offline
Зарегистрирован: 02.10.2016

ничего не отстало, но если так устанавливать время, то при каждом подключении ардуины к пк время будет выставляться, которые задано в сетапе? до этого же выставлялось автоматом время компиляции скетча в часах,да? вот с этим скетчем время начинается с 00:00, если не устанавливать вручную

#include <Wire.h> 
#include <SPI.h> 
#include "DHT.h" 
#include <DS3231.h>
#include <Adafruit_Sensor.h>

#define PIN_SQW 3
#define DHTPIN 2 
#define DHTTYPE DHT11 


static DS3231 Clock;
DHT dht(DHTPIN, DHTTYPE);

#define LATCH_PIN 10

#define SEG_A 0b10111111 
#define SEG_B 0b11011111 
#define SEG_C 0b11101111 
#define SEG_D 0b11110111 
#define SEG_E 0b11111011 
#define SEG_F 0b11111101 
#define SEG_G 0b11111110 
#define SYMBOL_0 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_1 (SEG_B & SEG_C) 
#define SYMBOL_2 (SEG_A & SEG_B & SEG_D & SEG_E & SEG_G) 
#define SYMBOL_3 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_G) 
#define SYMBOL_4 (SEG_B & SEG_C & SEG_F & SEG_G) 
#define SYMBOL_5 (SEG_A & SEG_C & SEG_D & SEG_F & SEG_G) 
#define SYMBOL_6 (SEG_A & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_7 (SEG_A & SEG_B & SEG_C) 
#define SYMBOL_8 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_9 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_F & SEG_G)  
#define SYMBOL_C (SEG_A & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_H (SEG_F & SEG_G & SEG_E & SEG_B & SEG_C) 
#define SYMBOL_grad (SEG_A & SEG_F & SEG_G & SEG_B)
#define SYMBOL_EMPTY  0xFF

volatile static const uint8_t allDigits[] = { SYMBOL_0, SYMBOL_1,SYMBOL_2,SYMBOL_3,SYMBOL_4,SYMBOL_5,SYMBOL_6,SYMBOL_7,SYMBOL_8,SYMBOL_9};

volatile static uint8_t clockScreen[4];  // Экран для часов
volatile static uint8_t temperatureScreen[4];  // Экран для температуры
volatile static uint8_t humidityScreen[4]; // Экран для влажности

static uint8_t * physicalScreen = clockScreen; // физический экран - просто указатель на виртуальный


void showOnScreen(const uint8_t *screen) {
  if (screen != physicalScreen) return;
  digitalWrite(LATCH_PIN, LOW);
  SPI.beginTransaction(SPISettings(F_CPU/2, LSBFIRST, SPI_MODE0)); 
  SPI.transfer(physicalScreen[0]); 
  SPI.transfer(physicalScreen[1]); 
  SPI.transfer(physicalScreen[2]); 
  SPI.transfer(physicalScreen[3]); 
  digitalWrite(LATCH_PIN, HIGH); 
  SPI.endTransaction();
}

static inline void fillUpScreen(volatile uint8_t * screen, 
      const uint8_t s0 = SYMBOL_EMPTY,  const uint8_t s1 = SYMBOL_EMPTY,  
      const uint8_t s2 = SYMBOL_EMPTY,  const uint8_t s3 = SYMBOL_EMPTY) {
  screen[0] = s0;
  screen[1] = s1;
  screen[2] = s2;
  screen[3] = s3;
  showOnScreen(screen);
}

void time2Screen(uint8_t h, uint8_t m) {
  fillUpScreen(clockScreen, allDigits[m % 10], allDigits[m / 10], allDigits[h % 10], allDigits[h / 10]);
}

void temperature2Screen(uint8_t t) {
  fillUpScreen(temperatureScreen,SYMBOL_C, SYMBOL_grad,  allDigits[t % 10], allDigits[t / 10]);
}

void humidity2Screen(uint8_t h) {
  fillUpScreen(humidityScreen, SYMBOL_H,SYMBOL_EMPTY, allDigits[h % 10], allDigits[h / 10]);
}

static inline void activateScreen(volatile uint8_t * screen) {
  physicalScreen = screen;
  showOnScreen(physicalScreen);
}

void activateClockScreen(void) { 
  activateScreen(clockScreen);
}

void activateTemperatureScreen(void) { 
  activateScreen(temperatureScreen);
}

void activateHumidityScreen(void) { 
  activateScreen(humidityScreen);
}


static void everyMinuteAlarm(void) {
  const byte oldSReg = SREG;
  sei();
  time2Screen(Clock.getHour(), Clock.getMinute());
  temperature2Screen(dht.readTemperature());
  humidity2Screen(dht.readHumidity());
  Clock.clearAlarmSignal(2);
  SREG = oldSReg;
}

  
void setup(void) {
  pinMode(PIN_SQW, INPUT);
  Serial.begin(115200);
  SPI.begin(); 
  dht.begin();
  Wire.begin();
  Clock.setClockMode(false);  // Часы в 24-часовом режиме. Нужен 12-ти - пишем true
  Clock.turnOffAlarm(2);  //  Для очистки совести, мы не знаем что там часы делают
  Clock.EnableMinuteInterrupt();  // включаем ежеминутное прерывание
  attachInterrupt(PIN_SQW - 2, everyMinuteAlarm, FALLING);  // собираемся его обрабатывать
  delay(10);  // на всякий случай, пусть всё устаканится.
  everyMinuteAlarm(); // Вызовем сразу, чтобы часы начали показываться сразу, а не ждали до начала минуты.
  
 
}

void loop(void) {
  static const unsigned long interScreenDeley = 5000;
  delay(interScreenDeley);
  activateTemperatureScreen(); 
  delay(interScreenDeley);
  activateHumidityScreen(); 
  delay(interScreenDeley);
  activateClockScreen(); 
  delay(interScreenDeley);
  
}

 






 

protone77
Offline
Зарегистрирован: 02.10.2016

.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

protone77 пишет:

ничего не отстало, но если так устанавливать время, то при каждом подключении ардуины к пк время будет выставляться, которые задано в сетапе? до этого же выставлялось автоматом время компиляции скетча в часах,да? вот с этим скетчем время начинается с 00:00, если не устанавливать вручную

Что-то у Вас каша в голове.

1. Если Вы один раз выставите время и никогда не будете снимать батарейку с модуля часов (и не будете допускать её критического разряда), то оно там будет правильным всегда.

2. Никакого отношения к времени компиляции это не имеет

3. Если батарея критичиски села (или была вытащена), то время надо переустанавливать заново.

4. При критической просадке батареи часы переходят в сверэкономичный режим с выключенным осциллятором. В этом режиме часы идут только при внешнем питании, а без такового - стоят). Если они перешли в такой режим, то осциллятор надо включить (выйти из этого режима)  ручками иначе часы будут замирать всякий раз при выключении внешнего питания. Я всегда включаю в сетапе не глядя было там выключено или нет.

5. Если хотите вообще забыть о ручной установке времени , добавьте в конструкцию модуль ESP01 (если дома Wi-fi есть) и поставьте в тот же сетап установки времени из Интернета с NTP сервера. У меня так и сделано.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

protone77 пишет:

ничего не отстало, но если так устанавливать время, то при каждом подключении ардуины к пк время будет выставляться, которые задано в сетапе? до этого же выставлялось автоматом время компиляции скетча в часах,да? вот с этим скетчем время начинается с 00:00, если не устанавливать вручную

Что-то у Вас каша в голове.

1. Если Вы один раз выставите время и никогда не будете снимать батарейку с модуля часов (и не будете допускать её критического разряда), то оно там будет правильным всегда.

2. Никакого отношения к времени компиляции это не имеет

3. Если батарея критичиски села (или была вытащена), то время надо переустанавливать заново.

4. При критической просадке батареи часы переходят в сверэкономичный режим с выключенным осциллятором. В этом режиме часы идут только при внешнем питании, а без такового - стоят). Если они перешли в такой режим, то осциллятор надо включить (выйти из этого режима)  ручками иначе часы будут замирать всякий раз при выключении внешнего питания. Я всегда включаю в сетапе не глядя было там выключено или нет.

5. Если хотите вообще забыть о ручной установке времени , добавьте в конструкцию модуль ESP01 (если дома Wi-fi есть) и поставьте в тот же сетап установки времени из Интернета с NTP сервера. У меня так и сделано.

1. да, но если я достану сейчас из свой ардуины провод питания и заного вставлю, то скетч же ресетится там?(а в скетче у меня вручную установлено время) получается , если я сделаю чтобы всё работало от розетки,  будет то же самое?

2. а как изначально часы узнают какое время ,допустим, в примере который вы скидывали? там же не ручная установка

4 а как его включить?

5 подумаю над этим

protone77
Offline
Зарегистрирован: 02.10.2016

кстати, хотел спросить про двоеточие. Допустим я буду использовать блинк, но как сделать или какую команду использовать, чтобы  светодиоды мигали только в тот момент, когда идёт время. Пытался делать через иф,элс. Но выдавало ошибку.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

protone77 пишет:

если я достану сейчас из свой ардуины провод питания и заного вставлю, то скетч же ресетится там?(а в скетче у меня вручную установлено время) получается , если я сделаю чтобы всё работало от розетки,  будет то же самое?

Конечно. В сетапе можно устанавливать фиксированное время только при отладке. В реальном устройстве этого делать нельзя иначе он при каждом включении питания часы будут с этого времени стартовать. Если в часах есть батарея, то они сами время знают.

protone77 пишет:

а как изначально часы узнают какое время ,допустим, в примере который вы скидывали? там же не ручная установка

Никак. В том примере они будут показывать то, что у них там есть (на что раньше были установлены). Им просто неоткуда узнать время.

protone77 пишет:

4 а как его включить?

Давайте это пока оставим в покое. Пока ставьте фиксированное время  в сетупе и не парьтесь. При написании итогового скетча разберёмся.

protone77 пишет:
как сделать или какую команду использовать, чтобы  светодиоды мигали только в тот момент, когда идёт время.

Я не понял этой фразы. Что значит "идёт время"? Время изменяется на экране раз в минуту. Мигать одно должно (на мой взгляд) с периодом в 1 сек (полсекунды горит, полсекунды - нет), а что Вы имели в виду?

 

protone77
Offline
Зарегистрирован: 02.10.2016

имелл в виду, когда она показано на дисплее, как будет мигать, это уже буду смотреть, когда соберу, чтобы смотрелось красиво, а то частое мигание напрягать глаза в темноте может

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Оно показано на дисплее тогда, когда активен виртуальный экран времени. Вот и проверяйте это. Если не знаете как. выложите текущий скетч как он у Вас есть.

protone77
Offline
Зарегистрирован: 02.10.2016
#include <Wire.h> 
#include <SPI.h> 
#include "DHT.h" 
#include <DS3231.h>
#include <Adafruit_Sensor.h>

#define PIN_SQW 3
#define DHTPIN 2 
#define DHTTYPE DHT11 


static DS3231 Clock;
DHT dht(DHTPIN, DHTTYPE);

#define LATCH_PIN 10

#define SEG_A 0b10111111 
#define SEG_B 0b11011111 
#define SEG_C 0b11101111 
#define SEG_D 0b11110111 
#define SEG_E 0b11111011 
#define SEG_F 0b11111101 
#define SEG_G 0b11111110 
#define SYMBOL_0 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_1 (SEG_B & SEG_C) 
#define SYMBOL_2 (SEG_A & SEG_B & SEG_D & SEG_E & SEG_G) 
#define SYMBOL_3 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_G) 
#define SYMBOL_4 (SEG_B & SEG_C & SEG_F & SEG_G) 
#define SYMBOL_5 (SEG_A & SEG_C & SEG_D & SEG_F & SEG_G) 
#define SYMBOL_6 (SEG_A & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_7 (SEG_A & SEG_B & SEG_C) 
#define SYMBOL_8 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_9 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_F & SEG_G)  
#define SYMBOL_C (SEG_A & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_H (SEG_F & SEG_G & SEG_E & SEG_B & SEG_C) 
#define SYMBOL_grad (SEG_A & SEG_F & SEG_G & SEG_B)
#define SYMBOL_EMPTY  0xFF

volatile static const uint8_t allDigits[] = { SYMBOL_0, SYMBOL_1,SYMBOL_2,SYMBOL_3,SYMBOL_4,SYMBOL_5,SYMBOL_6,SYMBOL_7,SYMBOL_8,SYMBOL_9};

volatile static uint8_t clockScreen[4];  // Экран для часов
volatile static uint8_t temperatureScreen[4];  // Экран для температуры
volatile static uint8_t humidityScreen[4]; // Экран для влажности

static uint8_t * physicalScreen = clockScreen; // физический экран - просто указатель на виртуальный


void showOnScreen(const uint8_t *screen) {
  if (screen != physicalScreen) return;
  digitalWrite(LATCH_PIN, LOW);
  SPI.beginTransaction(SPISettings(F_CPU/2, LSBFIRST, SPI_MODE0)); 
  SPI.transfer(physicalScreen[0]); 
  SPI.transfer(physicalScreen[1]); 
  SPI.transfer(physicalScreen[2]); 
  SPI.transfer(physicalScreen[3]); 
  digitalWrite(LATCH_PIN, HIGH); 
  SPI.endTransaction();
}

static inline void fillUpScreen(volatile uint8_t * screen, 
      const uint8_t s0 = SYMBOL_EMPTY,  const uint8_t s1 = SYMBOL_EMPTY,  
      const uint8_t s2 = SYMBOL_EMPTY,  const uint8_t s3 = SYMBOL_EMPTY) {
  screen[0] = s0;
  screen[1] = s1;
  screen[2] = s2;
  screen[3] = s3;
  showOnScreen(screen);
}

void time2Screen(uint8_t h, uint8_t m) {
  fillUpScreen(clockScreen, allDigits[m % 10], allDigits[m / 10], allDigits[h % 10], allDigits[h / 10]);
}

void temperature2Screen(uint8_t t) {
  fillUpScreen(temperatureScreen,SYMBOL_C, SYMBOL_grad,  allDigits[t % 10], allDigits[t / 10]);
}

void humidity2Screen(uint8_t h) {
  fillUpScreen(humidityScreen, SYMBOL_H,SYMBOL_EMPTY, allDigits[h % 10], allDigits[h / 10]);
}

static inline void activateScreen(volatile uint8_t * screen) {
  physicalScreen = screen;
  showOnScreen(physicalScreen);
}

void activateClockScreen(void) { 
  activateScreen(clockScreen);
}

void activateTemperatureScreen(void) { 
  activateScreen(temperatureScreen);
}

void activateHumidityScreen(void) { 
  activateScreen(humidityScreen);
}


static void everyMinuteAlarm(void) {
  const byte oldSReg = SREG;
  sei();
  time2Screen(Clock.getHour(), Clock.getMinute());
  temperature2Screen(dht.readTemperature());
  humidity2Screen(dht.readHumidity());
  Clock.clearAlarmSignal(2);
  SREG = oldSReg;
}

  
void setup(void) {
  pinMode(PIN_SQW, INPUT);
  Serial.begin(115200);
  SPI.begin(); 
  dht.begin();
  Wire.begin();
  Clock.setClockMode(false);  // Часы в 24-часовом режиме. Нужен 12-ти - пишем true
  Clock.turnOffAlarm(2);  //  Для очистки совести, мы не знаем что там часы делают
  Clock.EnableMinuteInterrupt();  // включаем ежеминутное прерывание
  attachInterrupt(PIN_SQW - 2, everyMinuteAlarm, FALLING);  // собираемся его обрабатывать
  delay(10);  // на всякий случай, пусть всё устаканится.
  everyMinuteAlarm(); // Вызовем сразу, чтобы часы начали показываться сразу, а не ждали до начала минуты.
  Clock.setHour(13);
  Clock.setMinute(01);
 
}

void loop(void) {
  static const unsigned long interScreenDeley = 5000;
  delay(interScreenDeley);
  activateTemperatureScreen(); 
  delay(interScreenDeley);
  activateHumidityScreen(); 
  delay(interScreenDeley);
  activateClockScreen(); 
  delay(interScreenDeley);
  
}

 

 

 

 
 
 
 
 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ой, блин. Я ж просил его на части разбить и всё связанное с экраном вынести, чтоы не таксать за собой такую ортянку.

Ну ладно.

Так и какие проблемы. Что собственно сделать надо? Давайте по пунктам.

1. Заводим флаг isClockScreenActive. Флаг должен быть true, если активен экран часов и false в противночм случае.

2. При деактивации любого экрана, сбрасваем этот флаг в false и гасим двоеточие (если он вдруг горит)

3. При активации экрана часов ставим это флаг в true

Собственно все. Как только мы это сделаем, мы можем ВСЁ связанное с миагнием заключать внутрь

if (isClockScreenActive) {
   // здесь всё связанное с миганием
}

и всё будет нормально.

Ну, давайте это делать. Также по пунктам

1. Перед строкой 82 вставляем

bool isClockScreenActive = true; // true потому что при включении у нас экран часов сразу активен

2. после строки 82 вставляем две строки

isClockScreenActive = false;
... // погасить двоеточие - не знаю каким digitalWrite Вы это делаете, сделайте как надо

3. После строки 88 вставляем

isClockScreenActive = true;

Вот и всё. теперь всё связанное с миганием заключайте в условие, как я выше написал и всё будет нормально.

protone77
Offline
Зарегистрирован: 02.10.2016

вот код, я , конечно, намудрил что-то. Светодиод не мигает, а просто горит. Но горит только, когда идёт время, тоесть проблема  в коде для светодиода, но я его просто копировал из блинка.Я сначала подумал что 2 вот этих unsigned long переменных вместе не хотят работать, но  нет:(



#include <Wire.h> 
#include <SPI.h> 
#include "DHT.h" 
#include <DS3231.h>
#include <Adafruit_Sensor.h>

#define PIN_SQW 3
#define DHTPIN 2 
#define DHTTYPE DHT11 
const int ledPin =  9;      
int ledState = LOW;             
long previousMillis = 0;        
long interval = 1000;    


static DS3231 Clock;
DHT dht(DHTPIN, DHTTYPE);

#define LATCH_PIN 10

#define SEG_A 0b10111111 
#define SEG_B 0b11011111 
#define SEG_C 0b11101111 
#define SEG_D 0b11110111 
#define SEG_E 0b11111011 
#define SEG_F 0b11111101 
#define SEG_G 0b11111110 
#define SYMBOL_0 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_1 (SEG_B & SEG_C) 
#define SYMBOL_2 (SEG_A & SEG_B & SEG_D & SEG_E & SEG_G) 
#define SYMBOL_3 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_G) 
#define SYMBOL_4 (SEG_B & SEG_C & SEG_F & SEG_G) 
#define SYMBOL_5 (SEG_A & SEG_C & SEG_D & SEG_F & SEG_G) 
#define SYMBOL_6 (SEG_A & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_7 (SEG_A & SEG_B & SEG_C) 
#define SYMBOL_8 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_9 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_F & SEG_G)  
#define SYMBOL_C (SEG_A & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_H (SEG_F & SEG_G & SEG_E & SEG_B & SEG_C) 
#define SYMBOL_grad (SEG_A & SEG_F & SEG_G & SEG_B)
#define SYMBOL_EMPTY  0xFF

volatile static const uint8_t allDigits[] = { SYMBOL_0, SYMBOL_1,SYMBOL_2,SYMBOL_3,SYMBOL_4,SYMBOL_5,SYMBOL_6,SYMBOL_7,SYMBOL_8,SYMBOL_9};

volatile static uint8_t clockScreen[4];  // Экран для часов
volatile static uint8_t temperatureScreen[4];  // Экран для температуры
volatile static uint8_t humidityScreen[4]; // Экран для влажности

static uint8_t * physicalScreen = clockScreen; // физический экран - просто указатель на виртуальный


void showOnScreen(const uint8_t *screen) {
  if (screen != physicalScreen) return;
  digitalWrite(LATCH_PIN, LOW);
  SPI.beginTransaction(SPISettings(F_CPU/2, LSBFIRST, SPI_MODE0)); 
  SPI.transfer(physicalScreen[0]); 
  SPI.transfer(physicalScreen[1]); 
  SPI.transfer(physicalScreen[2]); 
  SPI.transfer(physicalScreen[3]); 
  digitalWrite(LATCH_PIN, HIGH); 
  SPI.endTransaction();
}

static inline void fillUpScreen(volatile uint8_t * screen, 
      const uint8_t s0 = SYMBOL_EMPTY,  const uint8_t s1 = SYMBOL_EMPTY,  
      const uint8_t s2 = SYMBOL_EMPTY,  const uint8_t s3 = SYMBOL_EMPTY) {
  screen[0] = s0;
  screen[1] = s1;
  screen[2] = s2;
  screen[3] = s3;
  showOnScreen(screen);
}

void time2Screen(uint8_t h, uint8_t m) {
  fillUpScreen(clockScreen, allDigits[m % 10], allDigits[m / 10], allDigits[h % 10], allDigits[h / 10]);
}

void temperature2Screen(uint8_t t) {
  fillUpScreen(temperatureScreen,SYMBOL_C, SYMBOL_grad,  allDigits[t % 10], allDigits[t / 10]);
}

void humidity2Screen(uint8_t h) {
  fillUpScreen(humidityScreen, SYMBOL_H,SYMBOL_EMPTY, allDigits[h % 10], allDigits[h / 10]);
}
bool isClockScreenActive = true;
static inline void activateScreen(volatile uint8_t * screen) {
  isClockScreenActive = false;
  ledState = LOW;
  digitalWrite(ledPin, ledState);
  physicalScreen = screen;
  showOnScreen(physicalScreen);
}

void activateClockScreen(void) { 
  activateScreen(clockScreen);
  isClockScreenActive = true;
}

void activateTemperatureScreen(void) { 
  activateScreen(temperatureScreen);
}

void activateHumidityScreen(void) { 
  activateScreen(humidityScreen);
}


static void everyMinuteAlarm(void) {
  const byte oldSReg = SREG;
  sei();
  time2Screen(Clock.getHour(), Clock.getMinute());
  temperature2Screen(dht.readTemperature());
  humidity2Screen(dht.readHumidity());
  Clock.clearAlarmSignal(2);
  SREG = oldSReg;
}

void svetodiod() {if (isClockScreenActive) {
  unsigned long currentMillis = millis(); 
  if(currentMillis - previousMillis > interval) {   
    previousMillis = currentMillis; 
    if (ledState == LOW)
      ledState = HIGH;
      else
      ledState = LOW;    
    digitalWrite(ledPin, ledState);
  } 
}}

  
void setup(void) {
    pinMode(ledPin, OUTPUT);
     
  pinMode(PIN_SQW, INPUT);
  Serial.begin(115200);
  SPI.begin(); 
  dht.begin();
  Wire.begin();
  Clock.setClockMode(false);  // Часы в 24-часовом режиме. Нужен 12-ти - пишем true
  Clock.turnOffAlarm(2);  //  Для очистки совести, мы не знаем что там часы делают
  Clock.EnableMinuteInterrupt();  // включаем ежеминутное прерывание
  attachInterrupt(PIN_SQW - 2, everyMinuteAlarm, FALLING);  // собираемся его обрабатывать
  delay(10);  // на всякий случай, пусть всё устаканится.
  everyMinuteAlarm(); // Вызовем сразу, чтобы часы начали показываться сразу, а не ждали до начала минуты.
  Clock.setHour(14);
  Clock.setMinute(05);
 
}

void loop(void) {  
  static const unsigned long interScreenDeley = 5000;
  delay(interScreenDeley);
  activateTemperatureScreen(); 
  delay(interScreenDeley);
  activateHumidityScreen(); 
  delay(interScreenDeley);
  activateClockScreen(); 
  
   svetodiod();
   
}
  
  





            



 
  
     






 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, тот самый случай - о вреде неправильного использования delay.

Проведите пальцем по по строкам функции loop и чётко проговаривайте что каждася строка делает. Только внимательно и честно сами себе проговаривайте. И поймёте, что она у Вас в delay сидит всё время, вместо того, чтобы функцию svetodiod постоянно вызывать.

Замечания общего характера о тех местах, где "формально всё правильно, но лучше делать не так"  нужны?

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

 

Замечания общего характера о тех местах, где "формально всё правильно, но лучше делать не так"  нужны?

давайте, я сейчас как раз ухожу и вечером разберусь

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Ну, тот самый случай - о вреде неправильного использования delay.

Проведите пальцем по по строкам функции loop и чётко проговаривайте что каждася строка делает. Только внимательно и честно сами себе проговаривайте. И поймёте, что она у Вас в delay сидит всё время, вместо того, чтобы функцию svetodiod постоянно вызывать.

Замечания общего характера о тех местах, где "формально всё правильно, но лучше делать не так"  нужны?

а как можно избавится от этого дилея?

protone77
Offline
Зарегистрирован: 02.10.2016
#include <Wire.h> 
#include <SPI.h> 
#include "DHT.h" 
#include <DS3231.h>
#include <Adafruit_Sensor.h>

#define PIN_SQW 3
#define DHTPIN 2 
#define DHTTYPE DHT11 
const int ledPin =  9;      
int ledState = LOW;             
long previousMillis = 0;        
long interval = 1000;    


static DS3231 Clock;
DHT dht(DHTPIN, DHTTYPE);

#define LATCH_PIN 10

#define SEG_A 0b10111111 
#define SEG_B 0b11011111 
#define SEG_C 0b11101111 
#define SEG_D 0b11110111 
#define SEG_E 0b11111011 
#define SEG_F 0b11111101 
#define SEG_G 0b11111110 
#define SYMBOL_0 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_1 (SEG_B & SEG_C) 
#define SYMBOL_2 (SEG_A & SEG_B & SEG_D & SEG_E & SEG_G) 
#define SYMBOL_3 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_G) 
#define SYMBOL_4 (SEG_B & SEG_C & SEG_F & SEG_G) 
#define SYMBOL_5 (SEG_A & SEG_C & SEG_D & SEG_F & SEG_G) 
#define SYMBOL_6 (SEG_A & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_7 (SEG_A & SEG_B & SEG_C) 
#define SYMBOL_8 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_9 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_F & SEG_G)  
#define SYMBOL_C (SEG_A & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_H (SEG_F & SEG_G & SEG_E & SEG_B & SEG_C) 
#define SYMBOL_grad (SEG_A & SEG_F & SEG_G & SEG_B)
#define SYMBOL_EMPTY  0xFF

volatile static const uint8_t allDigits[] = { SYMBOL_0, SYMBOL_1,SYMBOL_2,SYMBOL_3,SYMBOL_4,SYMBOL_5,SYMBOL_6,SYMBOL_7,SYMBOL_8,SYMBOL_9};

volatile static uint8_t clockScreen[4];  
volatile static uint8_t temperatureScreen[4]; 
volatile static uint8_t humidityScreen[4]; 

static uint8_t * physicalScreen = clockScreen; 


void showOnScreen(const uint8_t *screen) {
  if (screen != physicalScreen) return;
  digitalWrite(LATCH_PIN, LOW);
  SPI.beginTransaction(SPISettings(F_CPU/2, LSBFIRST, SPI_MODE0)); 
  SPI.transfer(physicalScreen[0]); 
  SPI.transfer(physicalScreen[1]); 
  SPI.transfer(physicalScreen[2]); 
  SPI.transfer(physicalScreen[3]); 
  digitalWrite(LATCH_PIN, HIGH); 
  SPI.endTransaction();
}

static inline void fillUpScreen(volatile uint8_t * screen, 
      const uint8_t s0 = SYMBOL_EMPTY,  const uint8_t s1 = SYMBOL_EMPTY,  
      const uint8_t s2 = SYMBOL_EMPTY,  const uint8_t s3 = SYMBOL_EMPTY) {
  screen[0] = s0;
  screen[1] = s1;
  screen[2] = s2;
  screen[3] = s3;
  showOnScreen(screen);
}

void time2Screen(uint8_t h, uint8_t m) {
  fillUpScreen(clockScreen, allDigits[m % 10], allDigits[m / 10], allDigits[h % 10], allDigits[h / 10]);
}

void temperature2Screen(uint8_t t) {
  fillUpScreen(temperatureScreen,SYMBOL_C, SYMBOL_grad,  allDigits[t % 10], allDigits[t / 10]);
}

void humidity2Screen(uint8_t h) {
  fillUpScreen(humidityScreen, SYMBOL_H,SYMBOL_EMPTY, allDigits[h % 10], allDigits[h / 10]);
}
bool isClockScreenActive = true;
static inline void activateScreen(volatile uint8_t * screen) {
  isClockScreenActive = false;
  ledState = LOW;
  digitalWrite(ledPin, ledState);
  physicalScreen = screen;
  showOnScreen(physicalScreen);
}

void activateClockScreen(void) { 
  activateScreen(clockScreen);
  isClockScreenActive = true;
}

void activateTemperatureScreen(void) { 
  activateScreen(temperatureScreen);
}

void activateHumidityScreen(void) { 
  activateScreen(humidityScreen);
}


static void everyMinuteAlarm(void) {
  const byte oldSReg = SREG;
  sei();
  time2Screen(Clock.getHour(), Clock.getMinute());
  temperature2Screen(dht.readTemperature());
  humidity2Screen(dht.readHumidity());
  Clock.clearAlarmSignal(2);
  SREG = oldSReg;
}

void svetodiod() {if (isClockScreenActive) {
  unsigned long currentMillis = millis(); 
  if(currentMillis - previousMillis > interval) {   
    previousMillis = currentMillis; 
    if (ledState == LOW)
      ledState = HIGH;
      else
      ledState = LOW;    
    digitalWrite(ledPin, ledState);
  } 
}}

  
void setup(void) {
  pinMode(ledPin, OUTPUT); 
  pinMode(PIN_SQW, INPUT);
  Serial.begin(115200);
  SPI.begin(); 
  dht.begin();
  Wire.begin();
  Clock.setClockMode(false);  
  Clock.turnOffAlarm(2); 
  Clock.EnableMinuteInterrupt();  
  attachInterrupt(PIN_SQW - 2, everyMinuteAlarm, FALLING);  
  delay(10);  
  everyMinuteAlarm();
  Clock.setHour(23);
  Clock.setMinute(03);
 
}

void loop(void) {  
  
  if(millis() - previousMillis > 15000) {   
    activateTemperatureScreen();     
    }
  if(millis() - previousMillis > 10000) {   
    activateHumidityScreen(); 
    }
  if(millis() - previousMillis > 5000) {   
     activateClockScreen();
    }
  
  svetodiod();
   
}

вот, попробовал через millis, но не переключается на другие экраны, только время показано..Зато светодиод мигает:) 

p.s я тут решил начать читать книгу про C, чтобы разбираться хоть немного.

http://www.programming1189.ru/files/Kern_Ritch.pdf вот эта пойдет?

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

1. книга подойдёт.

Про переключения, так Вы

1. Не запоминаеете новое значение previousMillis

2. экраны перепутаются. Надо помнить какой экран сейчас и переключаться на следующий через равные интервалы.

На самом деле, это проще сделать через таймер. Либо ручками - там три строчки, тут примеров полно. Либо, если сильно хочется - взять библиотеку типа TimerOne

protone77
Offline
Зарегистрирован: 02.10.2016

я, наверное, понимаю почему не переключает когда пройдёт 11 секунд, то будет верно (millis() - previousMillis > 10000) и (millis() - previousMillis > 5000) но как иначе сделать я не знаю

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, нет, Вы испольуете один и тот же previousMillis для всего. Сядьте с карандашом и распишите как он у Вас меняется ведя пальцем по строкам программы. Всё поймёте.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

1. книга подойдёт.

Про переключения, так Вы

1. Не запоминаеете новое значение previousMillis

2. экраны перепутаются. Надо помнить какой экран сейчас и переключаться на следующий через равные интервалы.

На самом деле, это проще сделать через таймер. Либо ручками - там три строчки, тут примеров полно. Либо, если сильно хочется - взять библиотеку типа TimerOne

1. нужно в каждом условии millis()=previousMillis?

что за таймер? он тоже на millis будет?
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Таймер он сам по себе. Тикает вообще без Вашего участия.

Наберите в гугле "таймеры в AVR". Только обязательно найдите сначала статью где идеи и теория разъясняются - не хватайтесь за первый попавшийся код, пока понимания не появится.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Таймер он сам по себе. Тикает вообще без Вашего участия.

Наберите в гугле "таймеры в AVR". Только обязательно найдите сначала статью где идеи и теория разъясняются - не хватайтесь за первый попавшийся код, пока понимания не появится.

хорошо, попробую разобраться и вечером отпишусь

и ещё,как делать установку времени? потому что в ручную не получится, каждый раз когда подключаю ардуину она ресетит скетч. Или это в конце работы над часами лучше сделать?



 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

protone77 пишет:

и ещё,как делать установку времени? потому что в ручную не получится, каждый раз когда подключаю ардуину она ресетит скетч. Или это в конце работы над часами лучше сделать?



 
Батарея есть в часах? Если есть, то в сетапе вообще ничего устанавливать не надо. Один раз установите, а потом уберите. Тогда пусть себе ресетит - часы сами помнят который час.
 
Но какая-то установка всё равно нужна. Вы как-то собирались подумать насчёт ESP-01 - самое простое решение, но только если вай-фай дома есть. Опять же, сегодня есть - установили, а завтра нет - ну и не устанавливаем, часы сами нормально идут. У меня так и работает. Подумали?
 
Если нет, то нужны какие-то кнопки или энкодер для установки. Что именно - энкодер или кнопки - от дизайна зависит. Но в любом случае - не нужно принудительно устанавивать в сетапе - пусть часы сами помнят. А когда таки нужно - установить. Кроме конпок для такой "серьёзной" установки, очень приятно иметь возможность "подводки" - это кнопочка, которая при нажатии просто ставит время точно на ближайший час. Очень удобно. Допустим, ушли они на 12 секунд, ну и зачем их глобально переустанавливать - просто в момент "пика" по радио нажать кнопку - она и подправит эти секунды, установив точно на начало часа.
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Как дела с таймером?

Если что, то в этой теме есть готовое решение для мигания 9-ым или 10-м пином (на выбор) вместе с пояснениями и калькулятором констант для разных частот мигания.

Там в комментарии №1 есть дополнение про 10 пин и про то, как всё выключить, когда не надо мигать.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Как дела с таймером?

Если что, то в этой теме есть готовое решение для мигания 9-ым или 10-м пином (на выбор) вместе с пояснениями и калькулятором констант для разных частот мигания.

Там в комментарии №1 есть дополнение про 10 пин и про то, как всё выключить, когда не надо мигать.

Прочитаю и вечером отпишусь, неудобно писать с телефона.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

protone77 пишет:

и ещё,как делать установку времени? потому что в ручную не получится, каждый раз когда подключаю ардуину она ресетит скетч. Или это в конце работы над часами лучше сделать?



 
Батарея есть в часах? Если есть, то в сетапе вообще ничего устанавливать не надо. Один раз установите, а потом уберите. Тогда пусть себе ресетит - часы сами помнят который час.
 
Но какая-то установка всё равно нужна. Вы как-то собирались подумать насчёт ESP-01 - самое простое решение, но только если вай-фай дома есть. Опять же, сегодня есть - установили, а завтра нет - ну и не устанавливаем, часы сами нормально идут. У меня так и работает. Подумали?
 
Если нет, то нужны какие-то кнопки или энкодер для установки. Что именно - энкодер или кнопки - от дизайна зависит. Но в любом случае - не нужно принудительно устанавивать в сетапе - пусть часы сами помнят. А когда таки нужно - установить. Кроме конпок для такой "серьёзной" установки, очень приятно иметь возможность "подводки" - это кнопочка, которая при нажатии просто ставит время точно на ближайший час. Очень удобно. Допустим, ушли они на 12 секунд, ну и зачем их глобально переустанавливать - просто в момент "пика" по радио нажать кнопку - она и подправит эти секунды, установив точно на начало часа.

батарея есть. Вайфая не будет, думаю их на дачу поставить.

Наверное кнопки лучше всего сделать. Эндокодер как-то неочень выглядеть будет

p/s сейчас прочитаю про таймер и отпишусь

 

protone77
Offline
Зарегистрирован: 02.10.2016

#include <Wire.h> 
#include <SPI.h> 
#include "DHT.h" 
#include <DS3231.h>
#include <Adafruit_Sensor.h>

#define PIN_SQW 3
#define DHTPIN 2 
#define DHTTYPE DHT11 
           
long previousMillis = 0;   
long previousMillis1 = 5000;  
long previousMillis2 = 10000;       
   


static DS3231 Clock;
DHT dht(DHTPIN, DHTTYPE);

#define LATCH_PIN 10

#define SEG_A 0b10111111 
#define SEG_B 0b11011111 
#define SEG_C 0b11101111 
#define SEG_D 0b11110111 
#define SEG_E 0b11111011 
#define SEG_F 0b11111101 
#define SEG_G 0b11111110 
#define SYMBOL_0 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_1 (SEG_B & SEG_C) 
#define SYMBOL_2 (SEG_A & SEG_B & SEG_D & SEG_E & SEG_G) 
#define SYMBOL_3 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_G) 
#define SYMBOL_4 (SEG_B & SEG_C & SEG_F & SEG_G) 
#define SYMBOL_5 (SEG_A & SEG_C & SEG_D & SEG_F & SEG_G) 
#define SYMBOL_6 (SEG_A & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_7 (SEG_A & SEG_B & SEG_C) 
#define SYMBOL_8 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_E & SEG_F & SEG_G) 
#define SYMBOL_9 (SEG_A & SEG_B & SEG_C & SEG_D & SEG_F & SEG_G)  
#define SYMBOL_C (SEG_A & SEG_D & SEG_E & SEG_F) 
#define SYMBOL_H (SEG_F & SEG_G & SEG_E & SEG_B & SEG_C) 
#define SYMBOL_grad (SEG_A & SEG_F & SEG_G & SEG_B)
#define SYMBOL_EMPTY  0xFF

volatile static const uint8_t allDigits[] = { SYMBOL_0, SYMBOL_1,SYMBOL_2,SYMBOL_3,SYMBOL_4,SYMBOL_5,SYMBOL_6,SYMBOL_7,SYMBOL_8,SYMBOL_9};

volatile static uint8_t clockScreen[4];  
volatile static uint8_t temperatureScreen[4]; 
volatile static uint8_t humidityScreen[4]; 

static uint8_t * physicalScreen = clockScreen; 


void showOnScreen(const uint8_t *screen) {
  if (screen != physicalScreen) return;
  digitalWrite(LATCH_PIN, LOW);
  SPI.beginTransaction(SPISettings(F_CPU/2, LSBFIRST, SPI_MODE0)); 
  SPI.transfer(physicalScreen[0]); 
  SPI.transfer(physicalScreen[1]); 
  SPI.transfer(physicalScreen[2]); 
  SPI.transfer(physicalScreen[3]); 
  digitalWrite(LATCH_PIN, HIGH); 
  SPI.endTransaction();
}

static inline void fillUpScreen(volatile uint8_t * screen, 
      const uint8_t s0 = SYMBOL_EMPTY,  const uint8_t s1 = SYMBOL_EMPTY,  
      const uint8_t s2 = SYMBOL_EMPTY,  const uint8_t s3 = SYMBOL_EMPTY) {
  screen[0] = s0;
  screen[1] = s1;
  screen[2] = s2;
  screen[3] = s3;
  showOnScreen(screen);
}

void time2Screen(uint8_t h, uint8_t m) {
  fillUpScreen(clockScreen, allDigits[m % 10], allDigits[m / 10], allDigits[h % 10], allDigits[h / 10]);
}

void temperature2Screen(uint8_t t) {
  fillUpScreen(temperatureScreen,SYMBOL_C, SYMBOL_grad,  allDigits[t % 10], allDigits[t / 10]);
}

void humidity2Screen(uint8_t h) {
  fillUpScreen(humidityScreen, SYMBOL_H,SYMBOL_EMPTY, allDigits[h % 10], allDigits[h / 10]);
}
bool isClockScreenActive = true;
static inline void activateScreen(volatile uint8_t * screen) {
  isClockScreenActive = false;
  TCCR1A &= ~0xC0;
  physicalScreen = screen;
  showOnScreen(physicalScreen);
}

void activateClockScreen(void) { 
  activateScreen(clockScreen);
  isClockScreenActive = true;
}

void activateTemperatureScreen(void) { 
  activateScreen(temperatureScreen);
}

void activateHumidityScreen(void) { 
  activateScreen(humidityScreen);
}


static void everyMinuteAlarm(void) {
  const byte oldSReg = SREG;
  sei();
  time2Screen(Clock.getHour(), Clock.getMinute());
  temperature2Screen(dht.readTemperature());
  humidity2Screen(dht.readHumidity());
  Clock.clearAlarmSignal(2);
  SREG = oldSReg;
}

enum Prescalers {
  PRESCALER_1 = 1, PRESCALER_8 = 2, PRESCALER_64 = 3, PRESCALER_256 = 4, PRESCALER_1024 = 5
};

void svetodiod() {if (isClockScreenActive) {
   uint8_t prescaler = PRESCALER_256;
  uint16_t topValue = 65535; 
  TCCR1A = 0x40;      // Инвертирование пина 9 по сравнению
  TCCR1B = 0x08 | prescaler;  // Установить СТС режим и делитель частоты
  OCR1A = topValue;   // установить TOP равным topValue
}}

  
void setup(void) {
   pinMode(9, OUTPUT);
  pinMode(PIN_SQW, INPUT);
  Serial.begin(115200);
  SPI.begin(); 
  dht.begin();
  Wire.begin();
  Clock.setClockMode(false);  
  Clock.turnOffAlarm(2); 
  Clock.EnableMinuteInterrupt();  
  attachInterrupt(PIN_SQW - 2, everyMinuteAlarm, FALLING);  
  delay(10);  
  everyMinuteAlarm();
  
 
}

void loop(void) {  
  
  if(millis() - previousMillis2 > 25000) { 
    previousMillis2 = millis(); 
    activateTemperatureScreen();     
    }
  if(millis() - previousMillis1 > 20000) { 
    previousMillis1 = millis();  
    activateHumidityScreen(); 
    }
  if(millis() - previousMillis > 5000) { 
    previousMillis = millis();  
     activateClockScreen();
    }
  
  svetodiod();
   
}

вот светодиод мигает, всё нормально. Но как регулировать этим таймером время переключения экранов? это я не понял.

ещё хотел српосить про вот этот отрезок



 if(millis() - previousMillis2 > 25000) { 
    previousMillis2 = millis(); 
    activateTemperatureScreen();     
    }
  if(millis() - previousMillis1 > 20000) { 
    previousMillis1 = millis();  
    activateHumidityScreen(); 
    }
  if(millis() - previousMillis > 5000) { 
    previousMillis = millis();  
     activateClockScreen();
    }

 

я, думаю, если программа запускается она должна начинатся с времени, но высвечивается сразу влажность, потом время, потом опять влажность и т.д Что вообще делает строка previousMillis = millis();  я понимаю, что она писвивает значение, но для чего это?

p/s сейчас начинаю читать книгу про С может понятней всё станет

 


 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, не знаю, я думал, что Вы этим таймером будете двоеточием мигать.

А переключение экранов, там нужно чуть-чуть по-другому. Завтра поговорим.

protone77
Offline
Зарегистрирован: 02.10.2016

по поводу часов, батарейка есть. Но все равно, когда ардуина отключается от питания, то после включения время сбрасывается на 00 00

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Значит, у Вас выключена осцилляция от батареи. Надо включить. Знаете как? Если нет, давайте ссылку на свою библиотеку, я посмотрю как в ней это сделать.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Значит, у Вас выключена осцилляция от батареи. Надо включить. Знаете как? Если нет, давайте ссылку на свою библиотеку, я посмотрю как в ней это сделать.

https://drive.google.com/file/d/0B9r7cRXQ4DU4RTJibEN6OHRFTDQ/view

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Поставьте в setup

Clock.enableOscillator(true, true, 3);

Загрузите. Эта строка пусть там и остаётеся навсегда.

Затем уберите установку времени и снова загрузите. 

После этого поэкспериментируйте с питанием. Должно запоминаться время если батарею не вынимать.

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Поставьте в setup

Clock.enableOscillator(true, true, 3);

Загрузите. Эта строка пусть там и остаётеся навсегда.

Затем уберите установку времени и снова загрузите. 

После этого поэкспериментируйте с питанием. Должно запоминаться время если батарею не вынимать.

не знаю, всеравно сбивается на 00 00. Может это из-за акуумулятора? я измерил его напряжение выдало 4.34, вместо 3.6, как написано на нём.

 

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Поставьте в setup

Clock.enableOscillator(true, true, 3);

Загрузите. Эта строка пусть там и остаётеся навсегда.

Затем уберите установку времени и снова загрузите. 

После этого поэкспериментируйте с питанием. Должно запоминаться время если батарею не вынимать.

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Напряжение нормальное, такое и должно быть. Если при установленном флаге сбивается, это очень странно.

Вариантов два, либо там другие настройки часов входят в противоречие с этими, либо в библиотеке ошибка и она не устанавливает нужные флаги.

Давайте исключать проблемы по очереди.

1.
Сбросьте все настройки часов, для этого отключите их от питания и выньте батарею на несколько минут. Потом поставьте на место батарею. Запустите скетч в котором есть строка "Clock.enableOscillator(true, true, 3);", чтобы она точно отработала. Выждите несколько минут, отключите питание (батарею не трогайте) и включите снова - посмотрите, сохранилось ли время.

Если не поможет, попробуйте проделать тоже самое, но в моей строке меняйте последний параметр с 3 на 0, если не поможет, то на 1, потом на 2. Если совсем ничего не поможет, восстановите 3 и скажите мне, будем разбираться что там с библиотекой.

 

protone77
Offline
Зарегистрирован: 02.10.2016

ЕвгенийП пишет:

Напряжение нормальное, такое и должно быть. Если при установленном флаге сбивается, это очень странно.

Вариантов два, либо там другие настройки часов входят в противоречие с этими, либо в библиотеке ошибка и она не устанавливает нужные флаги.

Давайте исключать проблемы по очереди.

1.
Сбросьте все настройки часов, для этого отключите их от питания и выньте батарею на несколько минут. Потом поставьте на место батарею. Запустите скетч в котором есть строка "Clock.enableOscillator(true, true, 3);", чтобы она точно отработала. Выждите несколько минут, отключите питание (батарею не трогайте) и включите снова - посмотрите, сохранилось ли время.

Если не поможет, попробуйте проделать тоже самое, но в моей строке меняйте последний параметр с 3 на 0, если не поможет, то на 1, потом на 2. Если совсем ничего не поможет, восстановите 3 и скажите мне, будем разбираться что там с библиотекой.

 

все заработало, когда изменил 3 на 0

далее думаю нужно настроить смену дисплеев без дилея. Мигание светодиода я сделал по вашему примеру с таймером.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вот я бы это делал кнопкой, правда, а то, блин, нужно время узнать, и сиди жди, когда он соизволит переключиться. Но если уж так хотите, то определитесь, как часто Вы хотите сменять дисплеи?