NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Microcontroller Programming » Problem having button push polling switch modes properly
December 07, 2012 by adosch |
I'm having a slight logical dilemma with some code I am working with to try and make an LED lamp that switches lighting modes (low, bright, fade) with a momentary push button. Right now I'm using infinite loop polling just to rough out the logic, but I can't see past my error. For whatever reason, I'm fighting with the logic that happens on button push to change the mode. I've tried making my 3-bit shifting logic (2^1 was mode-1, 2^2 was mode-2 and 2^3 was mode 3) or by setting 3 directives and just switching between. I'm using an attiny2313; PB2 and PB3 have the two LEDs, and PD6 is where the push-button. Posted below is my simplified logic; I was fooling around to handle the button debounce better, but I've it out for simplicity sake:
|
---|---|
December 07, 2012 by adosch |
... (continued)I should have noted what issues I am experiencing (my apologies). After I write my flash my image to the AVR, mode-1 doesn't show at the brightness at it should that I have set in do_mode1(). Then when I push the button to rotate through the modes, I go straight to mode-3 and it's infinitely suck there, I get no more functionality out of the push-button. |
December 07, 2012 by JimFrederickson |
There are 2 problems that are stopping your program from working how you want it to. 1 - In the function "switch_mode" there is no wrap around back to mode1. (Note the last if statement you are using there...) 2 - you are looking for the "button being pressed", but that is only 1/2 of the event that you are looking for. Since you are NOT looking for the button to be released it just continuously processes a "button being pressed event". What you really want to be doing is to "process a button pressed event" and then you want to "wait for the button release event" before you process the next "button pressed event"... Those are the 2 initial problems that need to be remedied. I don't use the built-in PWM stuff for anything I do, but what you are doing there doesn't look quite right to me... I am also NOT a fan of using the "delay_ms()" function quite so rampantly. Using that function with large values creates "program stutters" and also limits how you should be viewing programs. (Programs should be viewed as a series of conditions, events, and actions...) If you go to the library and look for "Safety double tap routine with pushbutton" that should provide some additional insight. If you want to look at the whole discussion then look at this link: |
December 09, 2012 by adosch |
JimFrederickson, Thanks for the reply. That code block from 33-43 (e.g. switch_mode() ) was a typo; I was initially testing just MODE1 and MODE2 and forgot to change that back when adding my source code out here. So yes, I did have a wrap back to MODE1. As for the PWM portions, it looks pretty good to me from the datasheet point of view on how to setup and use. Raising and lowering values from OCR[10]A to adjust the forward voltage over the LED to adjust the 'brightness' level works well. I did find my problem, which is exactly what you described as 'stuttering' --- when I isolated my modes to static ORC[01]A values only (not using that loop business in do_mode3() ) in all three modes, I saw it. Only when I decided to take that PWM loop-over I was doing did I finally figure out what was happening; it was very unstable and jerky when trying to find that button switch while polling. After reading through that 'double tap discussion', I drew a personal conclusion that polling is quite the hack for button press-down/up; I spent that latter half of the afternoon trying to work polling logic and I found it much easier to set an external interrupt request on INT0 (PD2) and look for the rising/falling edge from that pin change (as opposed to using PCINT and not having that functionality). The actual switching between my LED 'brightness' modes isn't as 'smooth' as I want to, but it's MUCH improved now using an interrupt. It seems I have to have the button pressed in for ~0.5-1sec to get it to be smooth change from mode to mode. I'll work on that. Below is a snip from my new code I have now:
...my question is: Is there anything I should be doing in that infinite while() loop now that I'm ? I guess is that the 'the way' you do it? It would seem to me that's just adding extra cycle overhead spinning that loop just to keep from breaking out of main()? |
December 10, 2012 by JimFrederickson |
When you ask "Is there anything I should be doing in that infinite while() loop", you are doing something something "you are waiting for something that needs to be processed". Waiting for something that needs to be processed is not "adding extra cycle overhead". It is simply "waiting". The Microcontroller is processing millions of instructions per second. What seems like a "single event to you" will often look much different when it's broken into slices of 1,000, 100,000, or even millions. Anything that you process with your Microcontroller code that is able to be perceived by you in realtime, will need/benefit from some form of "timing" and/or "scaling". Anytime that something is "timed" or "scaled" then there will be some "waiting around in the code for something that needs to be processed". I think that your "smoothness issue" only has 3 possibilities: (Assuming that you are not employing some sort of hardware debounce or validation.) 1 - you are not processing the "key press event" properly. Just recognizing an "interrupt" as a "key press event", if that is what you are doing, will not by itself work. (Part of the the discussion in the thread I had pointed you was about "debouncing"/"validation" this could be affecting your results.) 2 - you are processing a "key press event" too quickly. Sometimes changing something immediately when detected is not going to work. 3 - There is a problem with the PWM that you are using, or the choices being used for each of your modes. (Maybe a hardware problem, but I think that is least likely since it seems to be working at all.) I think 1 or 2 are the mostly likely problems. If you are going to use a "key press event", ("button presses"), to select a mode for your PWM then you will need to consider what constitutes a "key press event" and a "key release event". ("timing".) Or If you don't want to think about a "key release event" then you will need to consider how long a "key press event" has to be constant before it is determined to be another "key press event". ("timing".) Sometimes, like in controlling brightness for an LED using PWM, a 50% on duty cycle is not really perceived as being 50% of the brightness. (A similar issue can occur with RGB LEDs when mixing to achieve certain colors...) So it may be your PWM choices need to be altered a bit. ("scaling".) Any "scaling" that you use would likely need to be determined by trial and error, and what looks good to you. |
December 10, 2012 by JimFrederickson |
Another thing to consider is the "extra cycles that you are using for your while() Loop" means that there are more things that you can do. For your current program there is only 1 thing that you are doing in your while() Loop, but that doesn't have to be the case. In future programs there may be more things that you will want to do and they all/each can be added into the loop and processed at the appropriate time. Programming a project with your Microcontroller can often become a matter of "managing constraints". (As with anything really...) Your Micrcontroller has 4 main resources that will "constrain" in various ways what you can do: If any program you create uses up any of those resources in their entirety then you have reached the limit of what you can do with your Microcontroller. (There are "other constraints" too, but I think those are more subordinate to these.) In order to do more you would then need to "free-up" one or more of these resources in order to be able to do that. Maybe you can be "more efficient" or maybe you will need to add additional "hardware". None-the-less there is a WHOLE LOT you can do with these chips and they are great for a variety of useful things in addition to learning. Good Luck... |
Please log in to post a reply.
Did you know that a piezoelectric buzzer can be used to play music with your microcontroller? Learn more...
|