Вывод информации на 6 разрядов 7ми сегментного индикатора
- Войдите на сайт для отправки комментариев
Здравствуйте!
Для одного проекта потребовалось выводить 6 цифр подряд, т.е. нужно шесть разрядов. (За основу была взята работа отсуда.) Т.к. под рукой небыло ничего кроме индикаторов KEM-4021BS (сдвоенный семисегментный с ОА) соединил их на макетке и вывел с каждого в один A,B,C,D,E,F,G и на каждый сегмент "+".
Все это должно! работать в динамической индикации с двумя 74НС595.

НО! Вот тут и начинается проблема. Не хатает знаний в программировании.
int latchPin = 8; //Пин "защелки" первого регистра подключен к ST_CP входу первого регистра отвечающего за сегменты
int clockPin = 12; //Пин подключен к SH_CP входу 74HC595
int dataPin = 11; //Пин подключен к DS входу 74HC595
int TimeLight = 5; //время для разогрева сегментов
int sensorPin=A0;
byte SegDisplay; // переменная для вывода символов на индикаторе
byte RazrDisplay; // переменная для включения разрядов
// Настройка комбинации для отображения каждого номера на дисплее.
// Комбинация выбрана на основе таблицы отображаемого знака данным порта
// Соответственно { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , dp, - }
byte g_digits[12]={192,249,164,176,153,146,130,248,128,144,127,255}; //массив цифр, генерирующий из сегментов цифры
byte g_registerArray[6]={1,2,4,8,16,32}; //массив цифр, указывающий разряды
void setup() {
// обозначаем все пины как выходы
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
int disp = 0; //создаем переменную для вывода на экран
disp = 8888;
// Разбиваем цифру по разрядам индикатора
if (disp < 10) // если наша цифра меньше 10, то
{
Indicate(0, 11); // пишем в первый разряд пусто
Indicate(1, 11); // пишем во второй разряд пусто
Indicate(2, 11); // пишем в третий разряд пусто
Indicate(3, 11); // пишем в третий разряд пусто
Indicate(4, 11); // пишем в третий разряд пусто
Indicate(5, disp); // пишем в четвертый разряд нашу цифру
}
else if (disp < 100) // если наша цифра меньше 100, то
{
Indicate(0, 11); // пишем в первый разряд пусто
Indicate(1, 11); // пишем во второй разряд пусто
Indicate(2, 11); // пишем во второй разряд пусто
Indicate(3, 11); // пишем во второй разряд пусто
Indicate(4, disp / 10); // пишем в третий разряд - цифру делёную на 10
Indicate(5, disp % 10); // пишем в четвертый разряд цифру оставшуюся от деления на 10
}
else if (disp < 1000)
{
Indicate(0, 11);
Indicate(1, 11);
Indicate(2, 11);
Indicate(3, disp / 100);
Indicate(4, (disp % 100) / 10);
Indicate(5, disp % 10);
}
else if (disp < 10000)
{
Indicate(0, 11);
Indicate(1, 11);
Indicate(2, disp / 1000);
Indicate(3, (disp % 1000) / 100);
Indicate(4, (disp % 100) / 10);
Indicate(5, disp % 10);
}
else if (disp < 100000)
{
Indicate(0, 11);
Indicate(1, disp / 10000);
Indicate(2, (disp % 10000) / 1000);
Indicate(3, (disp % 1000) / 100);
Indicate(4, (disp % 100) / 10);
Indicate(5, disp % 10);
}
else
{
Indicate(0, disp / 1000000);
Indicate(1, (disp % 100000) / 10000);
Indicate(2, (disp % 10000) / 1000);
Indicate(3, (disp % 1000) / 100);
Indicate(4, (disp % 100) / 10);
Indicate(5, 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); // пауза, чтобы сегменты "разгорелись"
}
Как видно из кода, за вывод цифр (значений) отвечает переменная disp.
Если число из 4х знаков, то все отображается отлично
disp=7777;

Если знаков больше четырех, то показывает все что угодно.
disp=77777;

По этому прошу помочь. Расскажите где я ошибся и как это исправить. Буду очень благодарен!
А готовый 8-разрядный индикатор чем не устраивает?
http://ru.aliexpress.com/item/J34-Free-Shipping-1PCs-8-Bits-Digital-Tube-LED-Display-Module-Eight-Serial-for-Arduino-595/32402492405.html?spm=2114.30010708.3.2.b0oJpO&ws_ab_test=searchweb201556_2,searchweb201644_5_505_506_503_504_301_502_10001_10002_10016_10005_10006_10012_10003_10004_10007,searchweb201560_8,searchweb1451318400_-1,searchweb1451318411_6448&btsid=95d99567-d907-4294-9819-0955122e9f41
164р
http://ru.aliexpress.com/item/7-Segment-LED-Display-Module-5V-MAX7219-High-Quality-8-Bit-Red-Digital-Tube-For-Arduino/32551946287.html?spm=2114.30010708.3.61.b0oJpO&ws_ab_test=searchweb201556_2,searchweb201644_5_505_506_503_504_301_502_10001_10002_10016_10005_10006_10012_10003_10004_10007,searchweb201560_8,searchweb1451318400_-1,searchweb1451318411_6448&btsid=95d99567-d907-4294-9819-0955122e9f41
на макс7219 - 375р
http://ru.aliexpress.com/item/MAX7219-8-bit-digital-tube-display-module-...
тоже на максе 198р
Я в курсе существования Aliexpress и что на нем есть. Я же сказал, что использовал то что было у меня в наличии.
Когда я задумал 3 месяца назад свой проект и хотел хоть прикинуть варианты реализации - поставил протеуса и нарисовал в минимальном варианте схему. Т.к. модуль 4-секционного индикатора в моделях протеуса не нашел - подкинул 4 индикатора и 595, на нем и опробовал как будет выглядеть. Но перед этим заказал индикаторы с али. После НГ они приехали - и через пару недель на макете все заработало.
Могу кинуть на свой проект в протеусе - но там 4 секции. Но можно добавить еще 2 и разбираться с кодом....
Причина в строке 26
int disp = 0;
максимальное значение 32767. Надо
long disp;
Andy, огромное спасибо. Я бы наверное и не додумался.
Теперь все нормально работает.
disp=123456;
и еще сразу обнаружилась ошибка в строке 81.
ее заменить на
Продолжаю свой проект дальше и сталкнулся с новой проблемой. Проблема заключается в некорректном отображении данных, а конкретно с миганием которое я убрать не могу.
#include <Wire.h> #include "RTClib.h" #include "DHT.h" // подключаем библиотеку #define DHTPIN 2 // вывод, к которому подключается датчик DHT dht(DHTPIN, DHT11); // определяем тип датчика: 22 или 11 RTC_DS1307 RTC; int latchPin = 8; //Пин "защелки" первого регистра подключен к ST_CP входу первого регистра отвечающего за сегменты int clockPin = 12; //Пин подключен к SH_CP входу 74HC595 int dataPin = 11; //Пин подключен к DS входу 74HC595 int TimeLight = 4; //время для разогрева сегментов byte SegDisplay; // переменная для вывода символов на индикаторе byte RazrDisplay; // переменная для включения разрядов byte g_digits[12] = {192, 249, 164, 176, 153, 146, 130, 248, 128, 144, 127, 255}; //массив цифр, генерирующий из сегментов цифры byte g_registerArray[6] = {1, 2, 4, 8, 16, 32}; //массив цифр, указывающий разряды void setup() { dht.begin(); // датчик передает данные Wire.begin(); RTC.begin(); // обозначаем все пины как выходы pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); } void loop() { long hour, minute, sec, disp = 0; DateTime now = RTC.now(); hour = now.hour(); minute = now.minute(); sec = now.second(); if (sec > 10 && sec < 20) { disp = dht.readHumidity(); } else { disp = (hour * 10000) + (minute * 100) + sec; } // Разбиваем цифру по разрядам индикатора if (disp < 10) // если наша цифра меньше 10, то { Indicate(0, 11); // пишем в первый разряд пусто Indicate(1, 11); // пишем во второй разряд пусто Indicate(2, 11); // пишем в третий разряд пусто Indicate(3, 11); // пишем в третий разряд пусто Indicate(4, 11); // пишем в третий разряд пусто Indicate(5, disp); // пишем в четвертый разряд нашу цифру } else if (disp < 100) // если наша цифра меньше 100, то { Indicate(0, 11); // пишем в первый разряд пусто Indicate(1, 11); // пишем во второй разряд пусто Indicate(2, 11); // пишем во второй разряд пусто Indicate(3, 11); // пишем во второй разряд пусто Indicate(4, disp / 10); // пишем в третий разряд - цифру делёную на 10 Indicate(5, disp % 10); // пишем в четвертый разряд цифру оставшуюся от деления на 10 } else if (disp < 1000) { Indicate(0, 11); Indicate(1, 11); Indicate(2, 11); Indicate(3, disp / 100); Indicate(4, (disp % 100) / 10); Indicate(5, disp % 10); } else if (disp < 10000) { Indicate(0, 11); Indicate(1, 11); Indicate(2, disp / 1000); Indicate(3, (disp % 1000) / 100); Indicate(4, (disp % 100) / 10); Indicate(5, disp % 10); } else if (disp < 100000) { Indicate(0, 11); Indicate(1, disp / 10000); Indicate(2, (disp % 10000) / 1000); Indicate(3, (disp % 1000) / 100); Indicate(4, (disp % 100) / 10); Indicate(5, disp % 10); } else { Indicate(0, disp / 100000); Indicate(1, (disp % 100000) / 10000); Indicate(2, (disp % 10000) / 1000); Indicate(3, (disp % 1000) / 100); Indicate(4, (disp % 100) / 10); Indicate(5, 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); // пауза, чтобы сегменты "разгорелись" }Вот как выглядит проблема:
Думал записывать данные в EEPROM, но не помогло.
Вот в чем вопрос- как убрать мигание значений температуры? И если такое возможно, как добавить после темпетаруты знак "С"?
Продолжаю свой проект дальше и сталкнулся с новой проблемой. Проблема заключается в некорректном отображении данных, а конкретно с миганием которое я убрать не могу.
Некорректное отображение данных - это отображение заведомо неправильных данных.
Мигание индикатора - это неправильная работа системы отображения.
Что есть совсем разные вещи %(
Вот в чем вопрос- как убрать мигание значений температуры? И если такое возможно, как добавить после темпетаруты знак "С"?
Запись в еепром еще более длительная процедура. Кстати о птичках - память еепром имеет таки ограниченное число циклов записи - и использование ее вместо РАМ просто убьет чип. Впрочем 150р не деньги даже в условиях кризиса - можно и поменять... Только ждать с али долго, а покупать у нас дорого.
Убрать мигание очень просто - использовать не проц ардуино для розжига индикатора, а использовать контроллер который сам реализует динамическое управление индикатором. Цена вопроса копеечная, но принципы важнее.....
Знак С в HEX==12
Т.е. нормальный контроллер с библой знает как минимум 16-ю ситему - 0-9,A,b,C,d,E,F
другие символы нужно лепить самому правкой библиотеки. Если понимаешь что и как делать.
PS - мне пока не надо - потому не делал.
Да, орфографию поправь плиз....
С динамической индикацией я вообще не знаком поэтому буду разбираться как эт о вообще работает.
К вопросу о символе "С", не могу правильно записать строчку, что-то неправильно делаю.
disp = dht.readHumidity(), 199; - так не работает
Добавить в массив цифру
byte g_digits[13] = {192, 249, 164, 176, 153, 146, 130, 248, 128, 144, 127, 255, 198}; //массив цифр, генерирующий из сегментов цифры
Попробовать в какй нибудь разряд, например в 0:
Indicate(0, 12);
Код нужно несколько переписать.... завтра набросаю.
Возьми библу от тм1637 например - там 16 шестнадцеритьчных цифр....
static int8_t TubeTab[] = {0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};//0~9,A,b,C,d,E,F
Вот так для начала
char g_digitsArray[6]; void loop() { byte hour, minute, sec; DateTime now = RTC.now(); hour = now.hour(); minute = now.minute(); sec = now.second(); if (sec > 10 && sec < 20) {TempToDigits(dht.readHumidity());} else {TimeToDigits(hour, minute, sec);} Indicate(); } void TimeToDigits(byte hour, byte minute, byte sec) { g_digitsArray[0]=g_digits[hour/10]; g_digitsArray[1]=g_digits[hour%10]; g_digitsArray[2]=g_digits[minute/10]; g_digitsArray[3]=g_digits[minute%10]; g_digitsArray[4]=g_digits[sec/10]; g_digitsArray[5]=g_digits[sec%10]; } void TempToDigits(byte temp) { g_digitsArray[0]=255; g_digitsArray[1]=255; g_digitsArray[2]=255; g_digitsArray[3]=g_digits[temp/10]; g_digitsArray[4]=g_digits[temp%10]; g_digitsArray[5]=198; } void Indicate() { for (byte r=0; r<6; r++) { SegDisplay = g_digitsArray[r]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре. RazrDisplay = g_registerArray[r]; // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре. digitalWrite(latchPin, LOW); // устанавливаем синхронизацию "защелки" на LOW shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда) shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay); // Записываем информацию для первого регистра (Номер символа) digitalWrite(latchPin, HIGH); //"защелкиваем" регистр, тем самым устанавливая значения на выходах delay(TimeLight); // пауза, чтобы сегменты "разгорелись" } shiftOut(dataPin, clockPin, MSBFIRST, 255); // Выключаем индикацию }