chipKIT® Development Platform

Inspired by Arduino™

JavaScript-Arduino/ChipKIT serial port communication library with API and desktop GUI

Created Fri, 28 Oct 2016 22:22:40 +0000 by benderamp


benderamp

Fri, 28 Oct 2016 22:22:40 +0000

Hello, this is my JavaScript-Arduino/ChipKIT serial port communication library with API and desktop GUI. I had some similar code migrating from one project to another, so at some point I have decided to put common parts into reusable library. It works both on ChipKIT and classical Arduino.

Desktop application demo (Node.js+Electron) works like this: https://www.youtube.com/watch?v=uLHPr1sS558

Generally, this is question-answer library: external user (desktop) sends command via serial port (manually via serial monitor or programatically from JS desktop app), board (Arduino/ChipKIT) executes command and sends back reply.

Source code and examples

Arduino/ChipKIT core library and examples https://github.com/1i7/babbler_h

JavaScript/Node.js part: https://github.com/1i7/babbler-js - core library https://github.com/1i7/babbler-js-material-ui - ReactJS Material-UI widgets library https://github.com/1i7/babbler-js-demo - examples

Aurduino/ChipKIT library: Babbler_h

To install, make git clone https://github.com/1i7/babbler_h.git repository and move/link babbler_h, babbler_serial and babbler_json directories from repository to $HOME/Arduino/libraries, so you will have:

$HOME/Arduino/libraries/babbler_h $HOME/Arduino/libraries/babbler_serial $HOME/Arduino/libraries/babbler_json

Then restart Arduino IDE and see examples in File/Examples/babbler_h/ menu https://github.com/1i7/babbler_h/tree/master/babbler_h/examples

Flash _1_babbler_hello example https://github.com/1i7/babbler_h/blob/master/babbler_h/examples/_1_babbler_hello/_1_babbler_hello.ino

#include "babbler.h"
#include "babbler_simple.h"
#include "babbler_cmd_core.h"
#include "babbler_serial.h"

// Размеры буферов для чтения команд и записи ответов
// Read and write buffer size for communication modules
#define SERIAL_READ_BUFFER_SIZE 128
#define SERIAL_WRITE_BUFFER_SIZE 512

// Буферы для обмена данными с компьютером через последовательный порт.
// +1 байт в конце для завершающего нуля
// Data exchange buffers to communicate with computer via serial port.
// +1 extra byte at the end for terminating zero
char serial_read_buffer[SERIAL_READ_BUFFER_SIZE+1];
char serial_write_buffer[SERIAL_WRITE_BUFFER_SIZE];

/** Зарегистрированные команды */
/** Registered commands */
extern const babbler_cmd_t BABBLER_COMMANDS[] = {
    // команды из babbler_cmd_core.h
    // commands from babbler_cmd.core.h
    CMD_HELP,
    CMD_PING
};

/** Количество зарегистрированных команд */
/** Number of registered commands*/
extern const int BABBLER_COMMANDS_COUNT = sizeof(BABBLER_COMMANDS)/sizeof(babbler_cmd_t);


/** Руководства для зарегистрированных команд */
/** Manuals for registered commands */
extern const babbler_man_t BABBLER_MANUALS[] = {
    // команды из babbler_cmd_core.h
    // commands from babbler_cmd.core.h
    MAN_HELP,
    MAN_PING
};

/** Количество руководств для зарегистрированных команд */
/** Number of manuals for registered commands */
extern const int BABBLER_MANUALS_COUNT = sizeof(BABBLER_MANUALS)/sizeof(babbler_man_t);

void setup() {
    Serial.begin(9600);
    Serial.println("Starting babbler-powered device, type help for list of commands");
    
    babbler_serial_set_packet_filter(packet_filter_newline);
    babbler_serial_set_input_handler(handle_input_simple);
    //babbler_serial_setup(
    //    serial_read_buffer, SERIAL_READ_BUFFER_SIZE,
    //    serial_write_buffer, SERIAL_WRITE_BUFFER_SIZE,
    //    9600);
    babbler_serial_setup(
        serial_read_buffer, SERIAL_READ_BUFFER_SIZE,
        serial_write_buffer, SERIAL_WRITE_BUFFER_SIZE,
        BABBLER_SERIAL_SKIP_PORT_INIT);
}

void loop() {
    // постоянно следим за последовательным портом, ждем входные данные
    // monitor serial port for input data
    babbler_serial_tasks();
}

Then open Serial Monitor and try to type some commands:

ping help help --list help ping help help

you will get reply on each of them.

This will look like a kind of command-line terminal with 2 built-in commands: ping and help.

Other examples show, how to add new custom commands (this is what babbler_h API was done for):

Custom commands to blink leds: https://github.com/1i7/babbler_h/blob/master/babbler_h/examples/_2_babbler_custom_cmd/_2_babbler_custom_cmd.ino

Custom commands with params (pin_mode and digital_write transport): https://github.com/1i7/babbler_h/blob/master/babbler_h/examples/_3_babbler_cmd_params/_3_babbler_cmd_params.ino

Library is divided into 3 layers:

  • transport layer: read input, detect packets, call input packet handler, write output
  • cmd api layer: add functions with own code and easily register them as commands by name
  • i/o protocol layer: take care of protocol details without impacting user code (receive input and send reply as plain text or wrap to some kind of JSON or XML)

They are mostly independent

For example, you can use babbler_serial (babbler_serial.h) module alone without cmd api layer (babbler.h) for raw input-reply: https://github.com/1i7/babbler_h/blob/master/babbler_h/examples/babbler_basic_io/babbler_basic_io.ino

Or add new communication transport modules in addition to babbler_serial (wifi and bluetooth are in mid-time plans).

JavaScript/Node.js library: babbler-js

Babbler-js library allows to communicate with Babbler-based Arduino/ChipKIT boards from Node.js environment. It would work only with JSON-based i/o protocol firmware with at least "ping" command available on board.

The device is considered connected when:

  1. Serial communication port is opened
  2. "ping" command (wrapped to JSON) is sent to device and device sends back reply with "ok" status (also wrapped to JSON).

To install/run

For JS desktop application first flash babbler_json_io example with JSON-based io-protocol to Arduino/ChipKIT (Arduino Mega would be required) https://github.com/1i7/babbler_h/blob/master/babbler_h/examples/babbler_json_io/babbler_json_io.ino

For JS part, install node, then git clone https://github.com/1i7/babbler-js-demo.git repo.

For basic API example go to babbler-basic dir, run: npm install node babbler-basic.js

https://github.com/1i7/babbler-js-demo/blob/master/babbler-basic/babbler-basic.js

var BabblerDevice = require('babbler-js');

var babblerDevice = new BabblerDevice();

babblerDevice.on('connected', function() {
    console.log("connected");
    
    console.log("send cmd: ping");
    babblerDevice.sendCmd("ping", [],
        // onReply
        function(cmd, params, reply) {
            console.log("got reply on '" + cmd + " " + params + "': " + reply);
        },
        // onError
        function(cmd, params, err) {
            console.log("fail with '" + cmd + " " + params + "': " + err);
        }
    );
    
    console.log("send cmd: help --list");
    babblerDevice.sendCmd("help", ["--list"],
        // onReply
        function(cmd, params, reply) {
            console.log("got reply on '" + cmd + " " + params + "': " + reply);
        },
        // onError
        function(cmd, params, err) {
            console.log("fail with '" + cmd + " " + params + "': " + err);
        }
    );
});

babblerDevice.on('disconnected', function(error) {
    console.log("disconnected" + (error != undefined ? ": " + error : ""));
});

babblerDevice.connect("/dev/ttyUSB0");
//babblerDevice.connect("/dev/ttyUSB0", {baudRate: 9600});

replace "/dev/ttyUSB0" with the correct device name. This code would connect to device and would send "ping" and "help --list" commands on success.

To run GUI desktop app (Electron+ReactJS+MaterialUI) like on video, go to babbler-serial-react dir and run: npm install ./babbler-serial.sh

Most custom code of this app is here: https://github.com/1i7/babbler-js-demo/blob/master/babbler-serial-react/react-app-ui.js

Notes for JS and custom commands:

  • Each command on device should be executed and return reply not later than in 5 seconds after being called, it would be considered failed on the JS side elsewhere.