Sonntag, 28. November 2010

protothread and arduino, a first easy example

I wrote a little example to demonstrate the possibilities of protothread and an avr µc. I decided to use some arduino specific functions like pinMode(), digitalWrite() and digitalRead() because i think this way it is very easy to understand what's happening in the code. But you should always keep in mind that these functions are up to 50 times slower than direct port access. It's easy to change the read and write functions to direct port access later on in a project if more I/O power is needed. For me arduino is a rapid prototyping platform...


What the code does, is that it toggles an LED every n ms using two independent protothreads for it. One pt toggles every 1000ms, the other one every 900ms. The result is an erratic blinking pattern. Download the protothread library and unpack it into your library directory, This example is already included as pde file. Restart your arduino IDE after unpacking and you will find it listed under "examples -> pt" in the "File" menue of the IDE.

#include <pt.h>   // include protothread library

#define LEDPIN 13  // LEDPIN is a constant 

static struct pt pt1, pt2; // each protothread needs one of these

void setup() {
  pinMode(LEDPIN, OUTPUT); // LED init
  PT_INIT(&pt1);  // initialise the two
  PT_INIT(&pt2);  // protothread variables
}

void toggleLED() {
  boolean ledstate = digitalRead(LEDPIN); // get LED state
  ledstate ^= 1;   // toggle LED state using xor
  digitalWrite(LEDPIN, ledstate); // write inversed state back
}

/* This function toggles the LED after 'interval' ms passed */
static int protothread1(struct pt *pt, int interval) {
  static unsigned long timestamp = 0;
  PT_BEGIN(pt);
  while(1) { // never stop 
    /* each time the function is called the second boolean
    *  argument "millis() - timestamp > interval" is re-evaluated
    *  and if false the function exits after that. */
    PT_WAIT_UNTIL(pt, millis() - timestamp > interval );
    timestamp = millis(); // take a new timestamp
    toggleLED();
  }
  PT_END(pt);
}
/* exactly the same as the protothread1 function */
static int protothread2(struct pt *pt, int interval) {
  static unsigned long timestamp = 0;
  PT_BEGIN(pt);
  while(1) {
    PT_WAIT_UNTIL(pt, millis() - timestamp > interval );
    timestamp = millis();
    toggleLED();
  }
  PT_END(pt);
}

void loop() {
  protothread1(&pt1, 900); // schedule the two protothreads
  protothread2(&pt2, 1000); // by calling them infinitely
}

I hope this example is easy to understand. I will post a more complex one the next days, dealing with input and output via the serial connection and some sort of calculation, all taking place in 'quasi'parallel. Maybe some sort of clock with the possibility to set it and some periodic actions like blinking a led and printing the actual time on the console.

1 Kommentar:

  1. Hi,

    first, very thanks for this tutorial,
    I am looking for a code which I can blink diference leds and start which one to blink by a pushbutton. I have two leds and two pushbuttons, When I push the first button, I want to blinking the first led and when a push again the first button I want to turnoff the blinking of first led. I want to control the two leds in the same way. Do you know how to do this?

    Thanks

    AntwortenLöschen