Go Down

Topic: MAX7219 and non-standard matrix sizes (10 x 20) (Read 585 times) previous topic - next topic

noiasca

Quote
As for using other sized matrices
it's just about your final layout. You can remove the 8x8 LED modules and use other LEDs like you want to.

but even if you insist to build your own layout - I still would use 6. And pay attention on the different colors of the LEDs, to get red yellow and green to the same brightness.

by the way, if you want to rebuild a SID: http://www.bloody-plastic.com/props/sidpanel.html

how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

PaulRB

Using addressable WS2812-compatible LEDs like PL9823s *might* be an option but it would be sacrificing some accuracy and brightness.
You can get these leds in 5mm round shape with diffusing lenses: search for apa106. So they could look accurate. And brightness would certainly not be a problem. Apa106 would be much brighter than using max7219 because no multiplexing is involved. You might need to turn the brightness down!

Grumpy_Mike

#17
Sep 16, 2020, 11:20 am Last Edit: Sep 16, 2020, 11:23 am by Grumpy_Mike
And be aware if this is for a movie then watch out for the strobe effect between the multiplexing and the shutter speed of the camera.
The brightness might also be a problem as LEDs are very difficult to photograph without the LEDs looking burned out.

Do some tests before you commit to building the whole thing.

Quote
Apa106 would be much brighter than using max7219 because no multiplexing is involved.
Other than the PWM used in the dimming. Here the APA106 is much faster than the WS2812.

Paul__B

The brightness might also be a problem as LEDs are very difficult to photograph without the LEDs looking burned out.
Well that is a problem with amateur photographers on these boards, but I suspect much less of a problem on a properly-lit movie set - unless it is a dark scene!

noiasca

Ok, it took my now some hours, but here comes my "Take it easy with 6 max7219" proof of concept.

Code: [Select]

/*
   This sketch simulates a spectrum analyzer with MAX7219
   e.g. the SID from the movie Back to the Future 
   or an AudioControl SA-3052
   based on the idea of: https://forum.arduino.cc/index.php?topic=704923.0
   
   hardware:
   - 8 MAX7219 with each 8x8 LED module, e.g. https://s.click.aliexpress.com/e/_dUpAJp9

   library:
   I'm using my Noiasca LED Control: https://werner.rothschopf.net/201904_arduino_ledcontrol_max7219.htm as it also supports Hardware SPI.
   But the sketch might work with the common known "LED Control" also.

   by noiasca
   2020-09-19
*/

const uint8_t LEDDATA_PIN = D8;  // LED DATA IN
const uint8_t LEDCLK_PIN  = D7;  // LED Clock
const uint8_t LEDCS_PIN   = D6;  // LED CS or LOAD
const uint8_t LED_MODULES = 8;

const uint8_t noOfColumns = 10;  // columns to show
const uint8_t ledsPerColumn = 20;//
const uint16_t speed = 250;      // refresh rate of display
const uint16_t highwater = 250;  // how long should the highwater mark stay

#include "NoiascaLedControl.h"  // download from https://werner.rothschopf.net/201904_arduino_ledcontrol_max7219.htm
LedControl lc = LedControl  (LEDDATA_PIN, LEDCLK_PIN, LEDCS_PIN, LED_MODULES);  // Software Bitbang - use this if you can't use Hardware SPI
//LedControl lc = LedControl  (LEDCS_PIN, LED_MODULES); // Hardware SPI (UNO/NANO: 13 CLK, 11 DATA_IN/MOSI)

struct Coordinate
{
  byte device;
  byte row;
  byte col;
};

struct Column
{
  byte previousMax;          // stores the highest value
  uint32_t previousMillis;   // timestamp of previousMax
} column[noOfColumns];

// Maps one pixel of the column to a technical device/col/row position
// the calculation has to fit to your layout - and could differ based on the column you hand over in the parameter
Coordinate getCoordinate(byte actualColumn, byte value)
{
  Coordinate actual;
  if (actualColumn < 8)
  {
    actual.device = value / 8;
    actual.col = 7 - value % 8;   // "in my hardware implementation" I needed the reverse order of the column...
    actual.row = actualColumn;
  }
  else
  {
    actual.device = (value / 8) + 3;  // "in my hardware implementation" the 9th column (and further) start at a different MAX7219 device
    actual.col = 7 - value % 8;
    actual.row = actualColumn - 8;
  }

// Serial.print (actual.device); Serial.print("\t"); // activate if you need to check your wiring
// Serial.print (actual.col); Serial.print("\t");
// Serial.print (actual.row); Serial.println();
  return actual;
}

void showColumn(byte actualColumn, byte value)
{
  Coordinate coordinate;
  for (byte i = 0; i < ledsPerColumn; i++)
  {
    coordinate = getCoordinate(actualColumn, i);
    lc.setLed(coordinate.device, coordinate.row, coordinate.col, i <= value); // Set or delete the pixel
  }
  // show a delaying highwater mark
  uint8_t currentMillis = millis();
  if (value < column[actualColumn].previousMax && currentMillis - column[actualColumn].previousMillis < (speed + highwater))
  {
    coordinate = getCoordinate(actualColumn, column[actualColumn].previousMax);
    lc.setLed(coordinate.device, coordinate.row, coordinate.col, true);         // Set pixel
  }
  else
  {
    column[actualColumn].previousMax = value;
    column[actualColumn].previousMillis = currentMillis;
  }
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println(F("BTTF SDI with MAX7219"));
  lc.begin();  /* The MAX72XX needs to initialize hardware */
  for (byte i = 0; i < LED_MODULES; i++)
  {
    lc.shutdown(i, false);
    lc.setIntensity(i, 4);  /* Set the brightness to a medium value, possible is 0-15 */
  }
  lc.clearDisplay(); /* and clear all displays */
  // test the  display to ensure your wiring is correct:
  showColumn(4, 4);
  showColumn(4, 8);
  showColumn(5, 9);
  showColumn(6, 12);
  showColumn(7, ledsPerColumn - 1);
  delay(3000);
  lc.clearDisplay();

  showColumn(9, ledsPerColumn - 1);
}

void loop() {
  for (byte i = 0; i < noOfColumns; i++)
  {
    byte value = random(1, ledsPerColumn);                        // simulate with random values
    Serial.print(i); Serial.print("\t"); Serial.println(value);
    showColumn(i, value);
  }
  delay(speed);  // dirty delay
}


In the end, it's just a question of how you map your visual "column" pixels to your real hardware.
The more complex your hardware wiring is, the more effort is needed for getCoordinate().
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

Go Up