I have for example this code on my function on my nodemcu:
mytimer = tmr.create()
mytimer:register(5000, tmr.ALARM_SINGLE, function() digitalWrite(16, HIGH) end)
But, before 5 seconds, I want delete this timer with another function, because if I want (before 5 seconds) launch a function like:
digitalWrite(16, LOW)
If I don't delete timers, it toggle state of led.
So, how can I delete certain timer?
You could either call mytimer:stop() or mytimer:unregister() depending on whether you want to restart it later on or not.
UPDATE: Just showing this picture to proof the working example:
Hint: make sure the mytimer variable is accessible from within the other function.
Please also have a look at the timer documentation before posting a question.
Related
I wrote a code for determining the push button state wheather it's long pressed or not. By the way this function is called by a timer interrupt routine in every 1 ms.
If you pressed more than 1 second, LongPressed is active ShortPressed is passive .so vice versa.
1- But it seems really dummy how can I make it shorter and more efficient according to both readibilty and professional rules?
BTW I updated the code like below.
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/*button pressed and count*/
if(!HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13))
{
usTick++;
}
/*not pressed*/
else
{
if( usTick > 1000){
ButtonState.PressedState = LongPressed;
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
usTick = 0;
}
else if( usTick >350){
ButtonState.PressedState = ShortPressed;
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
usTick = 0;
}
usTick = 0;
}
}
2- What should I add or change to get double Tap pressing information in this updated code?
Almost every STM32 timer has "external trigger synchronization" function. You can read about it in timer functional description in reference manual. You can use "Slave mode: Trigger mode" to start counting on "button down" event. And in EXTI interrupt of "button up event" you can read timer counter and do your business.
I don't know how to implement this via HAL, but Standard Peripheral Library should have the example.
1) Your code is only able to handle 1 button. Make it object oriented to read n buttons.
1 ms is much too fast. 20 ms should work fine. Remember: humans are slow.
2) I once had spent some time creating a LED controller with two pushbutton rotary encoders. These would feature advanced programming methods by means of pushing them long or multiple times. You could use the result of my sparring (it was never completed) as inspiration. The button code is fairly complex, it should fulfill your needs. And I remember it to be functional.
https://github.com/Jeroen6/LED-Rotary-Dimmer-SW/blob/master/user/button.c
https://github.com/Jeroen6/LED-Rotary-Dimmer-SW/blob/master/user/button.h
Forgive me for not having the indentations worked out correctly.
Arduino Nano and I need a timer within a timer and having some problems getting my head around the logic. I have played with some Libraries on GitHub, Timer, SimpleTimer and Metro but none seem to do what I need. Or, if they can I can't seem to get them to do it.
I need to switch a relay on for about 2-minutes and then off, every hour. I am trying
loop
{ if (millis() - 3600000 > TimeMax)
{ relay(on);
if (millis() - 12000 > relayMax)
TimeMax = millis();
}
}
It doesn't seem to work and I need this to all stay working within the "loop" as I have an nRF24L radio listening.
Could someone please help me with code snippets or at least an outline how to go about this.
Thanks
Ok, first of all timers in embedded dev speak means interrupts that gets fired after a delay. Generally speaking you want interrupts to handle very atomic actions, because you don't want to have an interrupt triggered while another one is triggered, because that could be the scenario of a horror movie.
But why would you want to make something hard, complex and overengineered, when it can be simple?
All you need to do is handle it through a simple dual state machine:
#define OPEN_DELAY 120*1000
#define CLOSE_DELAY 3600*1000
// N.B.: to be precise here, to make 2 minutes every hour,
// CLOSE_DELAY should be 3600*1000-OPEN_DELAY so it
// does not shift by 2 minutes every hour.
void loop() {
static bool open=false;
static long timestamp = millis();
if (!open && millis()-timestamp > CLOSE_DELAY) {
open=true; // change state
timestamp = millis(); // rearm timestamp
set_relay_on();
} else if (open && millis()-timestamp > OPEN_DELAY) {
open=false;
timestamp = millis();
set_relay_off();
}
}
The only reason you might want to use timer would be to save battery by keeping the AVR in sleep mode as much as possible. Then you'd set the timer to the biggest possible value before putting it to sleep, making it wake up the AVR with an interrupt every few seconds or so, so then you run the loop() once in CLOSE state going back to sleep — there you don't need to write an ISR, the main loop() is enough, or keeping it up for the full two minutes in OPEN state.
There's good documentation on timers you might want to read (beware the headaches, though):
http://maxembedded.com/2011/06/introduction-to-avr-timers/
Here's how to put the arduino to sleep for long delays:
http://www.bot-thoughts.com/2013/11/avr-watchdog-as-sleep-delay.html
HTH
I'am currently working on tinyos and I Am trying to reset timer
lets say to 2 seconds when it is running at 45 seconds
but it is not working, i can't figure out why,
can someone help me figure it out
here is the code:
printf("timer before resetting it %ld",call Timer1.getNow());
offset = ((TimeMote_t*) payload)->tdata;
call Timer1.startPeriodic(offset);
printf("timer after resetting it %ld",call Timer1.getNow());
now actually it should have reset the timer to offset but it's not resetting it.
both printf statements are giving the same time.
No, it shouldn't. Timer.getNow() returns absolute time, which can't be changed or reset. Timer interface can be used to schedule events at a particular moment in the future. Timer.startPeriodic(offset) starts the timer, meaning that the event Timer.fired() will be signaled in the future. In this particular example, the event will be signaled offset units from the call to Timer.startPeriodic and then repeated every offset units infinitely or until call to Timer.stop(). Return value of Timer.getNow() doesn't change and increases monotonically regardless of whether the timer is started or not.
See: Interface: tos.lib.timer.Timer
So I have a couple instances where I want to be able to 'freeze' the state of my game. It's a top-down scroller, and I want to give the player the ability to pause the scrolling of the screen for a short time by using a powerup (if you fall to the bottom of the screen you die). I also want to pause the game as it is starting, and draw a 3, 2, 1, go! to give the player time to get ready, because right now as soon as you hit play, the screen starts scrolling.
I have been using Timer to accomplish this, however it doesn't work if I want to freeze the screen on consecutive occasions. Like if a player uses a freeze, the screen sucesssfully freezes, but if they quickly use another freeze, it doesn't work. There seems to be an unintended cool-down. I have a similar problem for the 'intro delay' I explained earlier. For some reason it only works on the first 2 levels. Here is how I am using Timer.
if(gameState != STATE.frozen) {
camera.translate(0, (float) scrollSpeed);
staminaBar.setPosition(staminaBar.getX(), (float) (staminaBar.getY()+scrollSpeed));
staminaMeter.setPosition(staminaMeter.getX(), (float) (staminaMeter.getY()+scrollSpeed));
healthBar.setPosition(healthBar.getX(), (float) (healthBar.getY()+scrollSpeed));
healthMeter.setPosition(healthBar.getX(), (float) (healthMeter.getY()+scrollSpeed));
boostBar.setPosition(boostBar.getX(), (float) (boostBar.getY()+scrollSpeed));
boostMeter.setPosition(boostMeter.getX(), (float) (boostMeter.getY()+scrollSpeed));
screenCeiling += (float) scrollSpeed;
screenFloor += (float) scrollSpeed;
}
else {
Timer.schedule(new Task() { //freeze the screen for 5 seconds
#Override
public void run() {
gameState = STATE.playing;
}
}, 5);
}
From what I understand, it waits 5 second before resuming the game to the 'playing' state. But like I said, this only works when activated between large intervals and I don't know why. Is there a better way I can be doing this?
As for the intro delay, this may be a question better asked seperate, but I use the same method, but it doesn't let me draw sprites over my tiledmap, so if anyone knows how to do that please include it in your response
Assuming the code you posted is in your render loop, then whenever you are not in the frozen state, you are creating a new timer task on every frame. So if you freeze for 5 seconds and your game is running at 60fps, you will create 300 timer tasks, each of which is going to force the game to go back to playing state. The last one won't fire until 5 seconds after the first one fires, so there will be a five second "cooldown" during which you cannot change the state to anything besides playing, because there will be another timer task firing on every frame during that time.
You need to ensure that you only create one timer task, only when you first enter frozen state.
I do have a suggestion...instead of using a state to freeze the game, use a variable that's multiplied by scrollSpeed. Change that variable from one to zero when the player uses the powerup. Then you can do fancy stuff like quickly interpolating from one to zero so the speed change isn't so abrupt. And it will probably make your code simpler since there would be one less state that must be handled differently in the algorithm.
Check your gameState variable in the render method and if the game is playing, then update the game as usual and draw it.
If the game is not playing then skip the game's update method and create a time delay from the current time:
endTime = TimeUtils.millis()+5000;
Then each time through the render method check to see if current time is greater than the end time. When the current time is past your delay time, set gameState back to playing and have the game go back to updating.
You'll have to have another boolean flag so you only set the endTime once (you don't want to keep resetting this each time through the render loop), or if "STATE" is an enum, then include an option for "justPaused" for the exact frame that you pause the game, set the end time, then set STATE to "notPlaying".
You can also use this to create an alternative "update" method where you can update your countdown sprites, but not update the game itself. When the game is playing this other update method will be skipped.
In my project, I have three buttons where each triggers a function.
This function have to do two things, one action when the button is pressed (actually working), but I want to add a second functionality, in which if the button is pressed for more then 3 seconds, it do something, like calling a function.
So far, i'm initializing the interruption:
attachInterrupt(0, footOne, Falling);
and the function is:
void footOne(){
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
// Debounce
if (interrupt_time - last_interrupt_time > 200){
//Do things
if(debug==1){Serial.println("Button 1 pressed!");}
}
last_interrupt_time = interrupt_time;
}
Now I want to know how I can change the function to add the possibility if the button is pressed for longer then 3 seconds...
Remembering that this function is called from the interrupts.
Thank you!
With the way you have your program structured right now, you would need an external RTC to carry out this task. Once you initiate an interrupt, the internal clock on the arduino is compromised and therefore cannot be used reliably until leaving the interrupt. Is your implementation so time sensitive that an interrupt is required? Because if it isn't, polling the state of the button and then comparing the time elapsed would be a pretty easy implementation. If you want to stick with interrupts however, I'd take a look at volatile variables as a way to talk between your main loop and your interrupt functions.