mag155, дайте определение динамической индикации, а не выжимайте из AVR невозможного. Если динамику делать на ардуинке, то считаем: время затухания светодиода, после того как убираете напряжение и скорость обновления (полного прохода) по коду. Тут, как писано в старых учебниках, надо, при большом количестве диодов, повышать напряжение, что бы горели лучше. Но, индикатор может сгореть, если что то не так пойдет. Если мигает - результат большого времени работы программного кода.
Есть отдельные драйвера, которые сами делают индикацию, а ардуинка подает только данные для определенного диода.
А, так получается, Вы пытаетесь что выжать из ее максимума. Я не хочу Вас обидеть. Просто надо искать ошибки не только кода, но и железа.
Я и пытаюсь с ардуинки сделать драйвер чтоб можно было подключать любой индикатор. И к моему восторгу это таки получилось. Сейчас просто передаю значение с другой ардуины потенциометра но что то голова совсем зависла передает только от 0до 250 а надо от 0 до 1023??? Пойду наверно кофе бахну.
void loop() {
if (radio.available()) {
while (radio.available()) {
val = radio.read();
}
float numbers[] = {val};
Serial.println(val);
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
getDigits(numbers[numindex]);
numindex += 1;
if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
}
displayMessage(arr);
}
}
фигня получилась - скобки расставьте правильно, а то получается что отображение на дисплей происходит с периодом interval только в том случае если по SErial вам что то придет иначе ничего не отображается
нарисуте на бумаге (или в голове мысленно) что должно происходить
1. т.е. каждые полсекунды чтение датчика
2. при каждом loop отображение значения датчика
3. при приеме байта (слова) из Serial выводить в монитор число и что то делать
и все это должно работать независимо друг от друга
То что индикатор работает только если пришли данные мне подходит . Но я не пойму где вы видите что он моргает с периодом интервал ??? Подскажите а то реально не пойму где?
void loop() {
if (radio.available()) {
while (radio.available()) {
val = radio.read();
}
float numbers[] = {val};
Serial.println(val);
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
getDigits(numbers[numindex]);
numindex += 1;
}
if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
displayMessage(arr);
}
}
вот и разбирайтесь почему, т.е. эту переменную надо сделать или глобальной и учитывать в функции рисования или передавать значение как второй параметр в процедуру.
Чтоб отображать точку, надо установить нужный бит в нужное состояние, соответственно в вашей процедуре заполняющей нужные биты необходимо дополнить нужное условие, например если второй разряд = установить 7 бит - одна строка программы
В начале темы автор сделал схему подключения скетч для индикатора с общим анода. Что можно сделать если индикатор с общим катодом? без транзисторов не обойтись?
Только у вас там где 1 должен быть 0. К примеру цифра "0" при общем аноде имеет
бинарный вид: 11000000 = 192 в десятичном виде, при общем катоде:
бинарный вид: 00111111 = 63 в десятичном виде, и так далее для остальных символов.
При этом не забудте поправить и массив для разрядов. там так же нужно пересчитать по тому же принципу:
общий анод, первый разряд 00000001 = 1
общий катод, 11111110 = 254
а можно еще проще для разрядов - имеющийся адрес вычитать из 255:
255-1=254, 255-2=253, 255-4=251, 255-8=247 и тогда для разрядов адреса будут такие:
А нужны ли эти заморочки когда есть дешевая микросхема TM1650, а также TM1637 TM1638
Лично я затеял все это потому что было много трофейных 74hc595 и думал куда их можно пристроить, хотелось вообще разобраться как с ними можно работать и нужен был индикатор для одной поделки.
Лично я затеял все это потому что было много трофейных 74hc595 и думал куда их можно пристроить, хотелось вообще разобраться как с ними можно работать и нужен был индикатор для одной поделки.
Да я тоже самое делал. Просто сейчас если и ставить только расширения выходных портов, для семисегментного уже пожалуй нет
Есть статья на радиокоте https://www.radiokot.ru/lab/controller/08/ с использованием 9 разрядов 7 сегментного индикатора от телефона Русь 25-27. Лежал у меня подобный индикатор но сравнив схемы я обнаружил в своем варианте некоторые отличия и решил отрисовать свой вариант. Плата панельки построена на 3-х индикаторах TOT-3361AH-1N с общим катодом и двух сдвиговых регистра 74HC595D.
Сегменты распаяны хаотично. Первым идет сдиговый регистр разрядов а потом сегментов.
Вывести что то адекватное на него не получается. Код привожу ниже, адаптировав его под Общий катод и сдвиговые регистры.
1) То есть нужно воять свою таблицу символов под данную распайку сегментов?
int latchPin = 10; //Пин "защелки" первого регистра подключен к ST_CP входу первого регистра отвечающего за сегменты
int clockPin = 13; //Пин подключен к SH_CP входу 74HC595
int dataPin = 12; //Пин подключен к DS входу 74HC595
int TimeLight = 2; //время для разогрева сегментов
int sensorPin = A0;
byte SegDisplay; // переменная для вывода символов на индикаторе
byte RazrDisplay; // переменная для включения разрядов
// Настройка комбинации для отображения каждого номера на дисплее.
// Комбинация выбрана на основе таблицы отображаемого знака данным порта
// Соответственно { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , dp, - }
byte g_digits[12] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 128, 64}; //OK, массив цифр, генерирующий из сегментов цифры
byte g_registerArray[9] = {254, 253, 251, 247, 239, 223, 191, 127, 255}; //OK, массив цифр, указывающий разряды
void setup() {
// обозначаем все пины как выходы
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
int disp = 0; //создаем переменную для вывода на экран
int analogueValue = analogRead(sensorPin); // читаем аналоговый пин A0
analogueValue = map(analogueValue, 0, 1023, 0, 8888); //преобразуем диапазон с А0 (0-1023) в нужный нам (0-8888)
disp = analogueValue; // записываем получившуюся после преобразования цифру в переменну для вывода на экран
// Разбиваем цифру по разрядам индикатора
if (disp < 10) // если наша цифра меньше 10, то
{
Indicate(5, 11); // пишем в первый разряд пусто
Indicate(6, 11); // пишем во второй разряд пусто
Indicate(7, 11); // пишем в третий разряд пусто
Indicate(8, disp); // пишем в четвертый разряд нашу цифру
}
else if (disp < 100) // если наша цифра меньше 100, то
{
Indicate(5, 11); // пишем в первый разряд пусто
Indicate(6, 11); // пишем во второй разряд пусто
Indicate(7, disp / 10); // пишем в третий разряд - цифру делёную на 10
Indicate(8, disp % 10); // пишем в четвертый разряд цифру оставшуюся от деления на 10
/*
Допустим наша цифра 25.
Если мы ее поделим на 10, то у нас получится 2,5. Цифры после запятой, в данном случае,
у нас не остаются. Таким образом мы имеем в третем разряде цифру 2.
В чевертый разряд мы, как раз и записываем цифру-остаток полученную в результате деления.
В нашем случае это и есть та самая 5.
Аналогичным образом разбивается наша цифра и далее.
*/
}
else if (disp < 1000)
{
Indicate(5, 11);
Indicate(6, disp / 100);
Indicate(7, (disp % 100) / 10);
Indicate(8, disp % 10);
}
else
{
Indicate(5, disp / 1000);
Indicate(6, (disp % 1000) / 100);
Indicate(7, (disp % 100) / 10);
Indicate(8, 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); // пауза, чтобы сегменты "разгорелись"
}
2) Как адаптировать код на радиокоте под 9 разрядов к данной реализации?
Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!
Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!
ну там вроде все понятно обьяснено. Загружаете последовательно, сначала данные для 9-ого разраяда - в виде 0b00000000 для включения, 0b11111111 для выключения. а потом биты остальных восьми разрядов. Защелкиваете Latch и наслаждаетесь
Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!
ну там вроде все понятно обьяснено. Загружаете последовательно, сначала данные для 9-ого разраяда - в виде 0b00000000 для включения, 0b11111111 для выключения. а потом биты остальных восьми разрядов. Защелкиваете Latch и наслаждаетесь
Все оказалось намного проще, мал мал поправил код для 328p (Ардуино нано) и все получилось!
// WinAvr
#include <avr/io.h>
#include <avr/interrupt.h>
#define DATA 5
#define SHIFT 6
#define STORAGE 7
#define PORTSERIAL PORTD
#define DDRSERIAL DDRD
#define BUT 0
#define BIT(bit) (1<<(bit))
unsigned char lcd_buffer[9] = {0xEB, 0x48, 0x73, 0x7A, 0xD8, 0xBA, 0xBB, 0x68, 0xFB};
//*************************************************************
void data_shift(unsigned char data)
{
// выводим бит данных, сдвигаем и так 8 раз.
unsigned char i = 0;
for (i = 8; i ; i--) {
if (data & BIT(i - 1) ) PORTSERIAL |= BIT(DATA); // выводим бит данных
else PORTSERIAL &= ~BIT(DATA);
PORTSERIAL |= BIT(SHIFT); // сдвиг данных
PORTSERIAL &= ~BIT(SHIFT);
}
}
//*************************************************************
void num_out(unsigned char znmesto)
{
unsigned char i = 0;
PORTSERIAL |= BIT(STORAGE); // выводы микросхем в Z состояние
data_shift(lcd_buffer[znmesto]);// загружаем символ в первый регистр
if (znmesto == 7) i = 1; //7 знакоместо
if (znmesto == 8) i = 2; //8 знакоместо
znmesto = ~(1 << (znmesto)); // число в бит места (пример 0х3->0b11110111)
data_shift(znmesto);// вывод знакоместа, символ сдвигается в второй регистр
if ( i == 0 )
{
PORTSERIAL &= ~BIT(STORAGE);
PORTSERIAL |= BIT(STORAGE); // сохранили
PORTSERIAL &= ~BIT(STORAGE); // и вывели
}
else if (i >= 1) { // 7 знакоместо
PORTSERIAL &= ~BIT(STORAGE);
PORTSERIAL |= BIT(SHIFT) | BIT(STORAGE); // сохранили и вывели
PORTSERIAL &= ~(BIT(SHIFT) | BIT(STORAGE));
//shift нужен потому что 0 переместился из Q6 в -Q7
}
if (i == 2) data_shift(0x0); //9 разряд.
//Сейчас все выходы первого регистра уст в 1,
//загружаем регистр нулями в итоге -Q7 = 0, но не сохроняем.
PORTSERIAL &= ~(BIT(DATA) | BIT(SHIFT) | BIT(STORAGE));
}
//*************************************************************
int main( void )
{
unsigned char i = 0;
PORTSERIAL = BIT(BUT) | BIT(STORAGE);
DDRSERIAL = 0xf0;
TCCR0B = 3;
while (1) {
TCNT0 = 127;
while (!(TIFR0 & BIT(0))); // Задержка такая :-) по идеи 2ms
TIFR0 |= 1;
//if ( !TESTBIT(PIND,BUT) ) //если включить то вывод цифры
{
//while ( !TESTBIT(PIND,BUT) );// будет только по нажатию
if (i > 8) i = 0;
num_out(i);
i++;
}
}
}
http://arduino.ru/Reference/Serial/Available
Получилось вот так
Значение через val не могу вывести больше 250 ???
mag155, дайте определение динамической индикации, а не выжимайте из AVR невозможного. Если динамику делать на ардуинке, то считаем: время затухания светодиода, после того как убираете напряжение и скорость обновления (полного прохода) по коду. Тут, как писано в старых учебниках, надо, при большом количестве диодов, повышать напряжение, что бы горели лучше. Но, индикатор может сгореть, если что то не так пойдет. Если мигает - результат большого времени работы программного кода.
Есть отдельные драйвера, которые сами делают индикацию, а ардуинка подает только данные для определенного диода.
А, так получается, Вы пытаетесь что выжать из ее максимума. Я не хочу Вас обидеть. Просто надо искать ошибки не только кода, но и железа.
Точнее передать только 0-250
Я и пытаюсь с ардуинки сделать драйвер чтоб можно было подключать любой индикатор. И к моему восторгу это таки получилось. Сейчас просто передаю значение с другой ардуины потенциометра но что то голова совсем зависла передает только от 0до 250 а надо от 0 до 1023??? Пойду наверно кофе бахну.
Получилось вот так
фигня получилась - скобки расставьте правильно, а то получается что отображение на дисплей происходит с периодом interval только в том случае если по SErial вам что то придет иначе ничего не отображается
нарисуте на бумаге (или в голове мысленно) что должно происходить
1. т.е. каждые полсекунды чтение датчика
2. при каждом loop отображение значения датчика
3. при приеме байта (слова) из Serial выводить в монитор число и что то делать
и все это должно работать независимо друг от друга
а щас у вас каша и в голове и в коде
Так кажись лучше отображается когда что-то пришло и без периода интерва
Так кажись лучше отображается когда что-то пришло и без периода интерва
и как можно разобраться по этому огрызку кода, в котором даже не понятно где начало и конец фигурных скобок
Пардон
и чем последний код отличается от кода в сообщении 252?
ЗЫ. Вы мне напоминаете одного программиста из одной очень известной компании России,
промышленный банковский продукт, ошибка в работе его части кода,
он частенько тупо менял названия переменных, и типа исправил :)
естественно ошибка так и осталась.
То что индикатор работает только если пришли данные мне подходит . Но я не пойму где вы видите что он моргает с периодом интервал ??? Подскажите а то реально не пойму где?
вот так попробуйте
В порту данные есть а на индикаторе Err .??
В порту данные есть а на индикаторе Err .??
ниче не понял в чем вопрос
В порту цифры 66 на индикаторе Err а должно быть тоже 66 ?
вот смотрите:
приходят данные , переводятся в переменную val, выводяться в монитор,
далее каждые interval времени процедура getDigits формирует строку символов для вывода на экран - правильно?
возникает вопрос: а эта процедура которая формирует строку - она использует переменную val с исходными данными?
Получается что нет.
Получается что нет.
вот и разбирайтесь почему, т.е. эту переменную надо сделать или глобальной и учитывать в функции рисования или передавать значение как второй параметр в процедуру.
Ок.
Здялал так
И видимость переменной
Пкретикуйте если не сложно ??
Работает? Устраивает? Значит нефиг ломать работающее.
Работает устраивает. Но чё то точку не отображает?
Даже если вот так пишу показует только 9
Чтоб отображать точку, надо установить нужный бит в нужное состояние, соответственно в вашей процедуре заполняющей нужные биты необходимо дополнить нужное условие, например если второй разряд = установить 7 бит - одна строка программы
А разве 45 и 46 строки не для этого ?
Или все дело в 63 строке?
И 73 с 74 ?
Вроде они, но как видите не работает)
Разбираться надо - некогда
ПРОБЛЕМА ОКАЗАЛАСЬ В БИБЛИОТЕКЕ
Доброго времени суток решил добить тему с индикатором. Вопрос как допилить код чтоб работатл со здвиговыми регистрами как например в 174 сообщении ???
Доброго времени суток.
В начале темы автор сделал схему подключения скетч для индикатора с общим анода. Что можно сделать если индикатор с общим катодом? без транзисторов не обойтись?
Нужно управлять минусом тоест low.
Делаю все по схеме так же?
по части скетча где нужно поменять?
Буду благодарен за совет?
А нужны ли эти заморочки когда есть дешевая микросхема TM1650, а также TM1637 TM1638
Делаю все по схеме так же?
по части скетча где нужно поменять?
Буду благодарен за совет?
Вам нужно поправить только в этом месте:
А рассчитать можно по аналогии с табличкой:
Только у вас там где 1 должен быть 0. К примеру цифра "0" при общем аноде имеет
бинарный вид: 11000000 = 192 в десятичном виде, при общем катоде:
бинарный вид: 00111111 = 63 в десятичном виде, и так далее для остальных символов.
При этом не забудте поправить и массив для разрядов. там так же нужно пересчитать по тому же принципу:
общий анод, первый разряд 00000001 = 1
общий катод, 11111110 = 254
а можно еще проще для разрядов - имеющийся адрес вычитать из 255:
255-1=254, 255-2=253, 255-4=251, 255-8=247 и тогда для разрядов адреса будут такие:
Если лень вспоминать школьный курс информатики ;)
А нужны ли эти заморочки когда есть дешевая микросхема TM1650, а также TM1637 TM1638
Лично я затеял все это потому что было много трофейных 74hc595 и думал куда их можно пристроить, хотелось вообще разобраться как с ними можно работать и нужен был индикатор для одной поделки.
Лично я затеял все это потому что было много трофейных 74hc595 и думал куда их можно пристроить, хотелось вообще разобраться как с ними можно работать и нужен был индикатор для одной поделки.
Да я тоже самое делал. Просто сейчас если и ставить только расширения выходных портов, для семисегментного уже пожалуй нет
Получилось спасибо большое!
Всем привет.
Есть статья на радиокоте https://www.radiokot.ru/lab/controller/08/ с использованием 9 разрядов 7 сегментного индикатора от телефона Русь 25-27. Лежал у меня подобный индикатор но сравнив схемы я обнаружил в своем варианте некоторые отличия и решил отрисовать свой вариант. Плата панельки построена на 3-х индикаторах TOT-3361AH-1N с общим катодом и двух сдвиговых регистра 74HC595D.
Сегменты распаяны хаотично. Первым идет сдиговый регистр разрядов а потом сегментов.
Вывести что то адекватное на него не получается. Код привожу ниже, адаптировав его под Общий катод и сдвиговые регистры.
1) То есть нужно воять свою таблицу символов под данную распайку сегментов?
2) Как адаптировать код на радиокоте под 9 разрядов к данной реализации?
1) [РЕШЕНО]
Изменил кодовую страницу под данное подключение сегментов так
Все цифры отображаются нормально!
2) 9 разряд подключен на Q7S (14 и 9 пин регистра сдвига) [НЕ РЕШЕНО]
Как решение с радиокота перенести на ардуино код?
1) Только Вам хотел написать, что надо под свою распайку индивидуально коды указывать, а Вы уже всё решили :)
2) Могу заблуждаться, но предположу что 9 разряд не подключить, так как у 595 всего 8 выходов, а Q7S создан для иных задач- Выход для последовательного соединения регистров. Тут хорошая статья про 74hc595: https://codius.ru/articles/Arduino_Сдвиговый_регистр_74НС595_или_размножаем_экономим_выходы_платы
Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!
Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!
ну там вроде все понятно обьяснено. Загружаете последовательно, сначала данные для 9-ого разраяда - в виде 0b00000000 для включения, 0b11111111 для выключения. а потом биты остальных восьми разрядов. Защелкиваете Latch и наслаждаетесь
Знаний маловато, можно Вас попросить показать на примере?
Ну судя по решению с радиокота, автор там четко описал как юзая связку пина 9 и 14 двух регистров сдвига он смог использовать 9 разряд. Вот бы его решение перенести на ардуино код. Жалко терять 9 разряд!
ну там вроде все понятно обьяснено. Загружаете последовательно, сначала данные для 9-ого разраяда - в виде 0b00000000 для включения, 0b11111111 для выключения. а потом биты остальных восьми разрядов. Защелкиваете Latch и наслаждаетесь
Все оказалось намного проще, мал мал поправил код для 328p (Ардуино нано) и все получилось!
Всем спасибо за пинОК )))
Пофиксенный вариант.