3x3x3 LED matrix Programm (doesnt work yet)

Hey there,

I build a 3x3x3 led matrix using these http://www.ledstyles.de/index.php/Attachment/5162-Cube-Control-Schaltplan-gif/ schematics.
It consists of 9 columns of LEDs and 3 levels. All of them are controlled by an Attiny2313, which I am programming via the Arduino IDE and the Tiny hardware files from git. I also added a button to switch between different modes.

I found some code examples online, but none of them uses my setup. So I wrote my own programm.
It compiles and I can upload it. But then I only get some wildly blinking leds. Not what I expacted.
Sometimes you don’t see the errors in your own program, so I need your help!

This is my code:

// Pins
const int button = 2;
const int levels[] = {5,6,7};
const int pillars[] = {8,9,10,11,12,13,14,15,16};

// Variables
long timetick = 1000 / 30; // = run at x frames per 1000ms (=1s)
int button_state = 0; // Button pressed?
int button_laststate = 0; // for comparison
int currentMode = 0; // Switch between modes
unsigned long now = 0; // time
int level = 0; // current level of the matrix

// Values
const int maxMode = 2;
const int mode[maxMode][3][9] = { // [mode, level, leds]
                       {{1,1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1,1}},
                       {{1,0,1,0,1,0,1,0,1},{1,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,0}},
                       };


// the setup routine runs once when you press reset:
void setup() {                
  // initialize the pins
  for (int i=0; i < 9; i++) {
    pinMode(pillars[i], OUTPUT);
  }
  
  for (int i=0; i < 3; i++) {
    pinMode(levels[i], OUTPUT);
  }
  
  pinMode(button, INPUT);
  
  now = millis();
}

// the loop routine runs over and over again forever:
void loop() {

  // ***********************************************
  // Read the button and switch modes
  // ***********************************************
  button_state = digitalRead(button);  
  
  if (button_state != button_laststate && button_state == HIGH) {
    currentMode++;
    if (currentMode >= maxMode) currentMode = 0;
  }

  button_laststate = button_state;
  
  
  // ***********************************************
  // Paint the current mode's picture
  // ***********************************************
  
  if (millis() - now > timetick) {
   
    // Paint one level
    now = millis();
    
    for (int i = 0; i < 9; i++) {
      digitalWrite(pillars[i], mode[currentMode][level][i]);
    }
    
    resetPins();
    digitalWrite(levels[level], HIGH); 
    
    level++;
    if (level > 2) level = 0;
  }
  
}

// Resets all levels
void resetPins() {
    for (int i = 0; i < 3; i++) {
      digitalWrite(levels[i], LOW);
    }
}
const int mode[maxMode][3][9] = { // [mode, level, leds]
                       {{1,1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1,1},{1,1,1,1,1,1,1,1,1}},
                       {{1,0,1,0,1,0,1,0,1},{1,1,1,1,1,1,1,1,1},{0,0,0,0,0,0,0,0,0}},
                       };

Perhaps you need to waste more space using long, or even long long.

54 ints (108 bytes) where 54 bits (7 bytes) are needed…

  if (button_state != button_laststate && button_state == HIGH) {

Can you really recite the whole operator precedence table without looking? I certainly can’t, and I’ve been doing C(++) programming for 30 years. Some parentheses are in order.

    // Paint one level
    now = millis();
    
    for (int i = 0; i < 9; i++) {
      digitalWrite(pillars[i], mode[currentMode][level][i]);
    }

with some unknown set of values. Great idea.

Ditch that sketch. Make sure you can turn one specific LED on. Make the sketch cycle through the LEDs turning one at a time on. Make sure that the LED that you expect turns on.

Hey, thanks for your feedback!

  1. Yeah I know that integers are a waste of space. I haven’t found a good solution yet though. Afaik there is no bit type in gcc/arduino, so I cant use arrays of bits or something. And a byte (which exists) has one bit less then I need. So I could use 2 bytes per level, but that would be too much too. Any solution here?

  2. Yeah, you are right. It worked like that but I added some parantheses now.

  3. Unknown values? I did define them in the code as an array of 0 and 1’s. Sure you can’t use 2’s … but this code isn’t for “dummies”.

I did write a new sketch though, which (successfully) circles through the leds. It doesn’t have different modes yet though, and its already 1,3k from my 2k Bytes big, cause I haven’t found a good solution to store the values of the leds yet. As I said above I could use a hint here :slight_smile:

My code this time:

// Pins
const int button = 2;
const int levels[] = {5,6,7};
const int pillars[] = {8,9,10,11,14,12,16,15,13};

// Variables
long timetick = 1000 / 250; // = run at x frames per 1000ms (=1s)
long picturetick = 350; // takes x ms to change to a new picture
unsigned long now = 0; // time
unsigned long lastpicture = 0;
int level = 0; // current level of the matrix
int ledPillar = 0;
int ledLevel = 0;

// LEDs
int leds [3][9] = {
                    {1,0,0,0,0,0,0,0,0},
                    {0,0,0,0,0,0,0,0,0},
                    {0,0,0,0,0,0,0,0,0}
                  };



// the setup routine runs once when you press reset:
void setup() {                
  // initialize the pins
  for (int i=0; i < 9; i++) {
    pinMode(pillars[i], OUTPUT);
  }
  
  for (int i=0; i < 3; i++) {
    pinMode(levels[i], OUTPUT);
  }
  
  pinMode(button, INPUT);
  
  now = millis();
  lastpicture = millis();
}

// the loop routine runs over and over again forever:
void loop() {  

  // ***********************************************
  // Paint the levels
  // ***********************************************
  
   
  if ((millis() - now) > timetick) {
    
    // Paint one level
    now = millis();
      
    resetPins();
    setLEDs();
    
    digitalWrite(levels[level], HIGH); 
      
    level++;
    level = level % 3;  
  }
   
  
  // ***********************************************
  // Paint the current mode's picture
  // ***********************************************
  
  
  if ((millis() - lastpicture) > picturetick) {
    lastpicture = millis();
    
    for (int a = 0; a < 3; a++)
        for (int b = 0; b < 9; b++)
          leds[a][b] = 0;
           
    leds[ledLevel][ledPillar]=1;
  
    ledPillar++;
    if (ledPillar > 8) {
      ledPillar = 0;
      ledLevel++;
      ledLevel = ledLevel % 3;
    }
  }
}


// Resets leds
void resetPins() {
    for (int i = 0; i < 3; i++) {
      digitalWrite(levels[i], LOW);
    } 
}

// light the right leds
void setLEDs() {
  for (int i = 0; i < 9; i++) {
      digitalWrite(pillars[i], leds[level][i]);
  }
}

LastSamurai: Hey, thanks for your feedback!

  1. Yeah I know that integers are a waste of space. I haven't found a good solution yet though. Afaik there is no bit type in gcc/arduino, so I cant use arrays of bits or something. And a byte (which exists) has one bit less then I need. So I could use 2 bytes per level, but that would be too much too. Any solution here?

No, but a byte would contain enough bits (1) to store a number 1 or a number 0. Granted it still wouldn't be as efficient as using bitmasks for space, but changing 'int' to 'byte' would half your memory usage.

LastSamurai: I did write a new sketch though, which (successfully) circles through the leds. It doesn't have different modes yet though, and its already 1,3k from my 2k Bytes big, cause I haven't found a good solution to store the values of the leds yet. As I said above I could use a hint here :)

How is that sketch using 1.3kB? You know there is a difference between SRAM and Flash? (The IDE tells you about Flash usage)

Sure, I will use a byte array then. Thought there might be a better version (beside bit shifting).

[quote author=Tom Carpenter link=topic=228804.msg1654052#msg1654052 date=1395949899] How is that sketch using 1.3kB? You know there is a difference between SRAM and Flash? (The IDE tells you about Flash usage) [/quote]

It is flash usage then, because its what the IDE (1.0.3) shows me. I was wondering too why it's so big...

I'm still working on the programm (trying to get moving pictures atm) but I still dont know why the sketches are so big. Is there any way to get them (significantly) smaller? (best case: while still using arduino syntax) Because 2k isn't terribly much space and I want to use some more complex motions.

An Arduino Uno has 32k of Flash memory - program space. It has 2k of RAM - variables/heap/stack

I think you are getting the two confused again.

You can check it by adding this function to your program and printing it's return value out with Serial.print();

int freeRam(void)
{
  extern unsigned int __heap_start;
  extern void *__brkval;

  int free_memory;
  int stack_here;

  if (__brkval == 0)
    free_memory = (int) &stack_here - (int) &__heap_start;
  else
    free_memory = (int) &stack_here - (int) __brkval; 

  return (free_memory);
}

Thanks guys, but as I stated in my first post I am using an Attiny2313 with the arduino IDE, no Uno. It's flash is only 2 kb big.

...and only 128 bytes of RAM. Which, if you look carefully, is less than you were using in your first post.

Ah, missed that.

Anyway, if you want to reduce memory consumption (both Flash, and RAM) change EVERYTHING in your code which says ‘int’ to be ‘byte’. All of the places in the code you posted where you have used an int would be fine as a byte, but would be far less wasteful.

The next step is to forget about the Arduino functions when it comes to a microcontroller with very limited resources. Dump the digitalWrite and pinMode and digitalRead functions and use direct port manipulation instead.

I wrote a relatively simple chunk of code for an attiny24 one time and using the Arduino functions it compiled to 3kB, using direct port manipulation and dropping millis() and other Arduino rubbish, it compiled to <512bytes.