Go Down

Topic: Adafruit Neopix strip matrix with text input via nRF 8001 BLE - not displaying. (Read 33 times) previous topic - next topic

fixedcoil

I am using a Leonado and trying to recreate the Adafruit GuggenHat project in a ZIGZAG matrix (48 x 10). I have taken the project sketch and modified it for my matrix but it does not display anything. Adding a debug Serial.print() following the matrix.print() shows the text from my phone (using the Adafruit UART app) is being received. Here is the modified sketch:

Code: [Select]
/*--------------------------------------------------------------------------
  GUGGENHAT: a Bluefruit LE-enabled wearable NeoPixel marquee.

  Requires:
  - Arduino Micro or Leonardo microcontroller board.  An Arduino Uno will
    NOT work -- Bluetooth plus the large NeoPixel array requires the extra
    512 bytes available on the Micro/Leonardo boards.
  - Adafruit Bluefruit LE nRF8001 breakout: www.adafruit.com/products/1697
  - 4 Meters 60 NeoPixel LED strip: www.adafruit.com/product/1461
  - 3xAA alkaline cells, 4xAA NiMH or a beefy (e.g. 1200 mAh) LiPo battery.
  - Late-model Android or iOS phone or tablet running nRF UART or
    Bluefruit LE Connect app.
  - BLE_UART, NeoPixel, NeoMatrix and GFX libraries for Arduino.

  Written by Phil Burgess / Paint Your Dragon for Adafruit Industries.
  MIT license.  All text above must be included in any redistribution.

  Modified to display on a 48 x 10 zigzag matrix.
  --------------------------------------------------------------------------*/

#include <SPI.h>
#include <Adafruit_BLE_UART.h>
#include <Adafruit_NeoPixel.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_GFX.h>


// NEOPIXEL STUFF ----------------------------------------------------------

// Intended for use with a flat zigzag panel 48 x 10 Neopixels.
#define NEO_PIN     6 // Arduino pin to NeoPixel data input
#define NEO_WIDTH  48 // Hat circumference in pixels
#define NEO_HEIGHT 10 // Number of pixel rows (round up if not equal)
//#define NEO_OFFSET  (((NEO_WIDTH * NEO_HEIGHT) - 240) / 2)

// Set up the matrix
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(48, 10, NEO_PIN,
                            NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT +
                            NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
                            NEO_GRB            + NEO_KHZ800);

char          msg[21]       = {0};            // BLE 20 char limit + NUL
uint8_t       msgLen        = 0;              // Empty message
int           msgX          = matrix.width(); // Start off right edge
unsigned long prevFrameTime = 0L;             // For animation timing
#define FPS 20                                // Scrolling speed

// BLUEFRUIT LE STUFF-------------------------------------------------------
// This is how the nRF8001 is wired to the Leonado board
// CLK, MISO, MOSI connect to hardware SPI.  Other pins are configrable:
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RST  9
#define ADAFRUITBLE_RDY  2 // Must be an interrupt pin

Adafruit_BLE_UART BTLEserial = Adafruit_BLE_UART(
                                 ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
aci_evt_opcode_t  prevState  = ACI_EVT_DISCONNECTED;

// STATUS LED STUFF --------------------------------------------------------

// The Arduino's onboard LED indicates BTLE status.  Fast flash = waiting
// for connection, slow flash = connected, off = disconnected.
#define       LED LED_BUILTIN    // Onboard LED (not NeoPixel) pin
int           LEDperiod   = 0;   // Time (milliseconds) between LED toggles
boolean       LEDstate    = LOW; // LED flashing state HIGH/LOW
unsigned long prevLEDtime = 0L;  // For LED timing

// UTILITY FUNCTIONS -------------------------------------------------------
// This bit is not relevant as we are usig a flat panel.
// Because the NeoPixel strip is coiled and not a uniform grid, a special
// remapping function is used for the NeoMatrix library.  Given an X and Y
// grid position, this returns the corresponding strip pixel number.
// Any off-strip pixels are automatically clipped by the NeoPixel library.
// uint16_t remapXY(uint16_t x, uint16_t y) {
//  return y * NEO_WIDTH + x - NEO_OFFSET;
// }

// Given hexadecimal character [0-9,a-f], return decimal value (0 if invalid)
uint8_t unhex(char c) {
  return ((c >= '0') && (c <= '9')) ?      c - '0' :
         ((c >= 'a') && (c <= 'f')) ? 10 + c - 'a' :
         ((c >= 'A') && (c <= 'F')) ? 10 + c - 'A' : 0;
}

// Read from BTLE into buffer, up to maxlen chars (remainder discarded).
// Does NOT append trailing NUL.  Returns number of bytes stored.
uint8_t readStr(char dest[], uint8_t maxlen) {
  int     c;
  uint8_t len = 0;
  while ((c = BTLEserial.read()) >= 0) {
    if (len < maxlen) dest[len++] = c;
  }
  return len;
}

// MEAT, POTATOES ----------------------------------------------------------

void setup() {
  matrix.begin();
  // matrix.setRemapFunction(remapXY);
  matrix.setTextWrap(false);   // Allow scrolling off left
  matrix.setTextColor(0xF800); // Red by default
  matrix.setBrightness(31);    // Batteries have limited sauce

  BTLEserial.begin();
  Serial.begin(9600);

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
}

void loop() {
  unsigned long t = millis(); // Current elapsed time, milliseconds.
  // millis() comparisons are used rather than delay() so that animation
  // speed is consistent regardless of message length & other factors.

  BTLEserial.pollACI(); // Handle BTLE operations
  aci_evt_opcode_t state = BTLEserial.getState();

  if (state != prevState) { // BTLE state change?
    switch (state) {       // Change LED flashing to show state
      case ACI_EVT_DEVICE_STARTED: LEDperiod = 1000L / 10; break;
      case ACI_EVT_CONNECTED:      LEDperiod = 1000L / 2;  break;
      case ACI_EVT_DISCONNECTED:   LEDperiod = 0L;         break;
    }
    prevState   = state;
    prevLEDtime = t;
    LEDstate    = LOW; // Any state change resets LED
    digitalWrite(LED, LEDstate);
  }

  if (LEDperiod && ((t - prevLEDtime) >= LEDperiod)) { // Handle LED flash
    prevLEDtime = t;
    LEDstate    = !LEDstate;
    digitalWrite(LED, LEDstate);
  }

  // If connected, check for input from BTLE...
  if ((state == ACI_EVT_CONNECTED) && BTLEserial.available()) {
    if (BTLEserial.peek() == '#') { // Color commands start with '#'
      char color[7];
      switch (readStr(color, sizeof(color))) {
        case 4:                  // #RGB    4/4/4 RGB
          matrix.setTextColor(matrix.Color(
                                unhex(color[1]) * 17, // Expand to 8/8/8
                                unhex(color[2]) * 17,
                                unhex(color[3]) * 17));
          break;
        case 5:                  // #XXXX   5/6/5 RGB
          matrix.setTextColor(
            (unhex(color[1]) << 12) +
            (unhex(color[2]) <<  8) +
            (unhex(color[3]) <<  4) +
            unhex(color[4]));
          break;
        case 7:                  // #RRGGBB 8/8/8 RGB
          matrix.setTextColor(matrix.Color(
                                (unhex(color[1]) << 4) + unhex(color[2]),
                                (unhex(color[3]) << 4) + unhex(color[4]),
                                (unhex(color[5]) << 4) + unhex(color[6])));
          break;
      }
    }
    else { // Not color, must be message string
      msgLen      = readStr(msg, sizeof(msg) - 1);
      msg[msgLen] = 0;
      msgX        = matrix.width(); // Reset scrolling
    }
  }
  matrix.fillScreen(0);
  matrix.setCursor(msgX, 0);
  if (--msgX < -55) {
    msgX = matrix.width();

  }
  matrix.show();
  delay(150);

  if ((t - prevFrameTime) >= (1000L / FPS)) { // Handle scrolling
    matrix.fillScreen(0);
    matrix.setCursor(msgX, 0);
    matrix.print(msg);
    Serial.print(msg); // Debug print
    if (--msgX < (msgLen * -6)) msgX = matrix.width(); // We must repeat!
    matrix.show();
    delay(150);
    prevFrameTime = t;
  }

}


To check that I had not made a wiring error on my panel I used this sketch, modified for my layout:
https://create.arduino.cc/projecthub/gatoninja236/how-to-make-a-neopixel-matrix-3f5631 and it displays as expected.
Both use the Adafruit Neopixel libraries and matrix.print() and while the code differs so far as I can tell they both do the same with respect to the matrix functions. I'd be grateful if anyone can give me an idea as to where my problem lies.

Go Up