Возникла идея подключить плату Марсоход к смартфону с ОС Android так, что бы можно было с телефона подавать какие нибудь команды в плату.
Я уже пол-года пользуюсь недорогим HTC Wildfire S, так что телефон для экспериментов есть. Могу попробовать связать телефон с платой Марсоход. Для чего это нужно еще толком не придумал, но сама идея интересная. Как это можно сделать? У телефона есть разные интерфейсы и самый простой их них, пожалуй – это аудио выход. Я подумал, что, теоретически, я могу на телефоне воспроизводить короткие аудио файлы, например, тоны разной частоты. Если плата Марсоход сможет распознавать эти звуковые тоны, то их можно интерпретировать как разные команды.
Задумавшись о реализации этого проекта я понял, что придется преодолеть массу проблем. Самые серьезные – это:
- На плате Марсоход нет аналогового входа, куда можно было бы подавать звук с телефона. Все входы ПЛИС (Altera CPLD) на плате Марсоход цифровые.
- Я не умею писать программы для Android.
Понятно, что проект легким не будет, но, «мы не привыкли отступать».
Первая мысль была такая: «Нужно создать хотя бы один первый эталонный аудио файл, чтобы воспроизводить его на телефоне и пытаться слушать платой Марсоход».
Для создания аудио файла я использовал программу Audacity.
Это совершенно потрясающая свободная программа для редактирования аудио файлов. Позволяет записывать, редактировать, вырезать, склеивать и прочее и прочее. В ней я создал синусоиду 1000Гц длительностью 30 секунд и записал ее в WAV файл. По Bluetooth перенес файл на телефон. Теперь источник сигнала у меня есть.
Сделал провод для подключения телефона к плате. Решил так, что простейший проект для ПЛИС платы Марсоход должен быть почти пустой: просто брать сигнал на одном входе ПЛИС и выводить его на другой выход ПЛИС. На выходе смотреть осцилографом – есть ли там вообще хоть что-то. Была надежда, что аналоговый сигнал с разъема audio-jack телефона будет достаточно большой амплитуды, чтобы входной элемент ПЛИС включался и выключался на некотором уровне. К сожалению этого не произошло... Сигнал с телефона оказался слишком слабым. Делать какой-то усилитель не хотелось, ведь при этом пропадет красота идеи. Нужно как-то сдвинуть входной сигнал, может быть делителями напряжения на резисторах...
После нескольких экпериментов устойчивый результат получился вот так (показан фрагмент схемы платы Марсоход):
Внутри проекта для ПЛИС пины 12 и 14 (обычно в наших проектах это контакты с именами dn, dp ) сделаны выходами и подключены к нулю. На плате Марсоход установлены два джампера (перемычки), как показано на схеме выше. Получается делитель напряжения: резисторы R1 и R2 параллельны и тянут к земле, а резисторы R3 и R4 параллельны и тянут к питанию. К точке деления напряжения подключаю землю аудио сигнала с телефона. Собственно сигнальный провод подключаю к любому входу, например key0 платы Марсоход. Таким образом, сигнал с телефона оказывается «приподнятым» из-за того, что нулевой провод с телефона подключен к делителю. Это решение позволило уверенно «принимать аудио сигнал». Конечно, принятый сигнал внутри ПЛИС оказывается «оцифрованым», есть только ноль и единица – это сигнал с прямоугольными импульсами. Тем не менее, частота «оцифрованного» сигнала равна частоте подаваемого аудио сигнала, то есть равна частоте моей синусоиды с телефона.
Вот так выглядит плата Марсоход с подключенным проводом – интерфейсом к телефону.
Следующая задача – измерение частоты входного сигнала внутри ПЛИС. Это довольно просто. Я написал для ПЛИС платы Марсоход на языке 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
Принцип действия этой «программы» следующий:
- На плате Марсоход есть кварцевый генератор 100Мгц. Это слишком большая частота для нашей задачи, поэтому сразу делим ее на 256. Получается основная тактовая частота clk проекта 390625Гц.
- Входной «оцифрованный» сигнал сперва пересинхронизируется к тактовой частоте clk, а затем из него выделяется перепад с единицы в ноль. Можно наоборот выделять фронт, это не принципиально для измерения частоты. Итак есть короткие импульсы aedge с частотой равной частоте входного тона.
- Я хочу посчитать сколько периодов эталонной частоты clk поместится внутри периода входной частоты сигнала aedge. Для этого имеем двоичный счетчик counter, который сбрасывается при aedge=1 и считает (но не более 1023). Если счетчик counter досчитал до 1023 и больше aedge не приходит, то значит входной сигнал прекратился.
- Имеются двухбитные сдвиговые регистры вида reg [1:0]f1000. В младший бит этого регистра в момент aedge задвигается бит признака частоты. Например, при входной аудиочастоте 1000Гц в ее периоде поместится примерно 390625/1000=390 периодов эталонной частоты. Я несколько размываю границы и делаю проверку вида (counter>380 && counter<400). Поскольку это число задвигается в сдвиговый регистр, то получается, что если f1000==2’b01, то звуковой сигнал только что обнаружен. Если f1000==2’b11, то сигнал длится уже больше двух периодов. Если f1000==2’b10, то сигнал только что закончился.
- Светодиоды 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 на телефоне выглядят вот так (верхние две строчки в списке):
Вот это то, что мне нужно. Я могу писать скрипт на компьютере в простейшем редакторе вроде 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. Дальше выбираю и запускаю из списка скриптов мой собственный:
Программа запускается, вот так выглядит вся "система":
А вот видео демонстрация:
Теперь у нас есть плата Марсоход, как исполнительное устройство для телефона с OS Android!
Подробнее...