Unexpected result
Zeus
Posts: 79
Hello All,
I am having a problem with my program after changing some of my inputs. In short I switched the input button from one side of the stamp the other in order to simplify the physical layout of the circuit. I made what I thought would be the simple necessary changes to the program and assumed that I would be fine, this is not the case. Here is what happened. My button inputs were IN10, IN12, IN13, IN14 & IN15. They are now IN0, IN1, IN2 & IN3.
When I send the values to the DEBUG window they display the correct values as expexted however the program does not behave accordingly. When IN0 should increase the "Menu" value it decreases it and when IN1 should decrease the "Menu" value it increases.
IN2 & IN3 have no effect at all on the respective values.
What am I missing? Is this me not understanding the Select Case statement or something else entirely?
Any input you can offer is appreciated.
Thanks,
Zeus
I am having a problem with my program after changing some of my inputs. In short I switched the input button from one side of the stamp the other in order to simplify the physical layout of the circuit. I made what I thought would be the simple necessary changes to the program and assumed that I would be fine, this is not the case. Here is what happened. My button inputs were IN10, IN12, IN13, IN14 & IN15. They are now IN0, IN1, IN2 & IN3.
When I send the values to the DEBUG window they display the correct values as expexted however the program does not behave accordingly. When IN0 should increase the "Menu" value it decreases it and when IN1 should decrease the "Menu" value it increases.
IN2 & IN3 have no effect at all on the respective values.
What am I missing? Is this me not understanding the Select Case statement or something else entirely?
Any input you can offer is appreciated.
Thanks,
Zeus
Buttons_Sub: ' Start of Sub Routine. ' Menu Number Buttons Block IF (IN0 = 0) AND (IN1 = 0) THEN ' Start of "If" statement which adresses both buttons being presses. MenuNum = 0 ' If above statement is true "MenuNum" is set equal to zero. ELSEIF (IN0 = 0) THEN ' Begining of "If" Statement which adds 1 from "MenuNum" variable. MenuNum = MenuNum + 1 ' If above condition is true, adds 1 from "MenuNum" variable. ELSEIF (IN1 = 0) THEN ' Begining of "If" Statement which subtracts 1 from "MenuNum" variable. MenuNum = MenuNum - 1 ' If above condition is true, subtracts 1 from "MenuNum" variable. ENDIF ' End of "IF" statement. ' Alarm Hours Buttons Block IF (MenuNum = 0) THEN SELECT INA & 3 ' Start of "Select Case" statement, possibilities are 00, 01, 10 and 11. CASE = 0 ' Case 3, both buttons pressed... Reset AlmHrs = 6 ' If both buttons are pressed alarm hours set TO 6 Am. AlarmAmPm = 0 AlmMins = 0 AlarmAmPm = 0 SnzMins = 0 ' Resets snooze minutes to zero when alarm is switched off. SnzHrs = 0 ' Resets snooze hour to zero when alarm is switched off. CASE = 1 ' Case 1, one button is pressed... advance 1. AlmHrs = AlmHrs + 1 SnzMins = 0 ' Resets snooze minutes to zero when alarm is switched off. SnzHrs = 0 ' Resets snooze hour to zero when alarm is switched off. IF AlmHrs > 12 THEN AlmHrs = (AlmHrs - 12) ' Starts variable counting over at "12" if value is less than "1". CASE = 2 ' Case 2, other button is pressed... subtract 1. AlmHrs = AlmHrs - 1 SnzMins = 0 ' Resets snooze minutes to zero when alarm is switched off. SnzHrs = 0 ' Resets snooze hour to zero when alarm is switched off. IF AlmHrs < 1 THEN AlmHrs = 12 ' Starts variable counting over at "1" if value is greater than "12". ENDSELECT ENDIF ' Alarm Minutes Buttons Block IF (MenuNum = 1) THEN SELECT INA & 3 ' Possibilities are 00, 01, 10 and 11. CASE = 0 AlmMins = 0 ' Reset to Zero CASE = 1 AlmMins = AlmMins + 1 // 60 ' Count up mod 60 using // operator SnzMins = 0 ' Resets snooze minutes to zero when alarm is switched off. SnzHrs = 0 ' Resets snooze hour to zero when alarm is switched off. IF AlmMins//10 = 0 THEN FREQOUT Speaker, 100, 2000 PAUSE 1 ENDIF CASE = 2 AlmMins = AlmMins - 1 MAX 59 ' Count down mod 60, return to 59 when value becomes 255 SnzMins = 0 ' Resets snooze minutes to zero when alarm is switched off. SnzHrs = 0 ' Resets snooze hour to zero when alarm is switched off. IF ((AlmMins - 10)//10 = 0) THEN FREQOUT Speaker, 100, 2000 PAUSE 1 ENDIF ENDSELECT ENDIF ' Am/Pm Buttons Block ' MAY BE ABLE TO SIMPLIFY THIS CODE AS EITHER CASE TOGGLES AM/PM FLAG. IF (MenuNum = 2) THEN SELECT INA & 3 ' Possibilities are 00, 01, and 10. CASE = 0 DEBUG CRSRXY, 0, 2, "Test" CASE = 1 AlarmAmPm = AlarmAmPm + 1 MAX 1 ' Alarm set to "PM" mode. AlmAmPmFlag = 0 ' Flips Alarm Am/Pm indicator "AlmAmPmFlag" to alternate "AM" state. CASE = 2 AlarmAmPm = AlarmAmPm - 1 MAX 0 ' Alarm set to "AM" mode. AlmAmPmFlag = 1 ' Flips Alarm Am/Pm indicator "AlmAmPmFlag" to alternate "PM" state. ENDSELECT ENDIF
Comments
All of the SELECT/CASE statements mask at bits 0 and 1; INA & %0011. I do not see where bits 2 and 3 (IN2 and IN3) are being used.
Mike - The circuit is wired Active Low and was previously when it was operating correctly.
Stephen - All that I can say is that my program worked perfectly before I reassigned my button input inputs, given this I have not looked into the equal signs being the source of the problem.
Zeus
Yes I am, how did you know? Is this contrubuting to my problem?
Also - Mike G I missed the last part of your post... IN2 & IN3 were increasing and decreasing the value(s) accordingly.
Zeus
You say IN2 and IN3 should increase or decrease the "values", if that is the case you need to modify the Select Case conditions.
I am assuming here that IN0 and IN1 are the menu selection bits and that bits IN2 and IN3 adjust the alarm, unless there is some code you have not shown us.
You are correct. IN0 & IN1 scroll up and down through the alarm clock menu. IN2 & IN3 scroll up and down respectively allowing the user to set the alarm time.
I have been looking to a good Select Case reference for some time. My code used to work well but I adjusted the inputs and now it doesn't function at all so clearly I do not understand how Select Case statement work, and for that matter "INA/INA & #".
How do 12, 4 and 8 influence the Select Case statement?
Thanks,
Zeus
P.S. - Your changes helped and it is functional again, however I am still dealing with an issue where the up button decreases the value and the down button increases the value. While I realize that I could just edit the code and patch this my real concern is that I am still missing the fundamental concept(s).
Both instructions look for a certain condition so they are classed as conditional instructions, the condition they look for is usually the value of a variable.
So using IF THEN the first thing to do is specify which variable you are looking at
The SELECT instruction goes along the same lines, first specify the variable to watch for
The next part of both these instructions is to compare Myvar with some other value and to see if the comparison is true.
Using SELECT
The condition you are looking for would be Myvar is not equal to 1, this condition can only be true or false.
Additional conditions can be added to both instructions, the instructions are completed with an END IF and an END SELECT respectively.
The above code samples are examples and the syntax may not be right but the principal is the same for all forms of basic.
I think your usage of SELECT CASE is fine I think that using the INS register and masking binary values are probably where things might seem to get confusing, don't worry this is confusing for everyone to begin with.
As for 12 8 and 4 look at what happens to P0 P1 P2 and P3 when a button is pressed and Google binary.
Press button 1 = 0001 = 1 decimal
Press button 2 = 0010 = 2 decimal
Press button 1 & 2 = 0011 = 3 decimal
Press button 3 = 0100 = 4 decimal
Press button 1 & 3 = 0101 = 5 decimal
Press button 2 & 3 = 0110 = 6 decimal
Press button 1 & 2 & 3 = 0111 = 7 decimal
Press button 4 = 1000 = 8 decimal
Press button 1 & 4 = 1001 = 9 decimal
Press button 2 & 4 = 1010 = 10 decimal
Press button 1 & 2 & 4 = 1011 = 11 decimal
Press button 3 & 4 = 1100 = 12 decimal
Press button 1 & 3 & 4 = 1101 = 13 decimal
Press button 2 & 3 & 4 = 1110 = 14 decimal
Press button 1 & 2 & 3 & 4 = 1100 = 15 decimal
Thank you very much for your detailed explanation. I have printed it out and will try to implement the changes tonight.One thing that still confuses me is that if I send the button state to the Debug widow the appropriate button registers low when pressed. The disconnect for me is that this very input somehow has become inverted program wise. By this I mean this low should drive the program to increase the value but instead it is decreased, could this be caused by the INS registry statement somehow.
Zeus
The INS instruction will work the same whether active low or active high.
Should not:
Press button 1 & 2 & 3 & 4 = 1100 = 15 decimal
really read:
Press button 1 & 2 & 3 & 4 = 1111 = 15 decimal
Dave
Mechanical switches tend to "bounce" when going from one state to another, this has the effect of producing several pulses from just one button press. Its normal practice to code a small timer that ensures the microcontroller sees only one pulse for one press of the button, the timer is usually called a "debounce timer".
The sequence might look like this
If button is pressed then
pause 25mS and let the bounce settle
If button is still pressed then
produce one pulse
Its also practically impossible to press more than one switch at exactly the same time so depending how its coded this may also need a debounce timer.
To detect the press of two buttons it might go something like the following. I give the example using active low as this is how it should be if using the Stamp PDB. When writing the values of INA in your code you can use decimal notation (e.g. 9) or binary (e.g. %1001), which ever is your preference.
With no buttons pressed INA will contain all 1's %1111 which is decimal 15, the initial check does not look for a specific value it only checks to see if INA is less than 15, pressing any button will drop the value of INA below 15.
If INA < %1111 then a button is pressed
pause 25mS to let the switches settle
SELECT INA
CASE INA=x
CASE INA=y
etc etc
the SELECT CASE is where we look for a value which will indicate which buttons have been pressed, for example if buttons 1 and 4 are pressed INA will contain %0110 a decimal value of 6
I think I understand what you two are driving at however I cannot explain the code below delivering an inverse result? I am lost here.
The above does not employ a select case statement however it exhibits the same inverse behavior just as the select case statements do elsewhere in the code.
What have I missed? All that I changed was to switch IN12, IN13, IN14 and IN15 over to IN2, IN3, IN0 and IN1 respectively, and then adjusted my code accordingly. There has to be something else going on here.
Thanks,
Zeus
Stamp PDB with 4 buttons active low
Button1 connected to P0
Button2 connected to P1
Button3 connected to P2
Button4 connected to P3
Button1 and Button2 = menu selection
Button3 and button4 = alarm adjustment
If there are only three possible menu numbers and you want to use Button1 and Button2 for selection you might want to code your menu selection differently.
I mentioned debouncing and multiple pulses, I have not seen your complete program code but looking at the menu selection adding and subtracting in this way can give MenuNum unwanted values.
Try this, it ensures MenuNum gets a predetermined value. Debounce the switches before you enter the following block
Truth table for the first IF block
Let's assume both IN0 and IN1 are low (Pressed). The first IF block is invoked, (MenuNum = 0). It is highly likely that both buttons are still pressed when execution leaves the first IF. INA is logically ANDed with 3; INA & %0011. Since INA equals XX00, the first CASE branch is executed. It seems to me that you would have to push or release a button perfectly when execution moves from the first IF block to the next.
My code was working and I reconfigured my inputs, what I thought would be a simple matter of straight forward substitutions and now I am completely without any bearing.
My code below was working...
It is now...
IN14 is now IN0
IN15 is now IN1
IN12 is now IN2
IN13 is now IN3
I do not have a good understanding of "INS" statements despite Mike G and Unsoundcode's best efforts, and I am convinced that this is the root of my problem.
In short my code now produces then inverse menu value, up is down and down is up, and I am no longer able to change the alarm time values at all, again everything was working with my old code, no inversion of inputs at all.
When I send the current state to the debug window everything checks out and goes low as expected, the code however ultimately produces the inverse result.
Completely confused.
Zeus
I would think this would make more sense.
I don't care so much about the order at this point, my real concern is understanding why my substitution is not working. Does the substitution have to ascend just as it did in the original code in order for the INS statement and/or Select Case statement to work properly? And how does this affect my initial Menu "If Then" statement?
Zeus
IND is PIN 15, 14, 13, and 12
INA is PIN 03, 02, 01, and 00
IND & 3 means - I only want to deal with PIN 13 and 12
INA & 3 means - I only want to deal with PIN 01 and 00
Take some time to experiment with the INS register outside of your project. This might help your understanding.
Thank you for explaining that. I had thought that that was how it worked early on but where I had multiple "INx & 3" statements I think buttons were getting locked out and then I presumed that my understanding was incorrect. (Knowing that the order is critical is important as well.) I will have to experiment a bit to fully understand it but I think that I am headed in the right direction now. I will let everyone know how I make out.
Thank you very much for your persistence and patience.
Zeus
Still no luck. All four inputs are still delivering the inverse results. When I send the current state of each button to the Debug window the all behave as expected (0), however the program produces the opposite result. As a test I stripped everything out of the button sub and just focused in the initial Menu "If Then" statement as this does not employ a "Select Case" statement just to limit the variables, variables in the scientific testing sense, and despite the fact that the menu value increased by one in the Debug window it still decreased by one on the clock. I am convinced that I have a "Select Case" problem as well but it is clear that there is something bigger going on. Hopefully someone can help me spot what I am missing. I have included a portion of the code below.
Thanks,
Zeus
Also the button input should be debouced.
Here you go. The schematic is borrowed from Chris Savage's alarm clock project so I do not use some of the ICs, but regardless this is the schematic that I based my alarm clock off of.
I agree that the debounce statement would be nice, however I am holding off for now on adding it for now for two reasons.One, before I changed my inputs the code worked without a debounce and more importantly, as you will see in the attachment, I am running out of code space.
Thanks again,
Zeus
Modified Digital Alarm Clock - New Pin Layout - 7.8.12.bs2Schematic Small.bmp
Here's a simple button debouce example that reads all 4 buttons connected to INA - at one time - and places the result in buttons. Use this script to debug your wiring. It can also be used to optimize your alarm clock code.
I have confirmed that the button inputs are wired correctly physically as well as separate two ways via the Debug window. There is something strange going on as the menu value is indexing correctly however the menu selection that is actually displayed on the LCD is indexed in the opposite direction from what the numeric menu value is actually instructing it to do. I also seem to have some cross talk going on where the menu buttons are now affecting the alarm values.
Regardless, thank you for sticking with it. If I ever get it figured out I will post the solution.
Zeus