Event-Based Library for Arduino

First of all - thank you for this nice library. Everything works pretty well.
I have one question about ButtonEvent onHold().

The documentation says that the method is called only once. For my project I want to execute some code during the button was pressed.

The idea is to increment a variable by 1 during the button was pressed and to stop incrementing when the button is released.

Thank you in advance.

The idea is to increment a variable by 1 during the button was pressed and to stop incrementing when the button is released.

Then I would think you can start incrementing with onDown and stop with onUp.


Rob

Thanks for all who are enjoying this work! XD And sorry for this later reply. It will not happen anymore. :roll_eyes:

Terry King, are you trying to do a real-time based scheduler? It's a good idea. If you have a RTC circuit, it's possible to calculate the time left to reach a specific date/hour to use as event parameter. Or you could add an event for each second, for example, and then read RTC time to make the decision. Unfortunately I dont have a RTC circuit here to properly implemente this function. Remember that you can always change the interval directly through TimerInformation.intervalMillis (Sender->intervalMillis) variable when the event is raised.

Alexander Tzokev, are you trying to measure the button holding time? It can be read through ButtonInformation.holdMillis (Sender->holdMillis) on onUp event, and then you can transform it in your desirable scale.

More functionalities are comming soon. Any more ideas are welcome.

Thanks!!

Rferreira:
...
Terry King, are you trying to do a real-time based scheduler? It's a good idea. If you have a RTC circuit, it's possible to calculate the time left to reach a specific date/hour to use as event parameter. Or you could add an event for each second, for example, and then read RTC time to make the decision. Unfortunately I dont have a RTC circuit here to properly implemente this function.
...

Hi Renato, Sorry I was off on other things....

If you are interested in developing a way to integrate the RTC function,I'd be happy to send you one. Like this: http://arduino-direct.com/sunshop/index.php?l=product_detail&p=48 It will probably take a while through Infamous Brazil Shipping... Send me a shipping address to terry@yourduino.com

I think many people are looking for a straightforward way of scheduling events without writing it all in their own main loops. Ideally there would be a Processing/VB/Whatever program in an attachable computer that could update the schedule... Hmmmm.

The lastest ebl-arduino release (r52) brings to Arduino's users an easy way to exchange comands and data between PC and Arduino using .Net, being also easy to port to another languages and transports (TCP and so on).

AdvancedSerial

A new class that implements a serial protocol to make easier the communication between PC applications and Arduino sketches.

It is an example of sketch that receive commands from PC to control an LCD display:

#include <AdvancedSerial.h>
#include <LiquidCrystal.h>

#define BACKLIGHT_ON_MESSAGE 0
#define BACKLIGHT_OFF_MESSAGE 1
#define TEXT_MESSAGE 2

//pins
#define PIN_BACKLIGHT 7

//configure lcd
LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

void setup() {
  //configure backlight pin
  pinMode(PIN_BACKLIGHT, OUTPUT);
  //configure LCD
  lcd.begin(16, 2);
  //begin serial port with a desirable speed
  Serial.begin(115200);
  //configure receiver callback
  AdvancedSerial.setReceiver(onMessage);
}

void loop() {
  //AdvancedSerial job
  AdvancedSerial.loop();
}

void onMessage(AdvancedSerialMessage* message) {
  switch (message->id) {
    case BACKLIGHT_ON_MESSAGE:
      digitalWrite(PIN_BACKLIGHT, HIGH);
      break;
      
    case BACKLIGHT_OFF_MESSAGE:
      digitalWrite(PIN_BACKLIGHT, LOW);
      break;
      
    case TEXT_MESSAGE:
      lcd.clear();
      for (int i=0; i<message->size; i++) {
        if (i==16) lcd.setCursor(0, 1);
        lcd.write((char)message->payload[i]);
      }
      break;
  }
}

Client API - AdvancedSerialClient

AdvancedSerialClient is the communication entry-point for AdvancedSerial based sketches. It permits to ensure that the device is connect, send messages to it and receive asynchronous events.

This part of a C# code is responsible to send control messages to LCDWriter sketch from last example:

try
{
    //create object
    AdvancedSerialClient ArduinoClient = new AdvancedSerialClient();
    //connect to device
    ArduinoClient.Open(Arguments[PARAMETER_PORT].ToString(), 115200);

    //command for LED
    if (Arguments.ContainsKey(PARAMETER_BACKLIGHT))
    {
        SerialProtocol.AdvancedSerialMessage BacklightMessage = new SerialProtocol.AdvancedSerialMessage();

        if ((bool)Arguments[PARAMETER_BACKLIGHT])
            BacklightMessage.ID = BACKLIGHT_ON_MESSAGE;
        else
            BacklightMessage.ID = BACKLIGHT_OFF_MESSAGE;

        ArduinoClient.Send(BacklightMessage);
    }

    //command for text
    if (Arguments.ContainsKey(PARAMETER_TEXT))
    {
        SerialProtocol.AdvancedSerialMessage TextMessage = new SerialProtocol.AdvancedSerialMessage();
        TextMessage.ID = TEXT_MESSAGE;
        TextMessage.Payload = new System.Text.ASCIIEncoding().GetBytes(Arguments[PARAMETER_TEXT].ToString());
        TextMessage.Size = (byte)TextMessage.Payload.Length;
        ArduinoClient.Send(TextMessage);
    }
}
catch (Exception ex)
{
    Console.Write("Error: " + ex.Message);
}

The complete, and ready to use, source for this example is available in library source tree.

Running the example

It's needed to properly run this example:

  • 1 Arduino;
  • 1 Breadboard (don't forget the jumper wires);
  • 1 Display 1602A (16x2 with backlight);
  • 1 10k potentiometer.

The components must be assembled in breadboard as following:

Click here to download the Fritzing source file for this project.

Once you've uploaded the LCDWriter sketch from AdvancedSerial examples (IDE menu: File/Examples/AdvancedSerial/LCDWriter) to your Arduino board the LCDWrite.exe client API example (IDE directory: libraries\AdvancedSerial\clientapi\dotnet\Release) will be able to control the backlight and text shown in LCD display.

In closing, a short demonstration of this example running:

This project has their own repository with more information about the classes, usage instructions and download options. It could be accessed through the URL GitHub - renatoferreirarenatoferreira/ebl-arduino: Automatically exported from code.google.com/p/ebl-arduino.

Source: Controlling Arduino with .Net

Hello Renato,

Wow, you have been busy with this..

I am convinced this will be the way to go for sophisticated Arduino applications such as 24-7 Automation for Home, and other controls such as Garden/Hydroponic systems etc, etc.

I will write up my notes on a scheduling concept later today and maybe we can discuss that further.

I am in the throes of packing my Lab and other belongings that will be shipped to Italy for next year, and the Arduino stuff I will bring back to the US for the Summer. In a couple days that will settle down and I will be writing more...

The combination of non-blocking functions in your RTOS and efficient and easy to set up scheduling (A scheduled Time is just an Event, right?) will make many cool applications possible.

Hello, Terry... It's a bit boring to debug an serial application when the only interface to it is the same serial port. The IDE's Serial Monitor holds an exclusive access to serial port and does not permit things to work toguether. :smiley:

Send me an email when you feel ready to get back our discussion. OK? :wink:

Hi Renato,

Today all my stuff going to Italy for next year from here (Saudi Arabia) is going on the truck.

Couple more days and I can Think. (As we used to say in IBM ...)

From Saudi Arabia to Italy by truck?! :astonished:

Hi,

I have just been looking over your event lib. Very nice piece of work, well done. I also programme in .NET SF/CF/MF.

I was wondering if you might like to consider extending the properties lib to use an SD card to overcome the R/W cycle limitations.

I would also be very interested in an event driven ethernet lib and I2C for RFID etc. I am happy to collaborate on these if you fancy taking them on.

Cheers Pete.

Bainesbunch, I'm also interested to add more capabilities to the library. My main problem is that I don't have abundant access to electronics components. But feel free to colaborate. New members are realy needed for this project.

OK I think i am going to start work on an XML based Config reader/Writer that uses the SD card through any pins designated for SPI.

I have quite a bit of kit here that if you need to platform any beta code on i'll be happy to run it for you and give feedback.

Have you seen the AikoEvents library for adding time based events, this also looks like it has potential.

Cheers Pete.

Rferreira:
Bainesbunch, I'm also interested to add more capabilities to the library. My main problem is that I don't have abundant access to electronics components. But feel free to colaborate. New members are realy needed for this project.

I hope you don't mind some constructive criticism. If it were me, I'd go with a looper idiom. This way, the act of looping is completely detached from the logic of each widget's loop. This has some nice advantages in that it allows for the creation of a generalized, powerful, message passing mechanism, possibility of inlinned loop, reduction of code size (important here) helps prevent one widget from causing others to miss critical windows, and is especially useful for timer based events.

A looper implementation would look something like the following pseudo code. Obviously various schemes can be implemented based on your actual requirements and preferred method of dispatch. So don't get too caught up in the specifics.

setup {
  Looper myLooper ;
  Timer myTimer( myLooper ) ;
  MyButton1 myButton1( myLooper ) ; 
  MyButton2 myButton2( myLooper ) ; 
}


loop {
  myLooper.loop() ;
}

Then, rather than have a loop method defined in each looper aware widget, you would define an "execute" or "fire" method which would execute for that iteration through the loop.

Also, I noticed your addTimer method uses realloc. It seems realloc is buggy unless you have the latest avr-libc. It needs to be 1.7.x to avoid the bug from what I read.

Furthermore, your timer-loop implementation runs in linear time. That's bad for anyone who may have a lot of timers; especially when most of then are disabled. In fact, for anyone who may have a lot of timers, the implementation itself may lead to late timer execution/notification. For starters, you might want to look at a linked-list implementation, which would remove the need for a realloc as well as keeping your enabled and disabled timers in two different lists. Of course, ideally, there would not be a linear walk of timers for every loop (especially checking to see which ones are enabled, only to ignore disabled), rather, we would only care about the latest timer, and only ever need to look at the next timer to execute, only ever needing to look at the head of our linked list. That would, of course, require re-evaluation at timer addition rather than every loop interval. Basically forcing timer execution to O(1) [or O(1) + O(n-1) for late timers] and linear time for adding, deleting, and disabling timers.

And speaking of message handling, once you have something like the above, you can now register messages with handlers and/or have the widgets register messages with the looper. Then, when one widget sends a message, the looper can efficiently dispatch the message to another widget's message handler without widget a or b actually knowing about each other.

Aside from that, I love the fact you're trying to standardize on some design patterns. I especially appreciate you're doing this in C++ rather than C.

I was also going to through another wild card into the mix and suggest that rather than actually having a call to the events processor in the main loop we could actually attach one of the timer overflow interrupts to a pump that iterated through the invent processors, it could almost fall into the realms of multi thread then except that we could only run the interrupt thread at the cost of the main loop. so not true multi tasking :frowning:

When we register an event for testing then we could also specify the frequency of checking. I.E a button need only be tested at 50 hz but the uart or i2c faster so as not to loose data.

Cheers Pete.

That's the kind of thinking I meant when I said:

and is especially useful for timer based events.

Basically, if you have an RTC or other interrupt line, you can either set a flag which is checked in the timer's fire method or directly call the execute method from the ISR, depending on the nature of the event and exactly what all needs to be done. Always possible for further divide the ISR into a slow/fast split mechanism.

EDIT: Also want to add that it opens the door for IRQ dispatch via message passing too - again depending on design decisions and goals.

Bainesbunch, are you thinking about XML parsing using Arduino? I'm not sure if it will be good. XML is good when you want an easy to implement and humam readable way to exchange information, but in my opinion it's realy hard to parse and requires much memory space and processing power. I still prefer to use memory spaces that matches C structs.

gerg, you're right when say that avr memory allocation is buggy, but I also tried the new library version and it's still having a bad behaviour. I've added a method to pre-allocate a memory space to avoid sucessive reallocs, but I was not confident that it would be good and I just not commited it yet to source tree. I think that the Arduino/AVR has many memory issues, what make me avoid the idea of creating a new class to control the common functions like loops because it will spend more stack space and so on. It's a very limited environment when compared to PC programming. Everything needs to be simple as possible.

I liked the suggestion about keeping the next timer to avoid the checking of all array items everytime, I agree that many things may be optimized in this loop (and in the rest of library). I'm only not sure about how much it will improve the precision because if you set tight intervals to hard jobs the timer will never match anyway. And I prefer don't use interrupts because time elapsed measurements are needed for some functions and I also worry about losing serial data.

Be assured that the new versions will bring all your good sugestions. And feel free to submit patches for main source, documentation, examples, etc etc.

Rferreira:
Bainesbunch, are you thinking about XML parsing using Arduino?

Not exactly no. I was thinking more on the lines of using XML to store data for configuration and non volatile data from the application in XML on the CF card.

For configuration this would have that advantage of being able to write an XML based configuration for the application to a CF card in an eye readable format that in then converted into its types by the parser when the application loads. so the XML File might read

<Name="My Variable" Type="INT" Value="100">
<Name="My Variable" Type="STRING" Value="A Sample String">
<Name="My Variable" Type="REA" Value="123.456">

The parser would be able to find the element in the XML file by name and convert the value into its correct type on the Arduino, this would not be wasteful of memory.

To conserve memory further we only read one line of the XML file at a time to process. I think a full XML document reader is to memory hungry four our little toys.

Cheers Pete.

Sounds like a job for JSON, rather than XML.

It's not the same thing, oscarBravo. IMHO, if you can't take advantages of reusability, syntax validation, high level libraries for read/write operations, binary data encoding and so on, XML does not make any sense for me due to it's huge storage and performance overhead. XD

Hi again, Renato,

Sorry for the delay; I have been travelling and now settled back in Vermont USA for the summer.

((I am using a temporary logon/userid because I am locked out of the forum with my regular ID and no one responds to emails :0 ))

I have been thinking more about issues of "Scheduling", tasks, events etc. I need to read thru the discussion completely before saying too much. I have my own viewpoint and "terminology" in mind from my past experience with other RTOS systems like IBM's EDX. I even read thru the code of the RTOS I wrote long, long ago for the 6502. So a slow 8-bit micro can definitely do this :slight_smile:

So, more to come...

First pass "Scheduler" ideas: A scheduler simply is another source of "Events" in a system. The scheduler periodically compares the Real Time Clock with it's list of scheduled events, and if the time has arrived, it posts that event. I don't think the events posted by a scheduler need to be any different than events posted by other sensor-based or timer-based or counter-based "checkers"..

Maybe...

OK, back soon. Thanks for your work on this. Let me know what hardware you would like to test things and I'll get it to you.

Regards, Terry King terry@terryking.us