Проблема с bluetooth и большим количеством светодиодных лент

bluetooth led-strip

Я хочу иметь возможность управлять несколькими светодиодными полосами через Bluetooth с помощью одного arduino. Я закодировал свое собственное приложение для Android, и все отлично работает с одной или двумя светодиодными полосами с несколькими пикселями. Но как только мне пришлось много пиксельных данных отправлять по BT, пропало несколько байтов (например, "colfff5dff" вместо "color fff5dff"). Это происходит не каждый раз, но это нереально. Мне кажется, что отправка данных на светодиодную ленту занимает так много времени, что она пропускает какую-то букву.

Я использую dsd tech hc-05 с arduino UNO R3 и светодиодной лентой esp8266.

#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h>

#ifdef __AVR__
 #include <avr/power.h> 
#endif

//SoftwareSerial blueTooth(13,12);

#define PIN       5
#define SIZE      200

#define BRIGHTNESS 200

enum MODE {FIXED, LOOP_RGB, RUNNING, RAINBOW};
enum MODE mode = FIXED;

Adafruit_NeoPixel strip(SIZE, PIN, NEO_RGB + NEO_KHZ800);

int lastTime;

uint32_t color;
char Incoming_value = 0;
char bufferStr[100];
int bufferIndex = 0; 

void setup() {

  Serial.begin(9600); //открыть последовательный порт
  Serial.setTimeout(10);
  strip.begin();           
  strip.show();            
  strip.setBrightness(50); 

  color = Adafruit_NeoPixel::Color(0, 255 ,0 );  
}

void loop() {
  if(Serial.available() > 0)  
  {
    String s = Serial.readString();
    Serial.print(s);

    //Я пробовал какой-то другой способ, например read(); ReadString(); readBytes(); readBytesUntil();
    
    /*
     * ---- not needed for the issue
     */
  }
  switch (mode){
    case FIXED : fixedMode(); break;
    case RUNNING : runningLights(); break;
    case RAINBOW : rainbow(); break;    
    }  
    showAll();
}


void parseBlueTooth(){
  // - - - - не требуется для выпуска
}


void fixedMode(){
  setAll(color);
  showAll();
}

void rainbow(){
  //---- не требуется для выпуска
}


void runningLights() {
  // - - - - не требуется для выпуска
}


void setAll(byte r, byte g, byte b) {
  setAll(Adafruit_NeoPixel::Color(r,g,b));
}

void setAll(uint32_t color) {
  strip.fill(color, 0, SIZE);
}

void showAll(){
  long curTime = millis();
  if(curTime - lastTime >16){
    if(strip.canShow()) {
      strip.show();     
    }
    lastTime = curTime;
  }

}

, 👍2


3 ответа


-1

Я также работаю с HC-05 и извлекаю файлы поверх него. Я отправляю команды и получаю файлы обратно по Bluetooth. Скорость bluetooth должна быть в порядке. (Хотя вам нужно установить его быстрее - у меня 38400)

В цикле setup() выполните следующие действия:

Serial.begin(38400)

Кроме того, ваш код для считывания серийного номера немного отличается.

Вам просто нужно следующее:

while (Serial.available()){
    command = Serial.read();
}

Я отправлял строковые команды, но только сегодня решил изменить их на 1-байтовые команды, потому что с ними гораздо проще иметь дело в операторе switch. В приведенном выше коде моя командная переменная-это байт.

Тогда мой коммутатор выглядит следующим образом в loop():

switch (command){
    case 49: { // ASCII Char 1 - получить температуру
      SW_Serial.print(getString(currentRoom) + " : " + currentTemp);
      // ВЫЗОВИТЕ СВОЙ КОНКРЕТНЫЙ КОД, ЧТОБЫ СДЕЛАТЬ КАЖДУЮ ВЕЩЬ В КАЖДОМ КОНКРЕТНОМ СЛУЧАЕ
      break;
    }
    case 50: { // ASCII char 2 - начало записи данных
      // #### Разрешить запуск/остановку записи данных через BT
      // включает протоколирование временных данных (на SD-карту)
      // включить запись данных и светодиод
      // ВЫЗОВИТЕ СВОЙ КОНКРЕТНЫЙ КОД, ЧТОБЫ СДЕЛАТЬ КАЖДУЮ ВЕЩЬ В КАЖДОМ КОНКРЕТНОМ СЛУЧАЕ
...

Конечно, каждый раз, когда вы проходите цикл, вы должны установить свою командную переменную обратно в 0 (я использую 0 как no-command). В противном случае вы будете продолжать обрабатывать одно и то же значение команды.

,

0

Ваша проблема в том, что вы используете две блокирующие процедуры, которые не могут работать вместе. Как SoftwareSerial, так и объектам NeoPixel требуется время для выполнения операций, предотвращающих что-либо еще.

  • SoftwareSerial блокирует внутри ISR при получении байта
  • Блоки NeoPixel с отключенными прерываниями при выводе состояния светодиода

Это означает, что во время обновления NeoPixel SoftwareSerial не может получать никаких данных. Это было прекрасно, когда у вас было всего несколько светодиодов, так как обновление NeoPixel заняло очень мало времени, но теперь, когда у вас есть больше светодиодов, обновление занимает слишком много времени, и SoftwareSerial больше не может работать надежно.

Чтобы обойти эту проблему, вам придется использовать аппаратный порт UART. Uno имеет только один вывод 0/1 и последовательный объект. Если вы не используете это для связи с компьютером, вы можете подключить модуль Bluetooth туда и использовать Serial вместо SoftwareSerial - однако вам, скорее всего, придется отключать модуль Bluetooth каждый раз, когда вы хотите загрузить новый код на свой ардуино.

,

Это именно то, что я сделал, и это стало лучше, но не идеально., @Antoine Bacquet

Возможно, вам нужно обновить свой Arduino до такого, который будет обновлять NeoPixels с помощью DMA вместо блокировки процессора., @Majenko

Я попробую это сделать, спасибо за информацию, @Antoine Bacquet


1

ИМХО, прочитав ответ Майенко и раддевуса, вы можете сделать что-то, чтобы "уменьшить недостающие данные".

  1. уменьшите скорость передачи данных в бодах (может быть 9600), дайте больше времени для передачи данных по Bluetooth.

  2. добавьте байт контрольной суммы для ваших данных.

Перерегистрация :

https://lucidar.me/en/serialib/most-used-baud-rates-table/

,