Семи сигметный индикатор и массив из разрядов и сигментов

Jtest
Offline
Зарегистрирован: 02.06.2015

Дань добрый. Сижу 3й день, не могу понять как правильно реализовать.

Хочу через про мини подсоединить семи сигметный индикатор (+точка) на 9 разрядов. Физически это сделал, портов хватило. Начал кодить  и тут - повалились проблемы. Не буду приводить свой код, т.к. уже не знаю сколько раз он переписан и первоначальный вариант утерян, остался с кучей костылей и нерабочий.

Суть такая: Хочу создать массив из разрядов, в котором есть массив из сигментов. Но только, чтоб это был не int, а текстовый формат. Т.е, чтобы засветить "0" на первом разряде, а "1" - на втором, массив выглядит следующим образом

prt[0]=('11111100'); // ABCDEFGH
prt[1]=('01100000');

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

Как нужно вначале объявить prt массив, чтоб не ругался о неоответствии конвертации форматов? Как разбить значение ячейки, чтобы обработать каждый символ?

Прошу помощи, т.к. я уже запутался.

b707
Offline
Зарегистрирован: 26.05.2017

Jtest пишет:

Суть такая: Хочу создать массив из разрядов, в котором есть массив из сигментов. Но только, чтоб это был не int, а текстовый формат.

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

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

Jtest пишет:
Как нужно вначале объявить prt массив, чтоб не ругался о неоответствии конвертации форматов


например для девяти элементов
char prt[9][]=('11111100');

Jtest
Offline
Зарегистрирован: 02.06.2015

Может Вы и правы, пытался и как Вы описываете, но знаний не хватает. Уже несколько дней пытаюсь разобраться, только больше запутываюсь. По-этому на форум и обратился.

b707
Offline
Зарегистрирован: 26.05.2017

Jtest пишет:

Может Вы и правы, пытался и как Вы описываете, но знаний не хватает. Уже несколько дней пытаюсь разобраться, только больше запутываюсь. По-этому на форум и обратился.

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

Jtest
Offline
Зарегистрирован: 02.06.2015

void ALS_write(String source)
{
  int j, kj;
  unsigned char n;
  j = 0;
  while (j < 9) { // количество символов на индикаторе
    n = source[j];
    if (n == '0') {
      displayMessage(j, "11111100"); //Цифра 0
    }
    else if (n == '1') {
       displayMessage(j, "01100000"); //Цифра 1
    }
    j++;
  }
}

void loop() {
  source_f = String("101");
  ALS_write(source_f);
}
void displayMessage(int dignum, String dorw) {
for (int i = 0; i < 9; i++) { // Каждый разряд по очереди  
  unsigned char m;
  for (int k = 0; k < 8; k++) {// Каждый сегмент по очереди 
    m = dorw[k];
    if (m == '1') {
      digitalWrite(segmentsPins[k],  HIGH );
    }
  }
if (i==dignum)digitalWrite(anodPins[i], LOW);
delay(1);
digitalWrite(anodPins[i], HIGH);
}
}

Сейчас в трех разрядах мигают нули (при source_f = String("101");). при source_f = String("11111"); - 5 единиц.

Вопрос.1) Почему заметно мерцание, если задержка только "1", 2) почему неверное отображение? Где моя ошибка, я уже не в состоянии отследить (запутался)?

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

Ну текствый формат не глупость. Так можно создать char строку и вывести на экран дисплея. Это удобно при написании программ. Но не все символы ASCII  можно вывести на семисегментник. Так что приходится писать свою кодировку для знаков, что бы реализовать это. Укорочено это кодировка в 17 знаков (0123456789AbcdEF и пробел)

Jtest
Offline
Зарегистрирован: 02.06.2015

qwone, я хочу добавить нексолько русских символов, для обозначения режимов работы. Например, буква "P" у меня дожна выглядеть так:

    else if (n == 'P') {
       displayMessage(j, "11001110"); 
    }

 

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Я делал так:

int myVal[8]; // Массив хранящий номера символов для выводв на LED
static byte myDig[] = { 0, 6, 91, 79, 102, 109, 125, 7, 127, 111, 63, 134, 219, 207, 230, 237, 253, 135, 255, 239, 191, 99, 57, 227, 121, 120, 80, 92};
//                      s  1   2   3    4    5    6  7    8    9   0   1d   2d   3d   4d   5d   6d   7d   8d   9d   0d   D   C   Dd   E    t   r   o
// Коды соответствующие символам от " " до 0, потом от 1. до 0. потом знак градуса, знак С и знак градуса с точкой (прозапас)

В программе заполнял myVal[ ] тем что нужно выводить на экран. И в прерывании от таймера:

void Timer1_action() {  // Обработчик прерывания
  byte tp=1;   // Содержимое регистра позиции
  if (Pos == 9) { // Если позиция вышла за предел
    Pos=1;        // Позиция приравнивается к 1
    Time++;       // Мой счетчик времени
  }
  byte sym = myDig[myVal[Pos]];  // Содержимое знакового регистра
  tp=tp << (Pos-1);  // Вычисление содержимого регистра позиции
  tp=255^tp ;        // Побитовое инвертирование регистра позиции
  PORTC = 0;    // Гашение предыдущего символа
  PORTB = sym;  // Вывод нового символа
  PORTC = tp;  // Зажигание нового символа
  Pos++; // Переход к следующей позиции

}

Порты B и C - условные, что-то мне не найти скетч где использовались реальные. При этом порт С - общие для разрядов, порт В собственно выводы разряда.

P.S. Да говнокод, но давно я это писал и не переписывал ибо работает.

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Глючный форум дважды отправил пост.

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

Jtest . Программирование это смесь фундаментальных знаний и копромисов. Сильно много умов решались оптимизировать процесс программирования. И не оперется на их опыт глупо. Но я не хочу ради вам переносить эти знания сюда в вашу тему. Уж лучше вы туда идите. 

 Есть ASCII код. И в нем нет русских знаков. Русские знаки в уникоде. И все это байда нужна только что бы все написать просто

const char * line="12345"; 
display.print(line);

 

Jtest
Offline
Зарегистрирован: 02.06.2015

Alex-GK, для меня Ваш код - дремучий лес)) Не "дорос" до этого уровня. qwone, я, наверно, понял, что Вы хотели сказать, но у меня другой механизм.

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Jtest пишет:

Alex-GK, для меня Ваш код - дремучий лес)) Не "дорос" до этого уровня. qwone, я, наверно, понял, что Вы хотели сказать, но у меня другой механизм.

Не поверите, мне знакомо это чувство, до сих пор частенько бывает.

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

Jtest
Offline
Зарегистрирован: 02.06.2015

Alex-GK, Хорошо если до вечера ничего не придумаю, так и сделаю. Все-же хочется понять самому механизм, чтобы больше не обращаться.

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Механизм простой - отвяжитесь от char-ов, кодируйте зажигаемые сегменты битами, для наглядности можете записывать их как  B01010101.

И в вашем коде в сообщении 4 управление анодным пином засуньте в цикл перебора разрядов.

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

Alex-GK, здесь вы не разобрались в принципах. У ТС есть семисегметный дисплей. Но он без внутреней памяти и динамической индикации.  Вот Ардуине и надо ее организовать. Если у ТС 10 сегментов то нужен массив char buff[10]; из которого и обновлять изображение на дисплее.  Но вот вопрос как заносить информацию в этот буфер . Можно так void write(byte Pos,byte Data); а можно void print(char *Str);Если в первом случае можно по форме зажигаемого символ. То во втором уже ASCII коде в котором все незажигаемые символы банально игнорируются.

ПС: Пляска вокруг точки легко решается "1" и "1." печатаются в одно знакоместо

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Вы не правы, я разобрался уже давно и не раз реализовал.

Только у меня буфер в int , Он у меня называется myVal [ ].

А вот у ТС все немного иначе, вместо буфера у него строка source_f. И он в функции ALS_write, проходит по строке и пытается выводить символы процедурой displayMessage, в которой опять же перебирает строковую переменную digw в которой "закодирован" выводимый символ.

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
//----Дисплей-------------
char buffDisplay[10] = "0123456789";
byte cursorDisplay = 0;
void initDisplay() {} //иницирование дисплея
void showDisplay() {} // динамический вывод на экран
void clearDisplay() {}// очистка экрана
void setCursor(byte Pos){}// поставить курсор в позицию
void writeDisplay(byte Pos, byte Data) {}
void printDisplay(char *Str) {}// вывод строки
void printDisplay(char data) {}// вывод знака
//--------------------------------
char *line = "00000000";
//---main-----------------------------
void setup() {
  initDisplay();
  printDisplay(line);
}

void loop() {
  showDisplay();

}

 

bwn
Offline
Зарегистрирован: 25.08.2014

Alex-GK пишет:

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

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

Jtest
Offline
Зарегистрирован: 02.06.2015

Всем спасибо. Сделал по своему, получилось. Выводит и цифры и буквы (насколько можно).  Сейчас обвешиваю устровйство основным фукнционалом. Если интересно, через день-два, отшлифую код, размещу.

Alex-GK
Offline
Зарегистрирован: 10.04.2012

bwn пишет:

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

В принципе можно и так, все таки биты в байте, а не символы в стринг.

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

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

Jtest, как только функционалом наполните, так сразу только что описанное мной вылезет.

bwn
Offline
Зарегистрирован: 25.08.2014

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

Alex-GK
Offline
Зарегистрирован: 10.04.2012

Ну если два...

А я 12 в ряд запихал на меге, там заметно. У ТС вроде бы 9, тоже не мало.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
//----Дисплей-------------
char buffDisplay[10] = "0123456789";
byte cursorDisplay = 0;
void initDisplay() {} //иницирование дисплея
void showDisplay() {} // динамический вывод на экран
void clearDisplay() {}// очистка экрана
void setCursor(byte Pos) {} // поставить курсор в позицию
void writeDisplay(byte Pos, byte Data) {}
void printDisplay(char *Str) {}// вывод строки
void printDisplay(char data) {}// вывод знака
//--------------------------------
#include <MsTimer2.h>
char *line = "00000000";
//---main-----------------------------
void setup() {
  initDisplay();
  printDisplay(line);
  MsTimer2::set(100, showDisplay); // 100ms период
  MsTimer2::start();
}

void loop() {

}

 

Jtest
Offline
Зарегистрирован: 02.06.2015

Вот такой у меня получился приборчик с применением pro mini и индикатора АЛС318А (без дешифраторов):

https://youtu.be/-4n8-n5b_ss