Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] need help in develop decimal point logic in seven segment

Status
Not open for further replies.

ud23

Advanced Member level 3
Joined
Apr 20, 2011
Messages
926
Helped
185
Reputation
370
Reaction score
180
Trophy points
1,323
Activity points
6,138
hi all i am writing code for display sensor output on seven segment in which i need display decimal point. i am displaying sensor output from o to 99 digit i need one decimal point accuracy i am using atmega 16 controller.
 

You have to provide some details of what you are trying to do, what kind of sensor are you using?
Do you have only two digits?
If so how can you show any decimal , do you mean 0.0 to 9.9 ?
 

i have 4 multiplexed sevensegment display i am displaying 00.0 to 99.9 on seven segment i have LVDT sensor and using atmega inbuilt 10bit adc for now i just divided my 0 to 1023 count in 0 to 102 instead of 00.0 to 99.9
 

Attachments

  • sevenseg.JPG
    sevenseg.JPG
    141.6 KB · Views: 99

A simple way to improve the result accuracy without using any floats is to multiply Vref with 1000

For example if you have 5v then use

(ADCresult * 5000) /1023

The result that you can get from the above equation is 0 to 5000 (which is the measured voltage in mV) you can manipulate that number in order to get the values for your sensor
 
  • Like
Reactions: ud23

    ud23

    Points: 2
    Helpful Answer Positive Rating
how to display 00.0 to 99.9 i don't understand your 5000 logic.
 

It depends on the relation between measured value and output, what is the relation of input voltage and display output?
 

How to display a floating point number on three common cathod seven segment display

Forum for Electronics - papunblg - Blogs

Codes, Circuit, Picture

---------- Post added at 20:59 ---------- Previous post was at 20:53 ----------

You will find the complete code here. Before trying this you are requested to try to understand what Mr. Alexan_e is telling you. Its the main idea behind similar projects
 

Mr. Alexan_e sir i tried your logic its not showing floating point showing random numbers. I have lvdt sensor of 5mm length.its sensitivity is 75mv per mm i need display this. I have only have to measure 3mm displacement and display that into 00.0 to 99.9 digital values
 

The suggestion I have given was to use the reference voltage multiplied with 1000 so that you get a good accuracy for the result without using floats.
I assume that ADC reference voltage is 5v , if not modify the equation accordingly.
ADCmeasured_voltage should be a 16 bit variable like unsigned integer (or uint16_t).
I have also added typacasting to be sure that the used variable type can hold the temp result of the calculation

ADCmeasured_voltage = ((uint32_t)ADCresult * (uint32_t)5000) /1023

The result of this equation is just the measured voltage , 0v to 5000mV.
If your sensor has an output of 75mV/mm then you can get the result with a division ADCmeasured_voltage, in order to get more accuracy you can use the multiply trick again


mm_result= ((uint32_t)ADCmeasured_voltage * 100)/75

The result on this equation will be in mm/100.
Suppose that the distance was 2mm and you got a result of ADCmeasured_voltage = 150 (which is in mV)
If you apply the second equation (150 * 100) /75 = 200 , note that this result in multiplied with 100 so it actually represents 2.00mm

The you need to extract the digits

Code:
//Declare an array of three char
char display[3]

display[0]= mm_result/1000; // this is the first digit
display[1]= (mm_result % 1000)/100; // this is the second digit
display[1]= (mm_result % 100)/10; // this is the decimal

//If the value was 200 the after this conversion we will have 
//display[0] = 0
//display[0] = 2
//display[0] = 0

// for a measurement of 15.2mm the result would be
// ADCmeasured_voltage = 1140
// mm_result = 1520;
//display[0] = 1
//display[0] = 5
//display[0] = 2



Now you just need to show these three values and turn on the display dot between the second and third digit.
 

Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <math.h>
#include <util/delay.h>


#define SEVEN_SEGMENT_PORT PORTD
#define SEVEN_SEGMENT_DDR DDRD

/*global variable declaration
*/

//unsigned int values[11]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xC6};
unsigned int values[11]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xC6};
//unsigned char values[10]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b};

unsigned int var1,num1,num2,num3,num4,var2;
uint16_t t;
float volt,scale,offset,final,y,ac;





/*function declaration
*/ 
void ADC_init(void);
unsigned int ADC_read(unsigned char);
  



/*main programm starts here*/

void main()
{   


 
 // uint16_t adc_value;
  // uint8_t t;
   
     TCCR0=0x03;   // Prescaler = FCPU/1024

     TIMSK|=(1<<TOIE0); //Enable Overflow Interrupt Enable
 
     TCNT0=0; //Initialize Counter

 
   DDRB=0xff;
   PORTB=0xff;
   

   
 SEVEN_SEGMENT_DDR=0xff; //Turn off all segments
 SEVEN_SEGMENT_PORT=0XFF;

  
   DDRC=0x00;
   PORTC=(1<<PC1)|(1<<PC2);
 
   sei();//Enable Global Interrupts

  

while(1)
{

  ADC_init();
  t=ADC_read(1);
  //volt=(((5.000)*t)/1023)*1000;
    // scale=t*.01955;
        // final=((scale/2)-1);




		if(!(PINC&(1<<PINC1))&&(PINC&(1<<PINC2)))
        

	 
{ 
		
		
	  	 //scale=((t/2)/5);
		 //scale=(t/2);
		 scale=((t*5000)/1023);
	//	 _delay_ms(20);
	////	 while(PINC &(1<<0) !=0);
		
    //  PORTB=(1<<PB0);
     // SEVEN_SEGMENT_PORT=0xC6;
	 // _delay_us(650);
	 

}

  else if(!(PINC&(1<<PINC2))&&(PINC&(1<<PINC1)))
        

	//	if(!PINC & (1<<0)) == 0)//&& (PINC & ((1<<1)|(1<<2))==1)) 
{ 
		
		
	  	 scale=((t/2)/2.5);
	//	 _delay_ms(20);
	////	 while(PINC &(1<<0) !=0);
		
     // PORTB=(1<<PB0);
     // SEVEN_SEGMENT_PORT=0x83;
	 // _delay_us(650);
	 

}

}


}









void ADC_init(void) // Initialization of ADC
{
ADMUX=(1<<REFS0); // AVcc with external capacitor at AREF
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
// Enable ADC and set Prescaler division factor as 128
}

unsigned int ADC_read(unsigned char ch)
{
ch= ch & 0b00000111; // channel must be b/w 0 to 7
ADMUX |= ch; // selecting channel
 
ADCSRA|=(1<<ADSC); // start conversion
while(!(ADCSRA & (1<<ADIF))); // waiting for ADIF, conversion complete
ADCSRA|=(1<<ADIF); // clearing of ADIF, it is done by writing 1 to it
 
return (ADC);
}
 

ISR(TIMER0_OVF_vect) //ISR rutine for sevensegment

{


   var1=scale;
 
  
  num1=var1%10;					// Extracting Units place of seconds
  var1=var1-num1;
  var1=var1/10;
  
  num2=var1%10;					// Extracting tens place of seconds
  var1=var1-num2;
  var1=var1/10;





PORTB=(1<<PB0)|(0<<PB1)|(0<<PB2)|(0<<PB3)|(0<<PB4);       	// Turning ON Units place of display
   SEVEN_SEGMENT_PORT=values[num1];			// Writing corresponding number on Units place 	
   _delay_us(450);//rt delay
   
   PORTB=(0<<PB0)|(1<<PB1)|(0<<PB2)|(0<<PB3)|(0<<PB4);	  // Turning ON Tens place and Turning OFF Units place of seconds 
   SEVEN_SEGMENT_PORT=values[num2];			// Writing corresponding number on Tens place 
   _delay_us(450);// Short delay
 
    
       var2=var1;
	 
     num3=var2%10;				// Extracting Units place 
     var2=var2-num3;
     var2=var2/10;
	 
     num4=var2%10;				// Extracting Tens place 
     var2=var2-num4;
     var2=var2/10;

 
   
   PORTB=(0<<PB0)|(0<<PB1)|(1<<PB2)|(0<<PB3)|(0<<PB4);	           // Turning ON Units place of minutes      // Turning ON Units place of minutes
   SEVEN_SEGMENT_PORT=values[num3];			// Writing corresponding number on Units place of minutes
   _delay_us(450);
	
   PORTB=(0<<PB0)|(0<<PB1)|(0<<PB2)|(1<<PB3)|(0<<PB4); 	           // Turning ON Units place of minutes
	           // Turning ON Tens place and Turning OFF Units place of minutes
   SEVEN_SEGMENT_PORT=values[num4];			// Writing corresponding number on Tens place of minutes
   _delay_us(450);//

   
}

heres my code for this sensor

Always use CODE tags when you include code in your post, especially if it is more that a few lines
 
Last edited by a moderator:

OK, and what is the problem with it?
You didn't apply the method I have described, I hope you don't expect me to write your code.
In your code you are using float variables, it is up to you to select which method to use, it can definitely be done with floats too.
 

ya sir iam asking to use your way u suggested s should i get rid of flt and use them unsigned int or 16 bit integer?? other thing shuld i hav e to right logic for decimal point i mean dot in seven segment to make visible and rotate as its gone from higher segment to lower?/ and sorry i don't want you right code for me just have some confusion?

and thnx for your kind suggestions i am working on it now
 

In the seven segment display you only have to turn on the dot between the second and third digit, this will be constantly on since you want 0.0 to 99.0

The way I have described doesn't use floats , that is the point of the multiplications , to avoid using floats that require additional resourced.
If you use this way then there is no need for float, at lest for the parts I describe, if you want to use them in another section of the code then it is again up to you.

In my example ADCmeasured_voltage and mm_result are 16bit unsigned integers (0 to 65535).
While doing the calculations I typecast the values to 32bit unsigned int (0 to 4294967295) so that the multiplication result that can be higher than 65535 can fit and then after the division there is no problem to assign it back to a 16 bit variable since it becomes smaller than 65536
 

while(1)
{

ADC_init();
t=ADC_read(1);





if(!(PINC&(1<<PINC1))&&(PINC&(1<<PINC2)))



{



scale=((y*(t*5000))/1023);



}

i modified adc logic as u suggested i declared uint32_t as y and apply ur ADC_mesured logic i dont know when i simulated in protues it doesnt show any change in diplay of seven segment

OK sir i changed logic to 5000mv now i am getting values just changed scale=((y*(t*5000))/1023); this logic to scale=(((uint32_t)t)*((uint32_t)5000))/1023; this one now need decimal that i can put on between 2nd and third display using pin wise programming like just making seven segment dot pin high when second segment go on can i do that way sir?
 
Last edited:

My suggestion was scale = ((uint32_t)t * (uint32_t)5000) /1023

Why id ADC_init() in the super loop?
It should only be executed once.
Have you made the changes in the LCD conversion so that t is converted to what should be displayed?


Code C - [expand]
1
2
3
scale/1000; // this is the first digit
(scale % 1000)/100; // this is the second digit
(scale % 100)/10; // this is the decimal

 

hi Mr. alexan_e sir , thanx so much i test my code as u suggested but having problem in decimal point i changed my logic acorrding ur suggestiona nd sensor input i am getting 0 to 100 digits good but hav to problem

first see changed logic below
Code:
while(1)
{

 // ADC_init();
  t=ADC_read(1);
 
 scale=(((uint32_t)t)*((uint32_t)5000))/1023;


		if(!(PINC&(1<<PINC1))&&(PINC&(1<<PINC2)))
        

	 
{ 
		
		
	  
		
		 scale=(scale/10)*2;

		 
}


ISR(TIMER0_OVF_vect) //ISR rutine for sevensegment

{


 
 
    num1=(scale % 100)/10;

    num2= (scale % 1000)/100; 
 




PORTB=(1<<PB0)|(0<<PB1)|(0<<PB2)|(0<<PB3)|(0<<PB4);       	
   SEVEN_SEGMENT_PORT=values[num1];	
   _delay_us(450);
   
   PORTB=(0<<PB0)|(1<<PB1)|(0<<PB2)|(0<<PB3)|(0<<PB4);	 
  
   SEVEN_SEGMENT_PORT=values[num2];		

     _delay_us(450);// Short delay

	  SEVEN_SEGMENT_PORT=(0<<PD7);//making dot of 2nd seven segment on
 
    
     //  var2=var1;
	     
	   num3=scale/1000; 
   

 
   
   PORTB=(0<<PB0)|(0<<PB1)|(1<<PB2)|(0<<PB3)|(0<<PB4);	           
   SEVEN_SEGMENT_PORT=values[num3];			
   _delay_us(450);
	
   PORTB=(0<<PB0)|(0<<PB1)|(0<<PB2)|(1<<PB3)|(0<<PB4); 	           
	           
   SEVEN_SEGMENT_PORT=values[num4];			
   _delay_us(450);//

   
}

here code i changed the two problems now is

some time display change from 0 to 100 is not linear
and the 2nd seven segment dist stays always 8 not change with decimal point
wht is the problem according you?
 

You are using

Code:
if(!(PINC&(1<<PINC1))&&(PINC&(1<<PINC2)))
    {
        scale=(scale/10)*2;
    }

and

Code:
num1=(scale % 100)/10;
        num2= (scale % 1000)/100;

this is not the same as my suggestion
Code:
scale/1000; // this is the first digit
(scale % 1000)/100; // this is the second digit
(scale % 100)/10; // this is the decimal


---------- Post added at 11:44 ---------- Previous post was at 11:00 ----------

I noticed that you have

Code:
num1=(scale % 100)/10;
num2= (scale % 1000)/100;
num3=scale/1000;

So it seems to match my recommendation but there is still the part that I have no idea what it does

Code:
if(!(PINC&(1<<PINC1))&&(PINC&(1<<PINC2)))
    {
        scale=(scale/10)*2;
    }

If the problem is not caused from the above code then you have a problem with the multiplexing function.
From what I can see you are using a timer interrupt and you refresh all digits every single time that the interrupt occurs (using delays), this is not a very efficient way.
You should change your code to show only one digit each time that the interrupt triggers.
Use a static variable to hold a value of which digit to show and increase it in each execution.

Code:
ISR(TIMER0_OVF_vect) //ISR rutine for sevensegment
{
    static uint8_t show_digit;

    if (show_digit==0) {
		// write code to show digit 1
    }
    else if (show_digit==1)    {
		// write code to show digit 2
    }
    else if (show_digit==2)    {
		// write code to show digit 3
    }

    if (++show_digit==3) show_digit=0;  // after showing the third digit restart

}
 
  • Like
Reactions: ud23

    ud23

    Points: 2
    Helpful Answer Positive Rating
hi Mr. alexan_e sir thnx for your suggestion its gr8 help to me. i ll make changes and make let you inform about the result.

and the decimal point problem is solve now.

i changed this logic
Code:
 PORTB=(0<<PB0)|(1<<PB1)|(0<<PB2)|(0<<PB3)|(0<<PB4);	  // Turning ON Tens place and Turning OFF Units place of seconds 
  
   SEVEN_SEGMENT_PORT=values[num2];
  SEVEN_SEGMENT_PORT=(0<<PD2);

to this one
Code:
 PORTB=(0<<PB0)|(1<<PB1)|(0<<PB2)|(0<<PB3)|(0<<PB4);	  // Turning ON Tens place and Turning OFF Units place of seconds 
  
   SEVEN_SEGMENT_PORT=values[num2]+0x80;

as papunblg suggested in his post. thanx papunblg for useful post

to mr. alexan_e sir
Code:
if(!(PINC&(1<<PINC1))&&(PINC&(1<<PINC2)))
        	 
{ 	  
		 scale=(scale/10)*2;

		 
   

}

this logic is for display different scaling when according switch is pressed

in this i am dividing count in my output number 0to 100 range
 
Last edited:

Code:
		if(!(PINC&(1<<PINC1))&&(PINC&(1<<PINC2)))
        

	 
{ 
		
		
scale=(((uint32_t)t)*((uint32_t)5000))/1023;
		
		 scale=((uint32_t)scale * 100)/75;
		 

		 
   

	 

}

  else if(!(PINC&(1<<PINC2))&&(PINC&(1<<PINC1)))
        

	
{ 
		
		 scale=(((uint32_t)t)*((uint32_t)5000))/1023;

		
	  	 scale=((uint32_t)scale *50)/75;
	
	 

}

MR. alexan_e sir i tried this logic and i am not getting full 0 to 100 i am getting result for 00.0 to 66.6 for first condition and for 00.0 to 33.3 for second condition. and decimal point not varying 0 to 9 digit its come only 3 then direct 6 and then 9 i don't know what is wrong?? can you please help me
 

What is the expected resolution of the sensor?
For example it gives 75mV from 1mm, can it give 82.5mV for 1.1mm ?

The resolution of your ADC is about 5mV plus the error it has,I have calculated the values below for each ADC result, as you can see in the table you can only get 0.03mm results and this i probably what you refer to but your first decimal accuracy should be good.

It seems that when you divide the result with 75 to get the mm your result is a float but you are already multiplying scale with 100 so this is not the problem

Code:
ADC 	mV	mm
1	4.88	0.07
2	9.77	0.13
3	14.65	0.20
4	19.53	0.26
5	24.41	0.33
6	29.30	0.39
7	34.18	0.46
8	39.06	0.52
9	43.95	0.59
10	48.83	0.65
11	53.71	0.72
12	58.59	0.78
13	63.48	0.85
14	68.36	0.91
15	73.24	0.98
16	78.13	1.04
17	83.01	1.11
18	87.89	1.17
19	92.77	1.24
20	97.66	1.30
21	102.54	1.37
22	107.42	1.43
23	112.30	1.50
24	117.19	1.56
25	122.07	1.63
26	126.95	1.69
27	131.84	1.76
28	136.72	1.82
29	141.60	1.89
30	146.48	1.95
31	151.37	2.02
32	156.25	2.08
33	161.13	2.15
34	166.02	2.21
35	170.90	2.28
36	175.78	2.34
37	180.66	2.41
38	185.55	2.47
39	190.43	2.54
40	195.31	2.60
41	200.20	2.67
42	205.08	2.73
43	209.96	2.80
44	214.84	2.86
45	219.73	2.93
46	224.61	2.99
47	229.49	3.06
48	234.38	3.13
49	239.26	3.19
50	244.14	3.26
51	249.02	3.32
52	253.91	3.39
53	258.79	3.45
54	263.67	3.52
55	268.55	3.58
56	273.44	3.65
57	278.32	3.71
58	283.20	3.78
59	288.09	3.84
60	292.97	3.91
61	297.85	3.97
62	302.73	4.04
63	307.62	4.10
64	312.50	4.17
65	317.38	4.23
66	322.27	4.30
67	327.15	4.36
68	332.03	4.43
69	336.91	4.49
70	341.80	4.56
71	346.68	4.62
72	351.56	4.69
73	356.45	4.75
74	361.33	4.82
75	366.21	4.88
76	371.09	4.95
77	375.98	5.01
78	380.86	5.08
79	385.74	5.14
80	390.63	5.21
81	395.51	5.27
82	400.39	5.34
83	405.27	5.40
84	410.16	5.47
85	415.04	5.53
86	419.92	5.60
87	424.80	5.66
88	429.69	5.73
89	434.57	5.79
90	439.45	5.86
91	444.34	5.92
92	449.22	5.99
93	454.10	6.05
94	458.98	6.12
95	463.87	6.18
96	468.75	6.25
97	473.63	6.32
98	478.52	6.38
99	483.40	6.45
100	488.28	6.51
101	493.16	6.58
102	498.05	6.64
103	502.93	6.71
104	507.81	6.77
105	512.70	6.84
106	517.58	6.90
107	522.46	6.97
108	527.34	7.03
109	532.23	7.10
110	537.11	7.16
111	541.99	7.23
112	546.88	7.29
113	551.76	7.36
114	556.64	7.42
115	561.52	7.49
116	566.41	7.55
117	571.29	7.62
118	576.17	7.68
119	581.05	7.75
120	585.94	7.81
121	590.82	7.88
122	595.70	7.94
123	600.59	8.01
124	605.47	8.07
125	610.35	8.14
126	615.23	8.20
127	620.12	8.27
128	625.00	8.33
129	629.88	8.40
130	634.77	8.46
131	639.65	8.53
132	644.53	8.59
133	649.41	8.66
134	654.30	8.72
135	659.18	8.79
136	664.06	8.85
137	668.95	8.92
138	673.83	8.98
139	678.71	9.05
140	683.59	9.11
141	688.48	9.18
142	693.36	9.24
143	698.24	9.31
144	703.13	9.38
145	708.01	9.44
146	712.89	9.51
147	717.77	9.57
148	722.66	9.64
149	727.54	9.70
150	732.42	9.77
151	737.30	9.83
152	742.19	9.90
153	747.07	9.96
154	751.95	10.03
155	756.84	10.09
156	761.72	10.16
157	766.60	10.22
158	771.48	10.29
159	776.37	10.35
160	781.25	10.42
161	786.13	10.48
162	791.02	10.55
163	795.90	10.61
164	800.78	10.68
165	805.66	10.74
166	810.55	10.81
167	815.43	10.87
168	820.31	10.94
169	825.20	11.00
170	830.08	11.07
171	834.96	11.13
172	839.84	11.20
173	844.73	11.26
174	849.61	11.33
175	854.49	11.39
176	859.38	11.46
177	864.26	11.52
178	869.14	11.59
179	874.02	11.65
180	878.91	11.72
181	883.79	11.78
182	888.67	11.85
183	893.55	11.91
184	898.44	11.98
185	903.32	12.04
186	908.20	12.11
187	913.09	12.17
188	917.97	12.24
189	922.85	12.30
190	927.73	12.37
191	932.62	12.43
192	937.50	12.50
193	942.38	12.57
194	947.27	12.63
195	952.15	12.70
196	957.03	12.76
197	961.91	12.83
198	966.80	12.89
199	971.68	12.96
200	976.56	13.02
201	981.45	13.09
202	986.33	13.15
203	991.21	13.22
204	996.09	13.28
205	1000.98	13.35
206	1005.86	13.41
207	1010.74	13.48
208	1015.63	13.54
209	1020.51	13.61
210	1025.39	13.67
211	1030.27	13.74
212	1035.16	13.80
213	1040.04	13.87
214	1044.92	13.93
215	1049.80	14.00
216	1054.69	14.06
217	1059.57	14.13
218	1064.45	14.19
219	1069.34	14.26
220	1074.22	14.32
221	1079.10	14.39
222	1083.98	14.45
223	1088.87	14.52
224	1093.75	14.58
225	1098.63	14.65
226	1103.52	14.71
227	1108.40	14.78
228	1113.28	14.84
229	1118.16	14.91
230	1123.05	14.97
231	1127.93	15.04
232	1132.81	15.10
233	1137.70	15.17
234	1142.58	15.23
235	1147.46	15.30
236	1152.34	15.36
237	1157.23	15.43
238	1162.11	15.49
239	1166.99	15.56
240	1171.88	15.63
241	1176.76	15.69
242	1181.64	15.76
243	1186.52	15.82
244	1191.41	15.89
245	1196.29	15.95
246	1201.17	16.02
247	1206.05	16.08
248	1210.94	16.15
249	1215.82	16.21
250	1220.70	16.28
251	1225.59	16.34
252	1230.47	16.41
253	1235.35	16.47
254	1240.23	16.54
255	1245.12	16.60
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top