Event-Based Library for Arduino

This is a great idea.

I hope the main developers adopt these concepts and make it part of the core distribution.
Have you tried contacting them to inform them of this capability?

Thanks! I'm planning to write a few more classes and articles before doing it.

Looks cool! I downloaded the libraries, and will give them a try as soon as I get a chance.

theepdinker 8) Don't hesitate to post an issue if you have any problem....

Renato, this is very interesting and may be the thing that enables Arduino to go beyond "the Loop" for more complex tasks.

I'm an old EDX/EDL and other RTOS guy and I will be enjoying trying out your system...

Your idea of AnalogEvent in which the event is a known CHANGE in analog value is great! (I'm surprised I never thought of it! 8) ).

I have been working on Power Control for Arduino (http://arduino-info.wikispaces.com/ArduinoPower) and people want to be able to schedule actions while having flexibility to monitor sensors and conditions.

Can you give us a suggestion / example of scheduling an action some hours (days??) ahead?

I hope you will keep on developing this!!

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.