вторник, 7 января 2014 г.

Приём на сервере данных от Arduino

Для передачи данных на сервер буду использовать последовательное соединение (serialport). Соединяю Arduino с компьютером через USB.

Код для Arduino (из этого примера):
/*
  AnalogReadSerial
 Reads an analog input on pin 0, prints the result to the serial monitor 

 This example code is in the public domain.
 */

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  Serial.println(sensorValue);
}

Т.е. на сервере буду ловить целые числа.


Код для сервера (node.js), как не надо делать:
var SerialPort = require("serialport").SerialPort;
var serialPort = new SerialPort("/dev/ttyACM0", {
  baudrate: 9600
});

serialPort.on('data', function (data) { // call back when data is received
  console.log(data.toString() + ';');
});

Как видно, тут есть нюанс. Данные от Arduino приходят в виде каши, которую надо упорядочить. Т.е. вывод выглядит примерно так.
35;
0;
35;
1;
3;
51;
35;
0;
34;
9;
351
350;
3493;
49;
350;

Чтобы получать адекватные данные, разбираю их вручную, т.е. складываю в буфер readData и вручную разделяю на порции (в данном случае смотрю, чтобы данные были разделены с помощью \n и \r).
var SerialPort = require("serialport").SerialPort;
var serialPort = new SerialPort("/dev/ttyACM0", {
  baudrate: 9600
});

var readData = "";
serialPort.on('data', function (data) { // call back when data is received
  dataStr = data.toString();

  for (var i = 0, l = dataStr.length; i < l; i++) {
    if (dataStr.charAt(i) != "\n" && dataStr.charAt(i) != "\r") {
      readData += dataStr.charAt(i);
    }
    else if (readData) {
      console.log(readData + ';');
      readData = "";
    }
  }

});

Получаю то, что требовалось:
351;
350;
349;
351;
350;
349;
349;
350;

По сути, получился Serial Monitor.

UPD:
В дальнейшем заметил, что в начале вывода присутствуют странные символы, от них избавился так:
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;
var serialPort = new SerialPort("/dev/ttyACM0", {
  baudrate: 9600
});

serialPort.on("open", function () {
  console.log('');
  serialPort.flush();
  var readData = "";
  serialPort.on('data', function (data) { // call back when data is received
    var dataStr = data.toString();

    for (var i = 0, l = dataStr.length; i < l; i++) {
      if (dataStr.charAt(i) != "\n" && dataStr.charAt(i) != "\r") {
        readData += dataStr.charAt(i);
      }
      else if (readData) {
        console.log(readData + ';');
        readData = "";
      }
    }
  });
});

Вариант с указанием потока ввода:
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;
var serialPort = new SerialPort("/dev/ttyACM0", {
  baudrate: 9600
});

serialPort.on("open", function () {
  console.log('');
  serialPort.flush();
  var readline = require('readline');
  var rl = readline.createInterface({
    input: serialPort,
    output: process.stdout
  });
});

Почему в обоих случаях без строки console.log('') работает криво, пока идей нет. Надеюсь, что это связано не с чтением из порта, а с выводом в консоль. Но мне интереснее, что будет при выводе в веб интерфейс, это я попробую сделать в следующий раз.