Фантомная засветка на семисегментнике.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Доброго дня всем!

Экспериментирую с 7-семнетным индикатором. Для начала просто решил вывести цифры (1234). В итоге получаю "фантомную" засветку сегментов от предыдущей цифры "по кругу" - У 2 от 1 , у 3 от 2, у 4 от 3 и у 1 от 4. Да и цифры выводятся задом наперед (4321), но это пока мелочь.

Контроллер Atmega8A (тактовая от внутреннего генератора 1МГц, фьюз-биты "по умолчанию").

Код прилагаю:

// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК   =      { 15,      16,       17,       19,      14,      10,      9,       18}

// значения для вывода цифр 0-9

byte numbers[12] = {
  B11111100,  // | '0'             // Байт: ABCDEFGH
  B01100000,  // | '1'             //      A
  B11011010,  // | '2'             //    -----
  B11110010,  // | '3'             //   |     |
  B01100110,  // | '4'             //  F|  G  |B
  B10110110,  // | '5'             //   |-----|
  B10111110,  // | '6'             //  E|     |C
  B11100000,  // | '7'             //   |  D  |
  B11111110,  // | '8'             //    -----   * H
  B11110110,  // | '9'
};

// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
//        выводы МК = { 25,     23,       26,       24   }

void setup() {
  // Сконфигурировать контакты как выходы
  for (uint8_t i = 0; i < 8; i++) {
    pinMode(pinSegments[i], OUTPUT);
  }
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pinAnode[i], OUTPUT);
    digitalWrite(pinAnode[i], HIGH); // Выключаю
  }
}

void printNum (uint32_t num) {
  uint8_t bitNum;
  for (uint8_t i = 0; i < 4; i++) {
    if (num > 0) {
      bitNum = (uint8_t)(num % 10);
      for (int j = 0; j < 8; j++) {
        digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
      }
      num = num / 10;
    } else {
      num = 0;
      for (int j = 0; j < 8; j++) {
        digitalWrite(pinSegments[j], bitRead(numbers[num], 7 - j));
      }
    }
    for (uint8_t j = 0; j < 4; j++) {                           // | "Гашу" весь "дисплей":
      digitalWrite(pinAnode[j], HIGH);   // | 
    }
    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i    
    delay (2);
  }
}

void loop() {
  uint32_t number = 1234;
  printNum (number);
  delay(1);
}

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Используй ТМ1637, Люк. 

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

У меня тоже странные засветы были когда пробовал на делеях, затактовал на прерываниях от сети, исчезли. Эт не помощь, эт так, пожаловаться.))))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

DetSimen пишет:

Используй ТМ1637, Люк. 

Деда, мне нужно напрямую. Без ТМ1637. Да и у других то работает, даже на схожем коде... ((

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Попробуй поменять местами строки 53 и 54

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

BOOM пишет:

Деда, мне нужно напрямую. Без ТМ1637.

Значить, ты в джутовом мешке, с золотыми ногтями, хочешь странного. Я - пас. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

v258 пишет:

Попробуй поменять местами строки 53 и 54

Эффект нулевой (ничего не изменилось).

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

DetSimen пишет:

BOOM пишет:

Деда, мне нужно напрямую. Без ТМ1637.

Значить, ты в джутовом мешке, с золотыми ногтями, хочешь странного. Я - пас. 

ТМ1637 тоже ведь индикаторы не  волшебной палочкой зажигает.

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

Вы не слишком часто её дергаете? Поставьте в строке №54 5 вместо 2. Есть изменения?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Катоды "дрыгаю" тем что было под рукой - 2N3906. Мошт у них быстродействие низкое и поэтому такая ситуёвина возникает? Или это бред?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

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

Вы не слишком часто её дергаете? Поставьте в строке №54 5 вместо 2. Есть изменения?

Есть небольшие улучшения, но появилось заметное глазу мерцание.

Ради эксперимента - догнал значение до 20. Мерцание капец просто, но фантомы остались на уровне delay(5);

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Чтобы понять в аппаратной части проблемы или в программной - полез в интернет за примерами. Нашел вот такой громадный код (еле-еле в мегу8 влез):

// список выводов Arduino для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t segmentsPins[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК   =      { 15,      16,       17,       19,      14,      10,      9,       18}

// аноды/катоды семисегментного индикатора
uint8_t anodPins[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
//        выводы МК = { 25,     23,       26,       24   }

void setup() {
  for (int i = 0; i < 4; i++) pinMode(anodPins[i], OUTPUT);
  for (int i = 0; i < 8; i++) pinMode(segmentsPins[i], OUTPUT);
  Serial.begin(9600);
}

//{A, B, C, D, E, F, G,DP}
int seg[12][8] = {
  {1, 1, 1, 1, 1, 1, 0, 0}, //Цифра 0
  {0, 1, 1, 0, 0, 0, 0, 0}, //Цифра 1
  {1, 1, 0, 1, 1, 0, 1, 0}, //Цифра 2
  {1, 1, 1, 1, 0, 0, 1, 0}, //Цифра 3
  {0, 1, 1, 0, 0, 1, 1, 0}, //Цифра 4
  {1, 0, 1, 1, 0, 1, 1, 0}, //Цифра 5
  {1, 0, 1, 1, 1, 1, 1, 0}, //Цифра 6
  {1, 1, 1, 0, 0, 0, 0, 0}, //Цифра 7
  {1, 1, 1, 1, 1, 1, 1, 0}, //Цифра 8
  {1, 1, 1, 1, 0, 1, 1, 0}, //Цифра 9
  {0, 0, 0, 0, 0, 0, 1, 0}, //Знак -
  {0, 0, 0, 0, 0, 0, 0, 0}  //Пустой разряд
};

int err[4][8] = {
  {0, 0, 0, 0, 0, 0, 0, 0}, //Пусто
  {1, 0, 0, 1, 1, 1, 1, 0}, //E
  {0, 0, 0, 0, 1, 0, 1, 0}, //r
  {0, 0, 0, 0, 1, 0, 1, 0}  //r
};

float numbers[] = {520.45, 251, -12, 3.14159, 100000, -85.2563}; // По очереди будем показывать числа - на 100000 на дисплее будет отображена ошибка Err

static int arr[4][8]; // Переменная-массив для хранения данных, которые не нужно каждый раз пересчитывать

int numindex = 0;
float value = 0.0;

int counter = -1;
void loop() {
  counter += 1;
  if ((counter % 200) == 0) { // Пауза между сменами 200 мс
    counter = 0;
    getDigits(numbers[numindex]);
    numindex += 1;
    if (numindex >= sizeof(numbers)/sizeof(float)) numindex = 0;
  }
  displayMessage(arr);
}


void getDigits (float value) {
  Serial.println("");

  // Выдаем ошибку на те значения, которые не можем показать
  if ((value >= 10000) ||
      (value <= -1000)) {

    for (int i = 0; i < 4; i++) { // Каждый разряд по очереди
      for (int k = 0; k < 8; k++) {// Каждый сегмент по очереди - исходя из заданной карты
        arr[i][k] = err[i][k];
      }
    }
    return; // Выходим
  }

  int digits = 4; // У нас 4 разряда
  if (value < 0) digits = 3; // Из-за минуса один символ убирается*/

  // Делим число на 2 группы - отдельно целую часть и дробную.
  int intPart = (int)abs(value);
  int intLength = ((String)intPart).length(); // Смотрим, сколько разрядов занимает целая часть

  char valueChars[8]; // По нормальному float в String преобразовать нельзя, поэтому...
  dtostrf(value, 5, 4, valueChars); //... копируем данные float в массив chars[]

  // На дробную часть у нас остается разрядов: digits-intLength
  String valueStr = valueChars;                                                 // Теперь с текстовым форматом можно работать
  //  Serial.print("valueStr: "); Serial.println(valueStr);

  int fracIndex = valueStr.indexOf(".");                                        // Получаем индекс начала дробной части
  String fracPartStr = valueStr.substring(fracIndex + 1, valueStr.length());    // Выделяем цифры дробной части
  int fracDigits = digits - intLength;
  fracPartStr = fracPartStr.substring(0, fracDigits);                           // Вычленяем цифры, которые будут выводиться на дисплей
  //  Serial.print("fracDigits: "); Serial.println(fracDigits);
  //  Serial.print("fracPartStr: "); Serial.println(fracPartStr);

  int fracInt = fracPartStr.toInt();                                            // Переменная для проверки, нужно ли что-то выводить, если нули, то нет
  //  Serial.print("fracInt: "); Serial.println(fracInt);

  // Собираем строку для отображения
  String output = (value < 0) ? "-" : "";
  output += (String)intPart;

  String outputFrac = ((digits - intLength <= 0) || (fracInt == 0)) ? "" : ((String)"." + fracPartStr);

  output += (String)outputFrac;

  // Дополняем символы спереди, если цифр слишком мало, например для "-1" делаем "  -1"
  String spaces = "     ";
  digits = 4;
  if (~output.indexOf(".")) digits += 1;
  if (output.length() < digits) output = spaces.substring(0, digits - output.length()) + output;

  // Формирум данные для показа:
  int dig = -1;
  for (int i = 0; i < output.length(); i++) {
    String _char = output.substring(i, i + 1);

    if (_char != ".") dig += 1; // Точка не занимает сегмент - увеличиваем на 1

    int actualdigit = 11; // По умолчанию пустой символ
    if ((_char == "-")) {
      actualdigit = 10;
    }
    else if (_char == " " || _char == ".") {
    }
    else {
      actualdigit = _char.toInt();
    }

    if (_char == ".") {
      arr[dig][7] = 1; // Если нужно - ставим точку
    }
    else  {
      for (int n = 0; n <= 7; n++) {
        arr[dig][n] = seg[actualdigit][n];
      }
    }
  }
}

void displayMessage(int dig[4][8]) {
  for (int i = 0; i < 4; i++) { // Каждый разряд по очереди
    for (int k = 0; k < 8; k++) {// Каждый сегмент по очереди - исходя из заданной карты
      digitalWrite(segmentsPins[k], ((dig[i][k] == 1) ? HIGH : LOW));
    }
    digitalWrite(anodPins[i], LOW);
    delay(1);
    digitalWrite(anodPins[i], HIGH);
  }
}

С этим кодом отображение просто идеальное! Ничего не моргает и нет фантомов.

Всем спасибо. Буду помаленьку изучать эту "простыню" ))

Green
Offline
Зарегистрирован: 01.10.2015

Ну а эти PIN_PB, PC чего означают?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Green пишет:

Ну а эти PIN_PB, PC чего означают?

Номера выводов (пинов) микроконтроллера. Можно использовать чисто цифровые значения (как в ардуино), но я использую «голый» мк и мне проще так (не нужно в голове держать сопоставление вывода мк и цифрового значения ардуино). Это стандартные макросы ядра (ядро MiniCore).

Green
Offline
Зарегистрирован: 01.10.2015

Только если индикатор с ОА, что видно по наименованию массивов, то аноды активизируются HIGH, а сегменты LOW.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

У меня ОК и все работает (с портянкой из #12).

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Схема-то подключения индикатора какая?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

50-52 в топку

После 54 ой надо добавить digitalWrite(pinAnode[i], HIGH);

Анод подключил от одной цифры, а рисуешь уже другую ... что делаешь, то и видишь !

bizzon
Offline
Зарегистрирован: 29.03.2016

Овцелографом потыкать? Не? Или логанализатором? Может аппаратная проблема. Не люблю динамическую индикацию. Старовер.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

bizzon Проблемы никакой нет ! Что ТС сам организовал, то и увидел !

bizzon
Offline
Зарегистрирован: 29.03.2016

Так на осцилографе видно сразу. Может вместо прямоугольников у него на анодах синус или пила.

bizzon
Offline
Зарегистрирован: 29.03.2016

Командир! согласен.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

50-52 в топку

После 54 ой надо добавить digitalWrite(pinAnode[i], HIGH);

Анод подключил от одной цифры, а рисуешь уже другую ... что делаешь, то и видишь !

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

Перемудрил я, похоже))) Посыпаю голову пеплом )

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Мужики! Благодарю!

Однако ж другая проблема пришла. Изначально была не верная последовательность цифр (то есть вместо 1234 было 4321).

Если в функции printNum(num) код выглядит вот так:

void printNum (uint32_t num) {
  uint8_t bitNum;
  for (uint8_t i = 4; i > 0; i--) {
    if (num > 0) {
      bitNum = (uint8_t)(num % 10);
      for (int j = 0; j < 8; j++) {
        digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
      }
      num = num / 10;
    } else {
      num = 0;
      for (int j = 0; j < 8; j++) {
        digitalWrite(pinSegments[j], bitRead(numbers[num], 7 - j));
      }
    }
    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i    
    delay (1);
    digitalWrite(pinAnode[i], HIGH);   // | 
  }
}

То выводится только "пусто" и далее "123" (вот так: " 123"). Не пойму в чем дело. Если я меняю код в 3 строке вот так:

void printNum (uint32_t num) {
  uint8_t bitNum;
  for (uint8_t i = 4; i >= 0; i--) {
    if (num > 0) {
      bitNum = (uint8_t)(num % 10);
      for (int j = 0; j < 8; j++) {
        digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
      }
      num = num / 10;
    } else {
      num = 0;
      for (int j = 0; j < 8; j++) {
        digitalWrite(pinSegments[j], bitRead(numbers[num], 7 - j));
      }
    }
    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i    
    delay (1);
    digitalWrite(pinAnode[i], HIGH);   // | 
  }
}

То просто вспыхивают нули. Третий бит - как будто бы два раза (визуально), остальные по одному. Что за нафиг? 0_о

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Если вот так:

void printNum (uint32_t num) {
  uint8_t bitNum;
  for (uint8_t i = 5; i > 0; i--) {
    if (num > 0) {
      bitNum = (uint8_t)(num % 10);
      for (int j = 0; j < 8; j++) {
        digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
      }
      num = num / 10;
    } else {
      num = 0;
      for (int j = 0; j < 8; j++) {
        digitalWrite(pinSegments[j], bitRead(numbers[num], 7 - j));
      }
    }
    digitalWrite(pinAnode[i - 1], LOW);     // | Зажигаю цифру позиции i    
    delay (1);
    digitalWrite(pinAnode[i - 1], HIGH);    // | Гашу цифру позиции i
  }
}

То на "дисплее" - "0123".

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

4321 - Может надо было просто привязку анодов поменять ?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А программно разве это нельзя сделать в этом месте:

for (uint8_t i = 5; i > 0; i--)

Я сомневаюсь, что в этом дело. Какая разница слева направо или справа налево?

ЗЫ: К тому же "простыня" из #11 показывала все верно!

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

А почему i = 5 ?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Пока приходит на ум только "перевернуть" логику. Попробую...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

v258 пишет:

А почему i = 5 ?

Это сталось от экспериментов. Читай выше, там я все расписал.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ну что же, Деда на меня обиделся, помогать не хочет ((

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


// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК   =      { 15,      16,       17,       19,      14,      10,      9,       18}

// значения для вывода цифр 0-9

byte numbers[12] = {
  B11111100,  // | '0'             // Байт: ABCDEFGH
  B01100000,  // | '1'             //      A
  B11011010,  // | '2'             //    -----
  B11110010,  // | '3'             //   |     |
  B01100110,  // | '4'             //  F|  G  |B
  B10110110,  // | '5'             //   |-----|
  B10111110,  // | '6'             //  E|     |C
  B11100000,  // | '7'             //   |  D  |
  B11111110,  // | '8'             //    -----   * H
  B11110110,  // | '9'
};

// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
//        выводы МК = { 25,     23,       26,       24   }

void setup() {
  // Сконфигурировать контакты как выходы
  for (uint8_t i = 0; i < 8; i++) {
    pinMode(pinSegments[i], OUTPUT);
  }
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pinAnode[i], OUTPUT);
    digitalWrite(pinAnode[i], HIGH); // Выключаю
  }
}

void printNum (uint16_t num) {
  uint16_t bitNum;
  uint16_t temp = 1000;
  for (uint8_t i = 0; i < 4; i++) {
    bitNum = (uint16_t)(num / temp);
    for (int j = 0; j < 8; j++) {
      digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
    }
    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i
    delay (1);
    digitalWrite(pinAnode[i], HIGH);    // | Гашу цифру позиции i
    num = num - temp * bitNum;
    temp = temp / 10;
  }
}

void loop() {
  uint32_t number = 1234000;
  printNum (number / 1000);
}

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

Не, результат есть - чего ныть то?! А уж всем, кто принял участие, - тем огромное СПАСИБО!

Учусь дальше... )))

Впереди энкодер на ATmega8A...

Green
Offline
Зарегистрирован: 01.10.2015

Если учитесь, то старались бы писать изначально по нормальному. Вы пользуетесь Ардуино функциями, а не завязками на какое то ядро. Кому нужны ваши PIN_PB и ваши выводы МК! Нужно что бы человек взял ЛЮБУЮ Ардуино у него всё это работало... Или же пишите без Ардуино функций, но указывайте конкретный МК.
numbers[] - почему размер 12? pinAnode, когда реально это катоды? Подбирайте правильные имена. Пишите комментарий в начале для какого железа предназначена. А лучше делать что бы программа была универсальной - ОА/ОК, кол-во знакомест, инверсия общих и т.п. Ну и без delay конечно же.) Хоть и 1 мс, но завтра вам понадобиться отслеживать процессы менее 1 мс и что? Ну и по мелочи - то byte, то uint8_t, то int... 39 - лишнее приведение. Это что попалось.
Кто то говорил из наших - "старайся делать хорошо, плохо само получится".)

 
BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Green пишет:

Если учитесь, то старались бы писать изначально по нормальному. Вы пользуетесь Ардуино функциями, а не завязками на какое то ядро. Кому нужны ваши PIN_PB и ваши выводы МК! Нужно что бы человек взял ЛЮБУЮ Ардуино у него всё это работало... Или же пишите без Ардуино функций, но указывайте конкретный МК.
numbers[] - почему размер 12? pinAnode, когда реально это катоды? Подбирайте правильные имена. Пишите комментарий в начале для какого железа предназначена. А лучше делать что бы программа была универсальной - ОА/ОК, кол-во знакомест, инверсия общих и т.п. Ну и без delay конечно же.) Хоть и 1 мс, но завтра вам понадобиться отслеживать процессы менее 1 мс и что? Ну и по мелочи - то byte, то uint8_t, то int... 39 - лишнее приведение. Это что попалось.
Кто то говорил из наших - "старайся делать хорошо, плохо само получится".)

Согласен от части. Поэтому и учусь ещё...

12 у массива потому, что так нужно (на полёт не влияет), и я об этом знаю, это как раз «на будещее». 

PIN_PB и так далее потому, что я пишу код глядя на схему. Зачем мне заморочки с ардуино выводами - чтобы что? Постоянно сопоставлять их? Не критично. Код и так скомпилируется (если ядро стоит, да и кто такую схему собирать будет на голом мк? Это же не шилд в бребоард воткнуть). Ядро вроде бы тоже указывал? Забыл. Ну если нет - MiniCore.

МК указал в начале темы, этого мало (даже фьюзы указал)?

По поводу имени pinAnode - схема «универсальная», то есть рассчитана и на общий анод и на общий катод. Только перемычку изменить на плате при иных компонентах и всё. Ну и поменять в коде одно значение с 0 на 1. Как назвать и катоды и аноды одновременно? Поделитесь - переименую (хотя мне не критично). 

По типам (что разные мелькают , приведение и тп) - ты же понимаешь, что я не заморачиваюсь сейчас с типами пока идёт отладка. Когда заработает всё как нужно - можно будет и «причесать».

Ну и дэлеи тоже для отладки, если будут мешать - я их уберу. Блинк без дэлей знаю )))

ЗЫ: Без обид, как есть - так и рассказал. 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Если 7и сегметные индикаторы подключена к МК напрямую без ключей, то при динамической индикации "поциферно" яркость будет зависить от количества включенных сегментов. Если разряд один, то это особо не видно. Но при наличии нескольких - выглядит это все несколько неряшливо когда выводится что-нибудь вроде "1879.  Что бы яркость была одинакова надо  включать только по одному сегменту за раз. код, правда, получается чуть посложнее.

Green
Offline
Зарегистрирован: 01.10.2015

BOOM пишет:

12 у массива потому, что так нужно (на полёт не влияет), и я об этом знаю, это как раз «на будещее». 

На будущее - это выглядит неряшливо. Пишите без размера - вот оно любое будущее.

BOOM пишет:
PIN_PB и так далее потому, что я пишу код глядя на схему. Зачем мне заморочки с ардуино выводами - чтобы что? Постоянно сопоставлять их? Не критично. Код и так скомпилируется (если ядро стоит, да и кто такую схему собирать будет на голом мк? Это же не шилд в бребоард воткнуть). Ядро вроде бы тоже указывал? Забыл. Ну если нет - MiniCore.

МК указал в начале темы, этого мало (даже фьюзы указал)?


Причём здесь ваш голый МК? Чем он программно отличается от других плат Ардуино?
Указывать нужно в тексте программы, что бы не пересматривать весь топик.

BOOM пишет:
По поводу имени pinAnode - схема «универсальная», то есть рассчитана и на общий анод и на общий катод. Только перемычку изменить на плате при иных компонентах и всё. Ну и поменять в коде одно значение с 0 на 1. Как назвать и катоды и аноды одновременно? Поделитесь - переименую (хотя мне не критично). 

pinCommon[]. А вот пионеры то и не знают где какие перемычки и что менять в коде. Да и сам забудешь через неделю.

BOOM пишет:
По типам (что разные мелькают , приведение и тп) - ты же понимаешь, что я не заморачиваюсь сейчас с типами пока идёт отладка. Когда заработает всё как нужно - можно будет и «причесать».

Ну и дэлеи тоже для отладки, если будут мешать - я их уберу. Блинк без дэлей знаю )))


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

Green
Offline
Зарегистрирован: 01.10.2015

asam пишет:

Если 7и сегметные индикаторы подключена к МК напрямую без ключей, то при динамической индикации "поциферно" яркость будет зависить от количества включенных сегментов. Если разряд один, то это особо не видно. Но при наличии нескольких - выглядит это все несколько неряшливо когда выводится что-нибудь вроде "1879.  Что бы яркость была одинакова надо  включать только по одному сегменту за раз. код, правда, получается чуть посложнее.


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

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Даже интересно почему код из #11 "еле влез в atmega8".

Писал перед НГ вот такое:

Три регистра, все сегменты подключены в различных вариациях к 6 выводам. Работает эта херь посредством чарлиплексинга.

Занимает код чуть больше 2кб.

 

#include <avr/interrupt.h>
#include <avr/io.h>
#define nPIN 6
#define nREG 3
#define nSEG 8

//byte pinArr[6]={14,15,16,17,18,19};

//массив всех диодов {анод,катод}
const byte diodArr[nREG][nSEG][2]={
    {{2,3},{2,4},{5,2},{2,6},{2,5},{3,2},{4,2},{2,1}        
    },
    {{5,4},{3,5},{4,5},{3,4},{6,3},{4,3},{5,3},{3,1}        
    },
    {{1,6},{3,6},{5,6},{6,4},{4,6},{6,5},{1,5},{10,10}       
    }
};

#define space 10
const byte simbol[12]{//abcdefgDp
    0b11111100,//0
    0b01100000,//1
    0b11011010,//2
    0b11110010,//3
    0b01100110,//4
    0b10110110,//5
    0b10111110,//6
    0b11100000,//7
    0b11111110,//8
    0b11110110, //9    
    0b00000000,//space
    0b11101110,//A
};

byte value[3]={0,0,8};
byte stepDir[nPIN];
byte stepState[nPIN];
byte _stepDir[nPIN];
byte _stepState[nPIN];
float count=0;
boolean dot1=0,dot2=1;
volatile byte step=0;

void Calc(){    
    for(int i=0;i<nPIN;i++){/*
  количество шагов равняется количеству пинов.
 каждый шаг увеличивает номер вывода на который будет подаватся +5в на 1.
сначала смотрим вывод 1, потом 2 и тд  
        */
        //обнуляем массивы
        _stepDir[i]=0;
        _stepState[i]=0;
        
 for(int reg=0;reg<nREG;reg++){//для каждого из трех регистров
    for(int j=0;j<nSEG;j++){//по каждому из 8 сегментов (точка 8ой)
 //для вывода точек берем значение из массива знаков и работаем сним
 byte simbolCurrent=simbol[value[reg]];
 //если регистр самый левый добавляем к выводимому символу значение точки
                 if(reg==0)simbolCurrent=simbolCurrent+dot1;
//то же со средним регистром
if(reg==1)simbolCurrent+=dot2;
//если в текущей итерации сегмента нужно выводить то смотрим следующее условие
  if((simbolCurrent>>(nSEG-1-j))&1){
/*смотрим совпадает ли номер вывода текущего диода с текущим шагом
                    */
       if(diodArr[reg][j][0]==i+1){
                        /*
      если есть совпадение то по тогда пинаем в значение шага единичку на глубину указанную в массиве пинов
 то же для катода этого же диода , но плюс подаем только на анод
                        */
_stepDir[i]|=1<<(diodArr[reg][j][0]-1);
_stepDir[i]|=1<<(diodArr[reg][j][1]-1);
_stepState[i]|=1<<(diodArr[reg][j][0]-1);            }
  }
            }
   }
        }
    cli();
    //копируем из временного массива в массив вывода предварительно отключив прерывание
   memcpy(stepDir,_stepDir,nPIN);
   memcpy(stepState,_stepState,nPIN);
    sei();
}

ISR(TIMER1_COMPA_vect){
    
    DDRC=stepDir[step];
    PORTC=stepState[step];
   
    step==nPIN-1?step=0:step++;
}

void setup(){
    TCCR1A=0;
    TCCR1B=0;
    OCR1A=100;
    TCCR1B|=1<<WGM12;
    TCCR1B|=1<<CS11;
    TIMSK1|=1<<OCIE1A;
    sei();
}

void loop(){    
   static uint32_t calcTime=millis();
       int outVal=0;
    if(count<10){
        dot1=1;
        dot2=0;
        outVal=count*100;
    }else if(count<100){
        dot1=0;
        dot2=1;
        outVal=count*10;
    }
    
    value[0]=outVal/100;
    value[1]=(outVal/10)%10;
    value[2]=outVal%10;
   if(millis()-calcTime>=200){
        calcTime=millis();
        Calc();
        count+=0.01;
    }            
}

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Kakmyc пишет:

Даже интересно почему код из #11 "еле влез в atmega8".

В скомпилированном виде та "простыня" заняла 7кб из 8кб доступных. Я так думаю, что это из-за использования типа String в коде. Но точно не знаю.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Green пишет:

BOOM пишет:

12 у массива потому, что так нужно (на полёт не влияет), и я об этом знаю, это как раз «на будещее».

На будущее - это выглядит неряшливо. Пишите без размера - вот оно любое будущее.

Согласен, исправлюсь. )

Green пишет:

Да и людям на обозрение выкладываешь...

Я не на обозрение, я просто спросить )))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Причесал, работает. Меня устраивает.

// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК   =      { 15,      16,       17,       19,      14,      10,      9,       18}

// значения для вывода цифр 0-9

byte numbers[] = {
  B11111100,  // | '0'             // Байт: ABCDEFGH
  B01100000,  // | '1'             //      A
  B11011010,  // | '2'             //    -----
  B11110010,  // | '3'             //   |     |
  B01100110,  // | '4'             //  F|  G  |B
  B10110110,  // | '5'             //   |-----|
  B10111110,  // | '6'             //  E|     |C
  B11100000,  // | '7'             //   |  D  |
  B11111110,  // | '8'             //    -----   * H
  B11110110,  // | '9'
};

// аноды/катоды семисегментного индикатора
uint8_t pinAnode[] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
//        выводы МК = { 25,     23,       26,       24   }

void setup() {
  // Сконфигурировать контакты как выходы
  for (uint8_t i = 0; i < 8; i++) {
    pinMode(pinSegments[i], OUTPUT);
  }
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pinAnode[i], OUTPUT);
    digitalWrite(pinAnode[i], HIGH); // Выключаю
  }
}

void printNum (uint16_t num) {
  uint16_t bitNum, temp = 1000;
  for (uint8_t i = 0; i < 4; i++) {
    bitNum = num / temp;
    for (uint8_t j = 0; j < 8; j++) {
      digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
    }
    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i
    delay(1);
    digitalWrite(pinAnode[i], HIGH);    // | Гашу цифру позиции i
    num = num - temp * bitNum;
    temp = temp / 10;
  }
}

void loop() {
  printNum (1234);
}
=============
Скетч использует 782 байт (9%) памяти устройства. Всего доступно 8192 байт.
Глобальные переменные используют 31 байт (3%) динамической памяти, оставляя 993 байт для локальных переменных. Максимум: 1024 байт.

 

Green
Offline
Зарегистрирован: 01.10.2015

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

BOOM Если для сегментов выбран один порт целиком - зачем общаться с сегментами по одному ???

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

BOOM Если для сегментов выбран один порт целиком - зачем общаться с сегментами по одному ???

Я не умею "общаться сразу со всеми", поэтому сделал так как умею.

То же самое относится и к:

Green пишет:

Да, уж... Вообще, не так это делается.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

BOOM пишет:

учусь ещё...

Собственно, только поэтому и ответил.

Цитата:

По типам (что разные мелькают , приведение и тп) - ты же понимаешь, что я не заморачиваюсь сейчас с типами пока идёт отладка. Когда заработает всё как нужно - можно будет и «причесать».

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

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

26-28 меняем на DDRB=0B11111111

39-41 меняем на PORTB=numbers[bitNum]

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016
const byte simbol[] {  
    0b11111100, //  | '0'             // Байт: ABCDEFGH (H точка или двоеточие)
    0b01100000, //  | '1'             //      A
    0b11011010, //  | '2'             //    -----
    0b11110010, //  | '3'             //   |     |
    0b01100110, //  | '4'             //  F|  G  |B * ╗
    0b10110110, //  | '5'             //   |-----|     H
    0b10111110, //  | '6'             //  E|     |C * ╝
    0b11100000, //  | '7'             //   |  D  |
    0b11111110, //  | '8'             //    -----   * H
    0b11110110, //  | '9'   
    0b00000000, //  |space
    0b11101110, //  | 'A'
    0b00111110, //  | 'b'
    0b00011010, //  | 'c'
    0b10011100, //  | 'C'
    0b01111010, //  | 'd' 
    0b10011110, //  | 'E'
    0b10001110, //  | 'F'
    0b10111110, //  | 'G'
    0b01101110, //  | 'H'  
    0b00001100, //  | 'I'
    0b01110000, //  | 'J'
    0b00011100, //  | 'L'
    0b00101010, //  | 'n' 
    0b00111010, //  | 'o' 
    0b11111100, //  | 'O'
    0b11001110, //  | 'P'
    0b00001010, //  | 'r' 
    0b10110110, //  | 'S'
    0b00011110, //  | 't'  
    0b00111000, //  | 'u'  
    0b01111100, //  | 'U'
    0b01001110, //  | 'y' 
    0b11011010, //  | 'Z'                              
};

 

Green
Offline
Зарегистрирован: 01.10.2015

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

39-41 меняем на PORTB=numbers[bitNum]

Вот с этим засада. Кракозябры. Пробовал отрицание ( ! ) - вообще не светятся индикаторы. Ну а я, уже говорил, не понимаю еще в этом всем...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018
PORTB |= ~(numbers[bitNum]);

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

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018
dalay(1);

поменял на

delayMicroseconds(500);

При этом яркость примерно одинаковая. Если уменьшить до 300, то яркость существенно понижается.

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

BOOM пишет:

PORTB |= ~(numbers[bitNum]);

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


Стоит однозначно :)
Вот откопал древний пример
http://arduino.ru/forum/proekty/prosto-termometr-na-dvukh-7-segmentnykh-...
До сих пор полноценно использую железку.