Parsování výstupu z Arduina pomocí Node.js

Zápisník experimentátora

Hierarchy: Node.js

V dnešním článku si ukážeme, jak je možné výstup z Arduino parsovat v JavaScriptu. Arduino bude měřit teplotu pomocí senzoru DS18B20 a výsledky bude odesílat na sériový port. Obsah ze sériového portu budeme zpracovávat pomocí kódu v Node.js a budeme si ho transformovat do objektů. Získané objekty můžeme následně zpracovávat.

Arduino a DS18B20

Arduino a senzory jsou zapojeny podle obrázku. Na breadboardu mám dva senzory teploty. Oba jsou zapojeny pomocí jednoho pull-up rezistoru a k Arduinu jsou připojeny přes pin 2. Počet senzorů není důležitý. Měly by být minimálně dva, abychom měli dost podkladů pro Node.js. Arduino pro každý senzor získá dva údaje.

  • Jedinečnou adresu senzoru.
  • Odměřenou teplotu.

Získané údaje se odešlou na sériový port. Pro všechny senzory se výsledky odešlou v jednom řádku. Výsledek vypadá takto. Pro lidské oči to je nepříliš čitelné, ale takto máme k dispozici tabulku, která obsahuje jednotlivé sloupce odděleny středníkem. Údaje v takové podobě víme na straně Node.js dobře parsovat.

Zdrojový kód programu pro Arduino vypadá takto. Nastaví se rozlišení každého senzoru na 12 bitů a každých 5 sekund se odešle jeden řádek s měřeními na sériový port.

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

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 12 // Maximum resolution

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

int numberOfDevices; // Number of temperature devices found

DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address

void setup(void) {
  Serial.begin(9600);
  sensors.begin();
  numberOfDevices = sensors.getDeviceCount();
  for (int i = 0; i < numberOfDevices; i++) {
    if (sensors.getAddress(tempDeviceAddress, i)) {
      sensors.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);
    }
  }
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++) {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress) {
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print(tempC);
}

void loop(void) {
  sensors.requestTemperatures();
  for (int i = 0; i < numberOfDevices; i++) {
    if (sensors.getAddress(tempDeviceAddress, i)) {
      printAddress(tempDeviceAddress);
      Serial.print(";");
      printTemperature(tempDeviceAddress);
      Serial.print(i==(numberOfDevices-1) ? "" : ";");
    }
  }
  Serial.println("");
  delay(5000);
}

Parser v Node.js

Zdrojový kód v Node.js konvertuje údaje z každého řádku a mění je do podoby objektů. Každý objekt obsahuje dva parametry.

  • id - Jedinečná adresa senzoru.
  • temperature - Odměřená teplota.

Podle toho, kolik senzorů jsme měli, se ve výsledku objeví v javascipte tolik objektů. Tyto objekty si umíme následně pohodlně zpracovat. Můžeme je například.

  • Uložit do databáze.
  • Odeslat do cloudu.

Pro potřeby tohoto článku je pouze vypisuji na konzolu. Výsledek vypadá takto.

Zdrojový kód programu vypadá takto. Podobný kód jsem již publikoval v předchozím článku o komunikaci mezi Node.js a Arduinem. Na parsování využívám třídu DS18B20Controller. Ta je odvozena od třídy events.EventEmiter. To mi umožňuje odesílat události. Událostí je dvojice id a temperature. Příklad odeslání události je řádek self.emit ('temperature', t);. Zpracování události najdete na řádku ds18b20.on ('temperature', ..., kde se parametr události vypíše na konzolu.

'use strict';

const serialport = require('serialport');
const readline = require('readline');
const sp_readline = serialport.parsers.Readline;
const events = require('events');

class DS18B20Controller extends events.EventEmitter {

  constructor(config) {
    super();
    var self = this;
    this.config = config;
    this.port = new serialport(this.config.port, {
      baudRate: this.config.baudrate || 9600
      });
    const parser = new sp_readline();
    this.port.pipe(parser);

    parser.on('data', function(data){
      //console.log(data);
      var ar = data.trim().split(';');
      for(var i=0;i<ar.length;i+=2) {
        var t = {
          id: ar[i],
          temperature: parseFloat(ar[i+1])
        };
        self.emit('temperature', t);
      }
    });

    this.port.on('error', function(e) {
      console.error(e.message);
      process.exit(0);
    });

    this.port.on('open', function() {
      console.log('Serial Port Opened');
    });

    this.port.on('close', function(err) {
      console.log('Serial Port Closed: ' + err);
      process.exit(0);
    });

  }
}

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  prompt: 'select port> '
});

var idx = 0;
var ports = [];

console.log('COM port list:');
serialport.list(function (err, p) {
  p.forEach(function(p) {
    ports.push(p.comName);
    console.log(' [' + idx + '] ' + p.comName);
    idx++;
  });

  rl.prompt();
 
  rl.on('line', function(line) {
    //console.log(line);
    //console.log(ports);
    if(line<idx) {
      console.log('Opening ' + ports[Number(line)]);
      const ds18b20 = new DS18B20Controller({port: ports[Number(line)], baudrate: 9600});
      ds18b20.on('temperature', function(temp) {
        console.log('Temperature:', temp);
      });
 
    } else {
      console.error('ERROR: Wrong port number');
      process.exit(0);
    }
  });
 
  rl.on('close', function() {
    console.log('Bye!');
    process.exit(0);
  });

});

Zdrojový kód

Zdrojový kód se nachází na serveru GitHub.

Pokud máte nainstalovaný program git, můžete si zdrojové kódy nainstalovat například takto. Pokud ho nemáte, dají se stáhnout i jako zip archiv.

Instalace pro Arduino

Do svého Arduina nahrajte kód pomocí Arduino IDE.

Instalace pro Node.js

Spusťte si konzolu příkazového řádku. Důležitý je poslední řádek, který nainstaluje všechny související knihovny, které jsou v souboru package.json.

cd d:
mkdir arduino
cd arduino
git clone https://github.com/roboulbricht/arduinoslovakia
cd arduinoslovakia\node.js\arduino_ds18b20_parser\node
npm install

17.01.2018


Menu