Posts Tagged ‘timer’

A Simple Arduino Task Scheduler (1)

My motivation to write a task scheduler framework is to help me faster develop new Arduino projects. In most projects, we repeat the same tasks over and over before getting to play with the new stuff.

You can jump into the code right now by downloading it from my github account at:
https://github.com/pchretien/scheduler.

ITask Interface

Before using the scheduler functionalities, we have to explore the ITask interface. ITask is an interface that you must implement for all tasks to be scheduled and executed by the Scheduler. This interface has only two methods, “setup” and “run”.

The ITask::setup() method of your task object will be called in the global setup() function of your Arduino application. You place in this function all the initialization code your task object needs to execute correctly.

The ITask::run(Scheduler*) method is the method called by the scheduler when your task object is scheduled to run. It receives a reference to the Scheduler object so that your task object can re-schedule itself  or another task.

class ITask
{
  public:
    virtual void setup() = 0;
    virtual void run(Scheduler* scheduler) = 0;
};

Scheduler Singleton

The scheduler has two methods to schedule a task to run. To schedule a task to run immediately you use the queue(ITask*) method. This will add a task to the queue of tasks ready to run.

Then, to schedule a task to run in the future, you should use the schedule(ITask*, int) method. This method will set a task to run in a defined number of milliseconds in the future.

class Scheduler
{
  public:
    Scheduler();
    void setup();
    void processMessages();

    void queue(ITask* task);
    void clearQueue();

    void schedule(ITask*, int);
    void clearSchedule();

  private:
    ITask* _taskQueue[QUEUE_MAX];
    ScheduleItem _taskSchedule[SCHEDULE_MAX];
};

The setup() method should be called from the main setup() function of your Arduino application. Finally, you can clear the queue and the schedule by calling the clearQueue() and clearSchedule() functions.

Task Implementation

In this example I will create a task that will turn on/off a LED every 500 milliseconds. First, you must derive your task class from the ITask interface.

class Blinker : public ITask
{
  public:
    void setup();
    void run(Scheduler*);
    Blinker(int, int);

  private:
    int _pin;
    int _period;
    int _state;
};

Following is the implementation of this task …

The constructor initializes internal values. Here, you can put all the code you want to run at the time of creation of the Task object.

Blinker::Blinker(int pin, int period)
{
  _pin = pin;
  _state = 0;
  _period = period;
}

The “setup” method will be called from the setup() method of your Arduino program. In this example we only need to configure the digital pin #13 as an output.

void Blinker::setup()
{
  pinMode( _pin, OUTPUT);
}

The “run” method will be called by the scheduler when the task is ready to run. In this example, the first thing the Task does is to re-schedule itself to run in _period milliseconds. Once re-scheduled, the Task will toggle the LED connected on pin number _pin of the Arduino micro-controller.

void Blinker::run(Scheduler* scheduler)
{
  scheduler->schedule(this, _period);

  _state = (_state>0)?0:1;
  digitalWrite(_pin, _state);
}

Finally you must create the task and schedule it for the first run. In this example, the Task is created in the global scope and scheduled in the setup() method.

// Create a task scheduler singleton
Scheduler __scheduler;
...
// Create custom tasks
Blinker _blinker12(12, 1000);
...
void setup()
{
  ...
  _blinker12.setup();
  ...
  __scheduler.setup();
  __scheduler.queue(&_blinker12);
  // or ...
  //__scheduler.schedule(&_blinker12, 1000);  

  ...
}

void loop()
{
  __scheduler.processMessages();
}

You can download the complete example from my Github account. In this example I drive five different Tasks in parallel. Two tasks are driving servo motors, two others are driving LEDs and the last is printing data on the serial port.

This is a work-in-progress project and will keep you informed of new developments as I go. If you try it, please leave me your impressions in the comment section below or contact me via my Github account.

Netduino Plus (Part 2)

I have been playing with my Netduino Plus for about two weeks now and I love it. So far, the most interesting thing about the Netduino is the use of the .Net Micro Framework (.Net MF). Being a C# developer for a decade now, I really enjoy being able to take advantage of this language in my electronic projects. In this post I will demonstrate some of the .Net MF features I used in this small project.

Netduino Plus with Arduino Protoshield

Netduino Plus with Arduino Protoshield

The project used for this demonstration is quite simple. I have a temperature sensor and a photo-resistor taking measurements every minute and logging the results in a file. There is a watch-dog LED on pin #13 and a button on pin #8 used to toggle a LED attached to pin #7. The button and the LED controls are part of the Arduino protoshield.

The code for this project is available on my GitHub account at the following location:
https://github.com/pchretien/NetduinoPlusEthSD

InterruptPort

The InterruptPort is one of the cool things in the .Net MF. You can define a callback function that will be triggered when the status of an IO changes. In this project, an interrupt has been defined on pin #8. This IO is attached to the protoshield button (S1). The interrupt callback function toggles the green led of the protoshield attached to pin #7.

// Declare the output pin #7 attached to the protoshield green LED
private bool pin7Value;
private readonly OutputPort pin7 = new OutputPort(Pins.GPIO_PIN_D7, false);

...

// Create the interrupt port on pin #8 attached to the protoshield button (S1)
private readonly InterruptPort pin8 = new InterruptPort(
            Pins.GPIO_PIN_D8,
            true,
            Port.ResistorMode.PullUp,
            Port.InterruptMode.InterruptEdgeLow
            );

...

// Add a callback to the interrupt port
pin8.OnInterrupt += new NativeEventHandler(this.OnInterrupt);

...

// Declaration of the callback function
private void OnInterrupt(uint port, uint state, DateTime time)
{
    Debug.Print("Pin="+port+" State="+state+" Time"+time);
    pin8.ClearInterrupt();

    pin7Value = !pin7Value;
    pin7.Write(pin7Value);
}

The callback function receives the port number, the state and the DateTime of the event in parameters.

Internal Clock & Network

There is no real time clock with a battery on the Netduino but it is possible to set the board DateTime using code. But what time should we use if there are no RTC onboard? A simple answer is to use the net. The netduino Plus comes with an ethernet port and that is all we need to go and get time online.

The best way to do that by calling a time server using the Network Time Protocol (NTP). Don’t waste your time writing it … someone else has already done the job quite well. Micheal Schwartz is the author of the .Net Micro Framework Toolkit which includes a class that handles all that for you. You will find the code in my project.

Using this library, I load the current time at startup and set the internal clock of the Netduino. Once that’s done, you can call the DateTime.Now from anywhere in your project as long as the board is powered.

I wrote a short method to initialize the Netduino Plus networking options. All I do in this function is find the ethernet network adapter and make sure it’s using DHCP to connect on my local network.

private void InitNetwork()
{
	// write your code here
	NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

	foreach (NetworkInterface networkInterface in networkInterfaces)
	{
		if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
		{
			if (!networkInterface.IsDhcpEnabled)
			{
				// Switch to DHCP ...
				networkInterface.EnableDhcp();
				networkInterface.RenewDhcpLease();
				Thread.Sleep(10000);
			}

			Debug.Print("IP Address: " + networkInterface.IPAddress);
			Debug.Print("Subnet mask " + networkInterface.SubnetMask);
		}
	}
}

Timers

Timers are part of the standard .Net Framework and it’s great to know that they are supported by the .Net MF on Netduino. There are so many processes in the embedded world that need periodic actions that having access to the .Net Timers make development a lot faster and easier. I have three timers in this sample project. One is a watch-dog flashing a LED attached to pin #13, one is for temperature reading and the last is for light measurement.

//
// Timers declaration
//
private Timer tempTimer;
private Timer lightTimer;
private Timer watchDogTimer;

...

//
// Timers callback binding
//
TimerCallback watchDogDelegate = new TimerCallback(this.WatchDog);
watchDogTimer = new Timer(watchDogDelegate, null, 1000, 1000);

TimerCallback lightCheckDelegate = new TimerCallback(this.CheckLightLevel);
lightTimer = new Timer(lightCheckDelegate, null, 60000, 60000);

TimerCallback tempCheckDelegate  = new TimerCallback(this.CheckTemperature);
tempTimer = new Timer(tempCheckDelegate, null, 60000, 60000);

...

//
// Timers callback function declarations
//
public void WatchDog(Object stateInfo)
{
	pin13Value = !pin13Value;
	pin13.Write(pin13Value);
}

public void CheckLightLevel(Object stateInfo)
{
	a0Value = a0.Read();

	Debug.Print("Light: " + a0Value);
	AppendToFile(@"\SD\light.log", "Light level " + a0Value);
}

public void CheckTemperature(Object stateInfo)
{
	a1Value = a1.Read();
	double temperature = (a1Value*3500)/1024.0;
	temperature = (temperature - 500)/10.0;

	Debug.Print("Temp: " + temperature);
	AppendToFile(@"\SD\temp.log", "Temperature: " + temperature);
}

Multi-threading

It’s great to have Timers but what about multi-threading support? Well, we also have it with the .Net MF on Netduino. Many will argue we don’t really need multi-threading on micro-controllers, and they may be right, but hey, it makes programming for embedded devices so much more fun with multi-threading. Threads coupled with InterruptPort could save so many lines of code … that’s a really powerful addition to the micro-controllers world.

In the sample project, I instantiate a single thread that makes the protoshield LED flash every second. This is the same LED as the one toggled by the protoshield button.

// Declare the Thread handler
private Thread ledThread = null;

...

// Bind the thread handler to the thread function and start it ...
me.ledThread = new Thread(LedThread);
me.ledThread.Start();

...

// The Thread function ...
private static void LedThread()
{
	while (true)
	{
		pin7Value = !pin7Value;
		pin7.Write(pin7Value);
		Thread.Sleep(1000);
	}
}

File IO

The Netduino Plus comes with a micro SD card reader. It can handle up to 2Gb of SD card storage. The .Net MF offers mostly the same API to work with removable storage as the standard framework.

The SD card file system is mounted on the “\\SD\” root folder. Following are some basic utility functions to work with removable storage on the Netduino Plus.

// Check id the SD card is mounted
private bool VolumeExist()
{
	VolumeInfo[] volumes = VolumeInfo.GetVolumes();
	foreach (VolumeInfo volumeInfo in volumes)
	{
		if (volumeInfo.Name.Equals("SD"))
			return true;
	}

	return false;
}

// Append to a file.
// Create the file if it doesn't exist
private void AppendToFile(
	string filename,
	string message)
{
	if (!VolumeExist())
		return;

	try
	{
		FileStream file = File.Exists(filename)
							  ? new FileStream(filename, FileMode.Append)
							  : new FileStream(filename, FileMode.Create);

		StreamWriter streamWriter = new StreamWriter(file);
		streamWriter.WriteLine(DateTime.Now.ToString() + ": " + message);
		streamWriter.Flush();
		streamWriter.Close();

		file.Close();
	}
	catch(Exception)
	{
	}
}

Debugging

Finally, of all the features we get with the .Net MF on Netduino, the debugger is the all categories winner. Debugging code on embedded devices has always been a hassle. This is history with the .Net MF on Netduino. You can debug your code running on the device as if it was running on your desktop.

You can step through your code line by line and print debug info to the Output console while running the code on the real world device. I’m sure I don’t have to tell you how a good debugger makes life easier.

Conclusion

I’m a big fan of the Arduino and I’m convinced this platform will remain the leader of open source micro-controllers for a while because of the huge community that supports its development.

However, combining the richness of the .Net Micro Framework and the actual work done on porting it to Mono, I think the Netduino is a very serious pretender in the world of open source micro-controllers.

Try it on your own and let me know what you think.

Philippe Chrétien

Kids Clock

Kids Clock Arduino

Kids Clock Arduino

Ok, that one is not rocket science but it realy realy worth the 20$ Arduino micro controller I used to make that kids clock.

The idea here is to make sure my 4 years old kid will not wake up at 3:30AM because he has confused the small needle with big needle. The code is real simple … red LED on before wake up time … green LED on after wake up time.

Following is the code … of course that could have been a lot more complicated but this is doing the job just fine. Stay tuned for future enhancements.

#include <avr/interrupt.h>
#include <avr/io.h>

#define INIT_TIMER_COUNT 6
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT

#define RED_LED 8
#define GREEN_LED 11
#define BOARD_LED 13

#define NIGHT_TIME 36000 // 10*60*60

int led13 = HIGH;
long counter = 0;
long stepStack = 0;
long seconds = 0;

// Aruino runs at 16 Mhz, so we have 1000 Overflows per second...
// 1/ ((16000000 / 64) / 256) = 1 / 1000

ISR(TIMER2_OVF_vect) {
  RESET_TIMER2;
  counter++;
  if(!(counter%1000))
  {
    // enqueue step message
    stepStack++;
  }
};

void startup()
{
  int led = 0;
  for(int i=0; i<5; i++)
  {
    digitalWrite(RED_LED, led);
    digitalWrite(GREEN_LED, led^1);
    led ^= 1;
    delay(500);
  }

  digitalWrite(RED_LED, HIGH);
  digitalWrite(GREEN_LED, LOW);
}

void setup()
{
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(BOARD_LED, OUTPUT);
  //Timer2 Settings: Timer Prescaler /64,
  TCCR2A |= (1<<CS22);
  TCCR2A &= ~((1<<CS21) | (1<<CS20));
  // Use normal mode
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  // Use internal clock - external clock not used in Arduino
  ASSR |= (0<<AS2);
  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= (1<<TOIE2) | (0<<OCIE2A);
  RESET_TIMER2;
  sei();

  startup();
}

void loop()
{
  if(stepStack)
  {
    // Toggle the LED
    led13 ^= 1;
    digitalWrite(13, led13);

    seconds ++;
    stepStack--;
  }

  if( seconds > NIGHT_TIME )
  {
    digitalWrite(RED_LED, LOW);
    digitalWrite(GREEN_LED, HIGH);
  }
}