Display time on 4 digit display with Java and Raspberry Pi 3

Raspberry Pi can be very useful and fun to play with device. Here we are using it to display time on 4 digit 7 segment display which can be nice school project or so.

Things you will need

For this project im using:

  • 8 resistors with ≈ 220 Ω resistance
  • Raspberry Pi
  • 4 digit 7 segment display ( with 12 pins )
  • PC

For development I’m using IntelliJ Idea 2016.2.4 with Embedded Linux JVM Debugger  plugin for deploying and debugging Java code on Raspberry Pi and Pi4J library for GPIO control. Raspberry Pi 3 has Raspbian installed which I’m connected to with through SSH.

Connecting everything…

Almost every Raspberry Pi is using different GPIO pins which you can find at Pi4J website, I’m gonna be using Raspberry Pi 3 Model B which has following pins

raspberry-pi

 

 

Above picture is pretty much self explanatory, but its important to use it at all times, and we are gonna get back to this later next we need to learn how 4 digit display works. Display model I’m using has 12 pins so as simple as it can be. 8 pins are attached to 7 segments of  all digits, other 4 are used as ground for every digit. If we want to display any data ( not just light up all segments ) we need to light certain segments ( depending on the digit we display ) for a small amount of time and go to next one. So basically we only have one digit turned on at a time. Our eyes cant see those on and offs because they are happening so fast. Image below shows how segments and digits are used.

raspberry-pi

Now we need to connect everything together according to above pictures.

4_digit_display_scheme

Java development

Now let’s write some code.

First thing we need to do is initialize all pins.

final GpioController gpio = GpioFactory.getInstance();
 List<Pin> segmentsPins = new ArrayList(Arrays.asList(RaspiPin.GPIO_25, 
                                                      RaspiPin.GPIO_02, 
                                                      RaspiPin.GPIO_24, 
                                                      RaspiPin.GPIO_23, 
                                                      RaspiPin.GPIO_22, 
                                                      RaspiPin.GPIO_21, 
                                                      RaspiPin.GPIO_00, 
                                                      RaspiPin.GPIO_07));
 List<GpioPinDigitalOutput> segments = new ArrayList<>();
 for (int i =0; i<segmentsPins.size(); i++){
 segments.add(gpio.provisionDigitalOutputPin(segmentsPins.get(i), PinState.LOW));
 }
 List<Pin> digitsPin = new ArrayList(Arrays.asList(RaspiPin.GPIO_26, 
                                                   RaspiPin.GPIO_05, 
                                                   RaspiPin.GPIO_03, 
                                                   RaspiPin.GPIO_01));
 List<GpioPinDigitalOutput> digits = new ArrayList<>();
 for (int i =0; i<digitsPin.size(); i++){
 digits.add(gpio.provisionDigitalOutputPin(digitsPin.get(i), PinState.LOW));
 }

Best practice for this code would be to put all pins in two separate lists and initialize them at low state ( all pins are off which means display is black ) so we can use them easliy according to pin position, pins have to be positions in list accordingly. After that we are gonna map all numbers ( Java’s HashMap is best for this) with every entery having Integer array which holds numbers 1 or 0, 1 meaning PinState.HIGH and 0 meanging PinState.LOW.

Map<String, Integer[]> numbers =  new HashMap();
numbers.put("0", new Integer[]{1,1,1,1,1,1,0});
numbers.put("1", new Integer[]{0,1,1,0,0,0,0});
numbers.put("2", new Integer[]{1,1,0,1,1,0,1});
numbers.put("3", new Integer[]{1,1,1,1,0,0,1});
numbers.put("4", new Integer[]{0,1,1,0,0,1,1});
numbers.put("5", new Integer[]{1,0,1,1,0,1,1});
numbers.put("6", new Integer[]{1,0,1,1,1,1,1});
numbers.put("7", new Integer[]{1,1,1,0,0,0,0});
numbers.put("8", new Integer[]{1,1,1,1,1,1,1});
numbers.put("9", new Integer[]{1,1,1,1,0,1,1});

Now to most important part is where we determine which segments or digits we need to light up and getting current time( for time fetching we are gonna use Calendar util ).

try{
    Calendar calendar = Calendar.getInstance();
    String time;
    while (true){
        calendar = Calendar.getInstance();
        time = new SimpleDateFormat("HHmm").format(calendar.getTime());
        for(int i=0; i<digits.size(); i++){
            for(int j=0; j<segments.size()-1; j++){
                segments.get(j).low();
                if(numbers.get(String.valueOf(time.charAt(i)))[j] == 1){
                    segments.get(j).high();
                }
                if(i==1){
                    segments.get(7).high();
                }else{
                    segments.get(7).low();
                }
            }
            digits.get(i).high();
        }
    }
}catch (Exception e){
    e.printStackTrace();
}

This piece of code running all time until process is terminated, this isn’t good practice but its most simple one. So we are iterating through digits and segments, every digit has segments with high and low values which we determine from numbers HashMap. Before every segment check we set it to low value so we clear values from previous digit. We dont want last segment to be included in iteration since its Dot and not segment. Dot separates minutes and hours so we light it only on 2nd position ( that is position with index 1 in digits list ). For better appearance you can make dot blink every second if you put new condition in segment 7 if statement and of course you need current time seconds.

if(i==1 && seconds%2==0){
 segments.get(7).high();
}else{
 segments.get(7).low();
}

I made working demo, so here is picture:

 working demo

As you can see in picture above it looks a lot like a bomb so be careful where and how you carry it around.

Leave a comment

Your email address will not be published. Required fields are marked *