Go Down

### Topic: Help Multiplexing a 4 Digit Seven Segment Display (Read 283 times)previous topic - next topic

#### COMediSun

##### Oct 22, 2018, 02:07 pm
I'm working on an Arduino project where I'm attempting to display 4 digits from a serial monitor input to a 4-digit seven segment display based on an input from the serial monitor.... this seems like a very simple project, but my lack of Arduino and coding experience is the problem.

Fast forward...the circuit is wired appropriately and the display is illuminated,  I've also written the program code to get my serial input numbers separated into variables and displayed on the 4 digit display successfully where they should be....but they won't stay put.

I'm able to get four digits to display(very rapidly), but the numbers run through their sequence and end at the last one, remaining illuminated on the final digit.

The issue I'm having I believe comes down to multiplexing. I'm aware what multiplexing is, but again my lack of formal experience makes me unsure exactly how to apply it in my code or circuit. Is it as simple as switching the pin modes at HIGH and LOW at a VERY rapid pace? or somehting more complicated?

Here's the complete code I'm working with... please excuse my working mess:

Code: [Select]
`// Global declarations// shift register pinsconst int latchPin = 5;  //74HC595  pin 9 ST_CPconst int clockPin = 6;  //74HC595  pin 10 SH_CPconst int dataPin  = 4;  //74HC595  pin 8 DS// multi-segment digit select pinsconst int digit1Pin = 9;    // segment pin 12const int digit2Pin = 10;   // segment pin 10const int digit3Pin = 11;   // segment pin 8const int digit4Pin = 12;   // segment pin 6 // digitTable stores the binary patterns for displaying the hexadecimal digits 0-9byte digitTable[16]={                             B11111100,   //  0                              B01100000,   //  1                              B11011010,   //  2                             B11110010,   //  3                             B01100110,   //  4                             B10110110,   //  5                             B10111110,   //  6                                B11100000,   //  7                             B11111110,   //  8                             B11100110,   //  9                             };                             //  Declares a variable to store the integer.   int displayValue;  //  This is the value that will be shown on the multi-digit display.const byte numChars = 32;char receivedChars[numChars];char tempChars[numChars];        // temporary array for use when parsing      // variables to hold the parsed dataint integer1FromPC = 0;int integer2FromPC = 0;int integer3FromPC = 0;int integer4FromPC = 0;boolean newData = false;void setup() {   //  Set pinMode for shift register pins:  pinMode( latchPin , OUTPUT );   pinMode( clockPin , OUTPUT );   pinMode( dataPin  , OUTPUT );      //  Set pinMode for seven segment pins:  pinMode( digit1Pin , OUTPUT );   pinMode( digit2Pin , OUTPUT );    pinMode( digit3Pin , OUTPUT );    pinMode( digit4Pin , OUTPUT );         //  Setup serial port  Serial.begin(9600);         //  Initialize displayValue to 0.  displayValue = 0;      //  Display 0000 at Start  digitalWrite( latchPin , LOW );  shiftOut( dataPin , clockPin , LSBFIRST , digitTable[ displayValue ] );    digitalWrite( latchPin , HIGH );  Serial.println("This demo accepts up to 4 integers");    Serial.println("Enter data in this style < 1, 2, 3, 4 >  ");    Serial.println();}//  Sends binary pattern for 4 digits to the shift register */void displayDigit1(  byte integer1FromPC,   byte integer2FromPC,  byte integer3FromPC,  byte integer4FromPC){  digitalWrite( latchPin, LOW );  shiftOut(dataPin , clockPin , LSBFIRST , digitTable[ integer1FromPC ] );  digitalWrite( latchPin, HIGH);   //  Sets digit 1 ON  digitalWrite( digit1Pin , LOW  );  digitalWrite( digit2Pin , HIGH );  digitalWrite( digit3Pin , HIGH );  digitalWrite( digit4Pin , HIGH );   delay(100);  digitalWrite( latchPin , LOW );  shiftOut( dataPin , clockPin , LSBFIRST , digitTable[ integer2FromPC ] );  digitalWrite( latchPin, HIGH );   //  Sets digit 2 ON  digitalWrite( digit1Pin , HIGH );  digitalWrite( digit2Pin , LOW  );  digitalWrite( digit3Pin , HIGH );  digitalWrite( digit4Pin , HIGH );  delay(100);      digitalWrite( latchPin, LOW );  shiftOut( dataPin , clockPin , LSBFIRST , digitTable[ integer3FromPC ] );  digitalWrite( latchPin , HIGH );   //  Sets digit 3 ON  digitalWrite( digit1Pin , HIGH );  digitalWrite( digit2Pin , HIGH );  digitalWrite( digit3Pin , LOW  );  digitalWrite( digit4Pin , HIGH );  delay(100);    digitalWrite( latchPin , LOW );  shiftOut(dataPin , clockPin , LSBFIRST , digitTable[ integer4FromPC ] );  digitalWrite( latchPin , HIGH );     //  Sets digit 4 ON    digitalWrite( digit1Pin , HIGH );  digitalWrite( digit2Pin , HIGH );  digitalWrite( digit3Pin , HIGH );  digitalWrite( digit4Pin , LOW  );  delay(100);}void loop() {  recvWithStartEndMarkers();    if (newData == true) {        strcpy(tempChars, receivedChars);            // this temporary copy is necessary to protect the original data            //   because strtok() used in parseData() replaces the commas with \0        parseData();        showParsedData();        newData = false;displayDigit1(integer1FromPC, integer2FromPC, integer3FromPC, integer4FromPC);}}//void recvWithStartEndMarkers() {    static boolean recvInProgress = false;    static byte ndx = 0;    char startMarker = '<';    char endMarker = '>';    char rc;    while (Serial.available() > 0 && newData == false) {        rc = Serial.read();        if (recvInProgress == true) {            if (rc != endMarker) {                receivedChars[ndx] = rc;                ndx++;                if (ndx >= numChars) {                    ndx = numChars - 1;                }            }            else {                receivedChars[ndx] = '\0'; // terminate the string                recvInProgress = false;                ndx = 0;                newData = true;            }        }        else if (rc == startMarker) {            recvInProgress = true;        }    }}//void parseData() {      // split the data into its parts    char * strtokIndx; // this is used by strtok() as an index    strtokIndx = strtok(tempChars, ","); // this continues where the previous call left off    integer1FromPC = atoi(strtokIndx);     // convert this part to an integer     strtokIndx = strtok(NULL, ","); // this continues where the previous call left off    integer2FromPC = atoi(strtokIndx);     // convert this part to an integer    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off    integer3FromPC = atoi(strtokIndx);     // convert this part to an integer    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off    integer4FromPC = atoi(strtokIndx);     // convert this part to an integer        }//void showParsedData() {    Serial.print("Integer 1: ");    Serial.println(integer1FromPC);    Serial.print("Integer 2: ");    Serial.println(integer2FromPC);    Serial.print("Integer 3: ");    Serial.println(integer3FromPC);    Serial.print("Integer 4: ");    Serial.println(integer4FromPC);}`

I'm unsure if I need to implement a simple delay like this :

Code: [Select]
`//  Sets digit 1 ON  digitalWrite( digit1Pin , LOW  );  digitalWrite( digit2Pin , HIGH );  digitalWrite( digit3Pin , HIGH );  digitalWrite( digit4Pin , HIGH );   delay(100);`

or something more complicated like a timer or new function to implement in the loop.

#### Paul__B

#1
##### Oct 22, 2018, 02:51 pm
Cute toy.

Better to do  it properly - use a MAX7219.

Hey, look you say "the circuit is wired appropriately" but I even doubt that.  Fine to play about and learn coding, but if you want to use it for any purpose, you need to use the proper hardware.

#### COMediSun

#2
##### Oct 22, 2018, 03:06 pm
Cute toy.

Isn't it?

I realize there are better options out there, but I am limited to this configuration based on the assignment protocol.

I know it's hokey, but I need to get it working as assigned.

I've been tinkering with the circuit and I'm now able to get all digits to display appropriately, but now it's only displaying the final last digit of my 4 digit number on all digits of the display.

The code I'm using to get all digits to display is:

Code: [Select]
`//  Sends binary pattern for 4 digits to the shift register */void displayDigit1(  byte integer1FromPC,   byte integer2FromPC,  byte integer3FromPC,  byte integer4FromPC){  //  Sets digit 1 ON  digitalWrite( digit1Pin , LOW );  digitalWrite( latchPin, LOW );  shiftOut(dataPin , clockPin , LSBFIRST , digitTable[ integer1FromPC ] );  digitalWrite( latchPin, HIGH);  Serial.print(integer1FromPC);  digitalWrite( digit2Pin , LOW );    digitalWrite( latchPin , LOW );  shiftOut( dataPin , clockPin , LSBFIRST , digitTable[ integer2FromPC ] );  digitalWrite( latchPin, HIGH );  Serial.print(integer2FromPC);    digitalWrite( digit3Pin , LOW );   digitalWrite( latchPin, LOW );  shiftOut( dataPin , clockPin , LSBFIRST , digitTable[ integer3FromPC ] );  digitalWrite( latchPin , HIGH );   Serial.print(integer3FromPC);    digitalWrite( digit4Pin , LOW );   digitalWrite( latchPin , LOW );  shiftOut(dataPin , clockPin , LSBFIRST , digitTable[ integer4FromPC ] );  digitalWrite( latchPin , HIGH );   Serial.print(integer4FromPC);}`
Any ideas how I can get each individual number from a four-digit number to appear on the display at each digit?

#### COMediSun

#3
##### Oct 22, 2018, 03:53 pm
Got it! Now to make it look purty!

#### Paul__B

#4
##### Oct 22, 2018, 10:48 pm
Got it! Now to make it look purty!
Glad to hear you have solved it.

Without any details of what you have wired up, or how you have presently coded it, we naturally cannot help you with it.

#### Rintin

#5
##### Oct 24, 2018, 07:50 am
recvWithStartEndMarkers() seems to be blocking on unfinished data. This prevents displayDigit1() from updating the display. I think sending data with an ending line break might be unfinished data.

I think you have 3 options:
- use a max7219
- make recvWithStartEndMarkers() non-blocking
- rewrite displayDigit1() to use timer interrputs

Go Up