Use

To use the Nocan library in the Arduino API, the following steps need to be performed once:

Next, each time you wish to compile a sketch for the Omzlo One, make sure that the board "Omzlo One" is selected in the "Tools > Boards" sub-menu.

API

The source code corresponding to this API can be fount at https://github.com/omzlo/omzlo-one-arduino-package/tree/master/src/libraries/NOCAN .

Nocan.open

Synopsis

NocanNodeId Nocan.open()

Description

This function performs 3 main tasks:

  • initialise the I2C interface in master mode,
  • initialise the CAN bus driver (STM32F042)
  • request a node id to be attributed to the node (based on a unique 8 byte serial number).

Return value

This function returns either:

  • a value greater than 0 representing the node id attributed to the node.
  • 0 if no node id was assigned to the node
  • a value less than 0 in case of a hardware initialization issue

Nocan.close

Synopsis

int8_t Nocan.close()

Description

This function currently does nothing.

Nocan.lookupChannel

Synopsis

int8_t Nocan.lookupChannel(const char *channel, NocanChannelId &channel_id) 

Description

This function looks up the value of channel_id corresponding to the string channel.

Return value

It return 0 in case of success and a negative value in case of failure.

The value of of channel_id is updated.

Nocan.registerChannel

Synopsis

int8_t Nocan.registerChannel(const char *channel, NocanChannelId &channel_id) 

Description

This functions registers the channel named channel and obtains the corresponding channel_id.

Return value

It return 0 in case of success and a negative value in case of failure.

The value of of channel_id is updated.

Nocan.unregisterChannel

Synopsis

int8_t Nocan.unregisterChannel(uint8_t channel_id) 

Description

This function unregisters the channel identified by channel_id.

Return value

It return 0 in case of success and a negative value in case of failure.

Nocan.subscribeChannel

Synopsis

int8_t Nocan.subscribeChannel(NocanChannelId channel_id) 

Description

This function subscribes the node to the channel identified by channel_id.

A node can subscribe to a maximum of 12 channels simultaneaously.

Return value

It return 0 in case of success and a negative value in case of failure.

Nocan.lookupAndSubscribeChannel(const char *channel)

Synopsis

int8_t Nocan.lookupAndSubscribeChannel(const char *channel, NocanChannelId &channel_id) 

Description

This function simply a convenience function that combines the following 2 functions in one: lookupChannel and subscribeChannel.

Return value

It return 0 in case of success and a negative value in case of failure.

Nocan.unsubscribeChannel

Synopsis

int8_t Nocan.unsubscribeChannel(NocanChannelId channel_id)

Description

This function is the opposite of Nocan.subscribeChannel: it signifies that the node will stop receiving messages from the channel channel_id.

Return value

It return 0 in case of success and a negative value in case of failure.

Nocan.publishMessage

Synopsis

int8_t Nocan.publishMessage(NocanChannelID cid, uint8_t len, const uint8_t *data) 

int8_t Nocan.publishMessage(NocanMessage &msg) 

Description

This function publishes a message data of length len to the channel identified by cid.

The alternate form of the function uses the following structure instead.

typedef struct {
    uint8_t node_id;
    uint16_t channel_id;
    uint8_t dlen;
    uint8_t data[64];
} NocanMessageId

The value of node_id is automatically set by the function, based on the value obtained through Nocan.open().

Return value

It return 0 in case of success and a negative value in case of failure.

Nocan.processMessage

Synopsis

int8_t Nocan.receiveMessage(NocanMessage &msg) 

Description

This function allows to receive Nocan messages of up to 64 bytes.

The received message has the following structure:

typedef struct {
    uint8_t node_id;
    uint16_t channel_id;
    uint8_t dlen;
    uint8_t data[64];
} NocanMessageId

Where:

  • node_id is the address of the node (see Nocan.open()).
  • channel_id is the channel identifier of the received message.
  • dlen is a number between 0 and 64 describing the length of the message.
  • data is the actual message.

Return value

It return 0 in case of success and a negative value in case of failure.

Nocan.getUniqueDeviceIdentifier

Synopsis

int8_t Nocan.getUniqueDeviceIdentifier(uint8_t dest[8])

Description

This function populates dest with the serial number of the device.

Return value

It return 0 in case of success and a negative value in case of failure.

Nocan.signal

Synopsis

int8_t Nocan.signal() 

Description

This function return 1 if a incoming message is pending, and 0 otherwise.

If a message is pending, it can be read with Nocan.receiveMessage().

Return value

1 if a message is pending, 0 otherwise.

Examples

DS18B20 temperature sensor

The code below shows a full sketch of an Omzlo One application that reads data from a DS18B20 temperature sensor and broadcasts it to the channel called "temperature".

#include <OneWire.h>
#include <DallasTemperature.h>
#include <nocan.h>

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS); 
DallasTemperature sensors(&oneWire);
NocanChannelId tid;

void setup() {
  // put your setup code here, to run once:
  sensors.begin();
  for (;;) 
  {
     if (Nocan.open()>=0)
        break;
     delay(1000);
  }
  Nocan.registerChannel("temperature",tid);
}

void loop() {
  // put your main code here, to run repeatedly:
  float temp;
  NocanMessage msg;

  sensors.requestTemperatures();    // this takes some time

  temp = sensors.getTempCByIndex(0);
  dtostrf(temp, 6, 1, msg.data);    // transform temp into string

  msg.dlen = 6;
  msg.channel_id = tid;
  Nocan.publishMessage(msg);        // publish to the network

  delay(1000); 
}

LCD display

Once the above sketch for the DS18B20 is running on an Omzlo One, you could add a second Omzlo One node with an LCD shield. It's very simple to publish the temperature from the previous example on the LCD by simply using the following sketch.

#include <LiquidCrystal.h>
#include <nocan.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
NocanChannelId cid;

// Initialization
void setup() 
{
  lcd.begin(16, 2);              
  lcd.print("OMZLO ONE SAYS:");  
  lcd.setCursor(0, 1);
  lcd.print("Initializing....");

  for (;;)
  {
    if (Nocan.open() < 0)
      delay(1000);
    else
      break;
  }

  Nocan.registerChannel("temperature",cid);
  Nocan.subscribeChannel(cid);

  lcd.setCursor(0, 1);           // set the cursor to column 0, line 1
  lcd.print("Waiting.........");
}

// main loop
void loop() 
{
  int i;
  nocan_msg_t msg;
  int8_t status = Nocan.receiveMessage(msg);

  if (status==0)
  {
      if (msg.dlen>16) msg.dlen=16;    
      while (msg.dlen<16) msg.data[msg.dlen++]=' ';
      msg.data[msg.dlen]=0;

      lcd.setCursor(0, 1);
      lcd.print((const char *)msg.data);
  }
}