Вывод информации на 4 разрядный 7сегментный индикатор при помощи двух 74hc595

Sirox
Offline
Зарегистрирован: 24.02.2015

maksim пишет:

Так же возможен и 4 вариант - просто оптимизировать код:



Присоединяюсь к Nemo, огромное спасибо !

Только не знаю на какие цифры поменять для общего катода byte digits[4] = {255,255,255,255}; ?

valter61
Offline
Зарегистрирован: 20.03.2015

К сожалению в програмировании еще новичек. У меня температура высвечивается наоборот. Не могу разобраться, как инвертировать последовательность регистров.

valter61
Offline
Зарегистрирован: 20.03.2015

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

void Indicate() // Функция отображения цыфр на индикаторе.
{
  static uint32_t premillis = 0;
  if(millis()-premillis < 2) return;
  premillis = millis();
  static byte digit = 0;
  static byte digit1 = 3;

  digitalWrite(latchPin, LOW);   
  
 // shiftOut(dataPin, clockPin, MSBFIRST, 1<<digit); // разряд
 shiftOut(dataPin, clockPin, MSBFIRST, 1<<digit1); // разряд
  shiftOut(dataPin, clockPin, MSBFIRST, digits[digit]);  // символ
  digitalWrite(latchPin, HIGH);  //"защелкиваем" 

  digit++;
  digit1--;
  if(digit == 4) {
    digit = 0;
    digit1 = 3;
  }
}

но вот с точкой не получается решить

maksim
Offline
Зарегистрирован: 12.02.2012
shiftOut(dataPin, clockPin, MSBFIRST, 8>>digit); // разряд

 

valter61
Offline
Зарегистрирован: 20.03.2015

Спасибо! Пробывал digit>>8. Не получалось.

Sirox
Offline
Зарегистрирован: 24.02.2015

maksim пишет:

shiftOut(dataPin, clockPin, MSBFIRST, 8>>digit); // разряд

 

 

Пока вы здесь, подскажите пожалуйста нужно ли вообще тут что то менять "byte digits[4] = {255,255,255,255}; " для индикатора с общим катодом?

maksim
Offline
Зарегистрирован: 12.02.2012

Самый простой, но не самый правильный способ, это просто инвертировать значения перед выводом в регистры:

shiftOut(dataPin, clockPin, MSBFIRST, ~(digits[digit]));  // символ
shiftOut(dataPin, clockPin, MSBFIRST, ~(1<<digit)); // разряд

 

defezit
Offline
Зарегистрирован: 14.12.2014

Тут в самом начале был разговор про мерцание цифирь - путем нехитрых опытов выяснил что это резистор звенит.  Ради интереса поставил 111 максимальное значение - мерцание исчезло.

CheBuraw
Offline
Зарегистрирован: 10.02.2015

defezit, честно говоря непонятно о каком резисторе идёт речь. И правильно ли я понял что 111 это значение того самого резистора в Ом`ах?

defezit
Offline
Зарегистрирован: 14.12.2014

Дык, это, мерцание цифирь, или засвет. Я залил оба кода, протестил, в обоих вариантах у меня на индикаторе было мерцание разрядов, вернее не мерцание - цифры менялись оч быстро (я честно говоря с Омом не дружу) я так понял это про это говорилось в начале топика - засвет чегото там был. 

111 - это я поставил вместо 8888. число получилось поменьше - цифры перестали мерцать (видать переменный резистор выдаЁт плавающее сопротивление :) )

 

Gres
Gres аватар
Offline
Зарегистрирован: 26.03.2013

defezit пишет:
111 - это я поставил вместо 8888. число получилось поменьше - цифры перестали мерцать (видать переменный резистор выдаЁт плавающее сопротивление :) )

Это Вы про первый скетч?

Там автор для тестов зацепил переменный резистор на аналоговый вход А0 и этим резистором менял на нем входное напряжение от нуля до пяти вольт. При этом, считанные аналоговые значения на входе А0 принимают дисятичное значение от 0 до 1023, с помощью функции map этот диапазон растягивается на диапазонотображения на идикаторе от 0 до 8888, для того, чтоб можно было протестировать работу индикатора.

analogueValue = map(analogueValue, 0, 1023, 0, 8888);

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

 

 

CheBuraw
Offline
Зарегистрирован: 10.02.2015

Gres пишет:

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

Вы все правильно поняли про мою начальную проблему :) .

Но ту, начальную проблему мы с Datak уже решили:

http://arduino.ru/forum/proekty/vyvod-informatsii-na-4-razryadnyi-7segme...

Gres, Вы очень понятно пишите и объясняете :) Мне бы так! А то порой  я весьма косноязычен и мне довольно трудно описать свою проблему или подсказать решение другому человеку.
 

 

Gres
Gres аватар
Offline
Зарегистрирован: 26.03.2013

Я недавно баловался с трехразрядным 7-сегментным индикатором, подключил их, каждый разряд через 176ид3, это дешифратор двоичного кода в 7-сегментный, с защелкой. Микруху можно было и одну использовать, но купил их десяток, по 7 рублей и поставил на каждый разряд, зато больше ничего не нужно и вывод идёт поочерёдно на каждый разряд, но в момент отображения одного разряда, другие два показывают предыдущее значение, а не выключаются. Смотрится очень хорошо при изменении. Правда эта серия питается от 9 вольт. Ну и бонус, данные в порт выводятся в десятичном виде, но тогда остальные ноги порта нужно контролировать, если используются.

a5021
Offline
Зарегистрирован: 07.07.2013

Как-то у вас знакогенератор (синтез цифр из сегментов) сильно переусложнен. Я обычно делаю вот так:

  // where segment's cathodes are connected to
#define  SEG_A  (1 << PORTD5)
#define  SEG_B  (1 << PORTD7)
#define  SEG_C  (1 << PORTD0)
#define  SEG_D  (1 << PORTD3)
#define  SEG_E  (1 << PORTD4)
#define  SEG_F  (1 << PORTD6)
#define  SEG_G  (1 << PORTD1)
#define  SEG_DP (1 << PORTD2)

Тут сразу видно, какой сегмент подключен к какому пину порта.

Далее столь же наглядно "синтезируем" цифры из сегментов:

  // compose digits using separate segments
#define  SIGN_8  (0xFF - SEG_DP)
#define  SIGN_0  (SIGN_8 - SEG_G)
#define  SIGN_1  (SEG_B + SEG_C)
#define  SIGN_2  (SIGN_8 - SEG_C - SEG_F)
#define  SIGN_3  (SIGN_8 - SEG_E - SEG_F)
#define  SIGN_4  (SIGN_1 + SEG_F + SEG_G)
#define  SIGN_6  (SIGN_8 - SEG_B)
#define  SIGN_5  (SIGN_6 - SEG_E)
#define  SIGN_7  (SIGN_1 + SEG_A)
#define  SIGN_9  (SIGN_8 - SEG_E)
#define  SIGN_BLANK  0

Пишем таблицу соотвествия:

  // number-to-7seg code translation table
const unsigned char codeTable[] = {~SIGN_0, ~SIGN_1, ~SIGN_2, 
                                   ~SIGN_3, ~SIGN_4, ~SIGN_5, 
                                   ~SIGN_6, ~SIGN_7, ~SIGN_8, 
                                                    ~SIGN_9};

Буфер дисплея:

  // signs to be displayed      
volatile unsigned char displayBuffer[] = {~SIGN_0, ~SIGN_F, ~SIGN_F},

Процедура конвертации значения в семисегментное представление:

void fillDisplayBuffer(int value, unsigned char padChar) {
  // convert int to string and fill the display buffer
  unsigned char i = 3;             // digits at display
  div_t res;                       // conversion divider

    // padding left
  if (value < 100) displayBuffer[0] = padChar;
  if (value < 10) displayBuffer[1] = padChar;

    // convert integer to string and place it to the buffer
  do {
    res =  div(value, 10);
    displayBuffer[--i] = codeTable[res.rem];
    value = res.quot;
  } while (value != 0 && i != 0);
 }

 

Nestor Mahno
Offline
Зарегистрирован: 03.10.2015

Здравствуйте! Nemo, объясните пожалуйста, как работает обращение к массиву содержащему сегменты? Я всю голову сломал, прямо магия какая-то. Все работает, но я не могу понять как! Конкретно интересует момент из строки 124. Ведь X это посути определенная цифра, как она ссылается на массив, где хранятся сегменты, ведь номер элемента в массиве не соответствует значению этой цифры? Я понимаю, что я ничерта не понимаю в программировании(

SegDisplay=g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.

 

sirota
Offline
Зарегистрирован: 18.08.2015

Много уважаемый ТС, как на счет библиотеки? Кто-то обещал )

Nemo
Offline
Зарегистрирован: 07.03.2015

Nestor Mahno пишет:

Здравствуйте! Nemo, объясните пожалуйста, как работает обращение к массиву содержащему сегменты?

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

Главное - что все работает.

Сейчас полностью ушел от 7-сегментников (в прочем та тренировка была одной из первых, и на том и закончилась). На сегодня - полностью все проекты делаем на LCD-дисплеях. В основном - 4х20. Гораздо проще и намного информативнее.

sirota
Offline
Зарегистрирован: 18.08.2015

Как не соответствует? Все соответствовало. У меня все пошло с первого раза, единственное инвертировал цвета и все работает.

alexeko
Offline
Зарегистрирован: 03.01.2014

Доброго времени. Решил я поиграться с таким дисплеем. Вот только у меня дисплей на 14 разрядов, 8 из которыз на 7 сигментов и 6 - квадратики (по 1 сигменту).

Почитал Ваши коды, поигрался. Как итог: если используем код формирования вывода как

if (disp < 0) // Если значение минусовое, то выполняется следующее условие

 то все работает нормально на 4 разрядах. А вот на 6, 8, 14,этот код не подходит. Цифры начинают блекнуть. Скорости ардуинки не хватает. Конено, если просто писать число, то все в порядке. Но я просто взял часикии.

Но вот как только перевел вывод в цикл FOR, то тут все становится веселее. Яркость поднялась. А если мне пнадобится кроме часиков и температура, или еще что то. И везде надо прочитать данные, а это время, которое критично для амического режима. 

Дисплей,конечно интересный,но мало информативный. Динамическая индикация напрягае ардуинку. Есть ГОТОВЫЕ решения для вывода данных, там за вывод отвечает драйвер и вся работа ложится на него.

Ну это мое мнение.

Все пробовал на NANO + три сдвиговых регистра.

Вячеслав 151
Offline
Зарегистрирован: 25.03.2015

Добрый день!

А куда вешается DS1307 и как вводиться дата?



/*
********************************************************************
  Name    : Arduino, 4-разрядный 7-сегментный индикатор, 74HC595 сдвиговый регистр, DS1307 RTC
  Author  : CheBuraw
  Date    : 12 Feb, 2015
 Optimiser: Datak
  Version : 1.1
********************************************************************

4-разрядный 7-сегментный индикатор. общий анод
                1  A  F 2  3  B
 _______________|__|__|__|__|__|_____________
|         |         |    |         |         |
|    A    |    A    |    |    A    |    A    |
| F     B | F     B | dp | F     B | F     B |
|    G    |    G    |    |    G    |    G    |
| E     C | E     C | dp | E     C | E     C |
|    D    |    D    |    |    D    |    D    |
|_________|_________|____|_________|_________|
                |  |  |  |  |  |
                E  D dp  C  G  4

74HC595 Map:
     _______
Q1  |1 *  16|  Vcc                  PINS 1-7, 15   Q0 - Q7   Output Pins
Q2  |2    15|  Q0                   PIN 8	   GND	     Ground, Vss
Q3  |3    14|  DS                   PIN 9	   Q7"	     Serial Out
Q4  |4    13|  OE                   PIN 10	   MR	     Master Reclear, active low
Q5  |5    12|  ST_CP                PIN 11	   SH_CP     Shift register clock pin
Q6  |6    11|  SH_CP                PIN 12	   ST_CP     Storage register clock pin (latch pin)
Q7  |7    10|  MR                   PIN 13	   OE	     Output enable, active low
GND |8_____9|  Q7"                  PIN 14	   DS	     Serial data input
                                    PIN 16	   Vcc	     Positive supply voltage
           _______
   LED B -|1 *  16|-5V
   LED C -|2    15|-LED A
   LED D -|3    14|-PIN 11
   LED E -|4    13|-GND
   LED F -|5    12|-PIN 8
   LED G -|6    11|-PIN 12 ; 1uF TO GND
   LED dp-|7    10|-5V
      GND-|8_____9|-NILL
      
 */
 #include <Wire.h>
 #include "RTClib.h"
 RTC_DS1307 RTC;

 int latchPin = 7;     //Пин "защелки" первого регистра подключен к ST_CP (RCLK)входу первого регистра отвечающего за сегменты 
 int clockPin = 6;    //Пин подключен к SH_CP входу 74HC595 (SCLK) 
 int dataPin = 5;     //Пин подключен к DS входу 74HC595  (DIO)

 int TimeLight = 5;  //время для разогрева сегментов

 byte SegDisplay; // переменная для вывода символов на индикаторе
 byte RazrDisplay; // переменная для включения разрядов

 // Настройка комбинации для отображения каждого номера на дисплее.

 byte g_digits[11]={
 B01000000, B01111001,    // 0 1
 B00100100, B00110000,    // 2 3
 B00011001, B00010010,    // 4 5
 B00000010, B01111000,    // 6 7
 B00000000, B00010000,    // 8 9
 B11111111, }; 		  // все сегменты выключены

 byte g_registerArray[4]={8,4,2,1}; //массив цифр, указывающий разряды

 void setup() {
  Wire.begin();
  RTC.begin();
  
 // обозначаем все пины как выходы
  pinMode(latchPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
 }

void loop() {
  int hour,minute,disp = 0;

  DateTime now = RTC.now(); //Создаём переменную для вывода времени

  hour = now.hour(); // Считываем значение часов
  minute = now.minute(); // Считываем значение минут
  
  disp = (hour * 100) + minute; //"Собираем" значения часов и минут в одну цифру
 
 // Разбиваем цифру по разрядам индикатора
 for( int i = 0; i < 4; i++ )
 {
   if( i == 0 || disp != 0 )
      Indicate( i, disp % 10 );
   else
      Indicate( i, 10 );

   disp /= 10;
 }

 }

 void Indicate(int r,int x)
 {
 SegDisplay=g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
 RazrDisplay=g_registerArray[r];  // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
  digitalWrite(latchPin, LOW);  // устанавливаем синхронизацию "защелки" на LOW
      
      shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для первого регистра (Номер разряда)
      shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay);  // Записываем информацию для второго регистра (Номер символа)
 digitalWrite(latchPin, HIGH);  //"защелкиваем" регистр, тем самым устанавливая значения на выходах

   delay(TimeLight); // пауза, чтобы сегменты "разгорелись"
 }

 

alexeko
Offline
Зарегистрирован: 03.01.2014

У меня по I2C шине часики подключены.

Разбиваешь часики на константы (как часы, минуты, секунды) или просто из строки как из массива тянешь  знак, ну и это все выкидываешь в функцию void Indicate(int r,int x). Правда дисплей у меня другой и разделителя нет в виде точек " : " . Пришлось использовать dp второго сигмента как B11000000 == 0. Тоесть присваивание бита к int. B01000000 можите еще один массив с точками прописать. Как Вам угодно.

Вячеслав 151
Offline
Зарегистрирован: 25.03.2015

alexeko пишет:

У меня по I2C шине часики подключены.

Разбиваешь часики на константы (как часы, минуты, секунды) или просто из строки как из массива тянешь  знак, ну и это все выкидываешь в функцию void Indicate(int r,int x). Правда дисплей у меня другой и разделителя нет в виде точек " : " . Пришлось использовать dp второго сигмента как B11000000 == 0. Тоесть присваивание бита к int. B01000000 можите еще один массив с точками прописать. Как Вам угодно.

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

DrProg
Offline
Зарегистрирован: 07.08.2015

Всю тему не осилил. К вопросу в первом посте две поправки: 1. shifhOut - выкинуть, он меделенный, 2. засветы развести за счет небольших задержек между гашением и включением катодов. Ниже код для часового секундомера с обратным отсчетом времени (с пищалкой) на примере Ардуино Мега и Attiny, в принципе подойдет для любого, главное чтобы все ножки SPI на одном порту были. Частота обновления кадров порядка тысячи-двух кадров в секунду.


#define MEGA // закаментить если TINY

#if defined(MEGA)
#define DATA_PIN    13
#define LATCH_PIN   12
#define CLOCK_PIN   11
#define BUTTON      8
#define BUZZ        10
#else
#define DATA_PIN    2
#define LATCH_PIN   1
#define CLOCK_PIN   0
//#define BUTTON      4
#define BUZZ        PB3
#endif


byte segment [11] = {
  0b11101110, 0b00100101, 0b01111011, 0b01110111, 0b10110101,
  0b11010111, 0b11011111, 0b01100101, 0b11111111, 0b11110111,
  0b00000000,
};

byte razr [4] = {0b01110000, 0b10110000, 0b11010000, 0b11100000};

int second;
byte minute;
int oneSec = 1000; // длительность секунды
int dbP = 500;     // длительность двоеточия

unsigned long timerSekond;                          // секундный таймер
unsigned long timerPik;                             // таймер пищалки
unsigned long timerDbP;                             // таймер двоеточия
bool pik = false;
bool dbpOn = false;



void setup() {
  pinMode(DATA_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(BUZZ, OUTPUT);
  show();

  minute = 59;
  second = 59;
  pikpik(500);
  timerSekond = millis() + oneSec;
  timerDbP = millis() + dbP;
}

void loop() {
  setDisp ();
  //  pikOff();
  if (millis() >= timerSekond) {
    second--;
    if (second < 0) {
      //      pikOn(600);
      minute--;
      if (!minute) {
        stopTrain();
      }
      second = 59;
    }
    timerSekond = millis() + oneSec;
  }
  if (millis() >= timerDbP) {
    dbpOn = !dbpOn;
    timerDbP = millis() + dbP;
  }
}

void stopTrain() {                           // закончили
  digitalWrite(LATCH_PIN, LOW);
  writeByteP(0b00000000);
  writeByteP(0b01010011);
  digitalWrite(LATCH_PIN, HIGH);
  pikpik(1000);
  while (true);
}

void setDisp () {  // динамический секундомер
  byte digit;
  for (byte i = 0; i < 4; i++) {
    switch (i) {
      case 0:
        digit = second % 10;
        break;
      case 1:
        digit = second / 10;
        break;
      case 2:
        digit = minute % 10;
        break;
      case 3:
        digit = minute / 10;
        break;
    }
    byte segRaz = razr[i];
    byte segDig = segment[digit];
    (dbpOn) ? (segDig &= ~(1)) : (segDig |= 1);
    PBdigWL(LATCH_PIN);
    writeByteP(segRaz);
    writeByteP(segDig);
    PBdigWH(LATCH_PIN);
  }
}

void pikpik(int dur) {
  digitalWrite(BUZZ, HIGH);
  delay(dur);
  digitalWrite(BUZZ, LOW);
  delay(500);
  digitalWrite(BUZZ, HIGH);
  delay(dur);
  digitalWrite(BUZZ, LOW);
  delay(500);
}

inline void writeByteP(byte byteW) {                          // аналог shiftOut, работает намного быстрее
  for (int i = 0; i <= 7; i++)
  {
    if (bitRead(byteW, i)) {
      PBdigWH(DATA_PIN);
    } else {
      PBdigWL(DATA_PIN);
    }
    PBdigWH(CLOCK_PIN);
    PBdigWL(CLOCK_PIN);
  }
}

inline void PBdigWH(byte NB) {
  PORTB |= 1 << NB;
}

inline void PBdigWL(byte NB) {
  PORTB &= ~(1 << NB);
}

void show() {
  digitalWrite(LATCH_PIN, LOW);
  writeByteP(0b11111111);
  writeByteP(0b01010011);
  digitalWrite(LATCH_PIN, HIGH);
}

Вариант выделенного "драйвера индикатора" на Attiny. Число передается по UART от внешнего источника, Тинька его принимает и крутит на индикаторе. Освобождает главный МК от необходимости делать это самостоятельно.

//
// индикатор на ATTINY85/13
// компилить на 8МГц
// фьюзы DF, E2

#include <SoftwareSerial.h>

#define rx          3
#define tx          4
SoftwareSerial mySerial(rx, tx);

#define DATA_PIN    2    // индикатор пины
#define LATCH_PIN   1
#define CLOCK_PIN   0

int Val = 1234;
int i = 0;
char buf[8];

byte segment [12] = {
  0b11101110, 0b00100101, 0b01111011, 0b01110111, 0b10110101,
  0b11010111, 0b11011111, 0b01100101, 0b11111111, 0b11110111,
  0b00000000, 0b01010011,
};
byte razr [4] = {0b11100000, 0b11010000, 0b10110000, 0b01110000};

void setup() {
  pinMode(DATA_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);

  pinMode(rx, INPUT);
  pinMode(tx, OUTPUT);
  mySerial.begin(9600);
//  Serial.begin(9600);
}

void loop() {
  setDisp(Val);               // выводим число на индикатор
  //Serial.println(Val,DEC);
  if (mySerial.available() > 0) {
    buf[i] = mySerial.read();
    //Val=int(buf[3]) - 0x30;
    if (int(buf[i]) == 10) { // || int(buf[i]) == 10) {
      Val = (buf[1] - 0x30) * 1000 + (buf[2] - 0x30) * 100 + (buf[3] - 0x30) * 10 + (buf[4] - 0x30);
      i = 0;
    }
    i++;
  }
}


void setDisp (int Val) { // вывод на индикатор
  byte digit;
  for (byte i = 0; i < 4; i++) {
    switch (i) {
      case 0:
        digit = Val / 1000;
        break;
      case 1:
        digit = Val / 100 % 10;
        break;
      case 2:
        digit = Val / 10 % 10;
        break;
      case 3:
        digit = Val % 10;
        break;
    }
    byte segRaz = razr[i];
    byte segDig = segment[digit];
    PDdigWL(LATCH_PIN);
    writeByteP(segRaz);
    writeByteP(segDig);
    PDdigWH(LATCH_PIN);
    if (i < 3) delayMicroseconds(150); // выравнивание яркости (200мкс)
  }
}


inline void writeByteP(byte byteW) { // аналог shiftOut, работает намного быстрее
  for (byte i = 0; i <= 7; i++)
  {
    if (bitRead(byteW, i)) {
      PDdigWH(DATA_PIN);
    } else {
      PDdigWL(DATA_PIN);
    }
    PDdigWH(CLOCK_PIN);
    PDdigWL(CLOCK_PIN);
  }
}

inline void PDdigWH(byte NB) {
  PORTB |= 1 << NB;
}

inline void PDdigWL(byte NB) {
  PORTB &= ~(1 << NB);
}

 

А вот вариант для секундомера на  Attiny, катоды и аноды на ножках МК. Засвет идеально ровный за счет доводки таймингов по осциллографу. 

// индикатор на ATTINY2313
// компилить на 8МГц
// фьюзы HDF, LE4 - внутренний резонатор 8МГц (требуется подстройка OSCCAL)
// фьюзы HDF, LDE - внешний кварц 8МГц (рекомендуется)


unsigned int Val;
// i = 0;
unsigned int digit;
byte MIN = 60;
byte SEC = 00;
long timerSEC;
long timerBEEP;
long timerPRESS;
bool BEEP;
bool DOT;
bool oldPress = 0;

#define trimming 20      // время на антидребезг
#define oneSec 1000      // 1 секунда
#define longPress 2000   // длинное нажатие (мин)

byte segment [10] = {
  0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110,
  0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111,
};

void(* resetFunc) (void) = 0;

void setup() {
  //  OSCCAL = 80;       // подкрутка генератора (для каждого МК свой) по умолчанию 96 на 8МГц (чем меньше тем делает медленней)
  DDRB = 0b11111111; //76543210
  DDRD = 0b00111101; //NNGGGGKP
  //  timerDOT
  MIN = 60; //60;
  SEC = 00; //00
  Val = MIN * 100 + SEC;
  PORTB |= (1 << 7);
  DOT = 1;
  while (PIND & 2) setDisp(Val);
  delay(trimming);
  while (~PIND & 2) setDisp(Val);
  delay(trimming);
  beep(500);
  timerSEC = millis() + oneSec;
}

void loop() {
  setDisp(Val);               // выводим число на индикатор
  beepStop();
  if (timerSEC <= millis()) {  // минус секунда
    (DOT) ? (PORTB &= ~(1 << 7)) : (PORTB |= (1 << 7)); // точка
    DOT = !DOT;
    if (!SEC) {
      if (!MIN) Stop(); // закончили своим ходом
      MIN--;
      SEC = 59;
    } else {
      SEC--;
    }
    timerSEC = millis() + oneSec;
    Val = MIN * 100 + SEC;
    if (Val == 3000) beep(500);
    if (Val == 1000) beep(500);
    if (Val == 500) beep(1000);
  }

  if (!(PIND & 2)) { // остановка таймера кнопкой
    delay(trimming);
    timerPRESS = millis();
    while (~PIND & 2) {
      setDisp(Val);
      beepStop();
    }
    delay(trimming);
    if ((millis() - timerPRESS) > longPress) {
      Reset();
    } else {
      Pause();
    }
  }
  if (PIND & 64) { // остановка таймера окончанием задания
    Stop();
  }
}

inline void beep (int ms) {
  timerBEEP = millis() + ms;
  PORTD |= 1;
  BEEP = 1;
}

inline void beepStop () {
  if (BEEP) {
    if (timerBEEP < millis()) {
      PORTD &= ~1;
      BEEP = 0;
    }
  }
}

void Pause() {
  beep(200);
  while (PIND & 2) {
    setDisp(Val);
    beepStop();
    if (timerSEC <= millis()) {  // минус секунда
      (DOT) ? (PORTB &= ~(1 << 7)) : (PORTB |= (1 << 7)); // точка
      DOT = !DOT;
      timerSEC = millis() + 100;
    }
  }
  delay(trimming);
  timerPRESS = millis();
  while (~PIND & 2) setDisp(Val);
  delay(trimming);
  if ((millis() - timerPRESS) > longPress) Reset();
  beep(200);
}

void Reset () {
  resetFunc();
}

void Stop() {
  //  Val = 0;
  timerSEC = millis() + 2000;
  beep(1000);
  while (timerSEC > millis()) {
    setDisp(Val);
    beepStop();
  }
  while (PIND & 2) setDisp(Val);
  delay(trimming);
  while (~PIND & 2) setDisp(Val);
  delay(trimming);
  resetFunc();
}


inline void setDisp (int Val) { // вывод на индикатор
  for (byte ii = 0; ii < 4; ii++) {
    switch (ii) {
      case 0:
        digit = Val / 1000;
        break;
      case 1:
        digit = Val / 100 % 10;
        break;
      case 2:
        digit = Val / 10 % 10;
        break;
      case 3:
        digit = Val % 10;
        break;
    }
    //    PORTD |= 0b00111100;
    PORTD |= 0b00111100;
    PORTB &= 0b10000000;
    delayMicroseconds(2);
    PORTB |= segment[digit];
    PORTD &= ~(1 << (ii + 2));
    if (ii != 3) delayMicroseconds(150); // выравниваем яркость разрядов
  }
}

Все скетчи рабочие, выдраны из готовых устройств.

Есть еще интересый вариант на базе специальной микросхемы TM1380, но это уже другая история.

Вячеслав 151
Offline
Зарегистрирован: 25.03.2015

Добрый день!

Может кто из местных гуру найдет ошибку в выводе информации на дисплей. 4-х битный 7-сегментный модуль на сдвиговых регистрах 595-х.  В сериале все нормально работает показывает, а на дисплей переменные не выводит. Константы выводит нормально.

 //Термогигрометр на SHT и семисегмнтном индикаторе
 
 int latchPin = 7;     // Пин "защелки" первого регистра подключен к RCLK (SS, ST_CP) входу 
 int clockPin = 6;    // Пин "тактовый" подключен к SCLK (CLK, SH_CP) входу 74HC595
 int dataPin = 5;     // Пин "данных" подключен к QH (SDI, DS) входу 74HC595

 int TimeLight = 5;    // time для разогрева сегментов

 byte SegDisplay;      // Переменная для вывода символов на индикаторе
 byte RazrDisplay;     // Переменная для включения разрядов

 // Настройка комбинации для отображения каждого номера на индикаторе
 // Массив цифр, генерирующий на сегментах цифры в двоичной системе исчисления
 byte g_digits[25]={
 B11000000, B11111001, B10100100, B10110000, B10011001,   // 0 1 2 3 4
 B10010010, B10000010, B11111000, B10000000, B10010000,   // 5 6 7 8 9
 B01000000, B01111001, B00100100, B00110000, B00011001,   // 0. 1. 2. 3. 4.
 B00010010, B00000010, B01111000, B00000000, B00010000,   // 5. 6. 7. 8. 9. 
 B01111111, B10111111, B10011100, B11000110,   // ., -, °, С
 B11111111, }; 		                       // all segm.
 byte g_registerArray[4]={1,2,4,8}; //массив цифр, указывающий разряды
   
   
  #include <SHT1x.h>

  // Data and Сlock датчика  SHT1x 
  #define dataPin  10 
  #define clockPin 11 
  
  SHT1x sht1x(dataPin, clockPin);
   int temp_c=0;       // Переменная для целых чисел температуры               
     int humidity=0;     // Переменная для целых чисел влажности 
  
  void setup()
 { 
   Serial.begin(9600); 
   // pin 
  pinMode(latchPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
 }

 void loop()
 {
   
       
           
         temp_c = sht1x.readTemperatureC();
        Serial.print(temp_c); 
        Indicate(0, 22);      // °
        Indicate(1, (temp_c % 10));   // пишем во второй разряд - последнюю целую цифру 
        Indicate(2, (temp_c % 100) / 10);  // пишем в третий разряд - цифру оставшуюся от деления на 100 
        Indicate(3, (temp_c / 100));       // пишем в четвертый разряд - цифру делёную на 100
        delay(2000);
        
        humidity = sht1x.readHumidity();
        
        Serial.print(humidity); 
        Indicate(0, 21);      // -
        Indicate(1,(humidity % 10)+10);      // пишем во второй разряд -  цифру оставшуюся от деления на 10 с точкой
        Indicate(2, humidity / 10);   // пишем в третий разряд - цифру оставшуюся от деления на 10 
        Indicate(3, 21);          // -
        delay(2000);
       }
     
  
 void Indicate(int r,int x) // Функция собственно, отображения цыфр на индикаторе.
  {
    SegDisplay=g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
    RazrDisplay=g_registerArray[r];  // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
    digitalWrite(latchPin, LOW);   // устанавливаем синхронизацию "защелки" на LOW
      shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay);  // Записываем информацию для первого регистра (Номер символа)
      shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда)
     // shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay);  // Записываем информацию для первого регистра (Номер символа)
    digitalWrite(latchPin, HIGH);  //"защелкиваем" регистр, тем самым устанавливая значения на выходах
  
    delay(TimeLight); // пауза, чтобы сегменты "разгорелись"
  }

  

 

alexeko
Offline
Зарегистрирован: 03.01.2014

Что я Вам могу посоветовать. Вот накидал код, проверил. ПРАВДА я не стал циклом перебор выводимого "числа" делать, а просто определил место вывода. Все работает. НО! у меня дисплей немного не как у Вас. Смысл главное.

#include <Wire.h>

#include "RTClib.h"
RTC_DS1307 RTC;

int latchPin = 2;     //Пин "защелки" первого регистра подключен к ST_CP входу первого регистра отвечающего за сегменты 
int clockPin = 3;    //Пин подключен к SH_CP входу 74HC595
int dataPin = 4;     //Пин подключен к DS входу 74HC595

int TimeLight = 2;  //время для разогрева сегментов

byte SegDisplay; // переменная для вывода символов на индикаторе
byte RazrDisplay; // переменная для включения разрядов

// Настройка комбинации для отображения каждого номера на дисплее.

byte g_digits[17]={
B00111111, B00000110,    // 0 1
B01011011, B01001111,    // 2 3
B01100110, B01101101,    // 4 5
B01111101, B00000111,    // 6 7
B01111111, B01101111,    // 8 9
B00000000,
B00000001,  // A 11
B00000010,  // B 12
B00000100,  // C 13
B00001000,  // C 14
B00010000,  // C 15
B00100000,  // C 16
}; // 
byte g_digits1[11]={
B10111111, B10000110,    // 0 1
B11011011, B11001111,    // 2 3
B11100110, B11101101,    // 4 5
B11111101, B10000111,    // 6 7
B11111111, B11101111,    // 8 9
B00000000,
};

byte g_registerArray[8]={~32,~16,~8,~4,~2,~1,~128,~64}; //массив цифр, указывающий разряды

byte g_button[8];
// задаем константы
const int buttonPin1 = 12;     // номер входа, подключенный к кнопке
const int buttonPin2 = 11; 
// переменные
int buttonState1 = 0;         // переменная для хранения состояния кнопки
int buttonState2 = 0;


void setup() {
  
 
     Wire.begin();
     RTC.begin();
    
    
// обозначаем все пины как выходы
  pinMode(latchPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
      
  // инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin1, INPUT); pinMode(buttonPin2, INPUT); 
}

void loop() {
  
 DateTime now = RTC.now();   
  int hour,minute,disp,sec = 0;
  //Serial.print(now.hour(), DEC);
  hour = now.hour(); // Считываем значение часов
  minute = now.minute(); // Считываем значение минут
  sec=now.second();
  
  //disp = (hour * 100) + minute; //"Собираем" значения часов и минут в одну цифру
 
  if (minute < 10) // если наша цифра меньше 10, то
  {
    Indicate(3, 0); // пишем в третий разряд пусто
    Indicate(2, minute); // пишем в четвертый разряд нашу цифру
  }
  if (minute > 9) // если наша цифра меньше 10, то
  {
    Indicate(3, minute /10); // пишем в третий разряд пусто
    Indicate(2, minute % 10); // пишем в четвертый разряд нашу цифру
  }
 if (hour < 10) // если наша цифра меньше 10, то
  {
    Indicate(5, 0); // пишем в третий разряд пусто
    Indicate(4, hour); // пишем в четвертый разряд нашу цифру
  }
 if (hour > 9) // если наша цифра меньше 10, то
  {
    Indicate(5, hour /10); // пишем в третий разряд пусто
    Indicate(4, hour% 10); // пишем в четвертый разряд нашу цифру
  }
 
  if (sec < 10) // если наша цифра меньше 10, то
  {
    Indicate(1, 0); // пишем в третий разряд пусто
    Indicate(0, sec); // пишем в четвертый разряд нашу цифру
  }
 if (sec > 9) // если наша цифра меньше 10, то
  {
    Indicate(1, sec /10); // пишем в третий разряд пусто
    Indicate(0, sec% 10); // пишем в четвертый разряд нашу цифру
  }
  ///////////////////////////////////////////////////
  // считываем значения с входа кнопки
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  // проверяем нажата ли кнопка
  // если нажата, то buttonState1 будет HIGH:
  if (buttonState1 == HIGH){   
    // включаем светодиод   
    g_button[0]=1;
  }
  
  if (buttonState2 == HIGH) {     
    g_button[0]=0;
    }


  if(g_button[0]==1){
    Indicate(7, 11);
  }else {
     Indicate(7, 10);
  }
  if(g_button[1]==1){
    Indicate(6, 14);
  }else {
     Indicate(6, 10);
  }
  
  
 // Зажигаем точки  слева
   //Indicate(7, 11);
   //Indicate(7, 12);
  // Indicate(7, 13);
   // Зажигаем точки  справа
  // Indicate(6, 14);
  // Indicate(6, 15);
  // Indicate(6, 16);
 

 }

void Indicate(int r,int x)
{
 if(r==4){ 
SegDisplay=g_digits1[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифр}е.
}
else{
SegDisplay=g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
}
RazrDisplay=g_registerArray[r];  // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
  digitalWrite(latchPin, LOW);  // устанавливаем синхронизацию "защелки" на LOW
      shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда)
      shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay);  // Записываем информацию для первого регистра (Номер символа)
  digitalWrite(latchPin, HIGH);  //"защелкиваем" регистр, тем самым устанавливая значения на выходах

   // delay(5); 
    
    
    
}

 

kdafilm
Offline
Зарегистрирован: 10.04.2016

А что это за дисплей

alexeko
Offline
Зарегистрирован: 03.01.2014


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

Вот, что получилось в итоге.

 

zlodey000
Offline
Зарегистрирован: 22.04.2016

CheBuraw,

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

Всем, кто приложил руки, к окончательному варианту, так же огромное спасибо!

blecs
Offline
Зарегистрирован: 30.06.2011

Подскажите, как подключить 8 индикаторов, и вывести на них 2 переменные. 4 и 4.

alexeko
Offline
Зарегистрирован: 03.01.2014

Как вывести - читайте выше #125.

как подключить - последовательно, это же динамическая индикация, выше все описано. Схема стандартная. Разницы нет сколько сигментов используете. Обычная математика. Увеличивается число управляемых элементов.

alexeko
Offline
Зарегистрирован: 03.01.2014

Вот, переделал на 12 вольт. Использовал датчики от охранных систем. Изменил твердотельные реле.

Белый шлейф - на индикатор, рядом с индикатором приклеены две микросхамки для индикации.

Черная колодка - подключается шлейф на клавиатуру.

pedro
Offline
Зарегистрирован: 08.10.2016

Всем привет. 

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

Назовем библиотеку Display7

Код для Display7.h

/*
  Display7.h - Library for use 4LED display with 2 TM74HC595.
  Created by B R, October 8, 2016.
*/
#ifndef Display7_h
#define Display7_h
  
class Display7
{
  public:
        Display7 (int clockPin, int latchPin, int dataPin);
        void ledDigitDisplay(float temperature);
	void Indicate();

  private:
    int _clockPin;
	int _latchPin;
	int _dataPin;
};
 
#endif

Код Display7.cpp

/*
  Display7.cpp - Library
*/
 
#include "Display7.h"
#include <Arduino.h>

Display7::Display7(int clockPin, int latchPin, int dataPin)

{
  pinMode(latchPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

_clockPin = clockPin;
_latchPin = latchPin;
_dataPin = dataPin;

byte digits[4] = {255,255,255,255};

}

  const byte table[11] = {
  B11000000, B11111001, B10100100, B10110000, B10011001,   // 0 1 2 3 4
  B10010010, B10000010, B11111000, B10000000, B10010000,   // 5 6 7 8 9
  B10111111};   // минус 

void ledDigitDisplay(float temperature)
{              
  int disp = temperature * 100;   // Избавляемся от десятых и сотых (оставляем челую часть числа)

  if(disp < -5500 || disp > 12500)
  {
    // Обработаем выход за пределы min и max температур
    for (int i = 0; i < 4; i++) 
      digits[4] = table[10]; // Ставим во всех разрядах прочерки
    return;
  }

  bool point = 0;
  if(disp < -999 || disp > 9999) disp /= 10;
  else point = 1;

  if(disp < 0) 
  {
    digits[3] = table[10];
    disp *= -1;
  }
  else digits[3] = table[disp/1000];

  for(byte i = 0; i < 3; i++)
  {
    digits[i] = table[disp%10];
    disp /= 10;
  }

  if(point) digits[2] &= B01111111; // точка
  else digits[1] &= B01111111; // точка
}



void Indicate() // Функция отображения цифр на индикаторе.
{
  static uint32_t premillis = 0;
  if(millis()-premillis < 2) return;
  premillis = millis();
  static byte digit = 0;

  digitalWrite(latchPin, LOW);   
  shiftOut(dataPin, clockPin, MSBFIRST, digits[digit]);  // символ
  shiftOut(dataPin, clockPin, MSBFIRST, 1<<digit); // разряд
  digitalWrite(latchPin, HIGH);  //"защелкиваем" 

  digit++;
  if(digit == 4) digit = 0;
}

Ну и сам пример для проверки. 

#include <Display7.h>
int latchPin = 6; 
int clockPin = 9;   
int dataPin = 7;   


void setup() {
  // put your setup code here, to run once:
  pinMode(latchPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
}

void loop() {
  // put your main code here, to run repeatedly:
 ledDigitDisplay(12.34);
 Indicate();
}

Выдает ошибку что функции в loop не заданы. Где прокол? Камнями не кидайте. 

sirota
Offline
Зарегистрирован: 18.08.2015

pedro пишет:

Ну и сам пример для проверки. 

#include <Display7.h>
int latchPin = 6; 
int clockPin = 9;   
int dataPin = 7;   


void setup() {
  // put your setup code here, to run once:
  pinMode(latchPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
}

void loop() {
  // put your main code here, to run repeatedly:
 ledDigitDisplay(12.34);
 Indicate();
}

Выдает ошибку что функции в loop не заданы. Где прокол? Камнями не кидайте. 

Вы прикидываетесь? Где определения 

ledDigitDisplay();

и

Indicate();

?

pedro
Offline
Зарегистрирован: 08.10.2016

sirota пишет:

Вы прикидываетесь? Где определения 

ledDigitDisplay();

и

Indicate();

?

Они же в библиотеке. Все примеры создания библиотек что я нашел, делалилсь примерно так. Я по аналогии и сделал. 

Как по вашему должен выглядить пример? 

pedro
Offline
Зарегистрирован: 08.10.2016

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

Т.е, пусть будет температура. Получил я значение 23.50 и мне нужно тображать его 5 секунд. Внезависимости от того, что температура за бортом изменилась. 

sirota
Offline
Зарегистрирован: 18.08.2015

pedro пишет:

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

Т.е, пусть будет температура. Получил я значение 23.50 и мне нужно тображать его 5 секунд. Внезависимости от того, что температура за бортом изменилась. 


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

pedro
Offline
Зарегистрирован: 08.10.2016

sirota пишет:
Я думаю стоит начать с изучения языка программирования и принципов программирования, потом читать ошибки и варнинги компилчтора, а потом вам нужен будет таймер.

Я думаю, что если нечего сказть, то следует помолчать. 

Нет желание отвечать на четкий вопрос, нечего и клавиши напрягать. 

sirota
Offline
Зарегистрирован: 18.08.2015

pedro пишет:

sirota пишет:
Я думаю стоит начать с изучения языка программирования и принципов программирования, потом читать ошибки и варнинги компилчтора, а потом вам нужен будет таймер.

Я думаю, что если нечего сказть, то следует помолчать. 

Нет желание отвечать на четкий вопрос, нечего и клавиши напрягать. 


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

pedro
Offline
Зарегистрирован: 08.10.2016

Где целая задача? 

Вопрос четкий 

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

Еще раз, есть что сказать по сути моего вопроса? 

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

denya35a
Offline
Зарегистрирован: 13.09.2017

А не могли бы вы подсказать, как в вашем коде сделать настройку часов с кнопок?

Повторил ваш проект, все работает

alexeko
Offline
Зарегистрирован: 03.01.2014

denya35a пишет:

А не могли бы вы подсказать, как в вашем коде сделать настройку часов с кнопок?

Повторил ваш проект, все работает

Спасибо, что все работает. Тут такое дело. Я перевел "ЭТО безобразие" на ESP8266. Через WIFI, по MQTT проще менять и подстраивать данные, часы то же. НО! Часы, как модуль, можно выкинуть, хотя идут почти точно. Данные времени можено брать из GOOGle. Давно хотел объединить все проекты в доме.

По кнопачкам и настройке часов. Поставте модуль WiFi или bluetooth, и по Tx/Rx гоняйте данные с телефона. Но лучше esp8266.

denya35a
Offline
Зарегистрирован: 13.09.2017

Спасибо, наверно так и сделаю

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Добрый день!

Заказал вот такой дисплей для домашних часов/термометра/барометра.

Не нашел отдельного выхода для изменения яркости - можно как то реализовать регулировку?

Нашёл решение, отбой вопросу, придут модули - буду пробовать

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Отвечаю сам себе: реализовал подобие ШИМ с 7 сегментным индикатором,

выкладываю скетч часов/термометра/барометра - может кому пригодиться

#include <Wire.h>
#include <RTClib.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

#define DS_TPN 8 // DS18B20 grey
// GND black +5V white

OneWire oneWire(DS_TPN);
DallasTemperature sensors(&oneWire);

#define FOTORES A1 // grey
// GND yellow +5V maroon

#define RTC_SDA A4 // - red
#define RTC_SCL A5 // - black
// GND white +5V grey

RTC_DS1307 RTC;

//#define LED_PWM 9 // - OE on 74HC595
#define LED_SCLK 10 // - blue
#define LED_RCLK 11 // - green
#define LED_DIO 12 // - maroon
// GND yellow +5V orange

#define CYCLE_GET_TIME 60
#define CYCLE_SHOW 4
#define CYCLE_GET_TEMP 243

#define BMP_SCK 4
#define BMP_MISO 5
#define BMP_MOSI 6
#define BMP_CS 7

//Adafruit_BMP280 bmp; // I2C
//Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO,  BMP_SCK);

byte LED_0F[33] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E, 0xC2, 0x89, 0xF9, 0xF1, 0xC3, 0xA9, 0xC0, 0x8C, 0x98, 0x92, 0xC1, 0x91, 0xFE, 0xBF, 0xFF, 0x9C, 0xAB};
// 0123456789AbCdEFGHIJLnOPqSUY_- (null) (degree) (mm)
byte LED_NU[8] = {16, 32, 64, 128, 1, 2, 4, 8};
byte LED_BUF[8] = {30, 30, 30, 30, 30, 30, 30, 30};
byte LED_PWM = 3; // level light 7 = MAX 0 = MIN
byte PWM_MAX[8] = {0b00000001, 0b00010001, 0b00100101, 0b01010101, 0b01011101, 0b11011101, 0b11111101, 0b11111111}; // matrix level light
byte cicle_pwm = 0; //0..7

byte dd = 99; // day
byte mm = 99; // month
byte yh = 99; // high year
byte yl = 99; // low year
byte ho = 99; // hour
byte mi = 99; // minute
float tt = 99; // temp
float pr = 99; // pressure
float ut = 99; // street temp
byte lu = 10; // last data street temp - MAX = 9

unsigned long timerSec = 0;
byte timerGetTime = 37;
byte timerShow = 0;
byte timerGetTemp = 242;
byte flShow = 0; // 0 time and temp 1 date 2 press

void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LED_SCLK, OUTPUT);
  pinMode(LED_RCLK, OUTPUT);
  pinMode(LED_DIO, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  Serial.begin(9600);
  delay(1000);
  sensors.begin();
  pinMode(LED_PWM, OUTPUT);
  Wire.begin();
  if (! RTC.begin()) {
    while (1);
  }
  if (! RTC.isrunning()) {
    // following line sets the RTC to the date & time this sketch was compiled
    // RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  bmp.begin();
}

byte addPoint(byte inByte) {
  byte outByte = (inByte << 1);
  outByte = (outByte >> 1);
  return outByte;
}

void showLedBuf() {
  // select level light
  byte flbit;
  flbit = bitRead(PWM_MAX[LED_PWM], cicle_pwm);
  if (flbit == 1) {
    for (byte i = 0; i <= 7; i++) {
      digitalWrite(LED_RCLK, LOW);
      //shiftOut(LED_DIO, LED_SCLK, MSBFIRST, LED_0F[LED_BUF[i]]);
      shiftOut(LED_DIO, LED_SCLK, MSBFIRST, LED_BUF[i]); // full light
      shiftOut(LED_DIO, LED_SCLK, MSBFIRST, LED_NU[i]);
      digitalWrite(LED_RCLK, HIGH);
    }
  } else {
    // delay analog full light
    for (byte i = 0; i <= 7; i++) {
      digitalWrite(LED_RCLK, LOW);
      shiftOut(LED_DIO, LED_SCLK, MSBFIRST, 255); // empty
      shiftOut(LED_DIO, LED_SCLK, MSBFIRST, 255);
      digitalWrite(LED_RCLK, HIGH);
    }
  }
  // -
  ++cicle_pwm;
  if (cicle_pwm > 7) {
    cicle_pwm = 0;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  // count timers
  unsigned long ctmr = (long(millis() / 1000));
  if ((timerSec > 4294900) && (ctmr < 100)) {
    timerSec = 0;
  }
  if (ctmr > timerSec) {
    timerSec = ctmr;
    ++timerGetTime; ++timerShow; ++timerGetTemp;
    if (timerGetTime >= CYCLE_GET_TIME) {
      timerGetTime = 0;
      // get time and date
      DateTime now = RTC.now();
      dd = now.day();
      mm = now.month();
      yh = (now.year()) / 100;
      yl = (now.year()) % 100;
      ho = now.hour();
      mi = now.minute();
    }
    if (timerShow >= CYCLE_SHOW) {
      timerShow = 0;
      switch (flShow) {
        case 1 : {
            // show date
            if ((dd >= 1) && (dd <= 31)) {
              if (dd < 10) {
                LED_BUF[0] = LED_0F[30]; LED_BUF[1] = LED_0F[(dd % 10)];
              } else {
                LED_BUF[0] = LED_0F[(dd / 10)]; LED_BUF[1] = LED_0F[(dd % 10)];
              }
            } else {
              LED_BUF[0] = LED_0F[30]; LED_BUF[1] = LED_0F[30];
            }
            LED_BUF[1] = addPoint(LED_BUF[1]);
            if ((mm >= 1) && (mm <= 12)) {
              if (mm < 10) {
                LED_BUF[2] = LED_0F[0]; LED_BUF[3] = LED_0F[(mm % 10)];
              } else {
                LED_BUF[2] = LED_0F[(mm / 10)]; LED_BUF[3] = LED_0F[(mm % 10)];
              }
            } else {
              LED_BUF[2] = LED_0F[30]; LED_BUF[3] = LED_0F[30];
            }
            LED_BUF[3] = addPoint(LED_BUF[3]);
            if ((yh >= 20) && (yh <= 29) && (yl >= 00) && (yl <= 99)) {
              LED_BUF[4] = LED_0F[(yh / 10)]; LED_BUF[5] = LED_0F[(yh % 10)];
              if (yl < 10) {
                LED_BUF[6] = LED_0F[0]; LED_BUF[7] = LED_0F[(yl % 10)];
              } else {
                LED_BUF[6] = LED_0F[(yl / 10)]; LED_BUF[7] = LED_0F[(yl % 10)];
              }
            } else {
              LED_BUF[4] = LED_0F[30]; LED_BUF[5] = LED_0F[30]; LED_BUF[6] = LED_0F[30]; LED_BUF[7] = LED_0F[30];
            }
            ++flShow;
            break;
          }
        case 2 : {
            // show press
            if ((pr >= 600) && (pr <= 900)) {
              LED_BUF[0] = LED_0F[30]; LED_BUF[1] = LED_0F[30]; LED_BUF[5] = LED_0F[30];  LED_BUF[6] = LED_0F[32]; LED_BUF[7] = LED_0F[32];
              int hp = int(pr);
              LED_BUF[2] = LED_0F[(hp / 100)];
              byte pd = hp % 100;
              LED_BUF[3] = LED_0F[(pd / 10)]; LED_BUF[4] = LED_0F[(pd % 10)];
              flShow = 0;
              break;
            } else {
              LED_BUF[0] = LED_0F[30]; LED_BUF[1] = LED_0F[30]; LED_BUF[2] = LED_0F[30]; LED_BUF[3] = LED_0F[30];
              LED_BUF[4] = LED_0F[30]; LED_BUF[5] = LED_0F[30]; LED_BUF[6] = LED_0F[30]; LED_BUF[7] = LED_0F[30];
              flShow = 0;
            }
          }
        default : {
            // show time and temp
            if ((ho >= 0) && (ho <= 23)) {
              if (ho < 10) {
                LED_BUF[0] = LED_0F[30]; LED_BUF[1] = LED_0F[(ho % 10)];
              } else {
                LED_BUF[0] = LED_0F[(ho / 10)]; LED_BUF[1] = LED_0F[(ho % 10)];
              }
            } else {
              LED_BUF[0] = LED_0F[30]; LED_BUF[1] = LED_0F[30];
            }
            LED_BUF[1] = addPoint(LED_BUF[1]);
            if ((mi >= 0) && (mi <= 59)) {
              if (mi < 10) {
                LED_BUF[2] = LED_0F[0]; LED_BUF[3] = LED_0F[(mi % 10)];
              } else {
                LED_BUF[2] = LED_0F[(mi / 10)]; LED_BUF[3] = LED_0F[(mi % 10)];
              }
            } else {
              LED_BUF[2] = LED_0F[30]; LED_BUF[3] = LED_0F[30];
            }
            // show temp
            if ((tt >= (-30)) && (tt <= 40)) {
              byte ta;
              if (tt < 0) {
                LED_BUF[4] = LED_0F[29]; ta = abs(tt);
              } else {
                LED_BUF[4] = LED_0F[30]; ta = tt;
              }
              if (ta < 10) {
                LED_BUF[5] = LED_0F[30]; LED_BUF[6] = LED_0F[(ta % 10)];
              } else {
                LED_BUF[5] = LED_0F[(ta / 10)]; LED_BUF[6] = LED_0F[(ta % 10)];
              }
              LED_BUF[7] = LED_0F[31];
            } else {
              LED_BUF[4] = LED_0F[30]; LED_BUF[5] = LED_0F[30]; LED_BUF[6] = LED_0F[30]; LED_BUF[7] = LED_0F[30];
            }
            ++flShow;
          }
      }
    }
    if (timerGetTemp >= CYCLE_GET_TEMP) {
      timerGetTemp = 0;
      // get temp and bar
      sensors.requestTemperatures(); tt = sensors.getTempCByIndex(0);
      Serial.print("current DS18B20 = "); Serial.println(tt);
      if (tt == 0.00) {
        tt = 99;
      } else {
        tt = tt + 0.51;
      }
      // get bmp280
      pr = bmp.readPressure() / 133.322;
    }
  }
  // show info
  showLedBuf();
  // set display light
  word ll = analogRead(FOTORES);
  LED_PWM = map(ll, 0, 1023, 0, 7);
  //--- end loop
}



mag155
Offline
Зарегистрирован: 21.12.2017

Всем привет ! Такой вопрос как выводить с помощью вашего скетч значение переменной на экран. Например показание с потенцыометра ?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Заполнить нужными цифрами буфер в 46 строке скетч из 144 сообщения. 

mag155
Offline
Зарегистрирован: 21.12.2017

Всем привет пытаюсь подключить 6 сегментный индикатор на двух сдвиговых регистрах . Но работает только три сегмента и первый сегмент дублирует третий . Тоесть например цыфра 36 выводится как 636. В чем причина подскажите ??

mag155
Offline
Зарегистрирован: 21.12.2017

Всем привет пытаюсь подключить 6 сегментный индикатор на двух сдвиговых регистрах . Но работает только три сегмента и первый сегмент дублирует третий . Тоесть например цыфра 36 выводится как 636. В чем причина подскажите ??

mag155
Offline
Зарегистрирован: 21.12.2017

За основу взят скетч с 47 сообщения.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

mag155 пишет:

 6 сегментный индикатор на двух сдвиговых регистрах

что за чудо такое ? посмотреть бы

и хотелось бы увидеть ваш скетч измененный, а не основу скетча с 47 сообщения