Sending RGB data while receiving touch & accel data

Hello,

I'm using a Teensy 3.2 with OctoWS2811 to send RGB data from Max/MSP to 201 LEDs. I'm using start and end markers to denote each frame of RGB data.

I'm simultaneously trying to receive capacitive touch-sense data from the Teensy, and accelerometer data from a BNO055.

Receiving the touchsense data is fine, but receiving the accelerometer data seems to cause the frames of RGB data to stutter a little. I'm guessing that getting a sensor event from the BNO055 is blocking the incoming frames. Is there a way to make it non-blocking?

#include <OctoWS2811.h>

// the following includes are for the BNO055 accelerometer
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>

// Check I2C device address and correct line below (by default address is 0x29 or 0x28)
//                                   id, address
Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28, &Wire);

// Define constants
const unsigned long OUTPUT_RATE_ACCEL = 1000000; // Output rate in microseconds
const unsigned long OUTPUT_RATE_TOUCH = 2000; // Output rate in microseconds
const int MOVING_AVERAGE_WINDOW_SIZE = 10; // Size of the moving average window
const int config = WS2811_GRB | WS2811_800kHz;
const int ledsPerStrip = 26;
const int numStrips = 8;
const int numChannels = ledsPerStrip * numStrips * 3;
const int maxDataLength = numChannels;  // maxDataLength is the maximum length allowed for received data.

// Declare variables
unsigned long accelLastOutputTime = 0;
unsigned long touchLastOutputTime = 0;
int touchRead_pin = 1;
int touchRead_data = 0;
int touchRead_data_history[MOVING_AVERAGE_WINDOW_SIZE];
int touchRead_data_sum = 0;
int touchRead_data_average = 0;
float eventOrientationX = 0;
float eventOrientationY = 0;
float eventOrientationZ = 0;
float linearAccelX = 0;
char serial_array[numChannels];
int serial_array_length = 0;
DMAMEM int displayMemory[ledsPerStrip * 6];
int drawingMemory[ledsPerStrip * 6];
char receivedChars[numChannels + 1];
boolean newData = false;        // newData is used to determine if there is a new command

OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);

void setup()
{
  Serial.begin(115200);

  /* Initialise the sensor */
  if (!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while (1);
  }

  bno.setExtCrystalUse(false); // https://protosity.wordpress.com/2016/09/12/bno055-arduino-ros/

  leds.begin();
  test();
}

// https://arduino.stackexchange.com/questions/176/how-do-i-print-multiple-variables-in-a-string
// https://gist.github.com/EleotleCram/eb586037e2976a8d9884
int aprintf(char *str, ...) {
  int i, j, count = 0;

  va_list argv;
  va_start(argv, str);
  for (i = 0, j = 0; str[i] != '\0'; i++) {
    if (str[i] == '%') {
      count++;

      Serial.write(reinterpret_cast<const uint8_t*>(str + j), i - j);

      switch (str[++i]) {
        case 'd': Serial.print(va_arg(argv, int));
          break;
        case 'l': Serial.print(va_arg(argv, long));
          break;
        case 'f': Serial.print(va_arg(argv, double));
          break;
        case 'c': Serial.print((char) va_arg(argv, int));
          break;
        case 's': Serial.print(va_arg(argv, char *));
          break;
        case '%': Serial.print("%");
          break;
        default:;
      };

      j = i + 1;
    }
  };
  va_end(argv);

  if (i > j) {
    Serial.write(reinterpret_cast<const uint8_t*>(str + j), i - j);
  }

  return count;
}


void loop()
{
  recvWithStartEndMarkers();                // check to see if we have received any new commands
  if (newData)  {
    processCommand();   // if we have a new command do something
  }

  // https://forum.arduino.cc/t/demonstration-code-for-several-things-at-the-same-time/217158
  // Check if enough time has elapsed since last output
  unsigned long currentTime = micros();
  if (currentTime - touchLastOutputTime >= OUTPUT_RATE_TOUCH)
  {
    // Read touch sensor data
    touchRead_data = touchRead(touchRead_pin);

    // Update the last output time
    touchLastOutputTime = currentTime;

        // Check if it's time to update accelerometer data
        if (currentTime - accelLastOutputTime >= OUTPUT_RATE_ACCEL)
        {
          // Get a new sensor event
          sensors_event_t event;
          bno.getEvent(&event);
          eventOrientationX = event.orientation.x;
          //eventOrientationY = event.orientation.y;
          //eventOrientationZ = event.orientation.z;
          // Possible vector values can be:
          // - VECTOR_ACCELEROMETER - m/s^2
          // - VECTOR_MAGNETOMETER  - uT
          // - VECTOR_GYROSCOPE     - rad/s
          // - VECTOR_EULER         - degrees
          // - VECTOR_LINEARACCEL   - m/s^2
          // - VECTOR_GRAVITY       - m/s^2
          imu::Vector<3> linearaccel = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);

          linearAccelX = linearaccel.x();
          // Update the last output time of the accelerometer
          accelLastOutputTime = currentTime;
        }
    
    // serial.println() = "\r\n"
    aprintf("\r\n%d %f %f", touchRead_data, eventOrientationX, linearAccelX);
    Serial.flush();
  }
}

void processCommand()
{
  for (int i = 0; i < ledsPerStrip * numStrips ; i++)
    leds.setPixel(i, receivedChars[i * 3], receivedChars[i * 3 + 1], receivedChars[i * 3 + 2]);
  leds.show();
  newData = false;
}

void recvWithStartEndMarkers()
{
  static boolean recvInProgress = false;
  static int ndx = 0;
  int startMarker = 254;
  int endMarker = 255;

  if (Serial.available() > 0)
  {
    int rc = Serial.read();
    if (recvInProgress == true)
    {
      if (rc != endMarker)
      {
        if (ndx < maxDataLength) {
          receivedChars[ndx] = rc;
          ndx++;
        }
      }
      else
      {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }
    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}


void test() {
  for (int i = 0; i < ledsPerStrip * numStrips ; i++) {
    leds.setPixel(i, random(0, 255), random(0, 255), random(0, 255));
    leds.show();
    delay(16);
    leds.setPixel(i, 0, 0, 0);
    leds.show();
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.