среда, 30 октября 2013 г.

Памятка разработчикам Android NDK

В этом посте постараюсь собрать ответы на основные вопросы, возникающие при разработке на С++ для андройда (пост будет обновляться).

Как написать в лог из С++?

#include
__android_log_print(ANDROID_LOG_VERBOSE, "my_application name", "Hello, %s !", "android");

В Android.mk:

LOCAL_LDLIBS := -llog

суббота, 14 сентября 2013 г.

Просто об Android NDK

Иногда у разработчиков Android-приложений возникает необходимость писать часть кода не на Java, а на C\C++. Для этого нам помимо Android SDK понадобиться Android NDK (Native Development Kit).
Итак:

1.Скачиваем Android NDK. http://developer.android.com/tools/sdk/ndk/index.html
2.Распаковываем
3.В проект добавляем два новых файла - Android.mk и hello.c. В первом будут храниться настройки сборки, его содержание должно быть таким:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello
LOCAL_SRC_FILES := hello.c


include $(BUILD_SHARED_LIBRARY)
А в файле hello.c:

#include
#include
jstring Java_com_example_hellojni_MainActivity_helloFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return (env)->NewStringUTF("I am from C Language!");
}

В данном случае имя функции строится так: Java_<название пакета>_<имя класса откуда будет вызываться функция>_<имя функции>.
4.Теперь в нашем классе (например, MainActivity.java) пишем:
public native int helloFromJNI();

static {
System.loadLibrary("hello");
}
5. Затем собираем наш нативный код: 
cd <папка с проектом>
<путь к ndk>/ndk-build


Всё! Осталось собрать и запустить Android-приложение из Eclipse, как если бы оно было обычным Java-приложением=)

воскресенье, 21 апреля 2013 г.

"Контракту требуется свойство Duplex, однако..." (WCF)

Известно, что технология WCF (Windows Communication Foundation) поддерживает дуплексный режим общения сервера с клиентом. В таком случае не только клиент может обращаться к функциям сервера, но и сервер может вызывать функции на машине клиента. И если в обычном случае перед объявлением интерфейса контракта мы пишем аттрибут [Service Contract], то для дуплексного соединения нам необходимо написать что-то подобное:[ServiceContract(CallbackContract = typeof(IDuplexCallback))]
IDuplexCallback - это имя класса, обеспечивающего обратный вызов, его объявление аналогично объявлению других контрактов.
Однако, думаю, что у многих при попытке обновить Service Reference возникало сообщение вроде:
 "Контракту требуется свойство Duplex, однако привязка "BasicHttpBinding" его не поддерживает или этого не позволяет неправильная настройка."

Например, так:



Известно, что BasicHttpBinding не поддерживает дуплекс, нам нужен другой тип биндинга - wsDualHttpBinding. Открываем файл web.config (в проекте сервера - например, WCF Application и др.) Вот как он выглядит у меня:
Видимо, главное здесь - описать endpoint`ы.  Параметр binding имеет нужный нам тип - wsDualHttpBinding.
Вместо названия контракта (contract) duplexWCF.IDuplexService подставьте имя своего интерфейса-контракта, а вместо названия сервиса (service name) duplexWCF.DuplexService имя класса-реализации интерфейса-контракта (возможно, есть и другие варианты, но этот работает =) ). Endpoint MetaDataTcpEndpoint так же и оставляем - видимо, он нужен для получения каких-либо метаданных.
Обновляем Service Reference - работает =)

На сервере доступ к классу реализации функций обратной связи можно следующим способом:
OperationContext.Current.GetCallbackChannel();
IDuplexCallback - интерфейс класса обратной связи.
Возникает вопрос - а если клиентов несколько?  В таком случае эта функция при вызове серверной функции будет возвращать экземпляр класса того клиента, который производит вызов серверной функции. Нам остается только их хранить, например, в списке.

Теперь о клиентской реализации. Просто так объявить экземпляр сервиса-контракта не получится - ему нужно будет передать ссылку на нашу реализацию класса обратной связи.
Так что наследуемся от интерфейса и пишем нечто вроде:



Вот и всё)
Возможно, кому-нибудь поможет.

среда, 27 марта 2013 г.

Пишем в USART на STM32F3

Какое-то время я работал с STM32F100, однако стало необходимо освоить STM32F3.
Вот код инициализации всех USART-ов, если кому необходимо :)


void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
    /* enable usart clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);


    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_7);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7);

 
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = 9600;
    USART_Init(USART1, &USART_InitStructure);

    USART_Cmd(USART1, ENABLE);

    NVIC_EnableIRQ(USART1_IRQn);
}
void USART2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
    /* enable usart clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);


    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_7);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_7);
   
 
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = 9600;
    USART_Init(USART2, &USART_InitStructure);

    USART_Cmd(USART2, ENABLE);

    NVIC_EnableIRQ(USART2_IRQn);
}
void USART3_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
    /* enable usart clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);


    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

 
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_7);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_7);

 
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = 9600;
    USART_Init(USART3, &USART_InitStructure);

    USART_Cmd(USART3, ENABLE);

    NVIC_EnableIRQ(USART3_IRQn);
}
void UART4_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
    /* enable usart clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);


    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);

 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

 
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_5);
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_5);

 
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = 9600;
    USART_Init(UART4, &USART_InitStructure);

    USART_Cmd(UART4, ENABLE);

    NVIC_EnableIRQ(UART4_IRQn);
}
void UART5_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStructureC,GPIO_InitStructureD;
 USART_InitTypeDef USART_InitStructure;
    /* enable usart clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);


    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
 
    GPIO_InitStructureC.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructureC.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructureC.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructureC.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructureC.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOC, &GPIO_InitStructureC);

GPIO_InitStructureD.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructureD.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructureD.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructureD.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructureD.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOD, &GPIO_InitStructureD);
 

    GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_5);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_5);

 
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.USART_BaudRate = 9600;
    USART_Init(UART5, &USART_InitStructure);

    USART_Cmd(UART5, ENABLE);

    NVIC_EnableIRQ(UART5_IRQn);
}

Записываем так:
void USART1putc(const char ch)
{
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    USART_SendData(USART1, ch);
}
(конечно же, меняем номер порта на необходимый).
Чтение, скорее всего, аналогично.

вторник, 26 февраля 2013 г.

Робот "STAR"


Ученые Калифорнийского университета Беркли разработали шестиногого бионического робота длиной в 12 сантиметров. Ему дали имя "STAR", что означает "Sprawl Tuned Autonomous Robot" (на русский можно перевести как "автономный робот с настраиваемым раскидыванием"). Робот может растягивать свои конечности под разными углами, чтобы приспосабливаться к различным типам поверхностей. 
"С помощью своих конечностей робот может достичь высокой производительности при передвижении через неровные поверхности и препятствия, раскинув свои конечности под большим углом; и достичь производительности подобной колесным роботам на гладкой поверхности, растянувшись на небольшой угол. Изменив угол раскидывания, он может карабкаться через препятствия либо ползти под ними. "STAR" может двигаться со скоростью 5.2 метров в секунду (43 длины корпуса в секунду, число Фруда -  9.8) по гладкой поверхности, что делает его самым быстрым неуправляемым ползущим роботом." - сообщают нам в описании видео.

Оригинал здесь - робохаб.

понедельник, 4 февраля 2013 г.

STM32, UM6, SPI...

В сегодняшнем посте я опишу способ получения данных с платы навигации UM6 по протоколу SPI.
Вначале инициализация:

void SPI1_Init(void)
{
RCC->APB2ENR |=  RCC_APB2ENR_AFIOEN;     //включить тактирование льтернативных функций        /
RCC->APB2ENR |=  RCC_APB2ENR_IOPAEN;     //включить тактирование порта А
//вывод управления SS: выход двухтактный, общего назначения,50MHz                             /
GPIOA->CRL   |=  GPIO_CRL_MODE4;    //
GPIOA->CRL   &= ~GPIO_CRL_CNF4;     //
GPIOA->BSRR   =  GPIO_BSRR_BS4;     //

//вывод SCK: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL   |=  GPIO_CRL_MODE5;    //
GPIOA->CRL   &= ~GPIO_CRL_CNF5;     //
GPIOA->CRL   |=  GPIO_CRL_CNF5_1;   //

//вывод MISO: вход цифровой с подтягивающим резистором, подтяжка к плюсу
GPIOA->CRL   &= ~GPIO_CRL_MODE6;    //
GPIOA->CRL   &= ~GPIO_CRL_CNF6;     //
GPIOA->CRL   |=  GPIO_CRL_CNF6_1;   //
GPIOA->BSRR   =  GPIO_BSRR_BS6;     //

//вывод MOSI: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL   |=  GPIO_CRL_MODE7;    //
GPIOA->CRL   &= ~GPIO_CRL_CNF7;     //
GPIOA->CRL   |=  GPIO_CRL_CNF7_1;   //

RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //подать тактирование                                      /
SPI1->CR1     = 0x0000;             //очистить первый управляющий регистр
SPI1->CR2     = 0x0000;             //очистить второй управляющий регистр
SPI1->CR1    |= SPI_CR1_MSTR;       //контроллер должен быть мастером  
SPI1->CR1    |= SPI_CR1_BR;         //задаем скорость
SPI1->CR1    |= SPI_CR1_SSI;        //обеспечить высокий уровень программного NSS
SPI1->CR1    |= SPI_CR1_SSM;        //разрешить программное формирование NSS
SPI1->CR1    |= SPI_CR1_SPE;        //разрешить работу модуля SPI
}
Инициализация взята с одного из сайтов про STM32, однако там не было указанного главного: для того, чтобы читать с этой платы, необходимо устанавливать SS в 0.

Пример получения регистра Yaw(0x63):

float getYaw()
{
u8 b3,b2,b1,b0,temp1,temp2;
short tempshort;
float angle;
GPIOA->BSRR   =  GPIO_BSRR_BR4;
temp1=send_spi1(0x00);
temp2=send_spi1(0x63);
b3=send_spi1(0x00);
b2=send_spi1(0x00);
b1=send_spi1(0x00);
b0=send_spi1(0x00);
GPIOA->BSRR   =  GPIO_BSRR_BS4;
        tempshot=(b3*256)+b2;// глюк блоггера, не могу опубликовать код со смещением
angle=tempshort*0.0109863;
return angle;
}
Функция send_spi1 (взята с одного из форумов по контроллерам) одновременно пишет и читает данные:

u8 send_spi1(u8 byte)
{
    unsigned char rxbyte;
    while (!(SPI1->SR & SPI_SR_TXE));
    SPI1->DR = byte;
    while (!(SPI1->SR & SPI_SR_RXNE));
    rxbyte = SPI1->DR;
    return rxbyte;
}



среда, 23 января 2013 г.

Простой способ работы с I2C в STM32. Часть 2.

В предыдущем посте я кратко описал простой способ работы с протоколом I2C в STM32.
В этом сообщении я добавил несколько ссылок на необходимые файлы и документацию, а также код-примере работы с 
платой Pololu MinIMU-9.

1. Итак, для начала качаем AN2824 "STM32F101xx and STM32F103xx medium- and high-density devices: advanced I²C examples", он же "STM32F10xxx I2C optimized examples" вот отсюда.
Скаченный файл представляет собой архив с примерами работы по протоколу I2C. Распаковываем архив. Если у вас Keil, то вам необходим файл "папка_куда_вы_распаковали_архив\STM32F10x_AN2824_FW_V4.0.0\Project\OptimizedI2Cexamples\MDK-ARM\Optimized I2C examples.uvproj".

Документация здесь.

В файле main.c  находим следующий код.

2. Важные для нас функции:
I2C_LowLevel_Init(I2C1); - инициализируем I2C1 или I2C2
I2C_Master_BufferWrite(I2C1, Buffer_Tx1,1,Interrupt, _ADDRESS); - записываем данные из буфера. 
I2C_Master_BufferRead(I2C1,Buffer_Rx1,1,Polling, _ADDRESS); - читаем данные в буфер.


Читать или писать мы можем тремя способами - Interrupt, Polling или DMA. Все эти функции описываются и реализуются в файлах I2CRoutines.h и I2CRoutines.с (можно посмотреть код реализации).

3. А вот, собственно, и функции для работы с гироскопом, акселерометром и магнитометром. Вначале устройства инициализируются, затем происходит чтение данных в переменные x,y,z. 
Вот и сам код: http://pastebin.com/70rhVxNF



воскресенье, 23 декабря 2012 г.

Баг Qt 5

Ура! Долгожданная новость! Вышел Qt 5!
Как только я узнал об этом событии, сразу же скачал установочник и...
Попытка собрать стандартный проект завершилась неудачей с следующим недвусмысленным сообщением:


"cl" ­Ґ пў«пҐвбп ў­гв७­Ґ© Ё«Ё ў­Ґи­Ґ©
Є®¬ ­¤®©, ЁбЇ®«­пҐ¬®© Їа®Ја ¬¬®© Ё«Ё Ї ЄҐв­л¬ д ©«®¬.
jom: C:\Projects\cameratest-build-Desktop_Qt_5_0_0_MSVC2010_32bit_SDK-_______\Makefile.Debug [debug\widget.obj] Error 1"

Qt что-то требовал от меня, однако, какие могут быть ошибки в стандартном проекте?

Не знаю, в чем причина такого поведения, но в интернете было найдено решение.
В консоле необходимо запустить следующий батник:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat

Затем из этой же консоли запускаем Qt Creator. У меня:
C:\root\dvlp\QTVS5\Tools\QtCreator\bin\qtcreator.exe

Запускаем проект и всё собирается! =)

понедельник, 26 ноября 2012 г.

Красота-то какая!

Решил погуглить сегодня про WebGL.
И второй ссылкой в запросе оказался этот сайт - Chrome Experiments



Если у вас Гугл Хром или иной браузер, поддерживающий WebGL - перейдите по ссылкам, например, по этим:
Огромный глаз
Визуализация музыки
Обработка видео с вебки
Солнечная система
Звезды

среда, 7 ноября 2012 г.

Дизассемблер .Net

Оказывается с помощью стандартных средств Visual Studio можно дизассемблировать PE-файлы(exe,dll,mod,mdl) скомпилированные .Net компилятором. Для этого нам понадобится утилита ildasm.exe. 
У меня она находится в папке  C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin
Выбираем файл и смотрим=)


вторник, 23 октября 2012 г.

О проекте "Mobilebot"

Сделали небольшую презентацию нашего робота для конкурса. В которой вкратце описывается для чего всё это нужно и как будет работать.

вторник, 25 сентября 2012 г.

Простой способ работы с I2C в STM32

Оказывается многие сложные вещи можно сделать значительно проще.
Недавно пришлось работать вот с чем - необходимо реализовать обработку данных с платы Pololu MinIMU-9, включающей в себя акселерометр-магнитометр LSM303DLM и гироскоп L3G4200D. Как оказалось, для обмена данными есть только один путь - протокол I2C. 

Как и полагается, к плате есть документация. Однако, в данном устройстве разделены его составные части -  отдельно гироскоп и отдельно акселерометр-магнитометр. Поэтому, в документации были представлены ссылки на мануалы к каждой из частей. И самое главное - в комплекте были ссылки на исходные коды и даже скриншот работающей десктопной программы, которая принимала значения с платы и прорисовывала текущие углы наклона, азимут и проч.
Однако после скачивания директорий с github меня ждало разочарование. Рабочая программа из двух частей - одна на десктопе, получает данные по com-порту, всё визуализирует. Другая часть - работа с собственно платой, все математические расчеты, но... для Arduino.
И самая главная загвоздка - все операции с протоколом I2C в этих сырцах сводились к красочным и высокоуровневым:
Wired.Begin()
Wired.Read()
и так далее...

В первоначальную задачу ставилось хотя бы что-то прочитать с платы. Однако все запросы в гугле ("stm32 i2c" и проч.) сводились либо к описаниям работы протокола, либо к огромному  объёма кода. 
В конце концов, было найдено вот что:
AN2824
Application note
STM32F10xxx I2C optimized examples
ну и соответствующий этому архив с проектом для Keil`а.

Открываем проект, настраиваем как нам необходимо. Вот нужные функции - 
NVIC_Configuration();
I2C_LowLevel_Init(I2C1);
 - вызываем для инициализации (в данном случае I2C 1).
I2C_Master_BufferWrite(I2C1, Buffer_Tx1,1,Interrupt, _ADDRESS); 
I2C_Master_BufferRead(I2C1,Buffer_Rx1,1,Polling, _ADDRESS);
- соответственно функции записи и чтения. 
Параметры:
  1. Выбираем I2C1 или I2C2 - в зависимости от того, куда подключили устройство
  2. Буфер - массив unsigned char  (откуда читаем или куда записываем).
  3. Число байт для чтения или записи
  4. Тип работы - Interrupt, Polling или DMA.
  5. Адрес устройства
Естественно, функции чтения\записи используются, если STM32 работает в режиме Master.
В случае успешного обмена данными эти функции возвращают Success, в противном - Error.

Ну вот, собственно, и всё =)


воскресенье, 16 сентября 2012 г.

Mobilebot побывал на СелиАсе

Недавно привезли робота на форум "СелиАс-2012". На одной из аллей лагеря "Чудотворы" , где форум проходил, он бодро катался, встречая участников и гостей фразами "Здравствуйте всем", "Вперед, роботы!", "Мы уже среди вас"=)
Впервые продемонстрировали остановку по датчикам и автономное движение.




понедельник, 23 июля 2012 г.

Mobilebot в действии!

Решили мы снять пару видео.
На первом демонстрируется голосовое управление - робот здоровается, проезжает вперед, поворачивает и включает музыку. Движение пока что - по таймеру (можно и без него, но тогда придется останавливать=)) - говорим куда и на сколько секунды. Через заданное время робот остановится для ввода следующей команды.

На втором - управление по датчикам.
Идея такова - держим руки на заданном расстоянии от датчиков - робот не движется. Приближаем - едет назад. Отдаляем или выходим из зоны видимости - едет вперед. Так отдельно для каждого колеса.

четверг, 21 июня 2012 г.

Рыболовы и прогресс

Недавно АГТУ посетил руководитель федерального агенства по рыболовству А.А.Крайний.
В библиотеке, на 3 этаже, были представлены различные проекты, в том числе и наш MobileBot.

В этот раз мы показали обновлённую версию ПО - помимо портирования на Windows 7,  связи с оператором, ручного управления, мы впервые продемонстрировали голосовое управление роботом.

Ну и фотки=)




Вот она связь моей мечты=)




суббота, 9 июня 2012 г.

Презентация MobileBot для представителей Сбербанка

Недавно презентовали MobileBot для представителей из Сбербанка.
Транспортировали его в главный корпус АГТУ=)

 Показали, как робот двигается, а также возможность общения с оператором (обратите внимание на экран).

воскресенье, 3 июня 2012 г.

Хитрое восстановление пароля

Недавно узнал, что доступ к компьютеру в Windows 7 можно получить вот как.

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

Так и сделаем. Заходим в System32 и меняем название cmd.exe на sethc.exe (лучше это сделать с копией cmd, мало ли что, да и sethc предварительно переименовать). Перезапускаемся.

Когда нас встречает окно ввода пароля, нажимаем Shift пять раз и вуаля...Перед нами появляется командная строка.
Тут и можно сменить пароль.

На этом обычно останавливаются статьи во многих блогах, но я хотел бы рассказать, что же всё-таки произошло.
Для этого пойдем дальше.
В командной строке перейдем в папку System32 и запустим "Диспетчер задач". Перед нами необычная картина - оказывается, окно логина - самая обычная программа Виндоус. Но, естественно, попытки ещё завершить ни к чему не приводят - на секунду возникает черный экран и окно логина возникает снова.
Так. Если мы зашли всё-таки в систему, то можем ли мы увидеть рабочий стол?
Оказывается, можем. Нажав в Диспетчере "Новая задача" и введя туда "explorer", мы добьёмся и этого. Вначале у меня запустилось окно настройки конфигураций, а потом внезапно поверх окна логина снизу появилась панель задач и меню "Пуск". Правда, даже при наведении на миниатюру окна логина панель пропадала. А потом explorer перестал запускаться)
Но кроме того получить доступ к папкам в привычном виде можно и через "Обзор" из той же "Новой задачи...".
При этом оказалось, что папка пользователя имеет не свое привычное имя, а имя "система". Видимо, подобно Линуксу Винда вначале загружается от администратора, а потом передает управление пользователю.

Так что, восстанавливаете пароли!





пятница, 27 апреля 2012 г.

вторник, 13 марта 2012 г.

Serial port и групповая политика

Нередко при программировании устройств приходится иметь дело с com-портом. Если вы пользователь Windows, система беззаботно дает вам возможность читать и писать в это устройство. Естественно, в Linux всё не так. Запуск простейшей программы чтения строки из порта вызовет  "Permission denied", если вы не суперпользователь. Некоторые, конечно, будут писать sudo ./имя_программы после каждой компиляции, но это не наилучшее решение, на мой взгляд. И если вы компилируете свою программу в консоли, это будет не так заметно, но вот при разработке, скажем, в Qt Creator постоянный запуск будет надоедать.
Первое решение "в лоб" - программировать под суперпользователем. Однако, оно небезопасно - зачем предоставлять доступ ко всем частям системы, если нужен-то один файл, да и есть ещё один аспект. Если вдруг понадобится изменить свои исходники во время обычной работы, система вежливо отправит нас за получением прав - в начале процесса программирования мы создали файлы под root и, значит, их владелец - root. Изменение обычным пользователем невозможно.
Для того, чтобы избавится от всех этих проблем, мы можем воспользоваться функциями администрирования операционной системы Linux, настроив доступ так, как нам нужно.

Известно, что для каждого файла (и папки) можно настроить права доступа. В основном, они определяются:

  • правами на чтение
  • правами на запись
  • правами на исполнение (для исполняемых файлов)

Кроме того, Линукс, как многопользовательская система, разграничивает доступ в зависимости от пользователя и группы. Под группой в данном случае понимается набор пользователей, объединенных под каким-либо именем.В результате мы можем задавать вышеуказанные атрибуты для:

  • владельца файла
  • группы
  • всех остальных (пользователей, не являющихся владельцем и не входящих в указанную группу)
Конечно, для любого файла можно сменить пользователя или группу (chown, chgrp), однако для одного заданного com-порта это будет неудобно - сделав себя "хозяином" одного порта, установив необходимые атрибуты, мы можем записывать и читать только в него, а не в com-порты в целом. Как же сделать так, чтобы при подключении ещё одного устройства нам не приходилось всё время изменять его права?
Для этого придуманы стандартные пользовательские группы. Став их членом, пользователь получает доступ к определенному классу задач.
Теперь узнаем, к какой группы принадлежит файл-порт ttyUSB0.
Заходим в /dev. Выполняем " ls -l ". Напротив, нужного файла видим группу dialout. Она-то нам и нужна. 
В операционной системе OpenSuse самый простой способ изменить принадлежность пользователя к группам - Yast/Управление пользователями и группами. Добавляем себя в группу dialout. Всё! Настройка завершена!
З.Ы. Сразу после добавления в группу доступ к файлу может и не появится - сделайте logout и войдите снова.