Ультразвуковой дальномер 2: Серийный измеритель.

В предыдущей статье мы придумали, как прикрутить к ПЛИС ультразвуковой датчик с одной стороны и семисегментный четырехразрядный индикатор с другой. Сегодня мы открутим индикатор и прикрутим еще более многообещающую вещь — последовательный интерфейс. На свете существует сорок сороков разных способов его организовать. У меня ближе всего оказался достаточно распространенный bluetooth-модуль RF-BT0417C.


# На всякий случай добавлю пару команд для подключения к нему из Ubuntu.
$ hcitool scan
  Scanning ...
           54:10:A4:28:03:3A linvor
           D8:00:56:06:12:88 Milestone
$ sudo rfcomm bind /dev/rfcomm1 54:10:A4:28:03:3A
# Первая команда производит поиск доступных устройств.
# Вторая создает файл через который мы будем к устройству обращаться. 
# В других дистрибутивах Linux подключается скорее всего аналогично, 
# в Windows должно быть не сложнее.

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

Состав тестового стенда:
  1. Трансивер HC-SR04.
  2. ПЛИС.
  3. Счастливый Конденсатор 4.7 мкф.
  4. Bluetooth-модуль RF-BT0417C.


/************** serial_ping.v ****************/

module serial_ping (input wire clock,
                input wire echo,
                output wire trigger,
		output wire TX);

wire [20:0] w_time;
wire [13:0] distance;
wire [7:0] symbol;
wire next, busy, enable;

transceiver TRC1(clock, trigger, echo, w_time);

converter CR1(clock, w_time, distance);

symbol_counter SC1(clock, busy, next);

number2ascii NTA1(clock, distance, next, symbol, enable);

//async_transmitter(clk, TxD_start, TxD_data, TxD, TxD_busy);
async_transmitter AT1(clock, enable, symbol, TX, busy);

endmodule

/************** serial_ping.v ****************/

В исходнике основного модуля мы видим вызовы знакомых transceiver и converter. Первый — управляет HC-SR04, второй — вычисляет расстояние. Чтобы понять, чем заняты остальные модули, определимся, что и как мы будем по serial-интерфейсу передавать. Для наглядности будем отправлять данные в понятной человеку форме, в виде десятичных чисел (фактически — ASCII-строк).

0231
0231
0231
0232
0232
...

и т.д., пока не выключат электричество. А теперь про модули. number2ascii — преобразует двоичое число соответсвующее расстоянию в строку. symbol counter — командует отправкой отдельных символов. async_transmitter — непосредственно отвечает за отправку кода, который он получил по шине, на выход TX. async_transmitter — не моя задумка, его можно позамиствовать с сайта fpga4fun.com.

/*************** number2ascii.v ****************/

module number2ascii (input wire clock,
                     input wire [13:0] data,
                     input wire next,
                     output wire [7:0] symbol,
                     output wire enable);

wire [3:0] digit0;
wire [3:0] digit1;
wire [3:0] digit2;
wire [3:0] digit3;

wire [3:0] n2a;
wire [7:0] n2a_out;
reg  [3:0] n2a_reg;
assign n2a = n2a_reg;

// 13 = 00001101
wire [7:0] return = 8'b00001101;

reg [2:0] next_reg;
reg [7:0] symbol_reg;
assign symbol = symbol_reg;

reg enable_reg;
assign enable = next & enable_reg;

b2b_4dt DR1(data,
            clock,
            digit0,
            digit1,
            digit2,
            digit3);

n2a_converter(n2a, clock, n2a_out);

always @ (posedge next)
begin
    enable_reg = 0;
    case (next_reg)
    0: begin n2a_reg = digit2; symbol_reg = n2a_out; end
    1: begin n2a_reg = digit1; symbol_reg = n2a_out; end
    2: begin n2a_reg = digit0; symbol_reg = n2a_out; end
    3: begin n2a_reg = digit3; symbol_reg = n2a_out; end
    4: begin                   symbol_reg = return;  end
    endcase
    enable_reg = 1;
    next_reg = next_reg + 1;
    if (next_reg > 4) begin next_reg = 0; end
end

endmodule

/*************** number2ascii.v ****************/

Что для меня в собственном творении остается загадкой, так это почему:

digit2;
digit1;
digit0;
digit3;


Подобрал невероятное сочетание эмпирически потому, что очевидное не заработало.

Модуль number2ascii включает в себя модули b2b_4dt и n2a_converter. b2b_4dt(преобразует двоичное число в четыре двоично-десятичных) также перекочевал из предыдущего проекта. n2a_converter — преобразует двоично-десятичное число в ascii-код.

/****************** n2a_converter.v ******************/

module n2a_converter(input wire [3:0]DATA,
                    input wire CLOCK,
                    output wire [7:0]DOUT);

reg [7:0] dout_reg;
assign DOUT = dout_reg;

always @(posedge CLOCK)
    case (DATA)
    4'b0000: begin dout_reg <= 8'b00110000; end // 0
    4'b0001: begin dout_reg <= 8'b00110001; end // 1
    4'b0010: begin dout_reg <= 8'b00110010; end // 2
    4'b0011: begin dout_reg <= 8'b00110011; end // 3
    4'b0100: begin dout_reg <= 8'b00110100; end // 4
    4'b0101: begin dout_reg <= 8'b00110101; end // 5
    4'b0110: begin dout_reg <= 8'b00110110; end // 6
    4'b0111: begin dout_reg <= 8'b00110111; end // 7
    4'b1000: begin dout_reg <= 8'b00111000; end // 8
    4'b1001: begin dout_reg <= 8'b00111001; end // 9
    default: begin dout_reg <= 8'b00110000; end
    endcase
endmodule

/****************** n2a_converter.v ******************/

Назначение модуля symbol_counter — генерирование импульсов для отправки символов, но только таких, чтобы async_transmitter отправлял каждый символ только один раз. (если на входе TxD_start трансмиттера единица, то он отправляет код с шины "в эфир" циклично — сколько успеет, столько и натрудячит и мы получим 00000111112222233333 вместо 0123).

/**************** symbol_counter.v ***************/

module symbol_counter (clock, busy, send);

input clock;
input busy;
output send;

reg [19:0] hbr;
reg hl, bl, sndr;

assign send = sndr;

always @ (posedge clock)
begin
    hbr <= hbr + 1;
    if ((hbr[19] == 1) && (hl == 0)) begin sndr = 1; end
    if ((busy == 1)    && (bl == 0)) begin sndr = 0; end
    hl = hbr[19];
    bl = busy;
end

endmodule

/**************** symbol_counter.v ***************/

Модуль async_trancmitter используем практически без изменений. Достаточно поменять только пару параметров, если есть необходимость.

parameter ClkFrequency = 25000000;	// 25MHz
parameter Baud = 9600;

Ультразвуковой дальномер 2.0 готов.
В завершении статьи демонстрация работы устройства.

Пока собирался записывать видео, провел эксперимент со сборкой проекта на другой плате.
Arduino and Altera Cyclone II dev. board
На ней Bluetooth-модуль работал нестабильно, что не удивительно. В таком исполнении как у меня, модуль предназначен для подключения к устройствам работающим от 5В, а не от 3.3В. При этом другая плата, которую можно увидеть на записи, нормально работает с этим передатчиком. Сама схема, конечно, сыровата. Proof of concept и не более того. Мне приходилось видеть как кто-то жаловался, что у него HC-SR04 плохо работает, если расположен не перпендикулярно к поверхности. У меня же он умудрялся ловить эхо даже от параллельной поверхности. Сначала я хотел положить его на стол и двигать перед ним коробку, но показания постоянно прыгали со 140мм на то расстояние, на котором находилось препятствие.
  • +2
  • 19 июня 2011, 01:58
  • digides

Комментарии (10)

RSS свернуть / развернуть
круто а что не в коллективный )))
0
  • avatar
  • oss
  • 19 июня 2011, 03:24
В коллективный хочется отправлять что-то однозначно полезное. Посмотреть сначала на реакцию читателей.
0
Не помешало-бы видео о том, как на экране компа меняются циферки по мере приближения предмета к датчику. Ну это так, для наглядности.
0
Постараюсь в ближайшее время добавить видео.
0
Что для меня в собственном творении остается загадкой
… ну как, разобрался?
0
… так у тебя они так и расположены

    0: begin n2a_reg = digit2; symbol_reg = n2a_out; end
    1: begin n2a_reg = digit1; symbol_reg = n2a_out; end
    2: begin n2a_reg = digit0; symbol_reg = n2a_out; end
    3: begin n2a_reg = digit3; symbol_reg = n2a_out; end
… или это уже антиперекрутка?
0
:) affirmative. И ведь в варианте с индикатором так хитрить не пришлось.
0
Пока я с этим сюжетным поворотом не разбирался. Решил временно переключиться на что-нибудь другое.
0
Немного усложнив схему и программу можно сделать дальномер с одним датчиком. Сразу после излучения нужно переключиться на прием. Для малой дистанции импульс должен быть короче, для большой длиннее. При отсутствии цели — поиск от маленького импульса к большому, пока не произойдет захват.
0
Доброго времени суток! У меня такой вопрос к автору — а нет ли фото модуля RF-BT0417C не со стороны деталей, а с другой? Вопрос связан вот с чем — выбираю модуль BlueTooth для серийного автомобильного дывайса. В число претендентов входит HC-04. Судя по всему, он является аналогом RF-BT0417C (не в смысле софта, в смысле железа). Но в «даташыте» на HC-04 все интересные ноги центрального процессора модуля выведены на плату и к ним есть доступ, а вот в «даташыте» на BT0417C сказано (на схеме в конце документа), что эти ноги «NC» (то бишь, не подключены). Фото присутствует только со стороны деталей. А наличие подключения ног процессора к выводам модуля можно проследить только на фото для противоположной стороны. Заранее спасибо.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.