Dual ScrollPhatHD 17×14 LED Array

January 13, 2019 at 12:31 pm (maker) (, , , , , )

Having now had a play with my ScrollPhatHDs with the Arduino I’ve now successfully linked two together via a TCA9548A breakout board (having solved my Weird Multi-I2C Bus Issues as previously described).

The ultimate aim was to make a self-contained unit containing two ScrollPhatHD boards, an Arduino Nano and the TCA9584A.  I’ve now managed that using a square piece of breadboard, various jumper wires and most importantly, the Pimoroni Pogo-a-go-go Solderless header pins – I just didn’t want to spoil the neat look of the ScrollPhatHD’s by soldering to them directly.  The Pogo-pins are just perfect for spring-loaded connections between the ScrollPhatHDs and breadboard.

The one quirk, is that if I wanted all boards nicely sandwiched between the ScrollPhatHDs and the breadboard, but wanted to use the pogo-pins, then the breadboard needs to be strip-side up.

Here is the plan, followed by some photos of the finished item.

scrollphat-breakout_bb

I’ve left the nano and tca breakout off, so I can see the tracks.  This was from a first experiment with the two Phats, so it already had three full height sets of cuts in tracks – hence the few places where there were a couple of bits of patching to do, which were just done with solder links.  There are a few pins added to support the nano, especially at the USB end where I’ll be plugging in and out, which aren’t connected to anything on the stripboard.  And the four pins highlighted for the two ScrollPhat’s themselves weren’t soldered pins – that is the location for the pogo-pins.

In the final board, I put the jumper wires on the underside, and used headers pushed right through from below.  I also added a reset switch (not shown in the plan) wired to the Nano RST and ground on the strip board.

The linking of the two Phats isn’t perfect – the Nano USB port is just a fraction too high to perfectly fit, meaning the two boards bow out slightly in the middle.  Note the use of the pogo-pins.  I could replace them all with a slightly longer stand-off, but this is fine for a prototype.

Also, I made sure to drop some insulating tape on the bottom of both the Nano and the TCA board, to make sure it wouldn’t short anything on the copper of the stripboard.  I also put a bit around the shield of the USB port just in case, but I don’t think there was anything conductive on the back of the Phat.

So I now have a USB-accessible, self-contained, programmable 17×14 LED array.

Software wise, this uses the modified Adafruit IS31FL3731 Library I mentioned before, with the added quirk that one of the boards needs the coordinates reversing.  Coupled with the need to switch boards using the TCA as well, this means the basic idea of using the board is as follows:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <ScrollPhat_IS31FL3731.h>

// ScrollPhats connected using a TCA9548A I2C Multiplexer
// These are the I2C bus numbers used
#define TCAONE       0
#define TCATWO       1

//  HOR = number in horizontal (x) plane
//  VER = number in vertical (y) plane
#define HOR 17
#define VER 14

// Scrollphats have a hardcoded I2C address.
// Assumes connected as follows:
//      ledmatrix1 - using SC0 via the TCA
//      ledmatrix2 - using SC1 via the TCA
ScrollPhat_IS31FL3731 ledmatrix1 = ScrollPhat_IS31FL3731();
ScrollPhat_IS31FL3731 ledmatrix2 = ScrollPhat_IS31FL3731();

#define TCAADDR 0x70
void tcaselect(uint8_t i) {
  if (i > 7) return;
 
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}

void setup () {
  // Initialse the I2C handling
  Wire.begin();
  
  tcaselect(TCAONE);
  ledmatrix1.begin();
  tcaselect(TCATWO);
  ledmatrix2.begin();
    
  // Do something to initialse your pixel array
}

void loop () {
  // Do stuff on your pixel array
  // Don't forget to write the displayRead(x,y) function
  // used in the scan routine

  ScanDisplay();
}

// Note: you need to implement the displayRead (x,y) function
//      to determine if a pixel is on or off
//
void ScanDisplay () {
  // Scan the first matrix
  tcaselect(TCAONE);
  for (uint8_t x=0; x<HOR; x++) {
    for (uint8_t y=0; y<VER/2; y++) {
      if (displayRead (x, y)) {
        ledmatrix1.drawPixel(x, y, 64);
      } else {
        ledmatrix1.drawPixel(x, y, 0);
      }
    }
  }

  // Scan the second matrix
  // Note this is oriented 180 degrees, so reverse both
  // x and y prior to setting, also of course, only using
  // the second half of the pixel array to display here.
  tcaselect(TCATWO);
  for (uint8_t x=0; x<HOR; x++) {
    for (uint8_t y=0; y<VER/2; y++) {
      if (displayRead (HOR-x-1, VER/2-1-y+VER/2)) {
        ledmatrix2.drawPixel(x, y, 64);
      } else {
        ledmatrix2.drawPixel(x, y, 0);
      }
    }
  }
}

 

Kevin

Advertisements

Permalink Leave a Comment

Weird Multi-I2C Bus Issues

January 11, 2019 at 8:17 pm (maker) (, , , )

This is just a quick post as a future reminder really.  I have two ScrollPhat HD Pimoroni boards that I’m using with an Arduino Nano, but as the I2C address is fixed for the boards, I’m using a TCA9548A I2C multiplexer breakout board to change I2C buses between accessing the two ScrollPhatHD boards.

But I was getting weird bus issues – sometimes only one of the boards came up, sometimes none, very occasionally, they were both fine.  I tried different channels off the TCA, swapping the boards over, I tried linking the RESET line of the TCA to the RESET line of the Arduino.  I even tried connecting the RESET line of the TCA to a digital pin and resetting the TCA manually on power up, but nothing seemed to work.

Then I saw a post somewhere about some weird I2C bus issues and one of the responses was “make sure you are calling Wire.begin();”.  I’d forgotten to put that in.

Once the code was calling Wire.begin() (only once mind), all was well.  It now powers up reliably and no resetting of the TCA is required.  All is good.

Kevin

 

Permalink 1 Comment

Pimoroni ScrollPhat using Adafruit IS31FL3731 Library

December 29, 2018 at 11:08 pm (maker) (, , , , , , )

I finally got myself a genuine Adafruit IS31FL3731 driver board and LED matrix (that I mentioned in a previous post) and glued an Arduino Nano on the back, thus creating a very neat little self-contained USB-driven 16×9 matrix of surface mount LEDs, which is great.

This uses the same driver chip as the Pimoroni ScrollPhat HD board for the Raspberry Pi, which is another great board I have, but I wanted to drive it from an Arduino too, so set about looking to see if the Adafruit libraries would work for the Pimoroni board too.  Four connections are required, as usual for I2C – VCC, GND, SDA, SCL as defined in the pinout here.

In summary, yes, but the Pimoroni has an odd LED configuration, as can be seen in the provided Python library:

class ScrollPhatHD(Matrix):
    width = 17
    height = 7

    def _pixel_addr(self, x, y):
        if x > 8:
            x = x - 8
            y = 6 - (y + 8)
        else:
            x = 8 - x
        return x * 16 + y

So the key feature is getting this translation over into the Adafruit IS31FL3731 library in the correct place.  So, taking a copy of the Adafruit_IS31FL3731.cpp and Adafruit_IS31FL3731.h files there were a number of changes to make.

First of all, the Adafruit boards provide a matrix of 16×9 (total 144) leds, compared to the ScrollPhat’s 17×7 (119) leds, so everywhere there is a reference to a width of 16 and height of 9, that needs changing to 17 and 7 respectively.  Unfortunately, there were a number of hard-coded “16”s and “9”s that needed updating.

Then, the translation function is required as follows (added to the .cpp and defined in the .h files):

// ScrollPhat LED Mapping taken from:
// https://github.com/pimoroni/scroll-phat-hd/blob/master/library/scrollphathd/is31fl3731.py
uint8_t ScrollPhat_IS31FL3731::xy2led (uint8_t x, uint8_t y) {
  if (x>8) {
    x = x-8;
    y = 6-(y+8);
  } else {
    x = 8-x;
  }
  return x*16 + y;
}

This function is responsible for translating the x,y values into a serialised led offset number (0 to 144 in the case of a fully populated matrix like the Adafruit).  There is one place where this has to be called – in the function ScrollPhat_IS31FL3731::drawPixel the following line needs to be changed as indicated:

From:
  setLEDPWM(x + y*16, color, _frame);

To:
  setLEDPWM(xy2led(x,y), color, _frame);

Assuming all the 16×9 references have been updated correctly to 17×7, and no special rotations or anything were required (I’ve not tested all options in the Adafruit GFX libraries), then this largely seems to work, at least it works with the Adafruit Swirl and gfx demos (although there might be some sorting out still to do in terms of handling rotations).

Kevin

 

Permalink 2 Comments