Покритикуйте написанный код)) И несколько вопросов...

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Всем доброго времени суток! Написал скетч вывода на 4-х разрядный семисегментный индикатор времени с часов DS3231 и температуры с датчика BMP180. Применил сдвиговый регистр 74HC595 для экономии выходов ардуины. Работает всё хорошо, за исключением небольшого мерцания в момент чтения показаний температуры. Хоть скетч и работает, но всё же хочу попросить знатоков прокомментировать написанное. Что можно поправить, что убрать совсем или добавить, ну и так далее… 

Ну и куда же без вопросов))

Первый из них – каким образом можно избавится от мерцания разрядов индикатора в момент чтения показания. Как бы это не критично, мерцание не очень заметное, но всё же…

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

#include <Wire.h>
#include <BMP085.h>
#include <DS3231.h>  // Библиотека для работы с модулем DS3231
#define latchPin 3 // 12 вывод(защёлка)
#define clockPin 2 // 11 вывод (вход для тактовых импульсов)
#define dataPin  4 // 14 вывод (вход для последовательных данных)

DS3231 clock;           
RTCDateTime DateTime;
BMP085 dps = BMP085();


unsigned long gen1P = 0UL;
bool dot = false; // включение/выключение двоеточия
bool statusTime = false ; // разрешение отображения времени
bool statusTemp = false ; // разрешение отображения температуры
int Thousandth=0, Hundredth=0, Tenth=0, Ones=0; 
byte tenthTemp=0, onesTemp=0; 
long Temperature = 0; // хранение температуры

byte Pin_Digit[4] = {5, 6, 7, 8};  
byte Numbers_array[12] = 
{
  0x3F, 0x6, 0x5B, // 0, 1, 2
  0x4F, 0x66, 0x6D,// 3, 4, 5
  0x7D, 0x7, 0x7F, // 6, 7, 8 
  0x6F, 0x39,0x63, // 9,C,*
};

void setup() 
{
  //Serial.begin(9600);
  DDRD = B11111100; // 2, 3, 4, 5, 6, 7 - выход
  DDRB = B00000011; // 8,9 - выход
  PORTD |= B11100000; // выключаем 1, 2, 3 разряды
  PORTB |= B00000001; // выключаем 4 разряд
  clock.begin(); 
  Wire.begin();
  delay(1000);
  dps.init();   
  gen1P = millis();
}

void loop() 
{
  DateTime = clock.getDateTime(); // получаем текущее время   
  String Time = clock.dateFormat("Hi",DateTime); // записываем время в Time
  String Second = clock.dateFormat("s",DateTime);  // записываем секунды в Second
  byte switchTime = Second.toInt(); // конвертируем string в long и записываем в switchTime
  //Serial.println(switchTime);
  blinkDot(1000); // мигаем двоеточием раз в секунду
  displayTime(Time);
  displayTemp(switchTime);
  if (switchTime>=1 && switchTime<=6 ) // с 1 по 6 секунду отображаем температуру
   {
     statusTime = false;
     statusTemp = true;
   }
    else // затем время
     {
       statusTime = true;
       statusTemp = false;
     }
}

//_____ФУНКЦИЯ ОТОБРАЖЕНИЯ ДАННЫХ НА ИНДИКАТОРЕ_____//

void showNumber(byte reqDigit, byte reqNumber)
 {
   digitalWrite(latchPin, LOW); // защёлка LOW
   shiftOut(dataPin, clockPin, MSBFIRST, Numbers_array[reqNumber]); // передаём последовательность в регистр
   digitalWrite(latchPin, HIGH); // защёлкиваем регистр
   for(int i; i<4; i++)  digitalWrite(Pin_Digit[i], HIGH); // выключаем все сегменты
   // если разрешено отображение времени И запрещено отображение температуры ИЛИ запрещено отображение времени И разрешено отображение температуры
   // выводим данные на индикатор
   if (statusTime==true && statusTemp!=true || statusTime!=true && statusTemp==true ) digitalWrite(Pin_Digit[reqDigit], LOW); 
   delay(5);
 }

//_____ТАЙМЕР ОТЧЁТА КОЛИЧЕСТВА МИЛЛИСЕКУНД_____//

bool isTimer(unsigned long startTime, unsigned long period )
 {
   unsigned long currentTime;
   currentTime = millis();
   if (currentTime >= startTime) return (currentTime >= (startTime + period));
   else return (currentTime >= (4294967295 - startTime + period));
 }

//_____ФУНКЦИЯ ВКЛЮЧЕНИЯ/ВЫКЛЮЧЕНИЯ ДВОЕТОЧИЯ_____//

void blinkDot(int frequencyBlink) 
 {
  if (isTimer (gen1P, frequencyBlink)) 
   {
     gen1P = millis();
     dot = !dot; 
   }
   if (statusTemp==true) PORTB &= (0 << 1); // если включено отображение температуры,выключаем отображение двоеточия
   else  digitalWrite(9,dot); 
 }

//_____ФУНКЦИЯ РАЗДЕЛЕНИЯ ПЕРЕМЕННОЙ ВРЕМЕНИ НА ТЫСЯЧИ,СОТНИ,ДЕСЯТКИ И ЕДИНИЦЫ И ОТПРАВКИ ИХ В ФУНКЦИЮ SHOWNUMBER()_____//

void displayTime(String curTime)
 {
   int x = curTime.toInt(); // конвертируем string в long и записываем в х
   // Далее разбиваем число х на тысячи,сотни,десятки и единицы...
   Thousandth = x/1000;  // тысячи
   Hundredth = x/100%10; // сотни
   Tenth = x%100/10; // десятки
   Ones = x%10; // единицы
   if (statusTemp != true ) // если включено отображение температуры, запрещаем отправку значений времени в функцию showNumber()
    {
      // Выводим последовательно на индикатор
      showNumber(0, Thousandth);
      showNumber(1, Hundredth);
      showNumber(2, Tenth);
      showNumber(3, Ones);
    }
 }

//_____ФУНКЦИЯ РАЗДЕЛЕНИЯ ПЕРЕМЕННОЙ ТЕМПЕРАТУРЫ НА ДЕСЯТКИ И ЕДИНИЦЫ И ОТПРАВКИ ИХ В ФУНКЦИЮ SHOWNUMBER()_____//

void displayTemp(byte sec)
 {
   if(sec==1) dps.getTemperature(&Temperature); // каждую минуту считываем показания с датчика
   byte i = Temperature/10; // т.к с датчика получаем 3-х значное число без запятой (255==25,5), данным действием избавляемся от единиц
   // Далее разбиваем число i десятки и единицы...
   tenthTemp = i/10; // десятки
   onesTemp = i%10; // единицы
  if (statusTime != true) // если включено отображение времени, запрещаем отправку значений температуры в функцию showNumber()
   {
     showNumber(0, tenthTemp);
     showNumber(1, onesTemp);
     showNumber(2, 10); // отображаем С
     showNumber(3, 11); // отображаем знак *
     
   }
 }

 

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

странный код

//_____ФУНКЦИЯ РАЗДЕЛЕНИЯ ПЕРЕМЕННОЙ ВРЕМЕНИ НА ТЫСЯЧИ,СОТНИ,ДЕСЯТКИ И ЕДИНИЦЫ И ОТПРАВКИ ИХ В ФУНКЦИЮ SHOWNUMBER()_____//

как ты в десятичной системе времени ориентируешься?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

Клапауций 112 пишет:

странный код

//_____ФУНКЦИЯ РАЗДЕЛЕНИЯ ПЕРЕМЕННОЙ ВРЕМЕНИ НА ТЫСЯЧИ,СОТНИ,ДЕСЯТКИ И ЕДИНИЦЫ И ОТПРАВКИ ИХ В ФУНКЦИЮ SHOWNUMBER()_____//

как ты в десятичной системе времени ориентируешься?

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

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

Вы уверены, что хотите услышать критику?

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Ничего сложного нет,простая математика. Т.к индикация динамическая в любом случаи надо было каким то образом раздилить 4-х значное число на отдельные составляющие, этот метот один из самых простых))

Osgiliath
Offline
Зарегистрирован: 03.09.2016

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

Вы уверены, что хотите услышать критику?

Так за этим я и создал тему. Я только учусь этому делу, так, что готов выслушать всё, что посчитайте нужным сказать!

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

Osgiliath пишет:

Ничего сложного нет,простая математика. Т.к индикация динамическая в любом случаи надо было каким то образом раздилить 4-х значное число на отдельные составляющие, этот метот один из самых простых))

зачем делить 4-х значное число на отдельные составляющие - у тебя же экран 4-х значный и не вместит тысячные(6-ти значные)?

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Клапауций 112 пишет:

Osgiliath пишет:

Ничего сложного нет,простая математика. Т.к индикация динамическая в любом случаи надо было каким то образом раздилить 4-х значное число на отдельные составляющие, этот метот один из самых простых))

зачем делить 4-х значное число на отдельные составляющие - у тебя же экран 4-х значный и не вместит тысячные(6-ти значные)?

Объясняю ещё раз... Индикация у меня динамическая, при динамической индикации в каждый момент времени выводится только одна цифра, но происходит это очень быстро (каждые 5 мс.) и кажется,что цифры горят постоянно Можно было и без неё обойтись, но тогда бы потребовалось бы 7х4=28 + 2 точки = 30 ног микроконтроллера))

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

Osgiliath пишет:

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

Вы уверены, что хотите услышать критику?

Так за этим я и создал тему. Я только учусь этому делу, так, что готов выслушать всё, что посчитайте нужным сказать!

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

Osgiliath
Offline
Зарегистрирован: 03.09.2016

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

Osgiliath пишет:

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

Вы уверены, что хотите услышать критику?

Так за этим я и создал тему. Я только учусь этому делу, так, что готов выслушать всё, что посчитайте нужным сказать!

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

Нее..нее, если бы я не хотел выслушивать критику,тем более скет работает и работает в железе, я бы не стал тему создавать. А так готов выслушать... где какие ошибки. Тем более жду пока приедет плата arduino due и дисплей 2.4`на ILI9341 планирую делать полноценную метиостанцию. А этот проэкт так - учебный,подготовка к более серьёзным делам!

Logik
Offline
Зарегистрирован: 05.08.2014

Так давайте с чего начнем уже.

Вот к примеру

047  String Time = clock.dateFormat("Hi",DateTime); // записываем время в Time

Зачем  String? Вы не знаете какой максимальной длины вернется строка? Знаете. Потому масив char здесь явно лучше. А далее вы эту строку передаете в функцию чтоб там сразу конвертнуть в целое. Логичней уже в функцию передавать сразу int. И посмотреть внимательней на clock, может вобще без строк тут обойтись?

А вот типичная локальная Thousandth зачемто обявлена глобальной. И др. ей подобные. 

С пинами в сетапе Вы работаете оч. красиво, напрямую с регистрами. Хороше. Но не обязательно, сетап, он раз отработает, быстро или медленно не так важно. Но вот вывод на экран из лопа через digitalWrite. А именно здесь бы напрямую, по быстрому. Так нет жеж.

Аларм с ахтунгом! Империо в опасности!

077   delay(5);

Вобще странное архитектурное решение - каждый луп получать данные формировать его  а затем проверять условия и выводить чего.  Ну Вы представте как это будет выглядеть если будет больше типов экрана. Включаем здравый смысл, как бы чел по жизни все делал ручками?  На каждом проходе цикла он определял нужно ли чтото менять. А менять нужно будет одно из 2-х: сигналы динамической индикации для отображения того что сейчас надо отображать или сами отображаемые данные.  Очевидно что сигналы динамической индикации прийдется формировать для заданых ранее отображаемых данных. Значить их хранить надо, и назовем это хранилище экранным буфером. Получается для смены отображаемых данных надо просто сформировать новый экранный буфер в тот момент когда такая смена потребуется. Т.е. если изменилось время, пора мигнуть двоеточием или отобразить температуру - мы изменим содержимое экранного буфера на требуемое. Таков обычный подход.

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Logik пишет:

Так давайте с чего начнем уже.

Вот к примеру

047  String Time = clock.dateFormat("Hi",DateTime); // записываем время в Time

Зачем  String? Вы не знаете какой максимальной длины вернется строка? Знаете. Потому масив char здесь явно лучше. А далее вы эту строку передаете в функцию чтоб там сразу конвертнуть в целое. Логичней уже в функцию передавать сразу int. И посмотреть внимательней на clock, может вобще без строк тут обойтись?

Попробую пояснить. Да, возможно я не прав, но мне показалось проще конвертировать string в int функцией toInt(), чем зделать этоже с char массивом. Тем более, сначала я отправил Strig в сериал, там было 4-х значное значения минут и часов одной строкой, как раз то, что мне и нужно. Сегодня на свежую голову подумал, почему не попробовать записывать значения времени напрямую в int, примерно вот так:  int x = DateTime.minute; Не знаю будет ли это работать,вечером проверю!

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Logik пишет:

А вот типичная локальная Thousandth зачемто обявлена глобальной. И др. ей подобные. 

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

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Logik пишет:

С пинами в сетапе Вы работаете оч. красиво, напрямую с регистрами. Хороше. Но не обязательно, сетап, он раз отработает, быстро или медленно не так важно. Но вот вывод на экран из лопа через digitalWrite. А именно здесь бы напрямую, по быстрому. Так нет жеж.

Решил сделать такой setup, просто из-за того, что не захотелось расписывать каждый порт по отельности, по моему это даже правельнее, и как вы сказали выглядит красиво! Насчёт digitalWrite, если вы имейте ввиду функцию void showNumber(); Тут я просто не в курсе как, например оформить в виде битовой маски подубную запись 

digitalWrite(latchPin, LOW); // защёлка LOW 

Или цикл

for(int i; i<4; i++)  digitalWrite(Pin_Digit[i], HIGH); // выключаем все сегменты

Или когда портом управляет переменная, как в записи ниже

 digitalWrite(9,dot); 

 

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Logik пишет:

Аларм с ахтунгом! Империо в опасности!

077   delay(5);

Вобще странное архитектурное решение - каждый луп получать данные формировать его  а затем проверять условия и выводить чего.  Ну Вы представте как это будет выглядеть если будет больше типов экрана. Включаем здравый смысл, как бы чел по жизни все делал ручками?  На каждом проходе цикла он определял нужно ли чтото менять. А менять нужно будет одно из 2-х: сигналы динамической индикации для отображения того что сейчас надо отображать или сами отображаемые данные.  Очевидно что сигналы динамической индикации прийдется формировать для заданых ранее отображаемых данных. Значить их хранить надо, и назовем это хранилище экранным буфером. Получается для смены отображаемых данных надо просто сформировать новый экранный буфер в тот момент когда такая смена потребуется. Т.е. если изменилось время, пора мигнуть двоеточием или отобразить температуру - мы изменим содержимое экранного буфера на требуемое. Таков обычный подход.

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Osgiliath пишет:
Второй –  на этот скетч худо-бедно у меня мозгов хватило, но всё-таки хочется добавить возможность настройки часов и будильника. Подсадите, как правильно это реализовать???  

Вот еще нюанс. Как строют из домино башню. Ложат одну доминошку, поверх еще одну, и так далее, пока башня не станет шаткой. Разумеется ложат по 1 штучке. Можно и сразу по две и больше. Но конечная конструкция будет ниже. Так и просходит с программированием. У некоторых глючность программы происходит на 10 строке, у некоторой на 100, 200. Но конечность не глючности программы всегда есть. И это конечность индивидуальна для каждого программиста.  Как же средний программист строит большие программы, если "индивидуальная граничность не глючности программы у него уже пройдена". Разумеется он должен переходить и колличественных методов к качественным. Это технологии из С++, видуал Си , и визуал проектирования. 

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

Osgiliath пишет:
Подсадите, как правильно это реализовать???  
Ответ один: вам надо теперешнюю уже переписать полностью. 

Logik
Offline
Зарегистрирован: 05.08.2014

Osgiliath пишет:

Logik пишет:

Аларм с ахтунгом! Империо в опасности!

077   delay(5);

Вобще странное архитектурное решение - каждый луп получать данные формировать его  а затем проверять условия и выводить чего.  Ну Вы представте как это будет выглядеть если будет больше типов экрана. Включаем здравый смысл, как бы чел по жизни все делал ручками?  На каждом проходе цикла он определял нужно ли чтото менять. А менять нужно будет одно из 2-х: сигналы динамической индикации для отображения того что сейчас надо отображать или сами отображаемые данные.  Очевидно что сигналы динамической индикации прийдется формировать для заданых ранее отображаемых данных. Значить их хранить надо, и назовем это хранилище экранным буфером. Получается для смены отображаемых данных надо просто сформировать новый экранный буфер в тот момент когда такая смена потребуется. Т.е. если изменилось время, пора мигнуть двоеточием или отобразить температуру - мы изменим содержимое экранного буфера на требуемое. Таков обычный подход.

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

))))

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

Z=0 W=0 //две глобальные переменные

Луп

(

   если истекло время с прошлого обновления динамической индикации то 

    (

       выводим очередной символ из экранного буфера(меняем строб, выводим сигналы...)

    )

  если выводим часы т.е. Z==0 и прошло пол секунды с прошлого вывода времени

   ( 

     W=W+1  //некая глобальная переменная

    если W==1 (читаем время и формируем экранный буфер без ":" )

     если W==2(заменяем в экранном буфере ":" на " " W=0 )

   определяем не пора ли вывести температуру и  если пора Z=1

   )

 если пора выводить температуру т.е. Z==1

  (

    считываем с датчика температуру и формируем  экранный буфер 

   Z=2

  )

 если выводим температуру т.е. Z==2 и истекло время её вывода 

  (

   Z=0

  )

)

Гдето так. Обратите внимание что проверки "если пора ", "если истекло время " и пр. связаное с формированием временных интервалов делаем как в "блинк без делея".  При динамической индикации так же потребуется переменная похожая на использованая в коде  Z и W. 

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

qwone пишет:

... строют ...Ложат ... ложат ...

-Я им говорю: "Не ложте зеркало
в парту" -ложат!
-Я им опять говорю: "Не ложте!" -
все равно ложат

(с) Доживем до понедельника.

Logik
Offline
Зарегистрирован: 05.08.2014

Osgiliath пишет:

 просто из-за того, что не захотелось расписывать каждый порт по отельности

 

Когдато я себе такое написал для 328-го контролера

#define  ARDUINO_PORT(a)        ((a<8)?PORTD:(a<14?PORTB:PORTC))
#define  ARDUINO_PIN(a)           ((a<8)?PIND:(a<14?PINB:PINC))
#define  ARDUINO_DDR(a)          ((a<8)?DDRD:(a<14?DDRB:DDRC))
#define  ARDUINO_PIN_NUM(a)  ((a<8)?a:(a<14?(a-8):(a-14))) 

И соответственно работа с пинами так

вместо digitalWrite(pin, LOW) будет bitClear(ARDUINO_PORT(pin), ARDUINO_PIN_NUM(pin)); 

вместо digitalWrite(pin, HIGH) будет bitSet(ARDUINO_PORT(pin), ARDUINO_PIN_NUM(pin)); 

вместо pinMode(pin, OUTPUT) будет bitSet(ARDUINO_DDR((pin), ARDUINO_PIN_NUM(pin)); 

вместо digitalWrite(pin, val) будет val? bitSet(ARDUINO_PORT(pin), ARDUINO_PIN_NUM(pin)); :bitClear(ARDUINO_PORT(pin), ARDUINO_PIN_NUM(pin)); 

Это почти как в сетапе у Вас, но немного удобней в применении и не надо помнить какой пин в какой регистр попадает.

Logik
Offline
Зарегистрирован: 05.08.2014

wdrakula пишет:

qwone пишет:

... строют ...Ложат ... ложат ...

-Я им говорю: "Не ложте зеркало
в парту" -ложат!
-Я им опять говорю: "Не ложте!" -
все равно ложат

(с) Доживем до понедельника.

Так уже на это все поклали ;)

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Logik пишет:

Это почти как в сетапе у Вас, но немного удобней в применении и не надо помнить какой пин в какой регистр попадает.

Тут как говорят, на вкус и цвет и товарищей нет)) Так как у меня УНА и портов там не много, то подобная запись PORTD |= B11100000; лично для меня более понятна...

И всё таки, можно ли оформить подобные записи в виде битовых масок??

digitalWrite(latchPin, LOW); // защёлка LOW
for(int i; i<4; i++)  digitalWrite(Pin_Digit[i], HIGH); // выключаем все сегменты
digitalWrite(9,dot);

 

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Logik пишет:

Луп

(

   если истекло время с прошлого обновления динамической индикации то 

    (

       выводим очередной символ из экранного буфера(меняем строб, выводим сигналы...)

    )

  если выводим часы т.е. Z==0 и прошло пол секунды с прошлого вывода времени

   ( 

     W=W+1  //некая глобальная переменная

    если W==1 (читаем время и формируем экранный буфер без ":" )

     если W==2(заменяем в экранном буфере ":" на " " W=0 )

   определяем не пора ли вывести температуру и  если пора Z=1

   )

 если пора выводить температуру т.е. Z==1

  (

    считываем с датчика температуру и формируем  экранный буфер 

   Z=2

  )

 если выводим температуру т.е. Z==2 и истекло время её вывода 

  (

   Z=0

  )

)

Гдето так. Обратите внимание что проверки "если пора ", "если истекло время " и пр. связаное с формированием временных интервалов делаем как в "блинк без делея".  При динамической индикации так же потребуется переменная похожая на использованая в коде  Z и W. 

Често, не очень понятно как это реализовать на практике( Может всему свое время....

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Osgiliath пишет:
Тут как говорят, на вкус и цвет и товарищей нет
Вот тут то и проблема. Как помочь человеку у которого "вкус" другой. Так что мой или чей-то другой вариант вам покажется "несъедобным". Так что ваш единственный путь развития, улучшайте и развивайте ваш "вкус и цвет".

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

Osgiliath пишет:
не очень понятно как это реализовать на практике( Может всему свое время....

«Всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть» (Л. Кэрролл)

Osgiliath
Offline
Зарегистрирован: 03.09.2016

qwone пишет:

Так что ваш единственный путь развития, улучшайте и развивайте ваш "вкус и цвет".

Так этим я и пытаюсь заниматься)))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Osgiliath пишет:

Так этим я и пытаюсь заниматься)))

Так надо развиваться в качественную сторону, а не в количественную. Вы пытаетесь делать все только с помощью функций. Причем эти функции взаимодествуют не с одним объектом а с несколькими. А надо переходить на классы, представители классов, подключаемые библиотеки и прочее. Анализ событий и их обработки. И да "для привычных ардуино скечей" это не часто встречается. Так как все скетчи делаются новичками или для новичков. Боллее продвинутые скетчи у новичков "вызывают изжогу".

Logik
Offline
Зарегистрирован: 05.08.2014

Osgiliath пишет:

Често, не очень понятно как это реализовать на практике( Может всему свое время....

Время важный фактор, когда его тратят с пользой. Начните с простого. Прочитайте про блин без делея, попробуйте. Потом в него же впишите динамический вывод из экранного буфера, а в буфер что угодно закиньте, 1234 например, как увидите это на экране - знач процесс пошел:)

Osgiliath
Offline
Зарегистрирован: 03.09.2016

Logik пишет:

Osgiliath пишет:

Често, не очень понятно как это реализовать на практике( Может всему свое время....

Время важный фактор, когда его тратят с пользой. Начните с простого. Прочитайте про блин без делея, попробуйте. Потом в него же впишите динамический вывод из экранного буфера, а в буфер что угодно закиньте, 1234 например, как увидите это на экране - знач процесс пошел:)

Как без делея работать я в курсе, у меня это с двоеточием реализовано. Я пробовал выводит с момощью таймера, но получилась ху...я! Вот и решил на delay остановится, тем более попробовал подключить кнопку и во время работы программы управлять этой кнопкой процессом, добавляя дополнительные условия, типа: если кнопка нажата отображаем температуру, пробовал светодиодом управлять. Ну и в итоге, что удивительно, проблем не заметил, всё срабатывает без нареканий. С выводом с помощью таймера буду пробовать... может чего и получится))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот еще Почему вы выводите с помощью 1  74HC595. Лучше  выводить с помощью двух. Один у вас должен выбирать сегменты, а другой уже информацию на сегменте. массив из 4 byte для буфера  и переключать с частотой 50 гц*4 =200 => 5милисек.

void loop() {
  static uint32_t past = 0;
  static byte n = 0;
  if ((n == 0) && (millis() - past > 5)) {
    past = millis();
    n++; if (n >= 5)n = 0;
    // вывод след сегмента
    digitalWrite(latchPin, LOW); 
    shiftOut(dataPin, clockPin, MSBFIRST, Numbers_array[buffer[n]]);
    shiftOut(dataPin, clockPin, MSBFIRST, Numbers_seg[n]);
    digitalWrite(latchPin, HIGH); 
  }
}

 

Osgiliath
Offline
Зарегистрирован: 03.09.2016

qwone пишет:

Вот еще Почему вы выводите с помощью 1  74HC595. Лучше  выводить с помощью двух. Один у вас должен выбирать сегменты, а другой уже информацию на сегменте. массив из 4 byte для буфера  и переключать с частотой 50 гц*4 =200 => 5милисек.

void loop() {
  static uint32_t past = 0;
  static byte n = 0;
  if ((n == 0) && (millis() - past > 5)) {
    past = millis();
    n++; if (n >= 5)n = 0;
    // вывод след сегмента
    digitalWrite(latchPin, LOW); 
    shiftOut(dataPin, clockPin, MSBFIRST, Numbers_array[buffer[n]]);
    shiftOut(dataPin, clockPin, MSBFIRST, Numbers_seg[n]);
    digitalWrite(latchPin, HIGH); 
  }
}

 

Т.к сегмента всего 4, посчитал, что их можно и напрямую подключить и не заморачиваться c shiftOut(). Есть же массив byte Pin_Digit[4] = {5, 6, 7, 8};  он и занимается включением сегментов каждые 5 мс.

Osgiliath
Offline
Зарегистрирован: 03.09.2016

qwone пишет:

void loop() {

  static uint32_t past = 0;
  static byte n = 0;
  if ((n == 0) && (millis() - past > 5)) {
    past = millis();
    n++; if (n >= 5)n = 0;
    // вывод след сегмента
    digitalWrite(latchPin, LOW); 
    shiftOut(dataPin, clockPin, MSBFIRST, Numbers_array[buffer[n]]);
    shiftOut(dataPin, clockPin, MSBFIRST, Numbers_seg[n]);
    digitalWrite(latchPin, HIGH); 
  }
}

Ещё момент, в чём разница между uint32_t и unsigned long или, например int32_t и long, если вместимость у них одинаковая?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

uint32_t это unsigned long   только короче написано . unsigned long  и  long  без знака и с знаком.