Arduino Mega 2560 and 7 segment LED displays (74HC595) with PWM


hi everyone,

i using arduino mega 2560 control 72 high-powered led 7 segment displays 72 shift register (74hc595) driving transistors.

the setup:
- 4 rows of 18 digits (consisting 3 blocks of 6 digits)
- every row uses 4 pins on arduino mega 2560 (data, clock, latch, master reset). used pins: 22 37 4 rows
- each block of 6 digits has pwm signal in order change luminosity of screens. used pins: 2 13 12 blocks
- numbers displayed on screens generated in realtime using max msp , transmitted serial port arduino.

serial communication structured follow:
there 2 types of messages:
- control message, 2 bytes
- content message, 18 bytes (depending on how many digits active in row)

the control message sends index next row updated , number of digits consisting content message. arduino adjust serial buffer needed size of next content message , sending ready-message max msp. max msp sends content message 18 bytes fill digits of row. when shift register filled arduino returns 255 indicate action has been executed , setting serial buffer 2 bytes. , way iterating through 4 rows. working @ highest speed can get, @ 15 milliseconds updating 1 row.

everything working fine until point. problem need change luminosity on runtime. luminosity uses control message type of 2 bytes. first byte index of block , second byte pwm-value. if pwm-change needed max msp wait until the actual row finished , send pwm control-message before continuing next row.
at point getting out of control: either segments of digits lightened more or less randomly or entire row flickering , jumping around.

i can't explain how happening, seems pwm signal affecting pins shift register. when setting pwm signal on setup of arduino (not chaining on runtime) working fine.

any ideas on whats happening?

here arduino-code:

code: [select]
const int row_count = 4;    //count of rows
const int blk_count = 3;    //count of block per row
const int dpb_count = 6;    //count of digits per block
const int pin_count = 8;    //count of pins used per row

int actual_row;

int binary_pins[row_count][4] = {
  /*porta*/{0, 1, 2, 3},
  /*porta*/{4, 5, 6, 7},
  /*portc*/{7, 6, 5, 4},
  /*portc*/{3, 2, 1, 0}
};
int digit_pins[row_count][pin_count] = {
  {22, 23, 24, 25, 2, 3, 4, 40},    //row 0    [0]data , [1]clock, [2]latch, [3]master reset, [4]pwm_b1, [5]pwm_b2, [6]pwm_b3, [7]control in
  {26, 27, 28, 29, 5, 6, 7, 41},    //row 1    [0]data , [1]clock, [2]latch, [3]master reset, [4]pwm_b1, [5]pwm_b2, [6]pwm_b3, [7]control in
  {30, 31, 32, 33, 8, 9, 10, 42},   //row 2    [0]data , [1]clock, [2]latch, [3]master reset, [4]pwm_b1, [5]pwm_b2, [6]pwm_b3, [7]control in
  {34, 35, 36, 37, 11, 12, 13, 43}  //row 3    [0]data , [1]clock, [2]latch, [3]master reset, [4]pwm_b1, [5]pwm_b2, [6]pwm_b3, [7]control in
};
/* digit_pins
[row][data, clock, latch, masterreset, pwm_b1, pwm_b2, pwm_b3, control in]
*/

boolean phrase_check[row_count];                       //[rows] array verifie if register filled bits 0 or 1 [4]

int serial_length;
char serial_from_max[blk_count*dpb_count];
/*serial_from_max
------------------------------------------------------------------
1. message                                              set digits
[row][block]
row   = 0-3 (row index)    byte 1 (0-3)
block = 1-3 (block count)  byte 2 (1-3)

2. message
[digit]*count
array digits
------------------------------------------------------------------
[row/block][pwm]                                   set luminosity
row   = 1x-4x (row index)        byte 1 (10-42)
block = x0-x2 (block index)      byte 1
pwm   = 0-255 (pwm luminosity)   byte 2 (0-255) (0,1 = activity)
*/

void setup(){
  serial.begin(115200);
  serial_length = 2;
  for(int _row=0; _row<row_count; _row++){
    phrase_check[_row] = 0;                                              //set rows unverified
    for(int _pin=0; _pin<pin_count; _pin++){
      if(_pin<pin_count-1){ pinmode(digit_pins[_row][_pin], output); }   //declare outputs
      else{ pinmode(digit_pins[_row][_pin], input); }                    //declare inputs
    }
  }
  resetallrows();
}

void loop(){
  while(serial.available() > serial_length-1){
    serial.readbytes(serial_from_max, serial_length);
    if(serial_length == 2){
      byte index = byte(serial_from_max[0]); byte val = byte(serial_from_max[1]);
      if(index < 4){
        serial_length = val*dpb_count;
        actual_row = index;
        serial.write((index*10)+val);
      }
      else{
        setluminosity(index, val);
        serial.write(255);
      }
    }
    else{
      shiftrow(actual_row, serial_length);
      serial_length = 2;
      serial.write(255);
    }
  }
}

void setluminosity(int _index, int _val){
  analogwrite(digit_pins[int(floor((_index-10)/10))][(_index%10)+4], _val);
}

void shiftrow(int _row, int _length){
  resetrow(_row);
  writebit(1,0);
  for(int _digit=_length-1; _digit>=0; _digit--){
    for(int _bit=0; _bit<8; _bit++){                         
      writebit((serial_from_max[_digit] >> _bit) & 1, _row);  //read bit per bit serial message
    }
  }
  porta |=  (1 << binary_pins[_row][2]);                      //latch 1 causes display register
}

void writebit(boolean _bit, int _row){
  if(_row < 2){                                                                                    //porta (pin 22-29)
    porta = (_bit) ? porta | (1 << binary_pins[_row][0]) : porta & ~(1 << binary_pins[_row][0]);   //data
    porta |=  (1 << binary_pins[_row][1]);                                                         //clock 1
    porta &= ~(1 << binary_pins[_row][1]);                                                         //clock 0
  }
  else{                                                                                            //portc (pin 26-33)
    portc = (_bit) ? portc | (1 << binary_pins[_row][0]) : portc & ~(1 << binary_pins[_row][0]);   //data
    portc |=  (1 << binary_pins[_row][1]);                                                         //clock 1
    portc &= ~(1 << binary_pins[_row][1]);                                                         //clock 0
  }
}

void resetrow(int _row){
  if(_row < 2){
    porta &= ~(1 << binary_pins[_row][2]);   //latch 0 bevor filling memory
    porta &= ~(1 << binary_pins[_row][3]);   //master reset 0
    porta |=  (1 << binary_pins[_row][3]);   //master reset 1
  }
  else{
    portc &= ~(1 << binary_pins[_row][2]);   //latch low bevor filling memory
    portc &= ~(1 << binary_pins[_row][3]);   //master reset
    portc |=  (1 << binary_pins[_row][3]);   //master reset
  }
}

void resetallrows(){
  for(int _row=0; _row<row_count; _row++){
    digitalwrite(digit_pins[_row][2], low);   //latch low fill memory
    digitalwrite(digit_pins[_row][3], low);   //master reset
    digitalwrite(digit_pins[_row][3], high);  //master reset
    digitalwrite(digit_pins[_row][2], high);  //latch high execute memory
  }
}


i hope more or less understandable, please ask if need further informations.

thanks in advance,
wunjeld

quote
i can't explain how happening, seems pwm signal affecting pins shift register.
of course is!  sending 1 bit @ time bit register, , pwm bit "randomly" turned on & off.  (it's not random, there no logical relationship shift-clock.)

pwm doesn't work matrixing, since rows & columns "sharing" pwm outputs.



Arduino Forum > Using Arduino > Project Guidance > Arduino Mega 2560 and 7 segment LED displays (74HC595) with PWM


arduino

Comments

Popular posts from this blog

Convierte tu Raspberry en un NAS. Firmware fvdw-sl 15.3 - Raspberry Pi Forums

How to format a Get Request

avrdude: verification error, first mismatch at byte 0x0000 0x0c != 0x62