Ультразвуковой дальномер в паре с семисегментным индикатором

sergeevalex
Offline
Зарегистрирован: 15.10.2012

Разобрал старый магнитофон. Нашёл в нём плату 691FF-2 с распаянным семисегментным индикатором на два разряда NX2-A040RWB.

Так как схемы к нему не предполагалось, то пришлось прозванивать все провода. Спасало то, что с одной стороны выходило именно восемь проводов (на семь сегментов в виде красных диодиков и десятичную точку), а с другой от жгута отделено было два провода. При подключении так и получилось - на эти два провода должен подходить "+" - это включает первый и/или второй разряды, на восемь проводов "-" - это включает каждый из сегментов в разряде и точку.
Чтоб подключить индикатор к Ардуино (+5в. на выходе) пришлось выпаять с платы все джамперы и дополнительные светодиоды (остался на плате только сам индикатор), пробросить несколько дополнительных проводков и впаять 8 резисторов по 470 ом каждый для каждого из сегментов. Подключение к Ардуине - разъёмами от компьютерной материнской платы.


Чтобы индикатор проверить в автономном режиме решил в пару ему запустить дальномер.
Ультразвуковой дальномер HC-SR04 - от 2 см. до 4 метров.

К сожалению, на Nano получились заняты почти все цифровые пины (от D2 до D13, GND, 5v).

Скетч у дальномера совсем простой. Основную сложность у меня вызвало написание скетча для дисплея и попытка заставить его корректно отрабатывать "бегущую строку" при количестве символов больше количества разрядов индикатора.

/* Дальномер HC-SR04 в паре с двухсекторным 7-сегментным индикатором
 * автор Hoplik <hoplik@hoplik.ru>
 */
byte echoPin, trigPin; // Инициализация пинов дальномера HC
byte pin_[8], pin[2];  //Инициализация массива пинов сегментов и секторов
unsigned int sectorDuration, delaySector;  //Задержка между отображением разрядов цифр и сдвига секторов для значений более 2
unsigned int distance, maxdist, delayDist; // Расстояние до объекта (см.), максимальная дистанция и задержка для следующего измерения расстояния(ms)
unsigned long duration; // Длина отражённой волны в микросекундах
String distString; // Преобразование данных расстояния в строковый класс

/* Структура сегментов
 * Описание пинов индикатора
 *      a
 *    _____
 *   |     | 
 * f |  g  | b
 *   |_____|
 *   |     |
 * e |     | c 
 *   |_____|    . dot
 * 
 *      d
 * 7Seg    b   f   a   e   d   .   c   g
 * PIN     0   1   2   3   4   5   6   7
 * BIN     7   6   5   4   3   2   1   0
 */
#define SIGN_DEF(a, b, c, d, e, f, g, dot) \
(a+(b<<1)+(c<<2)+(d<<3)+(e<<4)+(f<<5)+(g<<6)+(dot<<7))
struct SegmentTrait
{
  static byte sign[10];  //Инициализация массива знаков
};
byte SegmentTrait::sign[] =
{
  SIGN_DEF(0, 0, 0, 0, 0, 1, 0, 1),  //0
  SIGN_DEF(0, 1, 1, 1, 1, 1, 0, 1),  //1
  SIGN_DEF(0, 1, 0, 0, 0, 1, 1, 0),  //2
  SIGN_DEF(0, 1, 0, 1, 0, 1, 0, 0),  //3
  SIGN_DEF(0, 0, 1, 1, 1, 1, 0, 0),  //4
  SIGN_DEF(1, 0, 0, 1, 0, 1, 0, 0),  //5
  SIGN_DEF(1, 0, 0, 0, 0, 1, 0, 0),  //6
  SIGN_DEF(0, 1, 0, 1, 1, 1, 0, 1),  //7
  SIGN_DEF(0, 0, 0, 0, 0, 1, 0, 0),  //8
  SIGN_DEF(0, 0, 0, 1, 0, 1, 0, 0),  //9
};

void setup()
{
  sectorDuration = 5; // Delay for sectors
  delayDist = 500; // Delay for next distance count
  delaySector = 500; // Delay for sectors movie
  maxdist = 400; // Maximum distance cm.
  echoPin = 13; // HC Echo Pin
  trigPin = 12; // HC Trig Pin
  pin[0] = 10;  //Pin d1 to digital pin 10
  pin[1] = 11;  //Pin d2 to digital pin 11
  pin_[0] = 3;  //Pin b to digital pin 3
  pin_[1] = 7;  //Pin f to digital pin 7
  pin_[2] = 2;  //Pin a to digital pin 2
  pin_[3] = 6;  //Pin e to digital pin 6
  pin_[4] = 5;  //Pin d to digital pin 5
  pin_[5] = 9;  //Pin dot to digital pin 9
  pin_[6] = 4;  //Pin c to digital pin 4
  pin_[7] = 8;  //Pin g to digital pin 8
//Определяем пины для семи сегментов и точки
  for (byte i = 0; i < 8; ++i)
  {
    pinMode(pin_[i], OUTPUT);  
  }
//Определяем пины для секторов  
  for (byte i = 0; i < 2; ++i)
  {
    pinMode(pin[i], OUTPUT);  
  }
//Определяем пины для дальномера
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  
 Serial.begin(9600); // Порт будем использовать для контроля данных
}

void loop() {

 digitalWrite(trigPin, HIGH); // Свистнули
 delayMicroseconds(10); 
 
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH); // Посчитали время отражённой волны

 distance = duration/58; //Расчёт дистанции (в см.) на основе скорости звука
 
 if (distance <= maxdist) { //Если в рамках максимальной дальности дальномера, то значение выводим на индикатор
   unsigned long endTime = millis() + delayDist; //Задержка перед следующим измерением дистанции
   Serial.println(distance);
   while (millis () < endTime) { //Выбор подпрограммы для индикатора в зависимости от количества символов
     distString = (String) distance;
     switch (distString.length()) {
       case 1:
      printSingleSign(distance,0);
      break;
       case 2:
      printDoubleSign(distString);
      break; 
       case 3:
      printMultiSign(distString);
      break;
     }
   }
 }
 else {
 clean();
 Serial.print("Distance out of range - ");
 Serial.println(distance);
 delay (delayDist);
 }
} 

//Подпрограммы исполнения печати значений
void pickSector(byte i)  //"Активировать указанный разряд" (номер разряда)
{
  for (byte j = 0; j < 2; ++j)
  {
    digitalWrite(pin[j], LOW);
  }
  digitalWrite(pin[i], HIGH);
}

void clean()  //"Очистить всё"
{
  for (byte i = 0; i < 8; ++i)
  {
    digitalWrite(pin_[i], HIGH);
  }
}
 
void printSign(byte n)  //"Печать одного знака" (номер знака)
{
  byte m = SegmentTrait::sign[n];
  for (byte i = 0; i < 8; ++i)
  {
    digitalWrite(pin_[i], m & 0x01);
    m >>= 1;
  }
}

void printSingleSign (byte n, byte i) //"Печать одного символа в указанном разряде" (номер знака, номер разряда)
{
  clean();
  pickSector(i);
  printSign(n);
}

void printDoubleSign (String n) //"Печать строки из двух символов" (Числовая строка для отображения из двух символов)
{
  clean();
  byte k = 1;
  for (byte i = 0; i < 2; ++i) {
    pickSector(i);
    printSign(byte (n[k]) - 48);
    k-=1;
    delay (sectorDuration);
  }
}

void printMultiSign (String n) //"Печать строки из нескольких символов" (Числовая строка из более чем двух символов)
{
  clean();
  
  printSingleSign(byte (n[0]) - 48, 0); // Первый знак в первом разряде
  delay(delaySector);
  
  for (byte i = 0; i < n.length() - 1; ++i) { // Все средние
    unsigned long endTimeSector = millis() + delaySector; //Задержка перед следующим сдвигом разряда
    while (millis () < endTimeSector) {
      String newstr = String((n[i]-48)*10 + (n[i + 1]-48));
      printDoubleSign (newstr);
    }
  }
  
  printSingleSign(byte (n[n.length() - 1]) - 48, 1); // Последний знак во втором разряде
  delay(delaySector);
}

 

fura
Offline
Зарегистрирован: 31.07.2014

Заинтересовал данный прибор.Однако мне кажется нужно применить 74HC595 для освобождения портов и выводить информацию по SPI на семисигментник(и).Есть затея сделать такое - нажимаешь на кнопку,ардуино высчитывает  расстояние, после выводит значение в  на некоторое время на индикатор(выводит среднее значение),можно до 10х  долей.