chipKIT® Development Platform

Inspired by Arduino™

Serial communication: need to wait 5 seconds before sending data after port is open

Created Sun, 02 Oct 2016 19:12:07 +0000 by benderamp


benderamp

Sun, 02 Oct 2016 19:12:07 +0000

Hello, I am writing desktop application in JavaScript/node.js to communicate with ChipKIT Uno32.

For testing: board sketch is simple Blink with nothing else. JS code below.

  • It opens board serial port and
  • starts sending "ping" message immediately just after receives "open" event with some defined timeout.

What I have noted is that the sketch will not start working (the led won't blink) if I send ping message every 1-2-3-4 seconds. It will only start blinking if I send "ping" message every 5 seconds (or will not send it at all).

It will never blink this way (from 'open' event):

// Arduino sketch will never start to work this way
    setInterval(writeData, 3000);

Will blink this way (4000 millis will not work either)

// the only way to make Arduino sketch to work (if we want to send messages)
    setInterval(writeData, 5000);

and another test - the board will start blinking after the last writeData is executed:

// Arduino sketch will start to work after the 
    // last writeData is executed
    //writeData();
    setTimeout(writeData, 3000);
    setTimeout(writeData, 6000);
    setTimeout(writeData, 9000);
    setTimeout(writeData, 12000);

If I wait for 5 seconds after the port "open" event and then start sending "ping" every second, nothing bad would happen, the led would blink, sketch won't freeze.

So what I suppose here is that the board bootloader might expect some commands in serial port when the board is rebooted (even if the sketch does not call Serial.begin) for some period of time (5 seconds?) and if it receives something wrong, it ignores it, but resets wait timeout and expects another block of data etc. So if I send some garbage to serial port every 3-4 seconds just after reboot, the board will never load to flashed sketch.

Am I right here? Should I always wait for 5 seconds before sending any data to opened serial port, or this might vary in some other cases? Or may be I can skip this earlier by sending some kind of special char to bootloader? Where can I read about this behaviour documented, so I can reference it from my code.

The whole js program (for reference):

// https://github.com/EmergingTechnologyAdvisors/node-serialport#usage
var SerialPort = require('serialport');

port = new SerialPort("/dev/ttyUSB0", {
    // скорость
    baudRate: 9600,
    // получать данные по одной строке
    parser: SerialPort.parsers.readline('\n'),
    // не открывать порт сразу здесь
    autoOpen: false,
    lock: true
});

function writeData() {
    data = "ping";
    console.log("write: " + data);
    port.write(data,
        function(err) {
            if(!err) {
                // данные ушли ок
                console.log("write ok");
            } else {
                // ошибка записи в порт 
                // (например, порт открыт, но не хватает прав на запись)
                console.log("write error: " + err);
            }
        }
    );
}

// 
// События
// 

// порт открылся
port.on('open', function () {
    console.log("open");
    
    // Arduino sketch will start to work after the 
    // last writeData is executed
    //writeData();
    setTimeout(writeData, 3000);
    setTimeout(writeData, 6000);
    setTimeout(writeData, 9000);
    setTimeout(writeData, 12000);
    
    // Arduino sketch will never start to work this way
    //setInterval(writeData, 3000);
    
    // the only way to make Arduino sketch to work
    //setInterval(writeData, 5000);
});

// пришли данные
port.on('data', function(data) {
    console.log("data: " + data);
});

// отключили устройство (выдернули провод)
port.on('disconnect', function () {
    console.log("disconnect");
});

// 
// Действия
//

// открываем порт
port.open(function(err) {
    if(err) {
        // не получилось открыть порт
        console.log("Error opening: " + err);
    } else {
        console.log("Open OK");
        //setInterval(writeData, 1000);
    }
});

majenko

Sun, 02 Oct 2016 19:35:50 +0000

I can see no logical reason for the behaviour you describe. The bootloader will only cancel the countdown to exiting if it receives a valid STK500V2 "Signon" message. Anything else should just let the bootloader timeout.

I have a chipKIT WiFire connected to an embedded Linux host which blasts it with packets of data all the time. Pressing reset so it cycles via the bootloader has no effect other than a couple of seconds delay. The bootloader ignores all the data being sent to it because it's not valid STK500V2 packets.

Mind, the sending program is written in C, not JS, so accesses the port using proper low-level functions - who knows what JS is doing to the port...


benderamp

Sun, 02 Oct 2016 20:07:40 +0000

I am using node-serialport library for node.js (version 4.0.1; tried 5.0.0-beta1 with same result)

https://github.com/EmergingTechnologyAdvisors/node-serialport/blob/master/lib/serialport.js#L276

they have C++ backends for Unix/Win here (I am using on Linux Ubuntu 14.04): https://github.com/EmergingTechnologyAdvisors/node-serialport/tree/master/src

Changing speed from 9600 to 115200 has same effect. Tried to send some different strings (in case if "ping" might be accepted like valid by some accident) like "xxx", "mmm" ect, same effect.

I have put my code here: https://github.com/1i7/snippets/tree/master/js-web/serialport-basic

Only 2 files: package.json and serialport-basic.js

In case if node+npm are installed, need to run in the directory with those 2 files

npm install

then

node serialport-basic.js

ChipKIT Uno32 sketch - is basic Blink from examples.


benderamp

Sun, 02 Oct 2016 20:18:46 +0000

Just tried another test with no JS. Run linux screen utility:

screen /dev/ttyUSB0 9600

it gives empty screen in console, I reboot board with reset button and type random keys to this empty console screen - the board stops to load until I stop typing and wait for some time. It then continues to load and starts blinking (Blink sketch).

Run

killall screen

in another terminal to kill screen+serial port communication session (or type ctrl+A, then '').


majenko

Sun, 02 Oct 2016 22:04:23 +0000

Nope, can't replicate it. Uno32, freshly flashed with the official Digilent bootloader, screen on Linux (and tried minicom too), works perfectly. Passes through the bootloader and the LEDs start blinking as I have ordained in my little sketch.


benderamp

Mon, 03 Oct 2016 20:38:09 +0000

ok, I have tested screen with 2 ChipKIT Uno32 and 1 Max32, all freezed when typing keys.

Then reflashed latest bootloader chipKIT-Uno32-v01000303.hex with PICKit3+MPLAB IPE to one Uno32 from here http://chipkit.net/wiki/index.php?title=ChipKIT_Uno32 https://reference.digilentinc.com/chipkit_uno32:chipkit_uno32

And now this Uno32 does not freeze on key press during boot, another one (with old bootloader) does freeze as before. JS sketch also now works in any mode. So this was old bootloader issue. thank's


majenko

Tue, 04 Oct 2016 00:52:16 +0000

Sounds like it - no wonder I couldn't get it to do it. I do know that Digilent had some interesting issues with their bootloader at one point - this may be a symptom of the same thing.