Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Обсуждение и вопросы по урокам Ардуино
komandor
Сообщения: 8
Зарегистрирован: 14 ноя 2016, 14:16

Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение komandor » 14 ноя 2016, 14:36

Подключил 7-ми сегментный 8-ми разрядный индикатор к PRO MINI. Использую только пять разрядов. Выводит нормально количество
импульсов (до 500 имп./сек.). Как ввести поправочный коэффициент счета (примерно 0.9-1.1) для нормального отображения на индикаторе.


Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение Эдуард » 14 ноя 2016, 17:28

Не совсем понятно.
Если речь идет об умножении целого числа на дробный коэффициент, то это делается так:

Код: Выделить всё

int numImp; // число импульсов, которое надо умножить на дробный коэффициент

numImp = (int) ( (float)numImp * 0.9 );

(float)numImp - явно преобразуем в тип float.
(float)numImp * 0.9 - умножаем на коэффициент
(int) ( (float)numImp * 0.9 ) - обратно преобразовываем в целочисленный тип

Если еще сделать округление:

Код: Выделить всё

numImp = (int) ( (float)numImp * 0.9 + 0.5);

komandor
Сообщения: 8
Зарегистрирован: 14 ноя 2016, 14:16

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение komandor » 14 ноя 2016, 22:20

Считываются импульсы (частотой 500гц.) оптическим энкодером и выводятся на 8-ми разрядный 7-ми сегментный индикатор
МАХ7219-MODUL. Как ввести поправочный коэффициент счета (примерно 0.9 - 1.1). Например, предварительно считал импульсы
и на индикаторе отобразилось 100.00 , а надо чтобы показания были 90.00 или 110.00. Импульсы умножить на поправочный
коэффициент и результат разложить для вывода на индикатор.
Вот используемый скетч:

Код: Выделить всё

#include "LedControl.h"

LedControl lc = LedControl(11, 13, 10, 1);

/////////////  энкодер  ///////////////////////////

int encoderPin1 = 2;
int encoderPin2 = 3;
volatile long lastEncoded = 0;
volatile long encoderValue = 0;
long lastencoderValue = 0;
long lastMSB = 0;
long lastLSB = 0;

long val;
long val_old = 0;

long distance = 0;
int n1 = 0;
int n2 = 0;
int n3 = 0;
long n4 = 0;
long n5 = 0;

void setup()
{
  lc.shutdown(0, false);   // функция lc.shutdown(0,true); снова его включит
  lc.setIntensity(0, 8);   // яркость свечения, доступные значения от 0 до 15
  lc.clearDisplay(0);

  pinMode(encoderPin1, INPUT);
  pinMode(encoderPin2, INPUT);
  digitalWrite(encoderPin1, HIGH);
  digitalWrite(encoderPin2, HIGH);
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);
}

void loop()
{
  val = encoderValue / 4;

  if (val > val_old)
  {
    n1 ++;
    if (n1 > 9)
    {
      n1 = 0;
      n2 ++;
    }
    if (n2 > 9)
    {
      n2 = 0;
      n3 ++;
    }
    if (n3 > 9)
    {
      n3 = 0;
      n4 ++;
    }
    if (n4 > 9)
    {
      n4 = 0;
      n5 ++;
    }
    if (n5 > 9)
    {
      n5 = 0;
    }
    val_old = val;
  }

  if (val < val_old)
  {
    if ( distance > 0)
    {
      n1 --;
      if (n1 < 0)
      {
        n1 = 9;
        n2 --;
      }
      if (n2 < 0)
      {
        n2 = 9;
        n3 --;
      }
      if (n3 < 0)
      {
        n3 = 9;
        n4 --;
      }
      if (n4 < 0)
      {
        n4 = 9;
        n5 --;
      }
    }
    val_old = val;
  }

  distance = n1 + n2 * 10 + n3 * 100 + n4 * 1000 + n5 * 10000;

  if (distance < 1000)
  {
    lc.setDigit(0, 1, n1, false);
    lc.setDigit(0, 2, n2, false);
    lc.setDigit(0, 3, n3, true);
    lc.setChar(0, 4, ' ', false);
    lc.setChar(0, 5, ' ', false);
  }
  if (distance >= 1000 && distance < 10000)
  {
    lc.setDigit(0, 1, n1, false);
    lc.setDigit(0, 2, n2, false);
    lc.setDigit(0, 3, n3, true);
    lc.setDigit(0, 4, n4, false);
    lc.setChar(0, 5, ' ', false);
  }
  if (distance >= 10000 && distance < 100000)
  {
    lc.setDigit(0, 1, n1, false);
    lc.setDigit(0, 2, n2, false);
    lc.setDigit(0, 3, n3, true);
    lc.setDigit(0, 4, n4, false);
    lc.setDigit(0, 5, n5, false);
  }
}

////////////////  енкодер ////////////////

void updateEncoder()
{
  int MSB = digitalRead(encoderPin1);
  int LSB = digitalRead(encoderPin2);

  int encoded = (MSB << 1) | LSB;
  int sum  = (lastEncoded << 2) | encoded;

  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
    encoderValue ++;
  if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
    encoderValue --;

  lastEncoded = encoded;

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение Эдуард » 15 ноя 2016, 14:28

Все как я написал, только для переменной val.

После:
val = encoderValue / 4;

Скорректировать переменную val :

val = (long) ( (float)val * 0.9 );

Можно умножить на коэффициент в той же строке:

val = (long) ((float)(encoderValue / 4) * 0.9);

komandor
Сообщения: 8
Зарегистрирован: 14 ноя 2016, 14:16

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение komandor » 15 ноя 2016, 16:45

Спасибо, попробую.

komandor
Сообщения: 8
Зарегистрирован: 14 ноя 2016, 14:16

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение komandor » 16 ноя 2016, 15:05

Протестировал. С коэффициентом 0.9 работает отлично.
С коэффициентом 1.1 показания индикатора, как при коэффициенте 1.

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение Эдуард » 16 ноя 2016, 17:17

Должно работать. Какая разница для умножения 0.9 или 1.1.

Если не работает при малых значениях, добавьте округление:
val = (long) ( (float)val * 0.9 + 0.5 );

А при каких значениях val работает не правильно? При любых? А если умножить не на 1.1, а на другие коэффициенты? Например 2.0.

komandor
Сообщения: 8
Зарегистрирован: 14 ноя 2016, 14:16

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение komandor » 16 ноя 2016, 21:21

Пробовал коэффициенты и 0.5 и 0.7. До 1 работает прекрасно. Ввожу 1, тоже отлично. Все, что больше 1 (пробовал и 2 и 10, и (1+0.1) и добавлял
округление) val во всем диапазоне работает с коэффициентом 1.

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение Эдуард » 16 ноя 2016, 23:25

Выводите для отладки промежуточные данные в последовательный порт:

Код: Выделить всё

void loop()
{
 val = encoderValue / 4;

 // массштабирование с выводом в последовательный порт
 Serial.print("val=");   
 Serial.print(val);

 float x;
 x = (float)val;
 Serial.print(" x=");   
 Serial.print(x);
 
 x= x * 1.1;
 Serial.print(" ");   
 Serial.print(x);

val = (long)x;
 Serial.print(" val=");   
 Serial.println(val);
 
 delay(300);


Не забудьте в setup() вставить
Serial.begin(9600);

Запустите монитор последовательного порта Arduino IDE и увидите все промежуточные результаты вычислений.

komandor
Сообщения: 8
Зарегистрирован: 14 ноя 2016, 14:16

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение komandor » 17 ноя 2016, 14:45

Данные вывел в последовательный порт.
Коэффициент 0.5
val=1000 x=1000.00 500.00 val=500 показания на индикаторе 5.00
Коэффициент 1
val=1000 x=1000.00 1000.00 val=1000 показания на индикаторе 10.00
Коэффициент 1.1
val=1000 x=1000.00 1100.00 val=1100 показания на индикаторе 10.00 (а должно быть 11.00)

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение Эдуард » 17 ноя 2016, 18:56

Переменная val типа long правильно умножилась на коэффициент 1.1.

Получается ошибка в программе преобразования двоичной переменной val в двоично-десятичный код для индикаторов.

komandor
Сообщения: 8
Зарегистрирован: 14 ноя 2016, 14:16

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение komandor » 17 ноя 2016, 19:28

Спасибо. Буду искать ошибку.

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Подключение 8-ми разрядного 7-ми сегментного индикатора к PRO MINI

Сообщение Эдуард » 18 ноя 2016, 01:22

Ошибка в том, что преобразование двоичного кода из val в двоично-десятичный в n1,n2,n,3,n4,n5 корректно происходит только в случае, если за один проход цикла loop() val изменяется не больше чем на 1

Код: Выделить всё

 if (val > val_old)
 {
 n1 ++;
 if (n1 > 9)
 {
 n1 = 0;
 n2 ++;
 }
 if (n2 > 9)
 {
 n2 = 0;
 n3 ++;
 }
 if (n3 > 9)
 {
 n3 = 0;
 n4 ++;
 }
 if (n4 > 9)
 {
 n4 = 0;
 n5 ++;
 }
 if (n5 > 9)
 {
 n5 = 0;
 }
 val_old = val;
 }


Команда val_old = val; в конце после первого же прохода делает равными переменные val_old и val. После этого код в теле if будет выполнен только при следующем изменении val. Т.е. не важно насколько изменился val, в любом случае n1,n2..,n5 изменится только на 1.

Надо не делать в каждом цикле val_old = val, а либо прибавлять 1 к val_old; либо вычитать 1. В val_old должен храниться двоичный эквивалент n1,n2,...,n5.

Или использовать другой способ преобразования двоичного кода в двоично-десятичный.


Вернуться в «Уроки Ардуино»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя