7 segment display not displaying all segments

I’m fairly new to Arduino and just finished my first project. The idea is to have a display that shows the total water usage of that day. The water usage is measured in Homeseer and is sent via UDP to my Arduino Mega board (and ethernet shield).

After some trial and error and help of people from the Homeseer board all works great, except for one thing.

The last figure of my led display doesn’t display the middle led (one of the 7 segments). When I program other Arduino codes (like a counter), that LED does display correctly.

Does anyone know what could be the cause of this problem?

My code is:

const int ledClockPin = 10;
const int ledDataPin = 9;
const int ledLatchPin = 3;
char bitSent = 'LSBFIRST';
int numbers[11] = {126, 12, 182, 158, 204, 218, 250, 14, 254, 222, 0}; //0 will turn off the display
int nummer;
int dig1;
int dig2;
int dig3;
int dig4;
#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h> 
byte mac[] = {
 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 178, 150);
unsigned int localPort = 8888;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
char  ReplyBuffer[] = "acknowledged";
EthernetUDP Udp;


void setup(){
 Ethernet.begin(mac, ip);
 Udp.begin(localPort);
 Serial.begin(9600);
 pinMode(ledLatchPin, OUTPUT);//Latch
 pinMode(ledClockPin, OUTPUT);//Clock
 pinMode(ledDataPin, OUTPUT);//Data
 digitalWrite(ledLatchPin, HIGH);
 Serial.begin(9600);
}

void loop(){

int packetSize = Udp.parsePacket();
   Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
   Serial.println(packetBuffer);
long nummer = atoi(packetBuffer);
dig1 = nummer / 1000;
nummer = nummer - (dig1*1000);
dig2 = nummer / 100;
nummer = nummer - (dig2*100);
dig3 = nummer / 10;
dig4 = nummer - (dig3*10);
     digitalWrite(ledLatchPin, HIGH);
     shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig4]);
     shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig3]);
     shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig2]);
     shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig1]);
     digitalWrite(ledLatchPin, LOW);
     delay(10000);
}

Hi, these parts are incorrect:

char bitSent = 'LSBFIRST'; <-- makes no sense, not needed

This part:

     shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig4]);
     shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig3]);
     shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig2]);
     shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig1]);

should be:

     shiftOut(ledDataPin, ledClockPin, LSBFIRST, numbers[dig4]);
     shiftOut(ledDataPin, ledClockPin, LSBFIRST, numbers[dig3]);
     shiftOut(ledDataPin, ledClockPin, LSBFIRST, numbers[dig2]);
     shiftOut(ledDataPin, ledClockPin, LSBFIRST, numbers[dig1]);

But I can’t see how these errors could cause one segment on one digit to not light…

That same segment lights on the other digits when running this sketch? And all segments light with other sketches?

I assume you are using 74xx595 shift registers to drive each digit?

Paul

I tried your suggested changes, but now my display messes up completely. I'm using the Sure Electronics DE-DP001 (4 digits with an SPI interface).

This lookup table is wrong:-

int numbers[11] = {126, 12, 182, 158, 204, 218, 250, 14, 254, 222, 0}; //0 will turn off the display

Look at the data sheet. The zero character has a value of 0xfc that is 252 in decimal, you have a value of 0x7E or 126 in decimal. Where did you get those numbers from?

Good question; picked these somewhere up, can't remember where. Also didn't understand why I needed this line in my code... Probably need to do some research first :-)

Looked at another (counter) code; uses the same values and display is showing these correctly...

abl1: Looked at another (counter) code; uses the same values and display is showing these correctly...

What numbers to use depends on how your hardware is wired up. I got the numbers from the data sheet of your device. You need them to act as a lookup table.

See this for some examples of how to work them out:- http://www.thebox.myzen.co.uk/Tutorial/Arrays.html

If you're using multiple digit 7-seg display, and using multiplexing, try to clear the individual digits immediately after they're written, this worked for me when some of my segments were not lighting up correctly. Also make sure if you're 7-seg display is common anode or common cathode, depending on what it is you might have to use LOW instead of HIGH when using digitalWrite()

Hope I helped somehow

@Mike; thanks for the provided link. I understood part of the explanation, but halfway it became a bit too theoretical. What I still didn't understand us why a simple counter does show correctly. So I reverted back to my preferred trial and error. When I tried to display a fixed number (so not received via UDP) AND deleted the UDP commands within the loop, it did show up correctly. The soon I included the UDP in the loop (so also with a fixed number) I was faced with the problem of the single LED segment not showing. Would it be better to have another way of data receival than UDP?

@trrychau: thanks for this idea; I will try tomorrow. I first have to find out how to clear the individual segments...

Post the two codes, the working one and the one reading the UPD. Please post all the code not just parts.

This is the code including receiving the number via UDP and then not displaying that specific segment (middle of last character):

const int ledClockPin = 10;
const int ledDataPin = 9;
const int ledLatchPin = 3;
char bitSent = 'LSBFIRST';
int numbers[11] = {126, 12, 182, 158, 204, 218, 250, 14, 254, 222, 0}; //0 will turn off the display
int nummer;
int dig1;
int dig2;
int dig3;
int dig4;
#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h> 
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 178, 150);
unsigned int localPort = 8888;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
char  ReplyBuffer[] = "acknowledged";
EthernetUDP Udp;


void setup(){
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  Serial.begin(9600);
  pinMode(ledLatchPin, OUTPUT);
  pinMode(ledClockPin, OUTPUT);
  pinMode(ledDataPin, OUTPUT);
  digitalWrite(ledLatchPin, HIGH);
}

void loop(){
int packetSize = Udp.parsePacket();
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
long nummer = atoi(packetBuffer);
dig1 = nummer / 1000;
nummer = nummer - (dig1*1000);
dig2 = nummer / 100;
nummer = nummer - (dig2*100);
dig3 = nummer / 10;
dig4 = nummer - (dig3*10);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig4]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig3]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig2]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig1]);
      digitalWrite(ledLatchPin, LOW);
      delay(10000);
}

And this is the code that displays the correct number. But when uploading this I noticed that the first 10 seconds also with this code the same segments is off and only turns on after 10 seconds delay (in the code).

const int ledClockPin = 10;
const int ledDataPin = 9;
const int ledLatchPin = 3;
char bitSent = 'LSBFIRST';
int numbers[11] = {126, 12, 182, 158, 204, 218, 250, 14, 254, 222, 0}; //0 will turn off the display
int nummer;
int dig1;
int dig2;
int dig3;
int dig4;
#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h> 
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 178, 150);
unsigned int localPort = 8888;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
char  ReplyBuffer[] = "acknowledged";
EthernetUDP Udp;


void setup(){
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  Serial.begin(9600);
  pinMode(ledLatchPin, OUTPUT);
  pinMode(ledClockPin, OUTPUT);
  pinMode(ledDataPin, OUTPUT);
  digitalWrite(ledLatchPin, HIGH);
}

void loop(){
//int packetSize = Udp.parsePacket();
//Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
//long nummer = atoi(packetBuffer);
int nummer;
nummer = 1234;  
dig1 = nummer / 1000;
nummer = nummer - (dig1*1000);
dig2 = nummer / 100;
nummer = nummer - (dig2*100);
dig3 = nummer / 10;
dig4 = nummer - (dig3*10);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig4]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig3]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig2]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig1]);
      digitalWrite(ledLatchPin, LOW);
      delay(10000);
}

The tip of clearing the 7 segments did the trick:

const int ledClockPin = 10;
const int ledDataPin = 9;
const int ledLatchPin = 3;
char bitSent = 'LSBFIRST';
int numbers[11] = {126, 12, 182, 158, 204, 218, 250, 14, 254, 222, 0}; //0 will turn off the display
int nummer;
int dig1;
int dig2;
int dig3;
int dig4;
#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h> 
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 178, 150);
unsigned int localPort = 8888;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
char  ReplyBuffer[] = "acknowledged";
EthernetUDP Udp;


void setup(){
  Ethernet.begin(mac, ip);
  Udp.begin(localPort);
  Serial.begin(9600);
  pinMode(ledLatchPin, OUTPUT);
  pinMode(ledClockPin, OUTPUT);
  pinMode(ledDataPin, OUTPUT);
  digitalWrite(ledLatchPin, HIGH);
}

void loop(){
int packetSize = Udp.parsePacket();
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
long nummer = atoi(packetBuffer);
nummer = 1234;
dig1 = nummer / 1000;
nummer = nummer - (dig1*1000);
dig2 = nummer / 100;
nummer = nummer - (dig2*100);
dig3 = nummer / 10;
dig4 = nummer - (dig3*10);
      digitalWrite(ledLatchPin, HIGH);
      
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[0x76]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[0x76]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[0x76]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[0x76]);

      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig4]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig3]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig2]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[dig1]);

      digitalWrite(ledLatchPin, LOW);
      
      delay(10000);
}

I’m not sure whether this is the correct way (number[0x76]) as I now got the last decimal LED on. If you have any further guidance on that than it would be perfect, but I of course can live with one dot…

Thanks very much for helping me out!

  shiftOut(ledDataPin, ledClockPin, bitSent, numbers[0x76]);
      shiftOut(ledDataPin, ledClockPin, bitSent, numbers[0x76]);

That is totally wrong. Numbers is an array with eleven elements so you address the one hundred and eighteenth element!! That is just picking up random crap from the memory, you have not even defined it.

@Mike; you're totallly right; I should have thought a bit better. The 0x76 should be replaced by 11 (last item of the array, being off). Thanks all for your help and now on to the next phase of having more screens showing other parameters (water/gas/power)...

abl1:
The 0x76 should be replaced by 11 (last item of the array, being off).

That’s still wrong. The last element in the array is 10.

In any case, writing zero to the same segment twice cannot have fixed your problem. You must have made some other change that fixed the problem.

You still did not make the corrections i pointed out in my first post.