Mainpage:Contiki drivers

From Zolertia

Jump to: navigation, search

Contents

Test applications and custom drivers for Zolertia's sensors

The following examples can also be found in the "/examples/z1 directory" of your Contiki files as they are integrated as part of Contiki release.

To visualize the test results you can use the terminal windows by just typing:

make z1-reset && make login

Or use a serial client like putty and configure it with a 115200 baudrate, 8/1/N.

You will also need a Makefile that looks like this:

ifndef TARGET
TARGET=z1
endif
 
CONTIKI_PROJECT = test-adxl345 tmp102-test test-sht11
CONTIKI_SOURCEFILES += cc2420-arch.c sensors.c sht11.c 
PROJECT_SOURCEFILES = i2cmaster.c tmp102.c adxl345.c sky-sensors.c
APPS=serial-shell
 
all: $(CONTIKI_PROJECT)
 
CONTIKI = ../..
include $(CONTIKI)/Makefile.include

Replace or add the names at CONTIKI_PROJECT with the names of the application you wish to compile.


Testing the built-in sensors

The Z1 mote has 2 built-in sensors: 3-axis ADXL345 accelerometer and the TMP102 temperature sensor, both sensors are digital and connected to the I2C port of the mote. If you want to see how the drivers look like, you will found them inside /platform/z1/dev directory.


TMP102 sensor

This test application continuously polls the sensor for data and send the data over the serial port

#include <stdio.h>
#include "contiki.h"
#include "dev/i2cmaster.h"  // Include IC driver
#include "dev/tmp102.h"     // Include sensor driver
 
#define TMP102_READ_INTERVAL (CLOCK_SECOND/2)  // Poll the sensor every 500 ms
 
PROCESS (temp_process, "Test Temperature process");
AUTOSTART_PROCESSES (&temp_process);
/*---------------------------------------------------------------------------*/
static struct etimer et;
 
PROCESS_THREAD (temp_process, ev, data)
{
  PROCESS_BEGIN ();
 
  {
    int16_t  tempint;
    uint16_t tempfrac;
    int16_t  raw;
    uint16_t absraw;
    int16_t  sign;
    char     minus = ' ';
 
    tmp102_init();
 
    while (1)
      {
        etimer_set(&et, TMP102_READ_INTERVAL);          // Set the timer
        PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));  // wait for its expiration
 
        sign = 1;
 
	raw = tmp102_read_temp_raw();  // Reading from the sensor
 
        absraw = raw;
        if (raw < 0) { // Perform 2C's if sensor returned negative data
          absraw = (raw ^ 0xFFFF) + 1;
          sign = -1;
        }
	tempint  = (absraw >> 8) * sign;
        tempfrac = ((absraw>>4) % 16) * 625; // Info in 1/10000 of degree
        minus = ((tempint == 0) & (sign == -1)) ? '-'  : ' ' ;
	printf ("Temp = %c%d.%04d\n", minus, tempint, tempfrac);
      }
  }
  PROCESS_END ();
}


ADXL345 sensor

A simple program for testing the adxl345 on-board accelerometer of the Zolertia Z1. Enables interrupts and registers callbacks for them. Then starts a constantly running readout of acceleration data. You can tap and double-tap the Z1 mote to test the accelerator interruptions, also you can test the free-fall interruption but... be careful and don't miss the mote on its way down!

#include <stdio.h>
#include "contiki.h"
#include "serial-shell.h"
#include "adxl345.h"
 
#define LED_INT_ONTIME        CLOCK_SECOND/2
#define ACCM_READ_INTERVAL    CLOCK_SECOND
 
static process_event_t ledOff_event;
/*---------------------------------------------------------------------------*/
PROCESS(accel_process, "Test Accel process");
PROCESS(led_process, "LED handling process");
AUTOSTART_PROCESSES(&accel_process, &led_process);
/*---------------------------------------------------------------------------*/
/* As several interrupts can be mapped to one interrupt pin, when interrupt 
    strikes, the adxl345 interrupt source register is read. This function prints
    out which interrupts occurred. Note that this will include all interrupts,
    even those mapped to 'the other' pin, and those that will always signal even if
    not enabled (such as watermark). */
 
void
print_int(uint16_t reg){
#define ANNOYING_ALWAYS_THERE_ANYWAY_OUTPUT 0
#if ANNOYING_ALWAYS_THERE_ANYWAY_OUTPUT
  if(reg & ADXL345_INT_OVERRUN) {
    printf("Overrun ");
  }
  if(reg & ADXL345_INT_WATERMARK) {
    printf("Watermark ");
  }
  if(reg & ADXL345_INT_DATAREADY) {
    printf("DataReady ");
  }
#endif
  if(reg & ADXL345_INT_FREEFALL) {
    printf("Freefall ");
  }
  if(reg & ADXL345_INT_INACTIVITY) {
    printf("InActivity ");
  }
  if(reg & ADXL345_INT_ACTIVITY) {
    printf("Activity ");
  }
  if(reg & ADXL345_INT_DOUBLETAP) {
    printf("DoubleTap ");
  }
  if(reg & ADXL345_INT_TAP) {
    printf("Tap ");
  }
  printf("\n");
}
 
/*---------------------------------------------------------------------------*/
/* accelerometer free fall detection callback */
 
void
accm_ff_cb(u8_t reg){
  L_ON(LEDS_B);
  process_post(&led_process, ledOff_event, NULL);
  printf("~~[%u] Freefall detected! (0x%02X) -- ", ((u16_t) clock_time())/128, reg);
  print_int(reg);
}
/*---------------------------------------------------------------------------*/
/* accelerometer tap and double tap detection callback */
 
void
accm_tap_cb(u8_t reg){
  process_post(&led_process, ledOff_event, NULL);
  if(reg & ADXL345_INT_DOUBLETAP){
    L_ON(LEDS_G);
    printf("~~[%u] DoubleTap detected! (0x%02X) -- ", ((u16_t) clock_time())/128, reg);
  } else {
    L_ON(LEDS_R);
    printf("~~[%u] Tap detected! (0x%02X) -- ", ((u16_t) clock_time())/128, reg);
  }
  print_int(reg);
}
/*---------------------------------------------------------------------------*/
/* When posted an ledOff event, the LEDs will switch off after LED_INT_ONTIME.
      static process_event_t ledOff_event;
      ledOff_event = process_alloc_event();
      process_post(&led_process, ledOff_event, NULL);
*/
 
static struct etimer ledETimer;
PROCESS_THREAD(led_process, ev, data) {
  PROCESS_BEGIN();
  while(1){
    PROCESS_WAIT_EVENT_UNTIL(ev == ledOff_event);
    etimer_set(&ledETimer, LED_INT_ONTIME);
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&ledETimer));
    L_OFF(LEDS_R + LEDS_G + LEDS_B);
  }
  PROCESS_END();
}
 
/*---------------------------------------------------------------------------*/
/* Main process, setups  */
 
static struct etimer et;
 
PROCESS_THREAD(accel_process, ev, data) {
  PROCESS_BEGIN();
  {
    int16_t x, y, z;
 
    serial_shell_init();
    shell_ps_init();
    shell_file_init();  // for printing out files
    shell_text_init();  // for binprint
 
    /* Register the event used for lighting up an LED when interrupt strikes. */
    ledOff_event = process_alloc_event();
 
    /* Start and setup the accelerometer with default values, eg no interrupts enabled. */
    accm_init();
 
    /* Register the callback functions for each interrupt */
    ACCM_REGISTER_INT1_CB((void *)accm_ff_cb);
    ACCM_REGISTER_INT2_CB((void *)accm_tap_cb);
 
    /* Set what strikes the corresponding interrupts. Several interrupts per pin is 
      possible. For the eight possible interrupts, see adxl345.h and adxl345 datasheet. */
    accm_set_irq(ADXL345_INT_FREEFALL, ADXL345_INT_TAP + ADXL345_INT_DOUBLETAP);
 
    while (1) {
	    x = accm_read_axis(X_AXIS);
	    y = accm_read_axis(Y_AXIS);
	    z = accm_read_axis(Z_AXIS);
	    printf("x: %d y: %d z: %d\n", x, y, z);
 
      etimer_set(&et, ACCM_READ_INTERVAL);
      PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
    }
  }
  PROCESS_END();
}
 
/*---------------------------------------------------------------------------*/


Test external sensors

The following briefs a list of the available sensors for the Z1 mote currently sold by us


ZIG001 Temperature and humidity sensor

  • More information about the sensor Here
  • Buy the sensor Here

The following test application polls the sensor every second and displays the temperature and humidity readings, if you want to take a close look to the driver refer to "/platform/z1/dev".

#include "contiki.h"
#include "dev/sht11.h"
 
#include <stdio.h>
 
PROCESS(test_sht11_process, "SHT11 test");
AUTOSTART_PROCESSES(&test_sht11_process);
 
PROCESS_THREAD(test_sht11_process, ev, data)
{
  static struct etimer et;
  static unsigned rh;
 
  PROCESS_BEGIN();
  sht11_init();
 
  for (etimer_set(&et, CLOCK_SECOND);; etimer_reset(&et)) {
    PROCESS_YIELD();
    printf("Temperature:   %u degrees Celsius\n",
	(unsigned) (-39.60 + 0.01 * sht11_temp()));
    rh = sht11_humidity();
    printf("Rel. humidity: %u%%\n",
	(unsigned) (-4 + 0.0405*rh - 2.8e-6*(rh*rh)));
  }
 
  PROCESS_END();
}


ZIG002 Light Sensor driver

  • More information about the sensor Here
  • Buy the sensor Here

Committed and well-tested on: 6df9ffb Zolertia's light sensor ziglet

Tested with msp430-gcc-4.4.5 and msp430-gcc-4.5.3, it works on both but with last one the serial output gets corrupted (this is isolated to be a problem with the toolchain).

See the files Here

Test app snippet:

#include <stdio.h>
#include "contiki.h"
#include "dev/i2cmaster.h"
#include "dev/light-ziglet.h"
 
#define PRINTF(...) printf(__VA_ARGS__)
#define SENSOR_READ_INTERVAL (CLOCK_SECOND)
 
PROCESS(test_process, "Test light ziglet process");
AUTOSTART_PROCESSES(&test_process);
/*---------------------------------------------------------------------------*/
static struct etimer et;
 
PROCESS_THREAD(test_process, ev, data)
{
  PROCESS_BEGIN();
 
  uint16_t light;
 
  light_ziglet_init();
 
  while(1) {
    etimer_set(&et, SENSOR_READ_INTERVAL);
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
 
    light = light_ziglet_read();
    PRINTF("Light = %u\n", light);
  }
  PROCESS_END();
}


Relay sensors (phidget-like connectors)

We are accustomed to working with Phidgets sensors and actuators, most of the devices sold by them follow the same pin distribution so we have adapter its guideline and you can plug in almost any Phidget to the Z1 mote through the 3V/5V Phidget ports (North port of the Z1 mote). The relays basically follow this guideline (See this relay), as it is only required to interface VCC, GND and a control pin to control the switching, the following code (already included as a test example at /examples/z1) uses one ADC pin as a regular GPIO to drive the relay.

You can go through the driver code and change the PORTx if you wish to use another pin other than the ones in PORT6, if you wish to use another ADC pin instead of the P6.7 pass the pin number in the relay_enable(uint8_t pin) function.

Keep in mind that depending of the required voltage/current of the relay, you may have to use an external BJT to drive the relay.

#include <stdio.h>
#include "contiki.h"
#include "dev/relay-phidget.h"
 
#define RELAY_INTERVAL (CLOCK_SECOND)
 
PROCESS(test_process, "Relay test process");
AUTOSTART_PROCESSES(&test_process);
/*---------------------------------------------------------------------------*/
static struct etimer et;
static uint8_t status;
 
PROCESS_THREAD(test_process, ev, data)
{
  PROCESS_BEGIN();
 
  /* Selects P6.7 as control pin of the relay module */
  relay_enable(7);
 
  while(1) {
    etimer_set(&et, RELAY_INTERVAL);
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
 
    status = relay_toggle();
    PRINTF("Relay [%d]\n", status);
  }
  PROCESS_END();
}

ZIG003 Barometric Sensor driver

  • More information about the sensor Here
  • Buy the sensor Here

Soon to be updated


ANLG001 Carbon Monoxide

  • More information about the sensor Here
  • Buy the sensor Here

Soon to be updated


MS-320 LP PIR Sensor

  • More information about the sensor Here
  • Buy the sensor Here

Soon to be updated

Personal tools
Navigation
MansOS Support
General guides and apps
Assistance