Skip to main content
Visitor II
July 10, 2024
Solved

Having a ghosting symbols on 4-digit 7-segment CC indicator

  • July 10, 2024
  • 1 reply
  • 1906 views

Hello, I'm practicing with dynamic indication on multidigit multisegment indicators, and run into the issue when on the screen appear some symbols that are not supposed to be printed. I'm using 3641AS, each segment is connected to PC0...7 via 2K2 resistor, and each digit's pin is connected to PC8...PC11.

The code is:

 

 

/* USER CODE BEGIN PV */

// binary presentation of numbers from 0 till 9
int numbers[10] = { 0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110,
		0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111 };
// the variable to be shown and changed during run of program
int value = 0;
// the decimal place to be depictured at the momen
int current_digit = 0;
// bitmasks of decimals to be depictured (including decimal point)
int digits[4] = { };

#define display_interval 5
#define count_interval 1000

uint32_t last_display_tick;
uint32_t last_count_tick;
uint32_t current_tick;

/* USER CODE END PV */

 

 

 

 

 

/* USER CODE BEGIN 2 */
//turn off all the LEDs
GPIOC->ODR = 0b000000000000;
refresh_digit_values();
/* USER CODE END 2 */

 

 

 

 

 

/* USER CODE BEGIN 3 */
		current_tick = HAL_GetTick();
		if (current_tick - last_count_tick > count_interval) {
			value = (value == 9999) ? 0 : value + 1;
			refresh_digit_values();
			last_count_tick = current_tick;
		};

		if (current_tick - last_display_tick > display_interval) {
			GPIOC->ODR = ((0b1111 ^ (1 << current_digit)) << 8)
					+ digits[current_digit];

			current_digit = current_digit > 3 ? 0 : current_digit + 1;
			last_display_tick = current_tick;
		};

	}
	/* USER CODE END 3 */

 

 

 

 

 

/* USER CODE BEGIN 4 */
void refresh_digit_values(void) {
	digits[3] = numbers[value / 1000];		// by default - integer division
	digits[2] = numbers[value % 1000 / 100];	//
	digits[1] = numbers[value % 100 / 10];		//
	digits[0] = numbers[value % 10];			//

	for (int i = 3; i > 0; i--) {
		if (digits[i] == numbers[0]) {
			digits[i] = 0b00000000;
		} else {
			break;
		};
	}
}
;

/* USER CODE END 4 */

 

 

 

THe expected activity was:

  • increase the value of variable for 1 (and if it hit 9999 reset it)
  • show the value on the screen and remove the leading zeroes ( like if the value is lower than a 1000)

 

Actual output is: 

20240710_184522.jpg

 

20240710_184523.jpg

 

 

20240710_184525.jpg

The counting itself works. But the printing is a problem. Please, advise on the solution.

    This topic has been closed for replies.
    Best answer by unsigned_char_array

    Display interval is wrong, it's a digit interval, entire display interval is 4 times larger.
    You also have an off-by-one error, you divide by 6, not 5.
    Assuming hal tick is 1 millisecond, then display is only updated at only 1ms*6*4=24ms=41.7Hz.
    This will lead to visible strobing when moving your head and can also lead to interference with camera exposure time.
    Better increase it. I would simply leave a timer out entirely. LEDs can switch fast enough (datasheet mentions 10KHz with 10% duty cycle at 200mA, so I assume it can switch at 250Hz 25% duty cycle).

    I actually recommend initially increasing the display interval and the counting interval so you can actually see things happening in case you have a bug somewhere that's setting the wrong segments.

     

    Edit: another off-by-one bug:

    current_digit = current_digit > 3 ? 0 : current_digit + 1;

     current digit can become 4.

    Better rewrite as:

    current_digit = (current_digit + 1) % 4;

    1 reply

    Graduate II
    July 11, 2024

    Display interval is wrong, it's a digit interval, entire display interval is 4 times larger.
    You also have an off-by-one error, you divide by 6, not 5.
    Assuming hal tick is 1 millisecond, then display is only updated at only 1ms*6*4=24ms=41.7Hz.
    This will lead to visible strobing when moving your head and can also lead to interference with camera exposure time.
    Better increase it. I would simply leave a timer out entirely. LEDs can switch fast enough (datasheet mentions 10KHz with 10% duty cycle at 200mA, so I assume it can switch at 250Hz 25% duty cycle).

    I actually recommend initially increasing the display interval and the counting interval so you can actually see things happening in case you have a bug somewhere that's setting the wrong segments.

     

    Edit: another off-by-one bug:

    current_digit = current_digit > 3 ? 0 : current_digit + 1;

     current digit can become 4.

    Better rewrite as:

    current_digit = (current_digit + 1) % 4;
    Visitor II
    July 11, 2024

    The code was functional because the same code, but placed into interrupts on timers was working like a charm:

     

    /* USER CODE BEGIN 4 */
    void refresh_digit_values(void) {
    	digits[3] = numbers[value / 1000];		// by default - integer division
    	digits[2] = numbers[value % 1000 / 100];	//
    	digits[1] = numbers[value % 100 / 10];		//
    	digits[0] = numbers[value % 10];			//
    
    	for (int i = 3; i > 0; i--) {
    		if (digits[i] == numbers[0]) {
    			digits[i] = 0b00000000;
    		} else {
    			break;
    		};
    	}
    }
    ;
    
    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    	if (htim->Instance == TIM2) {
    		GPIOC->ODR = ((0b1111 ^ (1 << current_digit)) << 8)
    				+ digits[current_digit];
    		current_digit = current_digit > 3 ? 0 : current_digit + 1;
    	};
    	if (htim->Instance == TIM3) {
    		refresh_digit_values();
    		value = (value == 9999) ? 0 : value + 1;
    	};
    }
    ;
    /* USER CODE END 4 */

     

    And yes, I tried different time intervals (the visual strobing started when `display_interval` is about 9). However, the use of:

     

    current_digit = (current_digit + 1) % 4;

     

    indeed resolved the problem when used HAL_GetTick. Thank you!

    P.S. Also updated the limiter for changed value:

     

    value = (value+1) % 10000;

     

     

     

     

    Graduate II
    July 12, 2024

    Great to hear you got it to work. If my post helped you please mark it as the answer so the topic can be marked as solved.