Control 4 digits 7 segments display

Hi,
I want to use my display 4 digits with 7 segments in W10 IoTCore on Raspberry PI 2 B+.

I’ve followed below tutorial

But it doesn’t works as expected, please look at
https://drive.google.com/open?id=0B4d4KeqKn1KfS0tTM3hBMlVpUlk

The display blink so not all digits are visible at same time.

Can you help me please? Do you know someone that has used 4 digits display with IoTCore?

Thank you

What 4-digit display do you have? How is it wired to the Pi header?

By the way, my approach here would be to go back to basics. Create your own single IO pin example that turns segments on the LED on and off, make sure you can achieve that, then move forward and add a second/third/etc IO pin and control them all. This helps you prove IO is working as you expect, and that the 7-seg display works as you expect.
Then look at the way the example project drives the LEDs and see if it matches what your hardware needs - if not, change it.

Plus, if you dive into the code, you can see it turns off all the digits in order and then turns on only one (pickDigt() ) which can give the effect of a display that is not fully on or off but flickers… that’s probably all you’re seeing.

Hi,
display model is hs420561k-32 (common cathode). I’ve uploaded electric scheme.

I’ve done a new software to handle the display, basically

// FourDigitsHelper.cs

public FourDigitsHelper(byte segA, byte segB, byte segC, byte segD, byte segE, byte segF, byte segG, byte dot, byte d1, byte d2, byte d3, byte d4)
        {
            var controller = GpioController.GetDefault();

            _SegPins = new List<GpioPin>(7);
            foreach (var pin in new byte[] { segA, segB, segC, segD, segE, segF, segG })
            {
                var gpioPin = controller.OpenPin(pin);
                _SegPins.Add(gpioPin);
                gpioPin.Write(GpioPinValue.High);
                gpioPin.SetDriveMode(GpioPinDriveMode.Output);
            }

            _DigitPins = new List<GpioPin>(4);
            foreach (var pin in new byte[] { d1, d2, d3, d4 })
            {
                var gpioPin = controller.OpenPin(pin);
                _DigitPins.Add(gpioPin);
                gpioPin.Write(GpioPinValue.High);
                gpioPin.SetDriveMode(GpioPinDriveMode.Output);
            }

            if (dot != 0)
            {
                _DotPin = controller.OpenPin(dot);
                _DotPin.SetDriveMode(GpioPinDriveMode.Output);
                _DotPin.Write(GpioPinValue.Low);
            }

        }

// Activate a specific digit in the 7-Segment.
        private void pickDigit(byte x)
        {

            // Turn off ALL digits
            for (int i = 0; i < 4; i++)
            {
                _DigitPins[i].Write(GpioPinValue.High);
            }

            // Turn ON only the desired digit
            _DigitPins[x - 1].Write(GpioPinValue.Low);
        }

        //---------------------------------------------------------------------
        // Write one number to a specific digit in the 7-Segment led
        public void digitWrite(byte digit, byte number)
        {

            // Activate the digit
            pickDigit(digit);

            // Activate each led in the digit
            number = (byte)(number > 9 ? 9 : number);
            byte[] bits = _Digits[number];
            for (byte i = 0; i < bits.Length; i++)
            {
                GpioPinValue pinValue = bits[i] == 1 ? GpioPinValue.High : GpioPinValue.Low;
                _SegPins[i].Write(pinValue);
            }
        }

// StartupTask.cs

while (true)
    {
        fourdigit.digitWrite(1, 7);
        Task.Delay(1).Wait();
    fourdigit.digitWrite(2, 1);
        Task.Delay(1).Wait();
    fourdigit.digitWrite(3, 2);
        Task.Delay(1).Wait();
    fourdigit.digitWrite(4, 5);
        Task.Delay(1).Wait();
}

In this way the display is more stable, but i’m not sure this is the best solution.

so let me ask, does it now work? Does it update correctly when you increment a counter or do whatever other test you have? And if so, is there anything else you need help with ?

The display is multiplexed so you will need to be able to refresh it very quickly to avoid flickering. Somewhere around every 10ms should be good enough.

I don’t think this is possible with NETMF as timing is not granular. This is why you are seeing flashing.

You need to disable the digit, write the new bit sequence and then able the digit. You seem to be enabling the digit first. Do this after you write the new sequence to it.

Repeat this for each one in turn as fast as you can and it may work.

Hi,
i’ve changed methods invoke: now i first change segments and after switch digits.
Same result
https://drive.google.com/open?id=0B4d4KeqKn1KfUEV4UVZCY1hLS0U

This is full code

public sealed class LM7SegDirect
    {
        private bool _isAnode;
        private byte qtyDigits = 1;
        private ThreadPoolTimer timer = null;
        private GpioPin[] pins = new GpioPin[8];
        private GpioPin[] digits = new GpioPin[4];
        private GpioController gpio;

        //--------
        // Define each valid number configuration to show in the display
        private byte[,] seven_seg_digits = new byte[10, 7]
        {
                { 0,0,0,0,0,0,1 },  // = 0
                { 1,0,0,1,1,1,1 },  // = 1
                { 0,0,1,0,0,1,0 },  // = 2
                { 0,0,0,0,1,1,0 },  // = 3
                { 1,0,0,1,1,0,0 },  // = 4
                { 0,1,0,0,1,0,0 },  // = 5
                { 0,1,0,0,0,0,0 },  // = 6
                { 0,0,0,1,1,1,1 },  // = 7
                { 0,0,0,0,0,0,0 },  // = 8
                { 0,0,0,1,1,0,0 }   // = 9
        };

        public int CurrentValue { get; set; }

        public LM7SegDirect(byte segA, byte segB, byte segC, byte segD, byte segE, byte segF, byte segG, byte segDotn, bool isAnode)
        {
            byte[] pin_order = new byte[8];

            _isAnode = isAnode;

            pin_order[0] = segA;
            pin_order[1] = segB;
            pin_order[2] = segC;
            pin_order[3] = segD;
            pin_order[4] = segE;
            pin_order[5] = segF;
            pin_order[6] = segG;
            pin_order[7] = segDotn;

            gpio = GpioController.GetDefault();

            // Show an error if there is no GPIO controller
            if (gpio == null)
            {
                //@ @ 
            }

            //----------------
            // Open each pin and turn the light of for it
            for (int i = 0; i < 8; i++)
            {
                pins[i] = gpio.OpenPin(pin_order[i]);
                pins[i].Write(GpioPinValue.Low);
                pins[i].SetDriveMode(GpioPinDriveMode.Output);
            }

            //----------
            // Create a timer that redraw the currentvalue each second
            // OBS: If you want to change numbers faster than that, just fix the timespan for this timer
            timer = ThreadPoolTimer.CreatePeriodicTimer(Timer_Tick, TimeSpan.FromMilliseconds(1));
        }

        //-----------------------------
        // defineDigits
        // Define how many digits the 7-segment have and what are the pin numbers
        public void defineDigits(byte digitsQty, byte dig1, byte dig2, byte dig3, byte dig4)
        {
            byte[] digit_order = new byte[4];

            qtyDigits = digitsQty;

            digit_order[0] = dig1;
            digit_order[1] = dig2;
            digit_order[2] = dig3;
            digit_order[3] = dig4;

            //----------------
            // Open each digit and turn the light of for it
            for (int i = 0; i < digitsQty; i++)
            {
                digits[i] = gpio.OpenPin(digit_order[i]);
                digits[i].Write(GpioPinValue.High);
                digits[i].SetDriveMode(GpioPinDriveMode.Output);
            }
        }

        //---------------------------------------------------------------------
        // Write one number to a specific digit in the 7-Segment led
        public void digitWrite(byte digit, int number)
        {
            try {
                // If the desired digit does not exist, return
                if (digit > qtyDigits)
                    return;

                // Activate each led in the digit
                int pinseq = 0;
                for (byte segCount = 0; segCount < 7; ++segCount)
                {
                    byte finalValue = seven_seg_digits[number, segCount];
                    if (!_isAnode)
                        finalValue = finalValue == (byte)1 ? (byte)0 : (byte)1;

                    pins[pinseq].Write(finalValue == 0 ? GpioPinValue.Low : GpioPinValue.High);
                    pinseq++;
                }

                // Here I am always turning off the DOT, because I dont want it
                pins[pinseq].Write(_isAnode ? GpioPinValue.High : GpioPinValue.Low);


                // Activate the digit
                pickDigit(digit);

            } catch(Exception e)
            {
                int c = 1;
            }
        }

        //---------------------------------------------------------------------
        // Dump the CurrentValue to the display.
        // Up to 4 digits
        public void valueWrite(int number)
        {
            CurrentValue = number;

            if (timer == null)
                timer = ThreadPoolTimer.CreatePeriodicTimer(Timer_Tick, TimeSpan.FromMilliseconds(500));
        }

        //--------------
        // Each timer interval redraw the number in the display
        private void Timer_Tick(ThreadPoolTimer timer)
        {
            if (CurrentValue < 10)
            {
                digitWrite(4, 0);
                digitWrite(3, 0);
                digitWrite(2, 0);
                digitWrite(1, CurrentValue);
            }
            else if (CurrentValue < 100)
            {
                digitWrite(4, 0);
                digitWrite(3, 0);
                digitWrite(2, CurrentValue / 10);
                digitWrite(1, CurrentValue % 10);
            }
            else if (CurrentValue < 1000)
            {
                digitWrite(4, 0);
                digitWrite(3, CurrentValue / 100);
                digitWrite(2, (CurrentValue % 100) / 10);
                digitWrite(1, CurrentValue % 10);
            }
            else
            {
                digitWrite(4, CurrentValue / 1000);
                digitWrite(3, (CurrentValue % 1000) / 100);
                digitWrite(2, (CurrentValue % 100) / 10);
                digitWrite(1, CurrentValue % 10);
            }

        }

        //---------------------------------------------------------------------
        // Activate a specific digit in the 7-Segment.
        private void pickDigit(int x)
        {
            // If only one digit (7-Segment 1 Digit) then no need to continue here
            if (qtyDigits == 1)
                return;

            // Turn off ALL digits
            try {
                for (int i = 0; i < qtyDigits; i++)
                {
                    digits[i].Write(_isAnode ? GpioPinValue.Low : GpioPinValue.High);
                }

                // Turn ON only the desired digit
                digits[x - 1].Write(_isAnode ? GpioPinValue.High : GpioPinValue.Low);
            } catch (Exception e)
            {
                int c = 0;
            }

        }
    }

Any ideas?

Thank you

Your issue is as far as I can see is with not understanding how multiplexing works.

What is your LED display? Common ANODE or common CATHODE?

Common cathode is easiest to driver from microcontroller. Common anodes needs a little more work.

Do you have a datasheet fro the LED so we can see what the pins are?

I see again after going over your code again that it LED is common ANODE

You need to create a thread or some other method to continually refresh the LED displays. You can’t simply do this once per second as your timer is now. You have to redraw each one over and over to give the impression of a solid display. Remember you are multiplexing the 7 segments with each anode controlling which one is going to be switched on.

Create an array that holds the value to be displayed or some other way to record it. In the thread do your digits for each one. Don’t worry about the COUNT of digits, just update them all and have some value that indicates a digit is blank. 0x0A is a good one.

Put your thread to sleep for 10ms and see how that goes.