LE Blog

Инженер с поэтической душой

21.07.2010 firtree_right Управление LEGO NXT Mindstorms с помощью телефона HTC Desire на Android

summer in the city

Введение

Лето в этом году выдалось жаркое, но пока ни о каких отпусках речи не идёт. Пока солнечно, тепло и сухо — самое время снимать панорамы улиц (или ГрадоГлядъ, как я это называю). Однако, не смотря на хорошую плотность работы, ничего принципиально нового, о чём интересно было бы рассказать, не произошло. Поэтому я покажу концепт, над которым работаю уже какое-то время, и который лежит в стороне от моих основных языков программирования.

Дистанционное управление

Итак, у меня уже давно есть конструктор LEGO Mindstorms, который довольно бодро взаимодействует через bluetooth с компьютером или с таким же конструктором.

А в апреле я обновил телефон на HTC Desire под управлением операционной системы Андроид, которая уже давно привлекла моё внимание, но всё руки не доходили.

В итоге появились повод, возможность и желание «пощупать» Андроид. И вот, что из этого получилось:

Секреты?

Для тех, кто соберётся заниматься чем-то подобным, могу поделиться небольшим секретом. Стандартный метод получения BluetoothSocket, рекомендованный командой Гугла, не работает, а нужен небольшой хак:

/* Не работает:
 * socket = device.createRfcommSocketToServiceRecord(MY_UUID)
 */

Method m = device.getClass().getMethod("createRfcommSocket",
            new Class[] { int.class });
socket = (BluetoothSocket)m.invoke(device, Integer.valueOf(1));

Вот и всё, что я могу рассказать :) Если я ещё буду писать про Андроид, то придётся сделать подсветку кода для него.

Материалы для самостоятельного изучения

Руководство для разработчиков под Андроид на тему bluetooth

12.06.2010 firtree_right Оказалось, не казалось

Пока вы спали (и я тоже спал) мне явился правильный ответ: это float в формате little endian (младшим байтом вперёд). Вот код для андроида.

int tmp = Float.floatToRawIntBits(new Float(number));
byte[] msg = {(byte)tmp, (byte)(tmp >> 8), (byte)(tmp >> 16), (byte)(tmp >> 24)};

Непонятно, зачем они так сделали, ведь работает NXT с целыми числами. Даже если и с точкой, то точность оборудования не та.

11.06.2010 firtree_right Профессиональное

Я тут вечерами не могу лечь спать, потому что управляю своим Lego Mindstorms роботом с телефона на Android (моего любимого ненаглядного HTC Desire то бишь) по bluetooth. Я уже написал базовое взаимодействие, и бодро передаю сообщения. Возник лишь один нюанс с передачей целых чисел. Вместо того чтобы совать их в трубу младшим байтом вперёд, как об этом говорят все интернеты, у меня они выглядят не так.

Это был целый детектив. Я слал ему little endian, но он отказывался. Сначала совсем. Потом везде видел нули Тогда я начал его пытать, и заставлял его посылать сообщения из целых чисел.

Если записать это в двоичной форме, то примерно понятно, что он имеет в виду. Но возможно есть матчасть, которую можно почитать, чтобы лучше это понять. Что это за представление, как его просто изобразить, скажем, на Java? Итак, имеем четыре байта:

... симметрично
-4 => 0x00 0x00 0x80 0xC0
-3 => 0x00 0x00 0x40 0xC0
-2 => 0x00 0x00 0x00 0xC0
-1 => 0x00 0x00 0x80 0xBF
0 => 0x00 0x00 0x00 0x00
1 => 0x00 0x00 0x80 0x3F
2 => 0x00 0x00 0x00 0x40
3 => 0x00 0x00 0x40 0x40
4 => 0x00 0x00 0x80 0x40
5 => 0x00 0x00 0xA0 0x40
6 => 0x00 0x00 0xC0 0x40
7 => 0x00 0x00 0xE0 0x40
8 => 0x00 0x00 0x00 0x41
9 => 0x00 0x00 0x10 0x41
10 => 0x00 0x00 0x20 0x41
...
15 => 0x00 0x00 0x70 0x41
16 => 0x00 0x00 0x80 0x41
17 => 0x00 0x00 0x88 0x41
...
555 => 0x00 0xC0 0x0A 0x44
...
2147483648 => 0x00 0x00 0x00 0x4F

По спецификации и из результата видно, что он старательно делает вид, что полностью использует все четыре байта, но тогда не было бы чисел, которые он бы не смог интерпретировать. В районе максимумов заметно, что очень большие числа он не различает между собой, если они отличаются на несколько единиц. Это какая-то экспоненциальная форма? Что это?