Leonardo и Seeedstudio Bluetooth Shield

Тема в разделе "Arduino & Shields", создана пользователем Sand, 25 мар 2013.

  1. Sand

    Sand Нерд

    Приветствую всех!
    Появилась небольшая проблема. Прикупил блютуз шилд ВОТ ТАКОЙ
    Подключил RX к TX, TX к RX leonando serial1(DIGITAL пины 0 и 1 )

    После подключения с компа к блютузу и отправки через терминал, например abc, появляется:
    a
    -1
    b
    -1
    c
    -1

    По идее, peek должна взять байт, следующий за a и я должен получить в терминале на компе что то типа:
    a
    b
    b
    c
    c
    -1

    peek()
    Returns the next byte (character) of incoming serial data without removing it from the internal serial buffer. That is, successive calls to peek() will return the same character, as will the next call to read(). peek() inherits from the Stream utility class.

    Код (Text):
    while (Serial1.available() > 0) {
        // get the new byte:
        char inChar  = (char)Serial1.read();
        char nextChar = (char)Serial1.peek();
        Serial.println(inChar);
        Serial.println(nextChar,DEC);
     
    Блютуз в режиме Slave, инициализация в setup():
    Код (Text):
    Serial1.begin(38400); //Set BluetoothBee BaudRate to default baud rate 38400
      Serial1.print("\r\n+STWMOD=0\r\n"); //set the bluetooth work in slave mode
      Serial1.print("\r\n+STNA=SeeedBTSlave\r\n"); //set the bluetooth name as "SeeedBTSlave"
      Serial1.print("\r\n+STOAUT=1\r\n"); // Permit Paired device to connect me
      Serial1.print("\r\n+STAUTO=0\r\n"); // Auto-connection should be forbidden here
      delay(2000); // This delay is required.
      Serial1.print("\r\n+INQ=1\r\n"); //make the slave bluetooth inquirable
      Serial.println("The slave bluetooth is inquirable!");
      delay(2000); // This delay is required.
      Serial1.flush();
     
  2. hibiki

    hibiki Гик

    поменяйте местами peek() и read()
    у вас peek() смотрит в поток после чтения, а там ничего нет
     
  3. Sand

    Sand Нерд

    Поменял.
    Результат:
    a
    a
    b
    b
    c
    c

    Ожидаю получить на выходе:
    a
    b
    b
    c
    c
    -1

    abc передается в порт одной строкой. запись идет таким образом: (Objective C)
    [portwriteString:sendString usingEncoding:NSUTF8StringEncodingerror:NULL];

    Это writeString:
    Код (Text):

    - (BOOL)writeString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(NSError **)error
    {
        NSData *data = [string dataUsingEncoding:encoding];
        return [self writeData:data error:error];
    }
    А это writeData
    Код (Text):
    // write to the serial port; NO if an error occured
    - (BOOL)writeData:(NSData *)data error:(NSError **)error
    {
        BOOL result = NO;
     
        const char *dataBytes = (const char*)[data bytes];
        NSUInteger dataLen = [data length];
        ssize_t bytesWritten = 0;
        int errorCode = kAMSerialErrorNone;
        if (dataBytes && (dataLen > 0)) {
            bytesWritten = write(fileDescriptor, dataBytes, dataLen);
            if (bytesWritten < 0) {
                errorCode = kAMSerialErrorFatal;
            } else if ((NSUInteger)bytesWritten == dataLen) {
                result = YES;
            } else {
                errorCode = kAMSerialErrorOnlySomeDataWritten;
            }
        } else {
            errorCode = kAMSerialErrorNoDataToWrite;
        }
        if (error) {
            NSDictionary *userInfo = nil;
            if (bytesWritten > 0) {
                NSNumber* bytesWrittenNum = [NSNumber numberWithUnsignedLongLong:bytesWritten];
                userInfo = [NSDictionary dictionaryWithObject:bytesWrittenNum forKey:@"bytesWritten"];
            }
            *error = [NSError errorWithDomain:AMSerialErrorDomain code:errorCode userInfo:userInfo];
        }
           
        return result;
    }
     
    Не совсем понятно, почему в буфере ничего нет после a и b
     
  4. hibiki

    hibiki Гик

    эмм.. да кагбе все правильно
    peek вернул первый символ
    read прочитал его же
    peek вернул второй символ
    read его прочитал
    и т.д.

    с чего бы должно не быть первого "a", и появиться -1?
     
  5. Sand

    Sand Нерд

    Может я чего то не понимаю...
    В буфере 3 символа. a, b и c.
    3 операции read()возвращают:
    a
    b
    c
    все верно.

    Делаю 1ю операцию read, получаю "a"
    После этого делаю peek(), ожидаю получить "b", а получается -1
    Если вместо peek() сделать read() - то результат, как и ожидается, "b"

    Задача - взяв, допустим, "а", посмотреть "вперед", если впереди "b", то одно, иначе - другое
     
  6. hibiki

    hibiki Гик

    а вы уверены, что в буфере есть "b" на момент вызова peek()?
    в общем случае полагаться на то, что в каждый момент времени у вас будет полученный и следующий готовый для чтения символ - нельзя. available() срабатывает, как только в буфер попадет хотя бы один байт.

    очень советую изменить логику, или хотя бы отложить принятие решения на следующий цикл чтения
     
    Sand нравится это.
  7. Sand

    Sand Нерд

    если вместо peek сделать read, то возвращается "b", соответственно "b" есть в буфере, на момент вызова, я правильно понимаю?
     
  8. hibiki

    hibiki Гик

    теоретически - да.
    но все равно впечатление такое, что каждый read читает свой байт и опустошает буфер, благо, ломаться там в коде нечему. в порядке бреда невероятного - у вас нигде не переопределяется RX_BUFFER_SIZE?

    и да, моя фраза
    Код (Text):
    полагаться на то, что в каждый момент времени у вас будет полученный и следующий готовый для чтения символ - нельзя
    остается в силе
     
  9. Megakoteyka

    Megakoteyka Оракул Модератор

    Правильно. А вот если после чтения посмотреть в буфер, то можно там уже ничего и не увидеть - первый байт уже прочитался, а второй еще не пришел.
     
    Sand нравится это.
  10. Sand

    Sand Нерд

    Вот вот, тоже так кажется. Пробовал делать read() и затем println(available()), available = 0 всегда. Хотя должны быть еще данные дальше - 100%.
    RX_BUFFER_SIZE нигде явно не переопределяю.

    Может после чтения через read нужно делать задержку? Кто его этого блютуза поймет
     
  11. HighDigital

    HighDigital Гик

    Попробуйте поставить задержку, я где то во внешке читал, что Ардуино может просто не успевать исполнять код, и пропускать его. Сам не проверял, но вроде об этом не один человек писал...
    Думаю ~50мс достаточно.
     
    Sand нравится это.
  12. Sand

    Sand Нерд

    Попробую с задержкой, видимо, действительно, не успевают все байты прилететь, я ведь не замерял, сколько времени проходит между приемом a и b. Еще думаю попробовать SerialEvent() . Так даже правильнее, наверное, будет. Что то типа прерывания. Смущает то, что Serial1 - Arduino Mega only, по мануалу с оф сайта. У Леонардо тоже есть hardware Serial1.
     
  13. Megakoteyka

    Megakoteyka Оракул Модератор

    Не может, тут наоборот ситуация - данные еще не пришли, а контроллер уже пытается их прочитать.
    Задержка не нужна, просто перед чтением каждого байта надо убедиться, что он есть в буфере.
    Если бы контроллер не успевал выполнять обработку, мы бы имели переполнение буфера.
     
  14. Megakoteyka

    Megakoteyka Оракул Модератор

    SerialEvent - самый правильный вариант. Либо проверяйте наличие каждого байта перед чтением. Если хотите прочитать сразу 5 байт, пишите так:
    Код (Text):
    byte buffer[5];
    ...
    if(Serial.available() >= 5) {
        for(int i = 0; i < 5; i++)
            buffer[i] = Serial.read();
    }
     
  15. HighDigital

    HighDigital Гик

    Я имею ввиду, что пришли данные, ждем ~50ms, читаем.
    Просто если мы отправили, должны чуть подождать, и считать. А так получается, что мы отправляем, данные не успели прийти (не хватило всего 5-10ms например) и мы считываем, а их в это время нету, они пришли спустя 10ms...

    Эти 50ms мы не заметим, а для кода лишним не будет.
     
  16. Sand

    Sand Нерд

    Всем спасибо, надо будет еще замерить время между появлением данных в буфере.
     
  17. Sand

    Sand Нерд

    Да, можно будет привести длины всех команд к общему знаменателю, например, длина всех команд - 5 и использовать что то типа вышеуказанного кода, если 5 и больше символов пришли, читаем. Но мне вариант с SerialEvent() больше всего нравится...
     
  18. Sand

    Sand Нерд

    Еще есть вопрос, есть PIO0 у дэвайса, подав на него 1 - мы дисконнектим подключенный дэвайс, судя по описанию(Given a rising pulse in PIO0, device will be disconnected. 6. Disconnect device Pulling PIO0 high will disconnect current working Bluetooth device.). Подскажите, где этот PIO0, на плате нигде не написано, только PIO1 переключатель

    про PIO0 ТУТ
    Даташит

    Bi-Direction RX EN - Нужно подать 1 на RX ногу ардуино при подключенном шилде? Это пробовал, ничего не меняется
     
  19. Megakoteyka

    Megakoteyka Оракул Модератор

    А ничего не меняется - Вам в любом случае нужно проверять количество данных в буфере.
     
  20. Megakoteyka

    Megakoteyka Оракул Модератор

    Если хотите надежно передавать команды, прикрутите пакетную передачу.
    Пакет в самом простом случае состоит из байта-заголовка, байта-длины пакета, собственно данных и контрольной суммы. Так Вы всегда надежно определите начало и конец пакета, а заодно проконтролируете, что данные не исказились при передаче. На форуме уже как-то приводилась реализация такого протокола.