I later changed that to the above since the code did not compile.
What I intend for the project is this:
The menu is to come up when the reference temperature needs to be adjusted (the menu should be called by the 'ok' switch).
The reference temperature is to be saved so it can remain the same even when the system restarts except it is changed. (the save is also carried out by the ok switch but only when the menu is called out already).
This reference temperature can then be used to set conditions for maybe a fan or a heater and stuff.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The 877a has the following interrupt capability (for this port). PORTBChange
So, your code will be On interrupt PORTBChange call MyISRHandler
Then, in your new sub called MyISRHandler you need to determine the source of the interrupt - which port raised the interrupt. Then, you can set a variable ( a state variable ) and exit. Then, in your main program examine state variable to update the LCD.
Do not try to updated the LCD within the interrupt handler - this will lead to many issues. If you do... the LCD will be updating very nicely and you will be missing all the other events... So, keep the interrupt handler very short.
Hope this helps.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have probable missed that you may have to clear the event in the handlers, and/or to raise the event per port you may have to set a specific bit. This will all be in the datasheet.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Page 44. Four of the PORTB pins, RB7:RB4, have an interrupton-change feature. Only pins configured as inputs can cause this interrupt to occur (i.e., any RB7:RB4 pin configured as an output is excluded from the interrupton-change comparison). The input pins (of RB7:RB4) are compared with the old value latched on the last read of PORTB. The “mismatch” outputs of RB7:RB4 are OR’ed together to generate the RB port change interrupt with flag bit RBIF (INTCON<0>)
So, set the interrupt and test the Port. As at least one of the RB7:RB4 pins changed state; a mismatch condition will continue to set the bit. Reading PORTB will end the mismatch condition and allow the bit to be cleared.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello, Anobium.
I've tried working on the code while looking at the datasheet and comparing with a sample demo (keypad demonstration with hardware serial).
Here's what I came up with.
It compiles but it does nothing on the simulation.
I've attached the gcb and asm files also.
#chip 16f877a, 4#option explicit#config osc=XT#config WDT = OFF#define sensor PORTA.5#define up PORTB.6#define down PORTB.5#define ok PORTB.4;lcdconnectionsettings#define LCD_Speed medium#define LCD_IO 4#define LCD_NO_RW#define LCD_RS PORTD.2#define LCD_Enable PORTD.3#define LCD_DB4 PORTD.4#define LCD_DB5 PORTD.5#define LCD_DB6 PORTD.6#define LCD_DB7 PORTD.7dirsensorindirupindirdownindirokindimtempnowasWorddimccountasWorddimtempoldasworddimtemprefasworddimIOCB4asBitdimIOCB5asBitdimIOCB6asBitdimtempref1asword;variablesusedccount=0print"System On..."wait3sclsPrint"Obtaining temp."wait2slocate1,0print"Please wait...."wait2scls'init tempold so it not equalt tempnow, if can never read 65535tempold=0xffffmain:doforeverdimtempnowasWordtempnow=scale(ReadAD10(AN4),0,1023,0,499)oninterruptPORTBchangecallMyISRhandlertempref=tempref1iftempold<>tempnowthenclsprinttempnowprint" degrees C"tempold=tempnowccount++endifwait10mssubMyISRhandlerifIOCB4=1thencallokendsubsubokclsprint"Adjust ref temp."EPReadEEADR,tempreflocate1,0printtempref1ifIOCB5=1thencalldownendififIOCB6=1thencallupendififIOCB4=1thencallsaveendifgotomainendsubsubdowntempref--endsubsubuptempref++endsubsubsaveintoffEPWriteEEADR,temprefintonendsubloop
A few changes.... I cannot test but it should work.
Sub up, down and save... I am not sure what is happening but I have renamed.
Look at the interrupt - now. It is short. It sets a variable. I was not clear - calling the sub from the ISR hanlder extends the time to complete the subs... so, short is goodness.
Then, I added a Select-Case. Seems an easy to test what happened in the ISR. You have had a lot of IF-THEN.. like eventvalue.6., eventvalue.5, eventvalue4 but the select looks nice.
You have all the code with in the loop. An odd approach. So, I have moved the loop and got rid of the goto.
Your bits. Not sure what they were doing. Not needed me things. So, gone.
While I ran the code, here are a few things I noticed:
1. The lcd constantly goes from 0-9 and starts again even for continous increase in temperature from the sensor.
2. The buttons don't work yet.
I saw the comment where you defined IOCB4 to IOCB6 as bit and I fhought it was meant to be a definition so I removed the apostrophe(after I tried with it on)
I should've responded earlier but I tried to accustom myself to the new stuff I saw such as the string, pad, and the select case condition to the extent to which I could.
I must say that I'm a bit stuck at this point.
I'm quite at a loss on what to do.
I'll really appreciate any pointers at all.
I'll try to attach the gcb file with the little corrections I made and my proteus simulation screenshot so far.
I have 2 observations
1)The select case is a great tool. The values you are looking for are wrong? You have pullup resistor on the three buttons so when no buttons are pushed the port value should be 0$FF or binary b'11111111'. When "save" button is pushed , b'11101111' not 16. fix the values in the select.
2)As the PIC16877A document says: in the Interrupt Service Routine, can clear theinterrupt in the following manner:a) Any read or write of PORTB. This will end themismatch condition.b) Clear flag bit RBIF.A mismatch condition will continue to set flag bit RBIF.Reading PORTB will end the mismatch condition andallow flag bit RBIF to be cleared..
So how do you handle waiting for the pressed button to be released and portB be returned to 0$FF? then you can clear the interruprt after reading the port again. Now you interrupt again but nothing happens because you haven't reset the RBIF. If the release does interrupt again this may be ok because select case doesn't do anything for 0$FF.
Maybe this would help.
subMyISRhandlereventvalue=PORTBRBIF=0endsub
GL
Mike
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Oh yes... Pull Ups. I would not have spotted that. See attached. Essentially, the test for the bits is now a little more complex (only a tad more).
See attached. I have added 'here' to show the three changes.
So, now.... the bits 4,5,6 are, as Mike says, 0b01110000 which is d112. So, we know we need to examine the state of those three bits. To do this we AND the eventvalue as the other bits may have generated an event. We test to see if the three bits are High (to match the pullups). Then, we test the bits (I used decimal - you may want to use binary notation).
But, Mike was 100% correct... the code is PULLUP, I assume PULLDOWN. But, we do not need to clear RBIF as the Great Cow BASIC handles this for you.
I'm sorry for the late reply. I wanted to make sure I try to have a basic understanding of the parts of the code before continuing.
Here's where I've some little issues:
For the problem where the LCD was constantly moving between 0-9 for consistent increase in temperature form the lm35, I found out that it was the lcdhome command that was causing it. It began to correlate when I took out that command. I also couldn't leave in the "lcdspace 16" command because it just printed spaces and displayed nothing.
I tried to use the 'case 96' which I think represents the ok button (even though I have no idea how it does. The cases weren't declared in the code above so I checked the datasheet to see if they were specific to IOC feature on this chip, still nothing) to call up the sub_save subroutine but I noticed two things:
The string "saved" was always displayed when I clicked the ok button to save (I even removed it from the code to know where it was from and recompiled but it kept on being displayed, maybe it was saved or something).
tempref was always at 20 (I don't know if it was saved at that and refused to change to the new value)
The 'goto main' statement at the end of the sub_save routine doesn't work. The LCD remains at that menu.
I've tried to read up a little on binary and hexadecimal to understand the initialization for portstatus.....Uhmm, little success.
I've also tried fiddling with the code a little more. The code didn't compile so I'll try to attach the gcb file.
Lastly, I'd appreciate any link to understand how to do debouncing to account for double presses.
96 and the other values are the decimale value of a the binary notation. d96=0b1100000 . And, we need to know that your ports go low (remember you choose pulled high which does make this a lot harder to explain when compare to pulled low). So, we mask the port with the constant PortStatus. PortStatus is d112 or 0b01110000. So, we makes the port value as follows - for a moment except that the top three bits all pulled high and we going to ingore the rest.
Where PortB = all high therefore 255. 255 AND PortStatus returns 112 as all the bits (that we are interested) are high,
So, where bit 4 is pushed low. So, the port would return 239 AND PortStatus returns 96 as we have one bit low.
We can use this method to determine the state of any port.
All that said.... a much easy method to understand may be to use IF-THEN
if tempold<>tempnow then
cls
print tempnow
print " degrees C"
locate 1,0
print "Atmospheric temp"
tempold=tempnow
ccount++
end if
if ( eventvalue and PortStatus ) <> PortStatus then
If eventvalue.6 = 0 then
sub_down
end if
If eventvalue.5 = 0 then
sub_up
end if
If eventvalue.4 = 0 then
sub_ok
end if
'reset eventvalue
'here - this essentially reset the event flag
eventvalue=PortStatus
else
wait 10 ms
locate 1, 15
Print " "
end if
Loop
Do NOT use goto. You are exiting the DO-LOOP. Rethink your use of GOTOs. By doing the GOTO do not reset the eventvalue.
:-) When I say works... it does the basic. You will have to resolve issues like:
1. Decrementing the value will overflow the variable and you can go from 0 to 65535.... so, you to stop that.
2. LCD needs a tidy up.... a later. :-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have been able to implement the circuit in hardware.
My LCD was giving me flickering issues at first but after doing the following, I was able to get a somewhat stable display:
* Adding a 100uf filtering capacitor to the LCD power supply.
* Increasing the LCD speed to "fast".
* Using a separate 7805 regulator for the LCD since it was dropping the PIC's 7805 to 3 plus volts.
After these, the LCD became stable but for the temperature values which were so randomly changing between 150-350 so quickly even when the lm35 is connected.
The lm35 still fails to output the expected temperature. It shares power supply with the pic which is 5 volts although this voltage drops to about 4.8 volts.
The buttons don't bring up the menu except when pressed like two to five times and it's also random.
For the up and down buttons to set a ref temp, it counts up to 65535 or so which seems strange.
Overall, someone suggested I put in a higher frequency crystal oscillator like 6MHz. I'm yet to do that.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anobium told you to make the interrupt handler very minimum amount of code. A 200 ms pulse is locking your micro in the interrupt for very long time. do not put the pulse out here.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Okay, thanks.
I probably didn't get that. I was looking for a way to have a buzzer beep for every key press.
It isn't even working yet.
(I first used
'Set A. 1 on'
'wait 200 ms'
'set A. 1 off'
didn't work too.)
What should be the best place to put it the pulseout pls?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I came across tone but I thought since the buzzer I'm using is an active one that gives out a tone of constant frequency once powered, tone might have problems.
I'll try it out
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry for the confusion.
That was formerly:
I later changed that to the above since the code did not compile.
What I intend for the project is this:
The menu is to come up when the reference temperature needs to be adjusted (the menu should be called by the 'ok' switch).
The reference temperature is to be saved so it can remain the same even when the system restarts except it is changed. (the save is also carried out by the ok switch but only when the menu is called out already).
This reference temperature can then be used to set conditions for maybe a fan or a heater and stuff.
OK. Sort out the interrupt first.
The 877a has the following interrupt capability (for this port). PORTBChange
So, your code will be
On interrupt PORTBChange call MyISRHandlerThen, in your new sub called
MyISRHandleryou need to determine the source of the interrupt - which port raised the interrupt. Then, you can set a variable ( a state variable ) and exit. Then, in your main program examine state variable to update the LCD.Do not try to updated the LCD within the interrupt handler - this will lead to many issues. If you do... the LCD will be updating very nicely and you will be missing all the other events... So, keep the interrupt handler very short.
Hope this helps.
Thanks a lot.
I'll try it.
I have probable missed that you may have to clear the event in the handlers, and/or to raise the event per port you may have to set a specific bit. This will all be in the datasheet.
Uhmm.... I'll see how I can do that though I must say that the datasheet is a bit confusing.
So, set the interrupt and test the Port. As at least one of the RB7:RB4 pins changed state; a mismatch condition will continue to set the bit. Reading PORTB will end the mismatch condition and allow the bit to be cleared.
Hello, Anobium.
I've tried working on the code while looking at the datasheet and comparing with a sample demo (keypad demonstration with hardware serial).
Here's what I came up with.
It compiles but it does nothing on the simulation.
I've attached the gcb and asm files also.
A few changes.... I cannot test but it should work.
Sub up, down and save... I am not sure what is happening but I have renamed.
Look at the interrupt - now. It is short. It sets a variable. I was not clear - calling the sub from the ISR hanlder extends the time to complete the subs... so, short is goodness.
Then, I added a Select-Case. Seems an easy to test what happened in the ISR. You have had a lot of IF-THEN.. like eventvalue.6., eventvalue.5, eventvalue4 but the select looks nice.
You have all the code with in the loop. An odd approach. So, I have moved the loop and got rid of the goto.
Your bits. Not sure what they were doing. Not needed me things. So, gone.
See what happens.
Okay, let me re-run.
I'll try to understand what's going on also.
Just thinking.... this will be smarter looking!
Oh, I just saw this.
While I ran the code, here are a few things I noticed:
1. The lcd constantly goes from 0-9 and starts again even for continous increase in temperature from the sensor.
2. The buttons don't work yet.
I saw the comment where you defined IOCB4 to IOCB6 as bit and I fhought it was meant to be a definition so I removed the apostrophe(after I tried with it on)
I should've responded earlier but I tried to accustom myself to the new stuff I saw such as the string, pad, and the select case condition to the extent to which I could.
I must say that I'm a bit stuck at this point.
I'm quite at a loss on what to do.
I'll really appreciate any pointers at all.
I'll try to attach the gcb file with the little corrections I made and my proteus simulation screenshot so far.
Judah,
Anobium is probably getting some sleep.
I have 2 observations
1)The select case is a great tool. The values you are looking for are wrong? You have pullup resistor on the three buttons so when no buttons are pushed the port value should be 0$FF or binary b'11111111'. When "save" button is pushed , b'11101111' not 16. fix the values in the select.
2)As the PIC16877A document says: in the Interrupt Service Routine, can clear theinterrupt in the following manner:a) Any read or write of PORTB. This will end themismatch condition.b) Clear flag bit RBIF.A mismatch condition will continue to set flag bit RBIF.Reading PORTB will end the mismatch condition andallow flag bit RBIF to be cleared..
So how do you handle waiting for the pressed button to be released and portB be returned to 0$FF? then you can clear the interruprt after reading the port again. Now you interrupt again but nothing happens because you haven't reset the RBIF. If the release does interrupt again this may be ok because select case doesn't do anything for 0$FF.
Maybe this would help.
GL
Mike
Thanks a lot, Mmotte.
Oh yes... Pull Ups. I would not have spotted that. See attached. Essentially, the test for the bits is now a little more complex (only a tad more).
See attached. I have added 'here' to show the three changes.
So, now.... the bits 4,5,6 are, as Mike says, 0b01110000 which is d112. So, we know we need to examine the state of those three bits. To do this we AND the
eventvalueas the other bits may have generated an event. We test to see if the three bits are High (to match the pullups). Then, we test the bits (I used decimal - you may want to use binary notation).But, Mike was 100% correct... the code is PULLUP, I assume PULLDOWN. But, we do not need to clear RBIF as the Great Cow BASIC handles this for you.
So, have a look at the revised code.
I'm sorry for the late reply. I wanted to make sure I try to have a basic understanding of the parts of the code before continuing.
Here's where I've some little issues:
For the problem where the LCD was constantly moving between 0-9 for consistent increase in temperature form the lm35, I found out that it was the lcdhome command that was causing it. It began to correlate when I took out that command. I also couldn't leave in the "lcdspace 16" command because it just printed spaces and displayed nothing.
I tried to use the 'case 96' which I think represents the ok button (even though I have no idea how it does. The cases weren't declared in the code above so I checked the datasheet to see if they were specific to IOC feature on this chip, still nothing) to call up the sub_save subroutine but I noticed two things:
The string "saved" was always displayed when I clicked the ok button to save (I even removed it from the code to know where it was from and recompiled but it kept on being displayed, maybe it was saved or something).
tempref was always at 20 (I don't know if it was saved at that and refused to change to the new value)
The 'goto main' statement at the end of the sub_save routine doesn't work. The LCD remains at that menu.
I've tried to read up a little on binary and hexadecimal to understand the initialization for portstatus.....Uhmm, little success.
I've also tried fiddling with the code a little more. The code didn't compile so I'll try to attach the gcb file.
Lastly, I'd appreciate any link to understand how to do debouncing to account for double presses.
:-)
Where PortB = all high therefore 255.
255 AND PortStatusreturns 112 as all the bits (that we are interested) are high,So, where bit 4 is pushed low. So, the port would return
239 AND PortStatusreturns 96 as we have one bit low.We can use this method to determine the state of any port.
All that said.... a much easy method to understand may be to use IF-THEN
Do NOT use goto. You are exiting the DO-LOOP. Rethink your use of GOTOs. By doing the GOTO do not reset the eventvalue.
See attached. Works in my SIM.
:-) When I say works... it does the basic. You will have to resolve issues like:
1. Decrementing the value will overflow the variable and you can go from 0 to 65535.... so, you to stop that.
2. LCD needs a tidy up.... a later. :-)
Hello, Anobium.
Thanks for the help so far.
I have been able to implement the circuit in hardware.
My LCD was giving me flickering issues at first but after doing the following, I was able to get a somewhat stable display:
* Adding a 100uf filtering capacitor to the LCD power supply.
* Increasing the LCD speed to "fast".
* Using a separate 7805 regulator for the LCD since it was dropping the PIC's 7805 to 3 plus volts.
After these, the LCD became stable but for the temperature values which were so randomly changing between 150-350 so quickly even when the lm35 is connected.
The lm35 still fails to output the expected temperature. It shares power supply with the pic which is 5 volts although this voltage drops to about 4.8 volts.
The buttons don't bring up the menu except when pressed like two to five times and it's also random.
For the up and down buttons to set a ref temp, it counts up to 65535 or so which seems strange.
Overall, someone suggested I put in a higher frequency crystal oscillator like 6MHz. I'm yet to do that.
Well progress.
Can you post your source? I can look at the code.
Okay, here's it.
Here is your worst problem!
Anobium told you to make the interrupt handler very minimum amount of code. A 200 ms pulse is locking your micro in the interrupt for very long time. do not put the pulse out here.
Okay, thanks.
I probably didn't get that. I was looking for a way to have a buzzer beep for every key press.
It isn't even working yet.
(I first used
'Set A. 1 on'
'wait 200 ms'
'set A. 1 off'
didn't work too.)
What should be the best place to put it the pulseout pls?
Morning,
For a beep look up
TONEin the Help. It does all the heavy work for you.I came across tone but I thought since the buzzer I'm using is an active one that gives out a tone of constant frequency once powered, tone might have problems.
I'll try it out