Выбрать главу

Далее приводится скетч для платы-получателя:

// sketch_10_03_Adruino_Receiver

#include "SoftwareSerial.h"

const int ledPin = 13;

int reading = 0;

SoftwareSerial receiver(8, 9); // RX, TX

void setup()

{

  pinMode(ledPin, OUTPUT);

  receiver.begin(9600);

}

void loop()

{

  if (receiver.available() > 1)

  {

    byte h = receiver.read();

    byte l = receiver.read();

    reading = (h << 8) + l;

  }

  flash(reading);

}

void flash(int rate)

{

  // 0 — редко, 1023 — очень часто

  int period = (50 + (1023 — rate) / 4);

  digitalWrite(ledPin, HIGH);

  delay(period);

  digitalWrite(ledPin, LOW);

  delay(period);

}

Принимающий скетч ждет, пока будет получено не менее 2 байт, и затем восстанавливает значение типа int, сдвигая старший байт на 8 бит влево и прибавляя к результату младший байт.

Для передачи данных с более сложной структурой можно использовать библиотеку EasyTransfer: www.billporter.info/2011/05/30/easytransfer-arduino-library/.

Несмотря на то что в этом примере контакт Tx одной платы Arduino связан проводом с контактом Rx другой, для взаимодействий точно так же можно использовать беспроводные соединения. Многие модули беспроводной связи действуют прозрачно, то есть как если бы связь осуществлялась по проводам.

Модуль GPS

В заключительном примере демонстрируется использование последовательного интерфейса ТТЛ для чтения географических координат (широты и долготы) из модуля глобальной навигационной системы (Global Positioning System, GPS), которые затем форматируются и выводятся в монитор последовательного порта (рис. 10.5).

Рис. 10.5. Чтение данных из модуля GPS в плату Arduino

Связь с модулем GPS возможна только в одну сторону, поэтому достаточно соединить вывод Tx модуля с выводом Rx на плате Arduino. В примере используется модуль GPS, выпускаемый компанией Sparkfun Venus (www.sparkfun.com/products/11058). Подобно большинству других модулей GPS, он имеет последовательный интерфейс ТТЛ и раз в секунду посылает сообщения на скорости 9600 бод.

Формат сообщений соответствует стандарту национальной ассоциации морской электроники (National Marine Electronics Association, NMEA). Сообщение — это текстовая строка, завершающаяся символом перевода строки, с полями, разделенными запятыми. Далее показано, как выглядит типичное сообщение:

$GPRMC,081019.548,A,5342.6316,N,00239.8728,W,000.0,079.7,110613,,,A*76

Поля в данном примере имеют следующие значения:

• $GPRMC — тип сообщения;

• 081019.548 — время (очень точное) в 24-часовом формате, 8:10:19.548;

• 5342.6316, N — широта, умноженная на 100, то есть 53,426316 градуса северной широты;

• 00239.8728,W — долгота, умноженная на 100, то есть 0,2398728 градуса западной долготы;

• 000.0 — скорость;

• 079.7 — курс 79,7 градуса;

• 110613 — дата, 11 июня 2013.

Остальные поля для данного примера не имеют значения.

ПРИМЕЧАНИЕ

Полный список сообщений NMEA GPS можно найти по адресу http://aprs.gids.nl/nmea/.

Далее приводится скетч для этого примера:

#include <SoftwareSerial.h>

SoftwareSerial gpsSerial(10, 11); // RX, TX (TX не используется)

const int sentenceSize = 80;

char sentence[sentenceSize];

void setup()

{

  Serial.begin(9600);

  gpsSerial.begin(9600);

}

void loop()

{

  static int i = 0;

  if (gpsSerial.available())

  {

    char ch = gpsSerial.read();

    if (ch != '\n' && i < sentenceSize)

    {

      sentence[i] = ch;

      i++;

    }

    else

    {

     sentence[i] = '\0';

     i = 0;

     //Serial.println(sentence);

     displayGPS();

    }

  }

}

void displayGPS()

{

  char field[20];

  getField(field, 0);

  if (strcmp(field, "$GPRMC") == 0)

  {

    Serial.print("Lat: ");

    getField(field, 3);  // число

    Serial.print(field);

    getField(field, 4); // широта N/S

    Serial.print(field);

    Serial.print(" Long: ");

    getField(field, 5);  // число

    Serial.print(field);

    getField(field, 6);  // долгота E/W

    Serial.println(field);

  }

}

void getField(char* buffer, int index)

{

  int sentencePos = 0;

  int fieldPos = 0;

  int commaCount = 0;

  while (sentencePos < sentenceSize)

  {

    if (sentence[sentencePos] == ',')

    {

      commaCount ++;

      sentencePos ++;

    }

    if (commaCount == index)

    {

      buffer[fieldPos] = sentence[sentencePos];

      fieldPos ++;

    }

    sentencePos ++;

  }

  buffer[fieldPos] = '\0';

}

Сообщения, посылаемые модулем GPS, имеют разную длину, но не более 80 символов, поэтому в скетче используется буфер емкостью 80 символов, который заполняется данными, пока не заполнится или не будет получен признак конца строки.

После того как полное сообщение будет прочитано, в конец буфера вставляется нулевой символ, завершающий строки в языке C. Это необходимо, только если вы пожелаете «напечатать» сообщение в его исходном виде.

Остальная часть скетча реализует извлечение полей и форматирование выходной строки для записи в монитор последовательного порта. Функция getField извлекает текст из поля с указанным индексом.