#1 2016-03-17 07:51:59

wiznet
Учасник
Зареєстрований: 2016-03-17
Повідомлень: 1

Лаги при bluetooth-соединении

Всем привет.

Нашел в загашнике aruino nano и адресную светодиодную ленту - захотелось запилить ambilight подсветку. Чтобы не придумывать велосипед - взял уже готовый софт (http://lightpack.tv/downloads.php) и запилил скетч реализующий этот протокол. Через USB все работает отлично и без нареканий.

Однако, там же в загашнике валялся bt-модуль hc-05 - решил и его приспособить чтобы, значится, еще и с телефона светомузыку играть :)
Подключил как serial и обнаружил неожиданную проблему: через bluetooth теряются пакеты.

1) Ресивер лежит в 15 см от трансмиттера (скорее всего дело не в помехах)
2) Пробовал разные скорости (9600 до 115200, устанавливая идентичные скорости и в софте, и в скетче, и в самом модуле через AT-команды) - говорю это для того чтобы отмести самые очевидные вопросы про несоответствие baud rate
3) Ни с одной библиотекой не срослось (подключал к HardwareSerial вместо usb, использовал идущую в комплекте с IDE SoftwareSerial, скачивал отдельую NewSoftSerial)

Результат один - если посылать данные с интервалом то все отлично проходит, как только слать друг за другом байты то даже в первых 100 байтах начинаются жуткие лаги и потери символов.

Собственно, вывод тут один: виноваты чьи-то руки из задницы :)
Возможно, переполняется какой-нибудь буфер и теряются пакеты? Возможно, уже есть готовые рецепты исправления которые я не знаю. К сожалению я не силен в особенностях arduino и микроконтроллеров в целом, а для кого-то проблема может быть сразу очевидна.

Поэтому, предлагаю на ваш суд мой скромный скетч (один из, этот эмулирует программно serial чтобы иметь возможность посылать AT-команды блютусине и вообще в два порта писать) - возможно, вы подскажете в чем может быть трабла? Сообщайте пожалуйста если нужна дополнительная инфорамция. Заранее спасибо.

// This sketch provide ability to control LED using USB and Bluetooth
// (with latency and packet losts but its work)
//
// 1) can understand Adalight protocol (Adalight, Prismatic etc software)
// 2) can switch custom leds using (to use in own plugins/implementations)
//
// Adalight protocol specification:
// A 'magic word' (along with LED count & checksum) precedes each block
// of LED data; this assists the microcontroller in syncing up with the
// host-side software and properly issuing the latch (host I/O is
// likely buffered, making usleep() unreliable for latch).  You may see
// an initial glitchy frame or two until the two come into alignment.
// The magic word can be whatever sequence you like, but each character
// should be unique, and frequent pixel values like 0 and 255 are
// avoided -- fewer false positives.  The host software will need to
// generate a compatible header: immediately following the magic word
// are three bytes: a 16-bit count of the number of LEDs (high byte
// first) followed by a simple checksum value (high byte XOR low byte
// XOR 0x55).  LED data follows, 3 bytes per LED, in order R, G, B,
// where 0 = off and 255 = max brightness.

// <a href="https://github.com/FastLED/FastLED" title="https://github.com/FastLED/FastLED" rel="nofollow">https://github.com/FastLED/FastLED</a>
#include <FastLED.h>
#include <SoftwareSerial.h>


/* === feel free to change this values for your board */
#define STRIP_TYPE WS2812B          // change to type you need
#define NUM_LEDS 120                // leds count in strip
#define LED_PIN 6                   // pin stip data output
#define USB_SERIAL_RATE 115200      // usb connection speed
#define BT_SERIAL_RATE 115200       // bt connection speed (default is 9600)
#define BT_RX_PIN 11                //
#define BT_TX_PIN 10                // bluetooth module rx/tx pins
/* ==== */

#define SEED 0x55
#define STATE_WAITING 0
#define STATE_HEADER 1
#define STATE_PAYLOAD 2

#define PROTO_DEFAULT 0
#define PROTO_CUSTOM 1

#define HEADERSIZE 3

String magic = "Ada";
CRGB leds[NUM_LEDS];

SoftwareSerial btSerial(BT_RX_PIN, BT_TX_PIN);

typedef struct Storage{
  uint8_t state;
  String buffer;
  int16_t expectedPayloadSize;
  uint8_t proto;
};

Storage usb;
Storage bt;

// flash message on USB connection
void flash() {
  LEDS.showColor(CRGB(255, 0, 0));
  delay(500);
  LEDS.showColor(CRGB(0, 255, 0));
  delay(500);
  LEDS.showColor(CRGB(0, 0, 255));
  delay(500);
  LEDS.clear(true);
}

// parse adalight-compatible packet
void parseDefaultPacket(Storage *storage) {
    // reset all leds in strip first
   memset(leds, 0, NUM_LEDS * sizeof(struct CRGB));
   // iterate over payload and set next led in row
   uint16_t ptr = 0;
   for (uint16_t i = 0; i < NUM_LEDS; i++) {
    leds[i].r = (byte)storage->buffer[ptr++];
    leds[i].g = (byte)storage->buffer[ptr++];
    leds[i].b = (byte)storage->buffer[ptr++];
   }
}

// parse custom user packet
void parseCustomPacket(Storage *storage) {
   // iterate over payload and set only required LEDs
  uint16_t i = 0;
  while (i < storage->buffer.length()) {
    byte hi = (byte)storage->buffer[i++];
    byte lo = (byte)storage->buffer[i++];
    uint16_t addr = (hi << 8) + lo;
    if (addr >= NUM_LEDS || addr < 0) {
      i += 3; // skip incorrect values
    } else {
      leds[addr].r = (byte)storage->buffer[i++];
      leds[addr].g = (byte)storage->buffer[i++];
      leds[addr].b = (byte)storage->buffer[i++];
   }
  }
}

// switch port state (waiting for packet, waiting for packet header, waiting for data for led's)
void updateState(Storage *storage, uint8_t flag) {
  storage->state = flag;
  storage->buffer = "";
}

// process incoming serial byte according current state
void handleIncomingByte(Storage *storage, char input) {
   storage->buffer += input;
    // new packet incoming
    if (storage->buffer.endsWith(magic)) {
      return updateState(storage, STATE_HEADER);
    }

    switch (storage->state) {
      // test header
      case STATE_HEADER:
        // time to check packet
        if (storage->buffer.length() >= HEADERSIZE) {
          byte hi = (byte)storage->buffer[0];
          byte lo = (byte)storage->buffer[1];
          byte chk = (byte)storage->buffer[2];
          if((hi ^ lo ^ SEED) != chk) {
            return updateState(storage, STATE_WAITING);
          }
          uint8_t len = (hi << 8) + lo;
          if (len == (NUM_LEDS - 1)) {
            storage->expectedPayloadSize = (len + 1) * 3;
            storage->proto = PROTO_DEFAULT;
          } else {
            storage->expectedPayloadSize = len * 5;
            storage->proto = PROTO_CUSTOM;
          }
          return updateState(storage, STATE_PAYLOAD);
        }
        break;
      case STATE_PAYLOAD:
        if (storage->buffer.length() >= storage->expectedPayloadSize) {
          switch (storage->proto) {
            case PROTO_DEFAULT:
              parseDefaultPacket(storage);
              break;
            case PROTO_CUSTOM:
              parseCustomPacket(storage);
              break;
          }
          FastLED.show();
          return updateState(storage, STATE_WAITING);
        }
        break;
      case STATE_WAITING:
      default:
        if (storage->buffer.length() > magic.length()) {
          storage->buffer = storage->buffer.substring(storage->buffer.length() - magic.length());
        }

    }
}

// execute code on startup
void setup() {
  FastLED.addLeds<STRIP_TYPE, LED_PIN, GRB>(leds, NUM_LEDS);
  flash();
  updateState(&usb, STATE_WAITING);
  updateState(&bt, STATE_WAITING);

  Serial.begin(USB_SERIAL_RATE);
  btSerial.begin(BT_SERIAL_RATE);
  Serial.println(magic);
}

// receive packets in endless loop
void loop() {
  if (Serial.available()) {
    char input = Serial.read();
    handleIncomingByte(&usb, input);
  }
  if (btSerial.available()) {
    char input = btSerial.read();
    handleIncomingByte(&bt, input);
  }
}

Неактивний

#2 2016-03-17 12:15:24

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: Лаги при bluetooth-соединении

привет
~366 это нормальный пакет, до 740 байт буффер модуля (  могу ошибаться  в 2 раза %) ) 
для Вас хеадер это начальные 3 байта с контролем?  и он начинается как новый пакет  после последнего успешного
я думаю что рассинхрон возможен
передача данных, лично я сделал бы пакет с уникального хеадера
например \t  и дальше идуут данные
завершал пакет бы  \r
данные что меньше  0x20  кодировал бы по принципу  TCP  но с признаком \a
т.е.  '\a''1'
декодировалось бы  как у байт ('1' ^ 0x20)
избыточноть некая, но Вы всегда синхронизируетесь на начало пакета
если реальный байт в пакете '\a'
значит приходит '\a''\a'  в буффер пишете  ('\a'^0x20 )
TCP стек вроде юзает 0x7E но давайте отсечем все что меньше пробела )
я думаю что такая переделка повысит надежность
по коду видно что разберетесь )) успеха ) и покажите что получилось )

add
если код не Ваш, и используете чужое приложение
то пропаяйте проводники

Остання редакція NoName (2016-03-17 12:15:38)

Неактивний

#3 2016-05-18 10:48:01

teon wereless technology
Гість

Re: Лаги при bluetooth-соединении

Всем привет. Ищу специалиста для программирование bluetooth контролеров.

1) Создание программы функционирования наушников как bluetooth (BE) гарнитуры, МР3 и кардио-датчика. ВЕ контроллер наушников (CSR8670) должен осуществлять многоуровневый прием и передачу данных между наушниками, брелком и телефоном (смартфоном, планшетом, ноутбуком, ПК, и т.п. с возможностью подключения ВЕ гарнитуры).

2) Создание программы для брелка bluetooth (ВЕ) наушников с функциями управления состояния проигрывателя, включения статуса поиска наушников и контроль питания аккумулятора. Программа должна обеспечивать также поддержание индивидуального канала с ВЕ контроллером наушников (CSR8670). Односторонняя передача данных CC2541 (режим master) на наушники.

Условия работы: оговариваем при встрече.

#4 2016-05-18 11:23:43

NoName
Customer
З Київ
Зареєстрований: 2014-07-08
Повідомлень: 1,446

Re: Лаги при bluetooth-соединении

Алексей, здравствуйте,
сайт лежит, почта не правильная (
но наушники  и спортсменка хороши )
исправляйтесь )

Неактивний

#5 2016-05-18 14:11:14

Nefreemen
Учасник
З Киев
Зареєстрований: 2015-12-19
Повідомлень: 716

Re: Лаги при bluetooth-соединении

wiznet, аналогичная потеря у меня была между arduino mega2560 и esp8266. Копал я долго, нудно пока не сделал монитор для сериал, в результате обнаружил что больше 63 байтов "одним махом" ардуино не шлет. Залез в библиотеку и подправил буфер, поставил больше ( по моему 128, точно не помню) и проблема решилась big_smile .

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму