Подключение платы Марсоход к телефону с ОС Android

android и плата Марсоход
Возникла идея подключить плату Марсоход к смартфону с ОС Android так, что бы  можно было с телефона подавать какие нибудь команды в плату.

Я уже пол-года пользуюсь недорогим HTC Wildfire S, так что телефон для экспериментов есть. Могу попробовать связать телефон с платой Марсоход.  Для чего это нужно еще толком не придумал, но сама идея интересная. Как это можно сделать? У телефона есть разные интерфейсы и самый простой их них, пожалуй – это аудио выход. Я подумал, что, теоретически, я могу на телефоне воспроизводить короткие аудио файлы, например, тоны разной частоты. Если плата Марсоход сможет распознавать эти звуковые тоны, то их можно интерпретировать как разные команды.

Задумавшись о реализации этого проекта я понял, что придется преодолеть массу проблем. Самые серьезные – это:

  1. На плате Марсоход нет аналогового входа, куда можно было бы подавать звук с телефона. Все входы ПЛИС (Altera  CPLD) на плате Марсоход цифровые.
  2. Я не умею писать программы для Android.

Понятно, что проект легким не будет, но, «мы не привыкли отступать».

Первая мысль была такая: «Нужно создать хотя бы один первый эталонный аудио файл, чтобы воспроизводить его на телефоне и пытаться слушать платой Марсоход».

Для создания аудио файла я использовал программу Audacity.

использование audacity для создания синусоидального сигнала

Это совершенно потрясающая свободная программа для редактирования аудио файлов. Позволяет записывать, редактировать, вырезать, склеивать и прочее и прочее. В ней я создал синусоиду 1000Гц длительностью 30 секунд и записал ее в WAV файл. По Bluetooth перенес файл на телефон. Теперь источник сигнала у меня есть.

Сделал провод для подключения телефона к плате. Решил так, что простейший проект для ПЛИС платы Марсоход должен быть почти пустой: просто брать сигнал на одном входе ПЛИС и выводить его на другой выход ПЛИС. На выходе смотреть осцилографом – есть ли там вообще хоть что-то. Была надежда, что аналоговый сигнал с разъема audio-jack телефона будет достаточно большой амплитуды, чтобы входной элемент ПЛИС включался и выключался на некотором уровне. К сожалению этого не произошло... Сигнал с телефона оказался слишком слабым. Делать какой-то усилитель не хотелось, ведь при этом пропадет красота идеи. Нужно как-то сдвинуть входной сигнал, может быть делителями напряжения на резисторах...

После нескольких экпериментов устойчивый результат получился вот так (показан фрагмент схемы платы Марсоход):

подключение аудио сигнала к ПЛИС платы Марсоход

Внутри проекта для ПЛИС пины 12 и 14 (обычно в наших проектах это контакты с именами dn, dp ) сделаны выходами и подключены к нулю. На плате Марсоход установлены два джампера (перемычки), как показано на схеме выше. Получается делитель напряжения: резисторы R1 и R2 параллельны и тянут к земле, а резисторы R3 и R4 параллельны и тянут к питанию. К точке деления напряжения подключаю землю аудио сигнала с телефона. Собственно сигнальный провод подключаю к любому входу, например key0 платы Марсоход. Таким образом, сигнал с телефона оказывается «приподнятым» из-за того, что нулевой провод с телефона подключен к делителю. Это решение позволило уверенно «принимать аудио сигнал». Конечно, принятый сигнал внутри ПЛИС оказывается «оцифрованым», есть только ноль и единица – это сигнал с прямоугольными импульсами. Тем не менее, частота «оцифрованного» сигнала равна частоте подаваемого аудио сигнала, то есть равна частоте моей синусоиды с телефона.

плата Марсоход с audio-jack

Вот так выглядит плата Марсоход с подключенным проводом – интерфейсом к телефону.

Следующая задача – измерение частоты входного сигнала внутри ПЛИС. Это довольно просто. Я написал для ПЛИС платы Марсоход на языке Verilog HDL вот такой проект:


//android commands coming from sound channel
module asound(
  input wire clk100Mhz,    //marsohod board crystal freq
  input wire asignal,        //from androind phone sound socket
  output reg [7:0]led,        //marsohod board leds,
  output reg dp,
  output reg dn
  );

//divide 100Mhz clock on 256
reg [7:0]cnt;
always @(posedge clk100Mhz)
  cnt<=cnt+1'b1;

//lowest clock is 390625Hz

wire clk; assign clk=cnt[7];

//resynchronize input signal to clk

reg [2:0]capture;
always @(posedge clk)
  capture <= {capture[1:0],asignal};

//find falling edge of sound signal
wire aedge;
assign aedge = capture[2:1]==2'b10;

reg [9:0]counter;
reg [1:0]f1000;
reg [1:0]f1200;
reg [1:0]f1400;
reg [1:0]f1600;
reg [1:0]f1800;

always @(posedge clk)
begin
  if
(aedge)
   counter<=0;
  else
  if
(counter<1023)
   counter<=counter+1'b1;

  if(aedge)
   f1000 <= { f1000[0] , (counter>380 && counter<400) };
  else
  if
(counter==1023)
   f1000 <= { f1000[0] , 1'b0 };

  if(aedge)
   f1200 <= { f1200[0] , (counter>305 && counter<335) };
  else
  if
(counter==1023)
   f1200 <= { f1200[0] , 1'b0 };

  if(aedge)
   f1400 <= { f1400[0] , (counter>270 && counter<290) };
  else
  if
(counter==1023)
   f1400 <= { f1400[0] , 1'b0 };

  if(aedge)
   f1600 <= { f1600[0] , (counter>235 && counter<255) };
  else
  if
(counter==1023)
   f1600 <= { f1600[0] , 1'b0 };

  if(aedge)
   f1800 <= { f1800[0] , (counter>207 && counter<227) };
  else
  if(counter==1023)
   f1800 <= { f1800[0] , 1'b0 };
end

always @(posedge clk)
begin
  if
(f1000==2'b10)
   led[4:0] <= 5'b00001;
  else
  if
(f1200==2'b10)
   led[4:0] <= 5'b00010;
  else
  if
(f1400==2'b10)
   led[4:0] <= 5'b00100;
  else
  if
(f1600==2'b10)
   led[4:0] <= 5'b01000;
  else
  if
(f1800==2'b10)
   led[4:0] <= 5'b10000;

led[7:5] <= 0;
end

always
@*
begin
  dp=0; dn=0;
end

endmodule


Принцип действия этой «программы» следующий:

  1. На плате Марсоход есть кварцевый генератор 100Мгц. Это слишком большая частота для нашей задачи, поэтому сразу делим ее на 256. Получается основная тактовая частота clk проекта 390625Гц.
  2. Входной «оцифрованный» сигнал сперва пересинхронизируется к тактовой частоте clk, а затем из него выделяется перепад с единицы в ноль. Можно наоборот выделять фронт, это не принципиально для измерения частоты. Итак есть короткие импульсы aedge с частотой равной частоте входного тона.
  3. Я хочу посчитать сколько периодов эталонной частоты clk поместится внутри периода входной частоты сигнала aedge. Для этого имеем двоичный счетчик counter, который сбрасывается при aedge=1 и считает (но не более 1023).  Если счетчик counter досчитал до 1023 и больше aedge не приходит, то значит входной сигнал прекратился.
  4. Имеются двухбитные сдвиговые регистры вида reg [1:0]f1000. В младший бит этого регистра в момент aedge задвигается бит признака частоты. Например, при входной аудиочастоте 1000Гц в ее периоде поместится примерно 390625/1000=390 периодов эталонной частоты. Я несколько размываю границы и делаю проверку вида (counter>380 && counter<400). Поскольку это число задвигается в сдвиговый регистр, то получается, что если f1000==2’b01, то звуковой сигнал только что обнаружен. Если f1000==2’b11, то сигнал длится уже больше двух периодов. Если f1000==2’b10, то сигнал только что закончился.
  5. Светодиоды led[4:0] зажигаются, когда появляется соответствующая частота: led[0], если 1000Гц.  led[1] зажигается, когда появляется 1200Гц, led[2], когда 1400Гц и так далее. Я выбрал сетку частот от 1000Гц и выше через каждые 200 Герц.

Весь проект в среде Altera Quartus II для платы Марсоход можно взять вот здесь:



Его можно практически сразу проверить. С помощью audacity я сделал несколько WAV файлов, которые поместил на телефон и при их запуске действительно загорается нужный светодиод!

Следующая серьезная задача – это написание какой нибудь демонстрационной программы для телефона под управлением Android. Как я уже написал, я это делать абсолютно не умею. Пришлось перерыть массу интернета, чтобы найти, на мой взгляд, очень простую среду программирования. Все прочие варианты мне показались очень громоздкими и трудоемкими: установка SDK от google, eclipse, отладчики и т.п. Все это показалось мне очень сложным. Мне же хотелось решения на «пару дней».

Я обнаружил такое средство SL4A – это Scripting Layer For Android. Как я понял это интерфейс к API телефона. Сайт этого проекта: http://code.google.com/p/android-scripting/ По сути дела на телефон нужно установить две программы: собственно SL4A, и еще нужно установить выбраный на ваш вкус скриптовый «язык», один из Python, Ruby, Lua, Perl или еще другие. Опять же я не специалист в скриптовых языках... Выбрал Python, так как показалось там есть больше примеров программ.

Итак, с сайта SL4A из раздела Downloads выкачиваю sl4a_r5.apk и PythonForAndroid_r4.apk и переношу их на телефон. Еще полезно выкачать python_scripts_r8.zip – это примеры каких-то готовых скариптов. По умолчанию приложения можно устанавливать только из Google Market (сейчас это Google Play). Это нужно изменить: зайти в телефоне и поставить галочку в Настройки =>Приложения=>Неизвестные источники. Теперь можно на телефоне запустить эти закачанные apk файлы и они установят приложение SL4A и Python.
Установленные программы SL4A и PythonForAndroid на телефоне выглядят вот так (верхние две строчки в списке):

sl4a и pythonforandroid

Вот это то, что мне нужно. Я могу писать скрипт на компьютере в простейшем редакторе вроде notepad и переносить на телефон через Bluetooth. Более того, можно исправлять скрипт прямо на телефоне и тут же пробовать! Кажется все очень просто и интересно.

Пришлось почитать про Python и посмотреть примеры скриптов. В итоге я смог написать вот такой Python скрипт:


import android
droid = android.Android()

def my_dialog():
  title = 'Marsohod'
  options = ["LED0", "LED1", "LED2", "LED3", "Exit"]
  droid.dialogCreateAlert(title)
  droid.dialogSetItems(options)
  droid.dialogShow()
  response = droid.dialogGetResponse().result
  id = response["item"]
  print id
  return id

def play( id ):
  if   (id==0):
   droid.mediaPlay('/mnt/sdcard/media/audio/s1000.wav')
  elif (id==1):
   droid.mediaPlay('/mnt/sdcard/media/audio/s1200.wav')
  elif (id==2):
   droid.mediaPlay('/mnt/sdcard/media/audio/s1400.wav')
  elif (id==3):
   droid.mediaPlay('/mnt/sdcard/media/audio/s1600.wav')

id=1
while id != 4:
  id = my_dialog()
  play(id)

print "Thanks Marsohod!"


Вот такой простой скрипт я написал. Пожалуйста не критикуйте, так как это мой первый скрипт на Python. Программа должна показать диалог с несколькими кнопками выбора: LED0, LED1, LED2 и LED3. По нажатию кнопки должен воспоизодиться короткий аудио файл содержащий синусоиду нужной частоты. Этот тон будет распознан платой Марсоход и она зажгет нужный светодиод.

Переношу скрипт на телефон и запускаю на нем SL4A. Дальше выбираю и запускаю из списка скриптов мой собственный:

Запуск скрипта Python на телефоне Android с помощью SL4A

Программа запускается, вот так выглядит вся "система":

Телефон с Android и подключенная плата Марсоход

А вот видео демонстрация:

Теперь у нас есть плата Марсоход, как исполнительное устройство для телефона с OS Android!

 


Добавить комментарий