Pages: [1] 2   Go Down
Author Topic: How to create a function dynamicaly ?  (Read 1229 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all !

I am doing a home automation project controlled with an android smartphone.

The issue is that I want do an scheduler to program things to turn on/off at any time that I want to. Ok, it is not hard to do when done hard coded (what I have been done).

The problems starts when I try to do it  dynamically.

I need that arduino creates an alarm (I am using the TimeAlarms library) function whenever it gets the parameters through the enthernet shield.

The question is, is possible to arduino creates functions dynamically on loop ?
Logged

Offline Offline
Edison Member
*
Karma: 33
Posts: 1435
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You cannot "create" functions dynamically, but you can do several things:
Create a bunch of functions and set a different ISR dynamically.
Use a switch/case statement to call a particular function based on some criteria.
Use function pointers to change which function gets called at a particular time.
Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From your description I would think that you just need to call an existing function with varying parameters, getting those parameters from the network. If so, there are many ways to do that but the simplest one is probably to define each parameter as a global variable and assign it a default value (so the program will not break if the variable is not set).

Then use the network connection to get the parameters, using for example a name:value format (e.g. alarm-duration:10), adding start and stop delimiters for further safety (e.g. <alarm-duration:10>). Decide whether the Arduino will request the parameters or just wait for them to arrive.

There is a limit on how far you can go with this method (changing the order of operations will be difficult) but it may cover a great deal of the use cases you have in mind. If not, please be more specific on what you need.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
From your description I would think that you just need to call an existing function with varying parameters, getting those parameters from the network. If so, there are many ways to do that but the simplest one is probably to define each parameter as a global variable and assign it a default value (so the program will not break if the variable is not set).

Yes, you are right spatula, it is what I am doing.

Quote
Then use the network connection to get the parameters, using for example a name:value format (e.g. alarm-duration:10), adding start and stop delimiters for further safety (e.g. <alarm-duration:10>). Decide whether the Arduino will request the parameters or just wait for them to arrive.

And yes again, you read my mind. I am using start and stop delimiters (<,>), it is already working to do other functions, but the problem is not how to get the parameters because I already did it, I need to find out a way to create alarms based on parameters sent from android's app.

I will explain exactly what I need.

I have created an android app to control my home automation system, in this app there is an option to program things to turn on/off at any date/time I want, but I have a lot of things in my house that I can turn on/off, and I want to do something in the arduino that enables me to turn on/off only one or all things that I want to.

I can't think how I can do that at the arduino side.

As I said ,I am using the TimeAlarms library and there is one thing that I do not know but I would like to. For example, if i call a function that calls the function "Alarm.alarmRepeat(20,02,00, MorningAlarm);" when I pass some parameters,  and then calls the function again  "Alarm.alarmRepeat(6,00,00, MorningAlarm);" when I pass another parameters, the function will create two different alarms or one overwrites the other ?

If every time I call the alarm function, one alarm is created, so I think it will be less hard, because I will need only one function to create all the alarms, but I will still need to send back to android the ID of each alarm that was created, case I want to cancel one of them.

If I am right, the difficult part will be to say to arduino what thing I want to turn on/off with only one function to do this considering that I have a lot of things that can be on or off.

That's why i asked about creating functions dynamically, if it were possible would be easy to do all that stuff, the program would create as many functions as I  would want to.

Any ideas ??
Logged

0
Offline Offline
Sr. Member
****
Karma: 8
Posts: 291
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're thinking of what I'm working on right now. I'm creating a device class with a timer method in it. Ever time I want to add a new device, I create a new instance of the device with new parameters etc..
In your case, you would add a new instance of a timed event.

I found this project that might help you out
http://code.google.com/p/ebl-arduino/wiki/RTCTimedEvent
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for replying mistergreen, but I think that the RTCTimedEvent library do the same thing as TimeAlarms library.

With TimeAlarms I can create a new instance of a timed event every time I need, but the problem is how to know what alarms is enabled or not and how to pass the parameters to turn one thing on or off.

Let's say that I can create an alarm through a function that only creates the alarms and two other (turn on and turn off functions).

Now I send a parameter that says to arduino call the function that creates the alarm event to turn on my bedroom's lamp.

When the time that I passed as parameter to arduino is reached the alarm event will be triggered, this alarm will call one of the two functions (turn on or off), turn on function in this case, now that comes my problem., how can I do a function that will only turn on the lamp of my room ?  I think I have to create an ID for every thing I want to control and associate to an arduino's pin, Is there any other better way of doing that ?
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 54
Posts: 1847
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you really need to study the blink without delay example sketch.  What you want to do is for each object, maintain a unsigned long timestamp of when it wants to fire and do whatever action.  You set this timestamp up to be the current time + the timeout time.  Then in the loop function, you go through each object, and see whether it is time to do that action, using the millis() function to return the current time in milliseconds.  If it isn't time to do the action, you just skip over it.  If it is, you reset the timestamp, and call the appropriate function.  This way you are only using one function, and can handle multiple objects.  If you expect your program to run over 56 hours or so, you will need to handle when the millis() rolls over.

As a matter of general programming, you don't want to do complex stuff in an interrupt handler.  You typically want to set a volatile global variable to say the interrupt has occurred, and then in loop process the interrupt.  On AVR systems, you typically would want this flag to be unsigned char, while on Arm systems, int might be more appropriate (you want the type to be a type that the machine uses a single store/load instruction for).
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4802
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you really need to study the blink without delay example sketch.  What you want to do is for each object, maintain a unsigned long timestamp of when it wants to fire and do whatever action.  You set this timestamp up to be the current time + the timeout time.

That will lead to messy code that at best cuts the maximum interval by half.

Why is because you don't always catch (millis() == timestamp).
If you use (millis() >= timestamp) then rollover presents problems that require work and at best cuts the interval in half.
I have worked this out the hard way twice, don't say no until you have a working example that uses timestamp and allows the full interval or is not messy using 1/2 interval. Sure, it can be done but messy (and slower) code with 1/2 interval.

What does work clean is to use 2 unsigned longs to do the unsigned rollover-tolerant math.
If the interval does not vary then you can store just the start time, otherwise store both.

Code:
if (millis() - start >= interval) // time is up!

=====================================================

With C++ you can write a class and overload the function to run with different args. The compiler will choose the one that matches or give you an error.
Of course you can make an example where that doesn't help but C++ wouldn't be much good if you couldn't!
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for replying MichaelMeissner, but have you ever seen the TimeAlarms library ?

The TimeAlarms library do all the complex stuff for me, I just need to create a task to make an event trigger when I want like this, Alarm.alarmRepeat(6,00,00, MorningAlarm). This would call the function MorningAlarm()  at 6:00 am every day.

I just need to know, how I can do the arduino identify what thing I want to control when I send the parameters through the android app, because when the clock reaches 6:00 am  the arduino goes into the MorningAlarm function, then it will need to know what thing it will toggle to on or off.

void MorningAlarm()
{
  digitalWrite(something, HIGH or LOW);
}

But what thing ? Can you understand me now ?
Logged

Ayer, Massachusetts, USA
Offline Offline
Edison Member
*
Karma: 54
Posts: 1847
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for replying MichaelMeissner, but have you ever seen the TimeAlarms library ?

The TimeAlarms library do all the complex stuff for me, I just need to create a task to make an event trigger when I want like this, Alarm.alarmRepeat(6,00,00, MorningAlarm). This would call the function MorningAlarm()  at 6:00 am every day.

I just need to know, how I can do the arduino identify what thing I want to control when I send the parameters through the android app, because when the clock reaches 6:00 am  the arduino goes into the MorningAlarm function, then it will need to know what thing it will toggle to on or off.

void MorningAlarm()
{
  digitalWrite(something, HIGH or LOW);
}

But what thing ? Can you understand me now ?
I could understand you before, but what is clear to me, is obviously opaque to you.  What I'm saying is you have one single function that is called from TimeAlarm.  That function has a list of all possible objects, and it goes through and sees whether it is time to do something or not.  I would do this as a class that implements a linked list with next/previous pointers, a timestamp, and then a virtual function to call to do the actual item.  Inside that function, you look to see whether you might do a DigitalWrite HIGH or LOW.  The begin function for the class would link it into the list of objects to test, and possibly an end function to remove it from a list.

Unfortunately, I don't know of a simple way to convey the stuff usually covered in a Data Structures 101 class to people who are not programmers.  Things like this take time, and often a human teacher with interaction.  It has been my experience, that a few people never seem to make the leap to be able to think of things abstractly, but for most people, it just takes time and amount of work until the aha moment comes (and sometimes people give up before the insight comes).  There is no simple silver bullet to instantly learn to think like a programmer.

I do stand by my assertion that you don't want to do complex things inside of interrupt handlers.  99.999% it may work correctly, but eventually you may hit the interrupt at just the wrong time, and a complex function may not be able to run correctly.
« Last Edit: March 20, 2013, 08:23:45 am by MichaelMeissner » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 610
Posts: 49077
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But what thing ? Can you understand me now ?
No. If you don't know what to do, how can you expect us to help you?

Perhaps you should explain WHAT the android is sending.
Logged

0
Offline Offline
Sr. Member
****
Karma: 8
Posts: 291
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you'll need write your own library. No, you can't dynamically write function but what you want to do is possible.

You'd want a class where to can pass in timed events and info of other devices you want to control, maybe an array of pins or object of devices.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks a lot mistergreen, you'd understand me !

I have thought in creating a library to do that stuff, but I have never did any library yet, so I think I will have to learn that.

Do you know some site or book that can teach it to me ?
Logged

0
Offline Offline
Sr. Member
****
Karma: 8
Posts: 291
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's the basics on how to build a library
http://arduino.cc/en/Hacking/LibraryTutorial

You'd want to study how the TimeAlarms library do its stuff.
With the newest ide, you can use the c++ 'new' and 'delete' operators to create and delete objects. You don't have to use malloc.
I'd store the instances in an array and loop through it to perform things.
« Last Edit: March 20, 2013, 10:13:43 am by mistergreen » Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Assuming you want to stick with the TimerAlarm library, you cannot assign variable parameters to the timer/alarm functions. You can build your own library starting from the TimerAlarm sources. What you need is to add an integer (an index into an array of parameters, or an index into an array of arrays of parameters) to the class member variables, e.g.
Code:
class AlarmClass
{
//...
  OnTick_t onTickHandler;
  uint8_t parm;
  void updateNextTrigger();
then change the typedef of the callback function:
Code:
typedef void (*OnTick_t)(uint8_t parm);  // alarm callback function typedef
change all methods creating an alarm or timer (create, alarmRepeat, alarmOnce, ...), and finally change the serviceAlarms() function so that this fragment
Code:
if( TickHandler != NULL) {       
  (*TickHandler)(parm);     // call the handler 
}
compiles without errors.

Then in your sketch you can define an array of parameters (or array of arrays of parameters) whose index is passed to the alarm creation function. Obviously, your previous sketch will be broken if you keep the old format for the alarm creation functions (e.g., Alarm.timerRepeat(15, Repeats) should become Alarm.timerRepeat(15, Repeat, 2)), and for the alarm function themselves (e.g., timerRepeat() should become timerRepeat(uint8_t parm)). How you define and use the parameters in your alarms is up to you, but at least you have a means to address them.

Please note I'm not recommending this approach in place of the more thoughtfully engineered approach others have suggested, it's just a quick and doable solution that may get you started with developing your own library.
Logged

Pages: [1] 2   Go Up
Jump to: