Project help (MAX7219) related... (connecting/dis-connecting from main project)

hey gang–

I have a problem I am trying to work through…

I dont believe it to be ‘code’ related…(but who knows… maybe its an initialization error on my end?) and am looking for some general discussion on my problem.

  • ** I am using the Led Control library from the PlayGround/GitHub for the MAX demos/examples

The project is made up of several PCB’s…
1 x main board (Arduino brain + Waveshield built-in)
1 x 3-digit/7-segment display (MAX chip #1)
1 x 30-smd led bargraph (wired matrix style) (MAX chip #2)
1 x constant current board for the high current RGB LED star.

*each board with a MAX chip has its own voltage regulator…etc set-up on the pcb… (FYI)


*the 3rd board with microSD socket is the ‘main’ board… a custom Arduino/Waveshield hybrid

and a quick mock-up of it:

everything was/is working just fine… like in the video, however I have some of events being triggered by some temporary momentary switches hanging off the side of the prop/blaster…

the end goal was to have the RELOAD button (current using a temp switch and manually reload) be connected to part of a DB9 (serial) connector and be secured int he magazine end… and triggered when the magazine is pulled/re-inserted…etc…

the 30 x smd led bargraph has a MAX chip on it as well

So I have the wiring like so:

‘6’ total wires going into the DB-9 (serial) connector on the gun/blaster side:
V+
GND
DOUT (from MAX CHIP #1)
CS
CLK
RELOAD PIN (D2 on Arduino)

and ‘5’ total wires going into the DB9 (serial) connector on the bargraph (magazine) side…
V+
GND
DIN
CS
CLK

on the magazine DB-9 (serial) connector… I took the open (matching) pin that the RELOAD (D2) is connected to (on the other DB-9 connector end)… and bridged it to GND… (so on magazine side of DB-9 9 (female) I have the GND pin bridged to where the RELOAD pin (D2) will be coming in once the connectors are plugged together)…

  • more or less making the DB-9 (serial) connector and using one of the pins as a momentary switch (magazine is inserted/serial connectors are mated up/‘psuedo momentary switch is being held down’…magazine is pulled/serial connectors are disconnected/‘psuedo momentary switch is “released”’.)

(and in my code… if switch is LOW… I can fire (magazine inserted)… …

if HIGH… cant fire… (magazine is not inserted)

again… this ALL WORKS FINE when using a momentary switch to reload (and the magazine is NOT being pulled/re-inserted)

with me so far? :slight_smile:

the problem is now that I have removed the manually reload switch and moved it to the DB-9 (serial) connector as being part of the magazine…

1.) the max chip gets pulled (with the magazine) so it looses power…
2.) the max chips gets powered up again (when the magazine is inserted)…

during this process… things ‘broke’.

when I re-insert the magazine… the audio plays…
but the bargraph does NOT ‘update’ (either reload the bargraph to full 30… or display the current ammo count (variable) that is there when pulled/re-inserted.)

I first thought… yikes!.. I need to initialize the chip all over again…(so I do…initialize, set intensity, clear…then call my update function)

then I thought maybe I needed to pause/delay a bit…to give the chip time to power on… which I did… 100, 300, 1000… didnt work.

  • I’m at the point that if I re-insert now…

only PART of the bargraph updates? (or sometimes none at all?)

so I guess just general question/discussion… suggestions on things to try?

how would YOU approach this? :slight_smile:

after some playing around… it ‘seems’ that when I powered back on… it ONLY wants to update the FIRST group of LEDS in the bargraph…??

everytime I pull & re-insert the magazine…

Here are the two functions I call when the magazine is inserted 9depending on if amo was empty when pulled… or ammo still had some left when magazine was pulled)…

if empty… i go back to full count (bargraph = 30)

if not empty when magazine was pulled/re-inserted… I just update the display to have the same remaining leds lit as it did before (whatever the bargraphCounter says… i use it as a look up in my array and apply the binary values)

void reloadMagazine(){
  Serial.println(F("MAGAZINE RELOADED"));
  bargraphCount = 30;
  /* re-initialize the second MAX chip (after being re-connected)*/
  for(int group=4;group>=0;group--) {
    for(int led=8;led>=0;led--) {
      delay(5);
      lc.setLed(1,group,led,true);
    }    
  }  
}


void magazineUpdate(){
  Serial.println(F("MAGAZINE UPDATE.............."));
  Serial.println(bargraphCount);
  /* re-initialize the second MAX chip (after being re-connected)*/
  //lc.shutdown(1,false); //initialize routine is done when magazine inserted now..before the function calls
  //lc.setIntensity(1,15);
  //lc.clearDisplay(1);
  //delay(loadDelay);  <-- yuk!
  if(bargraphCount > 0){   
    for(int i=0; i < 4; i++){
      Serial.println(pgm_read_byte_near(counterArray[30 - bargraphCount] + i), BIN); //<-- seems to print out fine? but not applied correctly?
      lc.setRow(1,i,(pgm_read_byte_near(counterArray[30 - bargraphCount] + i)));
    }
    playcomplete("magin.WAV");
  }  
  else if(bargraphCount == 0){
    isReloaded = true;
    playcomplete("reload.WAV");
    reloadMagazine();
    Serial.print(F("ZERO COUNTER MAGAZINE INSERT: "));
    Serial.println(bargraphCount);    
  }
}

so why does it work when using momentary switch (RELOAD pin (D2) on Arduino?)… but not when connected to the DB-9 (serial) connector? (due to powering down/up the MAX chip? having to do with initializing the chip again?

*why does only the FIRST group of 8 leds update when things are powered back up/initialized/magazine inserted?

SEGS DP-G & DIG0 only?

I fire ‘3’ shots…

and I look at the BINARY output from the ARRAY IN PROGMEM that I should be applying to the MAX chip… and it looks fine.
11111
11111111
11111111
11111100
I keep coming back to this being a power down/up and initializing problem… (sometimes when insert magazine (connect DB-9 connector)… the main 3-digit display gets funky? (happened like 2-3 times now maybe I bumped something)…

otherwise the bargraph updates… (correctly) but ONLY turned on the first set of 8 leds…and not the rest of the bargraph…??

tired now…

thanks! :slight_smile:

update:

after trying and trying… and writing out variables…and making sure my loops my running… it must be something with re-initializing the chip again (in the daisy chain of MAX chips)

since this chip is the ‘second’ (of only 20 max chips… and runs off the DOUT of the first max chip…

how can or should I re-initialize it once it gets ‘re-connected’ to the circuit?

the delay doesnt seem to be a factor…as it turns in quick/instantly… and ‘updates’… but only the first set of 8 (still)

whenever the magazine is re-inserted… this is how I re-initialize the chip again:

lc.shutdown(1,false);
lc.setIntensity(1,15);
lc.clearDisplay(1);      
=magazineUpdate();

//or

lc.shutdown(1,false);
lc.setIntensity(1,15);
lc.clearDisplay(1);      
reloadMagazine();

but it only ‘partially’ seems to update?

so maybe Im doing that/something wrong in that aspect??

thanks (again) :slight_smile:

Two things come to mind.

As a broad generality, use whatever code you use in the initialisation to update both displays - "just in case" there is some anomaly there, then update the data in both displays. Why? Well, you are using libraries there to do the initialisation, and I have no idea just how they work.

Secondly, I hope you are not using interrupts for any function here, particularly for the "reload" switch input or indeed for any switches. All switches need to be debounced prior to their data being used, by the main polling loop (which means you need to have the sound effects generated by something that does not hog the processor).

Why?

Because feeding erratic switch information to interrupts is almost certain to tie things up. I am sure there are ways to do it, but it is really going to mess up your code - unnecessarily.

I did try the original initialize code routine

(looping through all devices 'found'..setting them up again (both)..

I didnt see any change.. but I tried lots of things.. so I'll try that approach again..

I did believe the sketch uses interrupts for the audio.. (and the button checking) that is taken/being used from the original Adafruit WaveHC examples on how to play music and have 6 (or more) buttons being 'watched' for the switch states. (I do not believe this to be part of the problem though)

thanks..

bump…

still stumped.
cant figure out what is the particular aspect causing the problem… I was fairly certain it was because I was disconnecting/then re-connecting the MAX chip/pcb into the circuit…

but Im starting to move away from that stance now… only because if it ‘didnt’ initialize correctly/at all… then how does the first group of ‘8’ leds… always display correctly after an update/magazine pull-insert event…??

heres another example of behavior…

I boot things up (power on)…

and it plays the boot-up sound file… and checks to see if the magazine is inserted (D2/reload pin) is LOW (held to GND)…

if it is…it loads the bargraph to full (all leds on)
if not play fail sound… no leds on bargraphs… waits for magazine insert… (D2/reload pin is HIGH at this moment).

I power things on… (magazine inserted)…

I dont even press the trigger button… I remove magazine… (D2/reload HIGH… sound plays)…
I re-insert magazine (D2/reload pin LOW…sound plays)…

I grab my binary pattern from my array… and call my function passing that in as my argument to be passed onto the MAX chip.

I trace out what the pattern/values are from the array (they look correct, only 30 led total).

Serial.println(pgm_read_byte_near(counterArray[30 - bargraphCount] + i), BIN);

ROW: 0
11111111
ROW: 1
11111111
ROW: 2
11111111
ROW: 3
11111100

send it to MAX chip:

lc.setRow(1,i,(pgm_read_byte_near(counterArray[30 - bargraphCount] + i)));

but only the first set of 8 leds updates/displays anything? the rest are off/blank? even though the data looks to be correct?

is there something left over on the chip when I cut-power? something that needs to be erased before I send over a new binary pattern?

the loop(s) seems to be resetting and starting from the beginning?

Like mentioend above… I have even tried to re-initialize BOTH chips again… have a small delay and then try to update the bargraph leds…

code:

delay(loadDelay);
      //Initialize MAX7219/7221 chip(s)
      int devices=lc.getDeviceCount();
      //we have to init all devices in a loop
      for(int address=0;address<devices;address++) {
        /*The MAX72XX is in power-saving mode on startup*/
        lc.shutdown(address,false);
        /* Set the brightness to a medium values */
        lc.setIntensity(address,15);
        /* and clear the display */
        lc.clearDisplay(address);
      }           
      reloadMagazine();

funny thing is… I believe it to be working…as the first MAX chip (3-digit display pcb) clears out/is blank when this happens.

I think it works the other way as well… as it powers on and the first set of 8 leds ‘work’…

thanks!

How invested are you in the hardware coupling? (The DB-9 port.) From an engineering standpoint, that's not a great hot-disconnect connector. This is why, back in the glory days of serial ports, it was NOT recommended to hot-swap serial devices. (Or parallel for that matter -- same connector type, thus same reason.)

What you really want is to absolutely guarantee that the following happens in precisely this order:

1) Ground contacts meet -- the sooner this happens relative to everything else, the more stable things will be. 2) Power contacts meet -- also should happen before any signal pins can connect. 3) The MAX IC is held in reset by a pull-up/down resistor. (Does it have a reset pin? If not, I would control its power pin by a transistor to fake it.) 4) An "insert_detect" signal is sent from magazine PCB to AVR. This basically acts like a physical limit switch that loops the magazine's power input back to this pin, and is read as an input (like a switch contact) on the AVR. 5) After a settling time, where the AVR senses insert_detect continuously for a couple ms, the AVR sends a "power_good" signal to the magazine PCB. 6) The power_good signal pulls the MAX IC out of reset (or applies power to it). 7) The AVR sends initialization commands to the IC, and things continue operating as usual...

Doing this basically requires that you use dedicated ground/power pins, where ground is a longer pin that power, which is longer than any signal pins. Or use bare metal and spring contacts. Or some connector that has this covered for you (e.g., look at a SATA connector.)

update:

sorta got it working... by adding/redefining a NEW LedControl instance each time.. does this overwrite the current instance? or make a new one? (using the same name and pinouts?) (or killing my available RAM?)

LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)

this seems to get me a working BARGRAPH again..

but by re-instantiating a new instance... I am blanking out the still connected 3-digit display.. :(

so I need to make some calls to the updatedisplay() function..

however,....if I add a call to the function to update the display

I am back to running out of room in SRAM and the project doesnt work.. (I am extremely close on SRAM usage!)

freezes, reboots...audio stops playing while leds work... Serial output stops..etc.. (random behavior, which I believe is NO RAM)

*I am using PROGMEM for my multi-dimensional BINARY array *I am using F() in all my serial.println() strings. *commenting out Serial.begin() all together..

am not sure what else can be to save RAM usage..?

thanks!

@SirNickity-

yeah… that makes sense…

but not sure what kind of connector I can get/use that ‘does’ that…
(Im also pretty far into the game to be re-desiging with transistors…etc… but if it doesnt work at all in the end…I guess there is no choice!) LOL

I am NOT set on the serial connector… (heck I was originally going to try 2 x headphone jacks for easier connection/less friction)

but after looking at how the plug goes into the jack…brushing over each connector… I passed. (i have a small opening in which to work with… the DB-9 fits snug… anything bigger wont cut it. :frowning:

I was sorta under the impression that I was trying to do the above… with a bit code…etc… delays…giving things time enough to power on…etc…

ie:

the reload (D2) pin is connected to Arduino… its ‘GROUND’ connection (to bring it LOW, like magazine is inserted) is the OTHER end of the DB-9 (serial) connector (the magazine connector side of things… not the same connector the reload (D2) pin is soldered to)

when the plugs are connected…

I check the RELOAD (D2) pin…to see if it is being pulled LOW… (Im assuming that when this reload pin is showing LOW… the rest of the pins are now connected to… meaning the GND/V+ to the pcb/MAX chip… as well as the DIN/CS/CLK pins too…

HOWEVER… I throw in a small delay (using like 1-2 SECONDS now for testing)… giving time for power to be applied/settle in…

THEN I continue on to (re) initialize the chip over…and send the new BINARY patten to it from the array…

  • if I only do this:
lc.shutdown(1,false);
lc.setIntensity(1,15);
lc.clearDisplay(1);      
magazineUpdate();

or

//Initialize MAX7219/7221 chip(s)
      int devices=lc.getDeviceCount();
      //we have to init all devices in a loop
      for(int address=0;address<devices;address++) {
        /*The MAX72XX is in power-saving mode on startup*/
        lc.shutdown(address,false);
        /* Set the brightness to a medium values */
        lc.setIntensity(address,15);
        /* and clear the display */
        lc.clearDisplay(address);
      }           
      magazineUpdate();

then whenever I re-insert the magazine… ONLY THE FIRST GROUP of 8 leds will lit up/display correctly… (even though the pattern I output to serial monitor is correct)

Q1: So is the chip not initialized/ready? if not? then how is the first group being display correctly? if yes,…then whats going on with the other leds that dont light up? (these first group of 8 leds that DO respond…they are correct count each time…and they need no delay time, no time to power on/update… no re-initialization either?)

now… if I add this:

LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)

before the above snippet…

when I re-insert the magazine… the bargraph DOES update, display correctly… and work again.

but with that ‘fix’ introduced another problem… since I have re-instantiate the LedControl instance each time I insert the magazine… I clear/blank out the 3-digit display…

*normally wouldnt be a problem… but I have to add a few lines of code to call some functions that are already in the sketch to re-update the display… and that extra code (I believe) is pushing me over the limits on RAM (again)…

Im more than happy to post the WHOLE sketch… (if youre feeling up for some punishment!) :slight_smile: LOL

LOL…

It's entirely possible the internal state is inconsistent when it's powered up improperly... which can happen if signals are appearing before Vcc is stable, or there's not a solid ground, or power is bouncing during insertion, things like that. This is generally why anything with a "brain" (like the AVR itself) holds itself in reset for some time after power-up (or it requires you to do so).

Looking at the specs for the IC, I don't see a reset pin, but it's clearly a (somewhat) intelligent device since it can be programmed to perform a few tricks. (Like PWM, shutdown mode...)

You could test this theory by hacking a temporary constant power connection. I.e., tack-solder a ground and power cable -- or maybe just ground at first -- so the power supply is available during a remove/insert cycle. See if that changes the behavior.

BTW, I don't quite understand what you mean about having to re-init the decimal display and having that push you over a RAM limit. You're not allocating anything new there, are you? Just destroying the old class instance and creating a new one? Shouldn't change memory requirements unless there's a memory leak in that library, I wouldn't think....

Im not sure… hahaha.
I mean I can remove ANY kind of delay before running the intialize/trying to write to the chip…

I am using the RELOAD (D2) pin on the Arduino…to more or less tell me when I can start writing to the chip again. (to update now that it is plugged in and needs to display how ever many leds were lit before it was pulled (or full if empty when pulled)… I can/have added a delay() in there just to test or give time for the power to become stable… if I wait mSec… or 10’s of seconds… no matter… (unless I re-initialize) :(… and it seems I have to do BOTH? cant just target the second CHIP (because its already defined there is 2 chips in the chain/instance)

if I re-initialize… I need no delay.

//create LedControl lib instance
LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)

if I take that out… and wait for even 1 minute for the power to ‘stablize’… and then attempt to write to the chip…it wont work…
(only the first group of 8 leds will work/turn on and display correctly)…

if I add this:
//create LedControl lib instance
LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)

it ‘works’ (more or less)

here is the whole ‘reload button checking’ routine/code

//reload button 
  else if (justpressed[1]) {
    justpressed[1] = 0;
    //playcomplete("reload.WAV");
    //interval reload check
    if(reloadTime == true){
      isReloaded = true;
      reloadTime = false;            
      Serial.println(F("-- !!!! reload max bar graph !!!! --"));
      playcomplete("reload.WAV");      

      LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)
      //Initialize MAX7219/7221 chip(s)
      int devices=lc.getDeviceCount();
      //lc.shutdown(1,false);
      //lc.setIntensity(1,15);
      //lc.clearDisplay(1);

      //we have to init all devices in a loop
      for(int address=0;address<devices;address++) {
        //The MAX72XX is in power-saving mode on startup
        lc.shutdown(address,false);
        //Set the brightness to a medium values 
        lc.setIntensity(address,15);
        //and clear the display 
        //lc.clearDisplay(address);
      }
      //delay(loadDelay);
      //ammoCount = maxAmmo;
      updateDisplay();
      reloadMagazine();
    }
    //out of ammo check
    else if(ammoCount == 0){      
      isReloaded = false;
      reloadTime = false;
      Serial.println(F("-- !!!! reload max ammo & max bargraph!!!! --"));      
      playcomplete("reload.WAV");         

      LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)
      //Initialize MAX7219/7221 chip(s)
      int devices=lc.getDeviceCount();
      //lc.shutdown(1,false);
      //lc.setIntensity(1,15);
      //lc.clearDisplay(1);

      //we have to init all devices in a loop
      for(int address=0;address<devices;address++) {
        //The MAX72XX is in power-saving mode on startup
        lc.shutdown(address,false);
        //Set the brightness to a medium values 
        lc.setIntensity(address,15);
        //and clear the display 
        //lc.clearDisplay(address);
      }      
      //delay(loadDelay);
      ammoCount = maxAmmo;
      updateDisplay();
      reloadMagazine();      
    }    
    else if(justPulled == true){
      //do something
      Serial.println(F("Magazine Re-inserted..  -->  (continue)"));
      //playcomplete("magin.WAV");
      //updateBargraph();

      LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)
      //Initialize MAX7219/7221 chip(s)
      int devices=lc.getDeviceCount();
      //lc.shutdown(1,false);
      //lc.setIntensity(1,15);
      //lc.clearDisplay(1);

      //we have to init all devices in a loop
      for(int address=0;address<devices;address++) {
        //The MAX72XX is in power-saving mode on startup
        lc.shutdown(address,false);
        //Set the brightness to a medium values 
        lc.setIntensity(address,15);
        //and clear the display 
        //lc.clearDisplay(address);
      }
      //delay(loadDelay);
      //ammoCount = maxAmmo;
      updateDisplay();
      magazineUpdate();      
      justPulled = false;
    }
  }
  //check when magazine pulled-out
  else if (justreleased[1]) {
    justreleased[1] = 0;
    justPulled = true;
    Serial.println(F("MAGAZINE PULLED"));
    playcomplete("magout.WAV");
  }

I tried JUST initializing the bargraph MAX chip my itself… but doesnt work… only first set of 8 leds respond/turn on.

I need to re-define/create/instantiate an instance o the class (again)…

which I dont mind I guess…

but when I do that… it ‘clears’ my 3-digit display as well/in the process…

so I need to call the updateDisply() function… (that I already have defined and use throughout the sketch to update it normally when counting down…etc)

but it seems as soon as I add the part where I define a new class instance & add in the updateDisplay() (*which makes the display blink quickly because of the re-init of all MAX chips in the chain,…so its not optimal)…

and run the code… it compiles…runs… and after a few seconds.of firing, mode selecting… it freezes, tweaks out, resets, stops audio, leds only…serial output stops…etc

I have PM’d you the full code… (be kind!) LOL…

maybe I’m doing something wrong elsewhere?

Clearly the fault is in the library.

I haven't used that library to control MAX7219s - it isn't necessary in the first place, the functions are perfectly easy to define without it (and the "brains" are in the MAX7219 anyway). If anything, study the library itself for what you need and examine the code critically. Sooner or later the faults should be apparent.

Clearly, when you do the reload, you will need to re-initialise all the MAX7219 chips, and restore whatever they are displaying. That is a "given", but it should not involve all this malarkey about "creating" and "destroying" "classes" and it should be so fast that you hardly notice a flicker.

This library - however it works - is tripping you up. When you ditch it and implement only the functions you need, there will be no problems about "RAM leakage", however that may be evident.

if only it were that easy for me… LOL

Im not that experienced of a programmer to be able to rip into the library and understand everything thats going on ‘under the hood’…

I chose it because of its ease of use and to be able to implement it into my own sketch/needs is all.

when you say yes to re-initializing ALL the chip… are you just referring to the shutdown = false portion?

and in yo mind I should NOT be having to do this:
//create LedControl lib instance
LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)

each time?

thanks…

xl97: if only it were that easy for me.. LOL

As I see it, you have written the rest of the code - it can't be that bad!

xl97: I'm not that experienced of a programmer to be able to rip into the library and understand everything that's going on 'under the hood'..

Nevertheless, this is causing you grief, and the library is clearly the problem

xl97: I chose it because of its ease of use and to be able to implement it into my own sketch/needs is all.

Well, "ease of use" has clearly failed you here.

xl97: when you say yes to re-initializing ALL the chip.. are you just referring to the shutdown = false portion?

Without looking too closely, I presume so. I mean re-initialising all the MAX7219s. All of two as I understand it. There is no reason why this should not be essentially instantaneous, initialising and updating the displays. The only reason for the delay (and as before, you should never be using the "delay()" call in actual application code) it to ensure (or in fact, guess) that the cartridge has been completely inserted. Not sure how many pins you are using on the DE-9 connector (there is no such thing as a "DB-9"), but the obvious thing is to have a +5 and Ground on each end of it and use the remaining 5 pins for data with the centre pin itself for detect.

xl97: and in your mind I should NOT be having to do this: //create LedControl lib instance LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips) each time?

Absolutely not. It ain't working for you, and the library in general is not working.

Consider - how many different calls to the library do you use, and for what? I doubt the functions are that difficult.

I would suggest you go back and do a little study on just those functions, practice just each of the functions you need one at a time, to see how to do it without the library, then integrate those functions back in. It's going to be quicker "in the long run" to get it right.

Here’s a chunk (actually, the whole bang lot - just try it out on your rig with the right pin allocations set) of my code for demonstrating an 8 by 8 matrix - not what you are using it for as such, but the basic functions are in there and it will show you something:

/* code for max 7219 from maxim, 
reduced and optimised for using more then one 7219 in a row,
______________________________________

General notes: 


-if you are only using one max7219, then use the function maxSingle to control
 the little guy ---maxSingle(register (1-8), collum (0-255))

-if you are using more then one max7219, and they all should work the same, 
then use the function maxAll ---maxAll(register (1-8), collum (0-255))

-if you are using more than one max7219 and just want to change something
at one little guy, then use the function maxOne
---maxOne(Max you wane controll (1== the first one), register (1-8), 
collum (0-255))

/* During initiation, be sure to send every part to every max7219 and then
 upload it.
For example, if you have five max7219's, you have to send the scanLimit 5 times
before you load it-- other wise not every max7219 will get the data. the
function maxInUse  keeps track of this, just tell it how many max7219 you are
using.
*/

#include <Wire.h> 

int dataIn = 2;            // "DIN" on module
int load = 3;              // "CS" on module
int clock = 4;             // ""CLK" on module
const int ledPin =  13;    // the number of the LED pin

int maxInUse = 1;    //change this variable to set how many MAX7219's you'll use
int ledState = LOW;         // ledState used to set the LED

int e = 0;                 // just a varialble

                     // define max7219 registers
byte max7219_reg_noop        = 0x00;
byte max7219_reg_digit0      = 0x01;
byte max7219_reg_digit1      = 0x02;
byte max7219_reg_digit2      = 0x03;
byte max7219_reg_digit3      = 0x04;
byte max7219_reg_digit4      = 0x05;
byte max7219_reg_digit5      = 0x06;
byte max7219_reg_digit6      = 0x07;
byte max7219_reg_digit7      = 0x08;
byte max7219_reg_decodeMode  = 0x09;
byte max7219_reg_intensity   = 0x0a;
byte max7219_reg_scanLimit   = 0x0b;
byte max7219_reg_shutdown    = 0x0c;
byte max7219_reg_displayTest = 0x0f;



void putByte(byte data) {
  byte i = 8;
  byte mask;
  while(i > 0) {
    mask = 0x01 << (i - 1);      // get bitmask
    digitalWrite( clock, LOW);   // tick
    if (data & mask){            // choose bit
      digitalWrite(dataIn, HIGH);// send 1
    }else{
      digitalWrite(dataIn, LOW); // send 0
    }
    digitalWrite(clock, HIGH);   // tock
    --i;                         // move to lesser bit
  }
}

void maxSingle( byte reg, byte col) {    
//maxSingle is the "easy"  function to use for a     //single max7219

  digitalWrite(load, LOW);       // begin     
  putByte(reg);                  // specify register
  putByte(col);        //((data & 0x01) * 256) + data >> 1); // put data   
  digitalWrite(load,HIGH); 
}

void maxAll( byte reg, byte col) {    // initialize  all  MAX7219's in the system
  int c = 0;
  digitalWrite(load, LOW);  // begin     
  for ( c =1; c<= maxInUse; c++) {
  putByte(reg);                  // specify register
  putByte(col);             //((data & 0x01) * 256) + data >> 1); // put data
    }
  digitalWrite(load,HIGH);
}

void maxOne(byte maxNr, byte reg, byte col) {    
//maxOne is for adressing different MAX7219's, 
//while having a couple of them cascaded

  int c = 0;
  digitalWrite(load, LOW);  // begin     

  for ( c = maxInUse; c > maxNr; c--) {
    putByte(0);    // means no operation
    putByte(0);    // means no operation
  }

  putByte(reg);  // specify register
  putByte(col);//((data & 0x01) * 256) + data >> 1); // put data 

  for ( c = maxNr-1; c >= 1; c--) {
    putByte(0);    // means no operation
    putByte(0);    // means no operation
  }

  digitalWrite(load,HIGH); 
}

void putCol( byte colno, byte coldat) {
// Interprets colno as (zero ref) index in combined array
    byte t;
    t = colno >> 3;
    byte u;
    u = colno & 0x07;
    maxOne(t+1, u+1, coldat);
}


void dispon () {
 maxAll(max7219_reg_shutdown, 0x01);               // Display on
}  

void dispoff () {
 maxAll(max7219_reg_shutdown, 0x00);              // Display off
}  

byte irow = 0;          // Row index
byte icol = 0;          // Column index
byte pattern;           // bit mask
byte lcol;              // left border
byte rcol;              // right border
byte trow;              // top row marker
byte brow;              // bottom row marker

int s_vert;             // Vertical switch
int s_horz;             // Horizontal switch

// the follow variable is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 40;           // interval at which to blink (milliseconds)
long previousMillis = 0;      // will store last time LED was updated
int scantype = 0;             // switch mode

void worker () {

  if (pattern == 0) pattern = trow;            // pattern must be set
  if (s_vert != 0) {
    if (s_vert == -1) {                     // moving upward
      pattern = pattern >> 1;
      if (pattern == trow) {                   // hit the top
        s_vert = 0; s_horz = 1;
      }
    } else {
      pattern = pattern << 1;               // moving downward
      if (pattern == brow) {                // hit the bottom
        s_vert = 0; s_horz = -1;
      }
    }
    putCol(icol,pattern);              // Show the column.
    return;
  }

  if (s_horz != 0) {
    putCol(icol,0);                    // blank previous column.
    if (s_horz == -1) {                     // moving left
      icol--;
      if (icol == lcol) {                      // hit the side
        s_horz = 0; s_vert = -1;
      }
    } else {
      icol++;                               // moving right
      if (icol == rcol) {                      // hit the side
        s_horz = 0; s_vert = 1;
      }
    }
    putCol(icol,pattern);              // Show the column.
  }
 }
  

void setup () {

  pinMode(dataIn, OUTPUT);
  pinMode(clock,  OUTPUT);
  pinMode(load,   OUTPUT);
  pinMode(ledPin, OUTPUT);      

  //Serial begin(9600);
  digitalWrite(13, HIGH);  

//initiation of the max 7219
  maxAll(max7219_reg_displayTest, 0x00); // no display test
  maxAll(max7219_reg_scanLimit, 0x07);      
  maxAll(max7219_reg_decodeMode, 0x00);  // using an led matrix (not digits)
  maxAll(max7219_reg_shutdown, 0x01);    // not in shutdown mode
  for (e=1; e<=8; e++) {        // empty registers, turn all LEDs off 
    maxAll(e,0);
  }
  maxAll(max7219_reg_intensity, 0x08 & 0x0f);    // the first 0x0f is the value you can set
                                                 // range: 0x00 to 0x0f
                                                 
  pattern = 0;
  scantype = 0;
  s_vert = 0;
  s_horz = 1;
  lcol = 1;              // left border
  rcol = 6;              // right border
  trow = 0x02;           // top row marker
  brow = 0x40;           // bottom row marker      
      
}  

void loop () {


  //if you use just one MAX7219 it should look like this
   /*  
   maxSingle(1,1);                       //  + - - - - - - -
   maxSingle(2,2);                       //  - + - - - - - -
   maxSingle(3,4);                       //  - - + - - - - -
   maxSingle(4,8);                       //  - - - + - - - -
   maxSingle(5,16);                      //  - - - - + - - -
   maxSingle(6,32);                      //  - - - - - + - -
   maxSingle(7,64);                      //  - - - - - - + -
   maxSingle(8,128);                     //  - - - - - - - +
  */
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    // Alternate 1

    }
    else {
      ledState = LOW;

    // Alternate 2
    // set the LED with the ledState of the variable:
    // Timed process:
    
    worker();

    }

    digitalWrite(ledPin, ledState);

    }

}

It could be the library, if re-initializing the whole chain is sufficient... I don't see there being any way around the re-init BTW, even without the library. The only way to avoid it would be to break up the chain and treat them independently.

I'll look at the code after work. I don't see any reason why calling a display update function in a regular loop should be any different than after a re-init, in terms of memory usage. I must be missing something. However, being that close to the threshold of RAM is likely to cause problems regardless. Can you resize your sample buffer or anything? Any defines in the wave shield for that? (Again, have not used....) Maybe you could load samples into eeprom and forego the SD libs?

Re-initialising the MAX7219s (and refreshing the appropriate displays) is not a problem; it is virtually instantaneous (milliseconds if that) and requires no mucking about with RAM allocation. It's just not a problem, it's not something to be avoided in the first place.

In fact, you could perfectly happily re-initialise everything in one single function every time you updated the display and barely notice it.

I'm pretty sure that if you trash the offending library that both program size and RAM allocation will shrink - maybe just a little, or maybe by a surprising amount.

Well in the future when I have the time… I guess I can try and do it without the help (crutch) of the LedControl library…
but right now I dont have the luxury :(… and have done 99% of the rest of the project completed…
so thank you for the suggestion, but I’ll have to defer that until a later date. :frowning:

background info: (as SirNickity knows)

before this current problem… I was running into SRAM problems… and had posted about optimizing…
(some PROGMEM array storage, use of F() on my Serial.println() string…and converting some data type to byte vs int…etc…etc…etc) after some suggestions… the sketch was working good/fine and I continued on developing the code…

I was dangerously close then… and had added more code/routines to the sketch after… (still was running solid but had to be even closer to RAM limits)

now with this latest addition of code…etc… I believe I am there (again)… :frowning:

I understand that I ‘should’ have to be initializing the CHIPS again (I’m ok/fine with that… and yes it does have that barely noticeable blink upon re-initialization)…

but it should ONLY require this:

int devices=lc.getDeviceCount();
for(int address=0;address<devices;address++) {
     lc.shutdown(address,false);        
     lc.setIntensity(address,15);
     //lc.clearDisplay(address); 
 }
//ammoCount = maxAmmo;
 updateDisplay();
 reloadMagazine();

and not this:

LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)
int devices=lc.getDeviceCount();
for(int address=0;address<devices;address++) {
     lc.shutdown(address,false);        
     lc.setIntensity(address,15);
     //lc.clearDisplay(address); 
 }
//ammoCount = maxAmmo;
 updateDisplay();
 reloadMagazine();

but if it IS overwriting the same object/class instance…etc… then what is it hurting?

for fun… Im going to try to see if I can optimize it elsewhere… get some RAm back…and see if it doesnt run smooth again… of it is those:

LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)

lines causing all the trouble… (along with the library you dont care for) :slight_smile:

** aslo… there ‘are’ DB9 connectors… (D-Sub connectors…whatever)

Example:
http://www.jameco.com/1/3/db9-connector

@SirNickity-

thanks!.. let me know what you see… and if you have any suggestions!

take care

-xl

xl97: also .. there are DB9 connectors.. (D-Sub connectors..whatever)

Well, actually, there aren't. But they are so commonly mis-labelled that most people - including the vendors - are confused.

yikes!.. I dont know where I picked up that term? I have been using it for (incorrectly) for like 10 years. :blush:

either way…thats what I’m using currently for the physical connection/bridge due to the space (and intended usage) of the project/prop.

Im still banging my head into a wall trying to find a work around here on that Led Control lib. :slight_smile:

if I re-initialize using only this:

byte devices=lc.getDeviceCount();
    //we have to init all devices in a loop
    for(byte address=0;address<devices;address++) {
      /*The MAX72XX is in power-saving mode on startup*/
      lc.shutdown(address,false);
      /* Set the brightness to a medium values */
      lc.setIntensity(address,15);
      /* and clear the display */
      //lc.clearDisplay(address);
    }

(which make sense to do)…
only the first 8 leds in the strip/bargraph come back on/are responsive…

if I add this line on top…

//LedControl lc=LedControl(3, 6, 5, 2); //scab board (2 max chips)

they ‘all’ come back on… but then after a few button pressed… (or sometimes right away)… I get the freezes, resetting…etc…etc

on the forum pages…it shows running multiple chips… and even multiple instances…(but difference pins)… so is it NOT overwriting the instance correctly? (is there a way to delete it?)

http://playground.arduino.cc/Main/LedControl
http://playground.arduino.cc//Main/LedControlDemos

LOL… I know this is killing you… :slight_smile: but if you DO have some suggestions on how to fix the ‘current’ project (not starting over, re-writing from scratch…etc… I’d like to hear anything ya got) :slight_smile:

anyways…

thanks! :smiley:

bump… :slight_smile:

ok. I guess I’ll start by trying to dig into the LedControl library then?

I have never even created my own library yet…so I’m on new ground here. :slight_smile:

Im guessing I should be looking int he .cpp file instead of the .h file?

it sorta looks like its a nice ‘buffer’ for what you were saying to do directly…

it was mentioned it was a fault in the library… where to start?

1.) in how the instance/object is created (instantiated?)
2.) how it ‘initializes’ the chip (Im guessing all there is, is the shutdown() function)

here is the shutdown() function in the library:

#include "LedControl.h"

//the opcodes for the MAX7221 and MAX7219
#define OP_NOOP   0
#define OP_DIGIT0 1
#define OP_DIGIT1 2
#define OP_DIGIT2 3
#define OP_DIGIT3 4
#define OP_DIGIT4 5
#define OP_DIGIT5 6
#define OP_DIGIT6 7
#define OP_DIGIT7 8
#define OP_DECODEMODE  9
#define OP_INTENSITY   10
#define OP_SCANLIMIT   11
#define OP_SHUTDOWN    12
#define OP_DISPLAYTEST 15


void LedControl::shutdown(int addr, bool b) {
    if(addr<0 || addr>=maxDevices)
	return;
    if(b)
	spiTransfer(addr, OP_SHUTDOWN,0);
    else
	spiTransfer(addr, OP_SHUTDOWN,1);
}

does look like it does much?

so maybe its in how the the instance is being created? Is there any kind of ‘clear/delete’? (simply overwriting it isnt working)…

here is the function to create the instance or whatever. (from the .cpp file)

LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
    SPI_MOSI=dataPin;
    SPI_CLK=clkPin;
    SPI_CS=csPin;
    if(numDevices<=0 || numDevices>8 )
	numDevices=8;
    maxDevices=numDevices;
    pinMode(SPI_MOSI,OUTPUT);
    pinMode(SPI_CLK,OUTPUT);
    pinMode(SPI_CS,OUTPUT);
    digitalWrite(SPI_CS,HIGH);
    SPI_MOSI=dataPin;
    for(int i=0;i<64;i++) 
	status[i]=0x00;
    for(int i=0;i<maxDevices;i++) {
	spiTransfer(i,OP_DISPLAYTEST,0);
	//scanlimit is set to max on startup
	setScanLimit(i,7);
	//decode is done in source
	spiTransfer(i,OP_DECODEMODE,0);
	clearDisplay(i);
	//we go into shutdown-mode on startup
	shutdown(i,true);
    }
}

however… it looks like there might be a function to throw custom commands at it with? but I dont see any mention of this in the .h file… (so maybe its a ‘private’ function and we can not use it?..reaching/guessing) :slight_smile:

void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
    //Create an array with the data to shift out
    int offset=addr*2;
    int maxbytes=maxDevices*2;

    for(int i=0;i<maxbytes;i++)
	spidata[i]=(byte)0;
    //put our device data into the array
    spidata[offset+1]=opcode;
    spidata[offset]=data;
    //enable the line 
    digitalWrite(SPI_CS,LOW);
    //Now shift out the data 
    for(int i=maxbytes;i>0;i--)
 	shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]);
    //latch the data onto the display
    digitalWrite(SPI_CS,HIGH);
}

Sorry, can't really be much further help at this point. My next focus (and only one of many themes) is to study the Parola library (and its dependencies), which is for quite a different purpose ("Times Square" displays). Short of that, I simply write - relatively uncomplicated - code to do just what I need to do and nothing more as per my previous advice.

I remain deeply suspicious of this "instantiation" process.