Monday, June 15, 2015

Arduino IDE - MAX7219 - 8 Digit Display Driver







   As you know from my previous Article I got recently some nice MAX7219 8 Digit Display Modules.

   Had a lot fun fun with them, looks a nice and stable solution so I'm thinking to use them as Display for one of my future projects.

   Meanwhile I was also playing with ESP8266 CBDBv2 EVO and Arduino IDE and because it looks like the latest 1.6.4 version  it's becoming more stable and usable than previous releases I will give it a try for MAX7219 Driver implementation.

   I still consider ESP8266 + NodeMCU LUA interpreter as the best environment for Learning/Drivers Developpment or even small projects, offering you a great flexibility that a Interpreter can give you   but it's obviously that for bigger projects you need something else, so let's give Arduino IDE a try.



What we will need:


 I will not insist to much on the Arduino IDE install process, it is a quite trivial process. If anybody wants more details about please feel free to ask.


MAX 7219 - 8 digit display driver connections




Wire        MAX7219     ESP8266

Green      +5Vcc
Blue        GND               GND
Yellow     DIN                 13
White      CS                  12
Orange    CLK                14




   MAX7219 Driver  Implementation

    For details about MAX Timing Diagram,  Registers, Initialisation, etc please take a look at the detailed description from the previous MAX7219 article.


1.  Init

int INTENSITYMIN = 0; // minimum brightness, valid range [0,15]
int INTENSITYMAX = 1; // maximum brightness, valid range [0,15]

int DIN_PIN = 13;      // data in pin
int CS_PIN = 12;       // load (CS) pin
int CLK_PIN = 14;      // clock pin
int dly = 50;          // delay in us
int adc=0;             // read ADC
int spr=32;            // number of readings
int offset=5;          // input offset

float nr = 1.0054;     // number to be displayed

// MAX7219 registers
byte MAXREG_DECODEMODE = 0x09;
byte MAXREG_INTENSITY  = 0x0a;
byte MAXREG_SCANLIMIT  = 0x0b;
byte MAXREG_SHUTDOWN   = 0x0c;
byte MAXREG_DISPTEST   = 0x0f;



2. Write serialised data

void putByte(byte data)
{
  byte i = 8;
  byte mask;
  while (i > 0)
  {
    mask = 0x01 << (i - 1);        // apply bitmask
    digitalWrite( CLK_PIN, LOW);   // CLK
      delayMicroseconds(dly);
    if (data & mask)               // select bit
    {  digitalWrite(DIN_PIN, HIGH); // send 1
      delayMicroseconds(dly);
    }else{
      digitalWrite(DIN_PIN, LOW);  // send 0
      delayMicroseconds(dly);}
    digitalWrite(CLK_PIN, HIGH);   // CLK
      delayMicroseconds(dly);
    --i;                           // move to next bit
  }
}


3. Set Register

void setRegistry(byte reg, byte value)
{
  digitalWrite(CS_PIN, LOW);
  delayMicroseconds(dly);
  putByte(reg);   // specify register
  putByte(value); // send data

  digitalWrite(CS_PIN, LOW);
  delayMicroseconds(dly); 
  digitalWrite(CS_PIN, HIGH);
}


 

4. Convert anf Print float value in  xxxx.xxx format

void print_LED(float fVal, int w, int p)
{
  int d = 1;
  int ch = 1;
  int n = 0;
  int nr_size = 0;
  char charVal[11];               //temporarily holds data from vals
  String stringVal = "";     //data on buff is copied to this string
 
  //dtostrf(fVal, w, p, charVal);  //4 is mininum width, 3 is precision; 

                           //NOT WORKING FOR Values SMALLER THAT 0.01 !!
  // stringVal = charVal;
  // created a new function below for converting properly a pozitive xxxx.xxx float to string



  stringVal=ftos(fVal,3);
 
  int strl = stringVal.length()-1; 
  for (int i=0;i<strl+1;i++)
  { charVal[i]=stringVal[i]; }
 
    Serial.print("Length: ");Serial.println(strl); //display string
    Serial.println(stringVal);
  //convert charVal[] to LED Display string
  for(int i=0;i<strl+1;i++)
  {
    if ((charVal[i] == '.') && (d==1))
    {
    stringVal=charVal[i];
    n = 0;
    n = (n * 10) + (charVal[i-1] - 48);
    setRegistry(strl-i+1, 128+n);
    d = 0;   
    }
    else  {          
        stringVal=charVal[i];
        Serial.print("d: ");Serial.print(d); //display string
        Serial.print("  - Increment: ");Serial.print(i); //display string
        Serial.print(" - INT: ");Serial.println(charVal[i]); //display string
        n=0;
        n = (n * 10) + (charVal[i] - 48);
        int pos = i;
        if (d==0) { pos = i-1; }
        setRegistry(strl-pos,n);
    } 
  }
}




5. Convert float value to a string 
 
 String ftos(float fVal, int prec)
{
  int mlt=10;
  String snr; 
  String dp;
  int iprt,dprt;
 
  iprt = int(fVal);

   // Round fVal for proper prec printing - correctly so that print(1.999, 2) prints as "2.00"
   double rnd = 0.5;
   for(uint8_t i = 0; i < prec; ++i)
        rnd /= 10.0;
        mlt *= 100;
    fVal += rnd;
   

 // Check and count "0"'s proper after ZERO (0.00xx) number display
  dprt = 1000*(fVal-iprt); 
  if (dprt < 10)
  {
    dp = "00" + String(dprt);
  }else
        if (dprt < 100)
        {
          dp = "0" + String(dprt);
        }else {dp = dprt;}

  snr = String(iprt) +"."+String(dp); 

  //Serial.println("");
  //Serial.print("MLT: ");Serial.println(mlt);  
  //Serial.println("");
  //Serial.print("DEC Part: ");Serial.println(dprt);  
  //Serial.println("");
  //Serial.print("Int Part: ");Serial.println(iprt);             
  //Serial.print(" . "); 
  //Serial.print("DP: "); Serial.print(dp);

  return snr;
}




5. Create a  Display 'ZERO' init stage

void zero_lcd()
{
 for (int i=1;i<9;i++)
 {
  setRegistry(i, 0);
    delayMicroseconds(100); 
 }
}



6.  MAX7219 Initialisation  

void init_MAX7219()
{
  // select allocated I/O pins
  pinMode(DIN_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(CS_PIN, OUTPUT);

  // initialization of the MAX7219
  setRegistry(MAXREG_SCANLIMIT, 0x07);
    delayMicroseconds(dly);
  setRegistry(MAXREG_DECODEMODE, 0xFF);  // full decode mode BCD 7 Seg Display
    delayMicroseconds(dly);
  setRegistry(MAXREG_SHUTDOWN, 0x01);    // shutdown mode OFF
    delayMicroseconds(dly);
  setRegistry(MAXREG_DISPTEST, 0x00);    // no test
    delayMicroseconds(dly);
  setRegistry(MAXREG_INTENSITY, 0);
    delayMicroseconds(dly);
  zero_lcd();
}


 

7. Test Display Driver - Read live ADC values and print them


float read_adc()
{
  adc = 0;
  for (int i=0;i<spr;i++)
  {
   adc += analogRead(0);
  } 
  nr = (float)(adc/spr-offset)*0.0009657;
 return nr;
}


void setup ()
{
  Serial.begin(9600);
  init_MAX7219(); 
}
 


void loop ()
{
  nr = read_adc();

  Serial.println((float)adc/spr);
  print_LED(nr,4,3);
 
  delay(5000);
  }







No comments:

Post a Comment