|
|
View previous topic :: View next topic |
Author |
Message |
kamillas
Joined: 24 Oct 2011 Posts: 50
|
7 segment time |
Posted: Fri Feb 17, 2012 4:09 pm |
|
|
Hello, I made a circuit that calculates the temperature using DS18B20 and two 7-segment. But I found a problem in the multiplexing (time). With a time of 50 ms, the segment connected to pin D2 will stay on, but the segment connected with D3 appears occasionally. I want the number two in both segments to appear at the same time. Aide me please.
Code: |
#include <16F877A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=12000000)
#include <onewire.c>
#include <18b20.c>
int tab[10] = {0xbF,0x6,0x5b,0x4f,0x66,0x6D,0x7D,0x7,0x7f,0x6F};
byte temp1 , temp2 ;
int temperature ;
int i , j ;
void main()
{
aa:
temperature = ds1820_read();
temp1 = temperature %10;
temp2 = temperature /10;
i=500 ;
if (i=!0){
OUTPUT_d(0b00000100) ;
OUTPUT_b(tab[temp1]);
delay_ms( 50 );
{}
OUTPUT_d(0b00001000) ;
OUTPUT_b(tab[temp2]);
delay_ms( 50);
{}
i--;
if (i==0)
goto aa;
}
}
|
http://www.hostingpics.net/viewer.php?id=414689DSC02491.jpg
http://www.hostingpics.net/viewer.php?id=464604DSC02490.jpg |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Fri Feb 17, 2012 4:23 pm |
|
|
There are so many things wrong it is difficult to know where to start....
First, what can an int (i) hold?. Can it hold '500'?.
Second, try to use some logic in your code layout. Indent stuff when it is in a loop or code section, don't use random indenting, makes the code difficult for you (and everyone else) to follow, and encourages errors....
Third avoid goto, unless you have good reason. Your loop would be much easier handled by a while or do.
Fourth, what happens at the end of your code, when i does _not_ equal zero?. This ties with #3.
Fifth, what size number does ds1820_read return?. Is this going to fit in your 'temperature' variable?.
etc. etc... |
|
|
kamillas
Joined: 24 Oct 2011 Posts: 50
|
|
Posted: Fri Feb 17, 2012 5:16 pm |
|
|
The temp is selected for the segment that is still on. I want another explanation. Thank you for your effort but I did not understand, sorry. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Feb 17, 2012 5:42 pm |
|
|
Like Ttelmah says its a wonder anything works at all.
Your layout is absolutely horrendous.
I thought goto's were banned last century.
Make your code layout neater so that you and I can follow it easily.
From what I can decipher of your code, the multiplexing rate is almost an order of magnitude too slow.
Your display is going to flicker for several reasons.
Curly brackets {} come in pairs, indent so that a closing bracket appears below its opening bracket.
Present a simple schematic so that we can relate code to hardware.
Mike |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Does this work any better? |
Posted: Fri Feb 17, 2012 6:03 pm |
|
|
Code: | void main()
{
while (TRUE)
{
temperature = ds1820_read();
temp1 = temperature %10;
temp2 = temperature /10;
OUTPUT_d(0b00000000);
OUTPUT_b(tab[temp1]);
OUTPUT_d(0b00000100);
delay_ms(5);
OUTPUT_d(0b00000000);
OUTPUT_b(tab[temp2]);
OUTPUT_d(0b00001000);
delay_ms(5);
}
}
|
|
|
|
kamillas
Joined: 24 Oct 2011 Posts: 50
|
aide |
Posted: Sat Feb 18, 2012 3:51 am |
|
|
thank you, you understand me, if you use this program, my system shows that the "temp2" in segment 2, but I see no temp1 appears in a segment, and this delay is due to "5ms "So the problem, if I want to see the number two at the same time in both segments must be played on time multiplexing, and that is his problem .. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Sat Feb 18, 2012 4:28 am |
|
|
Mike Walne wrote: | I thought goto's were banned last century. |
Thankfully not. Goto allow you to implement error handling and exit simply in a complex function. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
kamillas
Joined: 24 Oct 2011 Posts: 50
|
|
Posted: Sat Feb 18, 2012 5:09 am |
|
|
asmallri wrote: | Mike Walne wrote: | I thought goto's were banned last century. |
Thankfully not. Goto allow you to implement error handling and exit simply in a complex function. | I want a clear answer, I want a solution to my problem |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sat Feb 18, 2012 4:44 pm |
|
|
To asmallri on goto's
OK I stretched a point. As a general rule, goto's are a bad idea. They make for poor programming style. With the sole exception of catastophic failure recovery, I've not used one for over quarter of a century. If I've got a loop / sequence, I'm having difficulty getting out of then it's telling me I need to restructure it.
To kamillas
You are not making it easy for us.
We obviously have a translation barrier.
To keep things simple, I will use short sentences.
I don't have 18B20 so can't help with that bit.
I can do LED multiplexing.
I have tried to decipher your code.
I have compiled what I can of your code.
It does appear as though the multiplexing should work.
I am assuming that ds1820_read() returns temperature in Celcius as an integer.
You then calculate temp1 as unit's digit. (Why not call it temp_unit?)
You then calculate temp2 as ten's digit. (Why not call it temp_ten?)
I am assuming that your digit drive is active high.
(i.e. a 1 turns the digit on and a 0 turns it off.)
In both your jpg pictures the TEN's digit IS lit.
In one jpg picture the UNIT's digit is NOT lit.
In your code you:-
(1) Activate D2.
(2) Load segments with UNIT's code.
(3) Wait 50ms.
(4) Activate D3.
(5) Load segments with TEN's code.
(6) Wait 50ms.
(7) loop back to (1)
You complain that D2 IS working and D3 NOT.
It does not make sense!
Surely it's the other way round.
i.e. D3 IS working, and D2 NOT.
I don't have your hardware in front of me.
So I'm relying on your answers to try and help.
I looks to me that you've got a hardware problem.
Maybe a poor connection in your rats nest.
See what happens when you try:
(1) Swapping connections to D2 and D3 at the PIC.
(2) Swapping connections to the common terminals on LEDs.
(3) Moving to different D port pins, and recompile.
If you are really convinced that the problem is sofware try:-
Swapping the order in which you multiplex the drives.
If all else fails try out the code below.
Don't argue.
Don't ask questions.
Just try the code.
Don't tell us it's not answering your question.
But please tell us what you SEE.
Then we can move forward.
Code: |
#include <16F877A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=12000000)
int tab[10] = {0xbF,0x6,0x5b,0x4f,0x66,0x6D,0x7D,0x7,0x7f,0x6F};
byte temp_unit , temp_ten ;
int temperature = 0;
int i ;
void main()
{
While (TRUE)
{
temperature = 0;
while (temperature < 100 )
{
temp_unit = temperature %10;
temp_ten = temperature /10;
i = 0 ;
while ( i < 100 )
{
OUTPUT_d(0b00000000) ;
OUTPUT_b(tab[temp_unit]) ;
OUTPUT_d(0b00000100) ;
delay_ms( 5 );
OUTPUT_d(0b00000000) ;
OUTPUT_b(tab[temp_ten]);
OUTPUT_d(0b00001000) ;
delay_ms( 5 );
i++;
}
temperature++;
}
}
}
|
Mike |
|
|
kamillas
Joined: 24 Oct 2011 Posts: 50
|
Thank you M. MIKE WALNE |
Posted: Sun Feb 19, 2012 5:42 pm |
|
|
Really sir, thank you for your very clear answer, but yesterday I found myself what's the problem, the subroutine DS18B20 it really takes a lot of time for reading the temperature. Therefore, I delayed playback by 05 seconds, so the multiplexing worked well, and therefore every 05 seconds, the display in both segment flashes since the program read the temperature that blocks multiplixage.
I really thank you again "M.MIKE", for your great effort, and I wish you that your method of explanation must be generalized in this forum. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Sun Feb 19, 2012 6:43 pm |
|
|
The DS18B20 will take 750ms( that 3/4 of one second) for a 12 bit reading, the default for it.
You can reprogram it for faster results but lose resolution. If you can accept 9 bits, it'll be a lot faster.
Just read the datasheet, it's in there...I read it months ago though.
Since you're only displaying 2 digits ( 20*c, 21*c), you may want to go to 9 bit mode so your display is 'quicker'. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Multiplexing with a timer |
Posted: Tue Feb 21, 2012 2:58 am |
|
|
Glad you got things to work. Thanks for your generous comments.
What made you realise where the problem was?
You do NOT have to stop the display whilst you get data from the temperature sensor.
I do not normally do this sort of thing but I'm making an exception for you.
Try the code below AS IS.
It should count from 0 to 99 at ~2/s then repeat.
When that's OK:-
(1) Remove time delay and temperature test from main().
(2) Put your read temperature sense back into main().
(3) Leave isr as is.
(4) Leave timer setup as is.
(5) I.e. effectively rewrite the WHILE {} loop.
Note:-
(i) Display runs whilst main() reads temperature data.
(ii) Main() spends most of its time in delay_ms(1000) twiddling its thumbs.
(iii) You can SEE code structure at a glance.
(iv) Each closing } bracket is immediately below its opening { bracket.
(v) ALL code between any pair of {} brackets is indented.
(vi) You can view the WHOLE of a routine within a screen, i.e. without scrolling.
(vii) You've been told MOST of this before in YOUR previous topics.
(viii) If a routine / function expands beyond a screen-full, it's time to consider splitting it.
(ix) There is no right way for most programmes, but some are better than others.
(x) You can improve on my code.
(xi) Eg. for more digits I would use either more arrays or pointers
(xii) Coding for compactness, readability, and speed are often different.
(xiii) This list goes on.................
Code: |
/*
**************************************************************************************
** Multiplexes temperature value on two seven segment displays
**
** Digits are updated @ ~700Hz in isr
**
** Main spends time collecting temperature data at its own pace
**
**************************************************************************************
*/
#include <16F877A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=12000000)
// Declare constants & variables
int tab[10] = {0xbF,0x6,0x5b,0x4f,0x66,0x6D,0x7D,0x7,0x7f,0x6F}; // segment table, symbols 0 - 9
int temperature;
byte temp_unit , temp_ten ; // temperature tens & units
int digit; // current active display digit index
// main()
//
// sets up timer0 for interrupts.
//
// in a loop
// forces temperature value to advance twice per second
// confirms temperature display multiplex is working
//
// when happy that multiplex is working:-
// remove delay_ms(500).
// replace temperature advance with read_18B20() function.
//
// *****************************************************************************************
void main()
{
setup_timer_0(RTCC_DIV_16 | RTCC_INTERNAL | RTCC_8_BIT); // timer 0 interrupts @~700Hz
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
While (TRUE)
{
temperature = 0;
while (temperature < 100 )
{
temp_unit = temperature %10;
temp_ten = temperature /10;
delay_ms( 500 );
temperature++;
}
}
}
// *****************************************************************************************
// timer0 interrupt isr.
// selects new digit to light.
// turn last digit off
// sets new digit segments
// turn new digit on
// exit isr
// *****************************************************************************************
#int_timer0
void segment_mux_isr()
{
digit++; // advance to next digit
digit%=2; // reset to 0 if > 1
if (!digit) // test for digit 0
{
OUTPUT_d(0b00000000) ;
OUTPUT_b(tab[temp_unit]) ;
OUTPUT_d(0b00000100) ; // digit 0 is units i.e. 10^0
}
else
{
OUTPUT_d(0b00000000) ;
OUTPUT_b(tab[temp_ten]);
OUTPUT_d(0b00001000) ; // digit 1 is tens i.e. 10^1
}
}
// *****************************************************************************************
|
Best wishes
Mike |
|
|
kamillas
Joined: 24 Oct 2011 Posts: 50
|
Good |
Posted: Tue Feb 21, 2012 5:07 pm |
|
|
Hello Mike,
Thank you, so what I understood from your program is that you have made the multiplexing program interruption, so I read_ds18b20 mid function, in the main program.
I also have 4 questions:
1 - what does this function: if (! Digit)?
2- why did you put on the main program temperature = 0?
3 - why in the main pogramme, you mentioned delay_ms (500)?
But this time is useless!
4 - this function: digit%=2, if for example I did: digit%=3 means what?
Thanks |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Tue Feb 21, 2012 8:50 pm |
|
|
Kamillas...you've got to read and re-read Mike's test program again...
He was very nice to take the time to cut test code for you, very nice to add comments as to why he did what he did!!
from what I just quickly read...
1) !digit, as the comment /...... says, tests for the '0' digit( units)
2) temperature=0; is the starting value for the variable called temperature.It allows the display to go from 00 to 99. He could have put in 32 , then the display would increments 32,33,34,....99.
3)delay_ms(500) is for us humans to SEE the display,judge if the refresh( update,multiplex,scan) rate is OK or not.You have to read his comments in the preamble !
4) that's a quick and clever test to determine which of the 2 digits( 10s or 1s ) to use to display the data
This version of C is not that hard compared to say Delphi which has 1,000s of functions,keywords, and 'interesting' syntax.I do prefer to cut assembler though as I've always found 'higher level' languages a bit of a 'cheat'. However YOU have to do read,test,observe and try again and again in order to learn.This does not come overnight or in a few short weeks working just a couple hours a day.I've got thousands of hours over the past 20 years of using PIC C and learn new things everyday. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Multiplexing |
Posted: Wed Feb 22, 2012 3:35 am |
|
|
temtronic.
Thank you for doing the comments. We seem to be singing from the same hymn sheet. We're obviously in different time zones. I find it amazing.
kamillas.
Have you tried my code?
If no. Why?
If yes. Did it work?
Mike |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|