node-serialport: SerialPort write not working

Hi, I tray to send string data from pc to arduino, Opened port and write message but it does not work 😦

const SerialPort = require('serialport');
const Readline = require('@serialport/parser-readline');
const port = new SerialPort('COM7', {baudRate: 9600});

const parser = new Readline({delimiter: '\n'});
port.pipe(parser);

SerialPort.list((error, ports) => {
    if (ports) console.log(`connected to ${ports[1].manufacturer}`);
});

port.on('open', () => console.log(`port open. Data rate: ${port.baudRate}`));
port.write('0\n', (err) => {
    if (err) return console.log('Error on write: ', err.message);
    console.log('message written')
});```

// Code
```void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600); 
}

void loop() {
   if(Serial.available()){
    switch(Serial.read()){
      case '0': digitalWrite(LED_BUILTIN, LOW); break;
      case '1': digitalWrite(LED_BUILTIN, HIGH); break;
      default: break;
    }
  }
}```

- SerialPort@ 7.1.4
- Node.js 10.4.2
- Windows
- Hardware and chipset Arduino Mega 2560

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 16 (5 by maintainers)

Most upvoted comments

Just to expand on the on the above

Simple Node App

    const SerialPort = require('serialport');
    const Readline = require('@serialport/parser-readline');

	const writeDelay = 2000; // reducing this value stops it working
	const path = '/dev/tty.usbmodem113401';
	const port = new SerialPort(path, {
		lock: false,
		baudRate: 9600,
	});

	port.on('open', () => {
		setTimeout(function () {
			console.log('sending: ping');
			port.write('ping');
		}, writeDelay);
	});

	const parser = new Readline({ delimiter: '\r\n' });

	port.pipe(parser);

	parser.on('data', function (data) {
		console.log('from arduino:', data);
	});

Arduino Code

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

void loop() {
  while (Serial.available() > 0) {
    String str = Serial.readString();

    if (str == "ping") {
      Serial.println("pong");
      Serial.flush();
    }
  }
}

Debug with 2000ms delay (Working)

  serialport/bindings loading DarwinBinding +0ms
started
  serialport/stream opening path: /dev/tty.usbmodem113401 +0ms
  serialport/binding-abstract open +0ms
  serialport/stream _read queueing _read for after open +2ms
  serialport/bindings/poller Creating poller +0ms
  serialport/stream opened path: /dev/tty.usbmodem113401 +5ms
  serialport/stream _read reading { start: 0, toRead: 65536 } +1ms
  serialport/binding-abstract read +9ms
  serialport/bindings/unixRead Starting read +0ms
  serialport/bindings/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -35,
  code: 'EAGAIN',
  syscall: 'read'
} +1ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +0ms
  serialport/bindings/poller Polling for "readable" +3ms
sending: ping
  serialport/stream _write 4 bytes of data +2s
  serialport/binding-abstract write 4 bytes +2s
  serialport/bindings/unixWrite Starting write 4 bytes offset 0 bytesToWrite 4 +0ms
  serialport/bindings/unixWrite write returned: wrote 4 bytes +2ms
  serialport/bindings/unixWrite Finished writing 4 bytes +0ms
  serialport/stream binding.write write finished +4ms
  serialport/bindings/poller received "readable" +3s
  serialport/bindings/unixRead Starting read +3s
  serialport/bindings/unixRead Finished read 6 bytes +1ms
  serialport/stream binding.read finished { bytesRead: 6 } +1s
from arduino: pong
  serialport/stream _read reading { start: 6, toRead: 65530 } +3ms
  serialport/binding-abstract read +1s
  serialport/bindings/unixRead Starting read +3ms
  serialport/bindings/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -35,
  code: 'EAGAIN',
  syscall: 'read'
} +1ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +0ms
  serialport/bindings/poller Polling for "readable" +5ms

Debug with 1000ms delay (Not Working)

  serialport/bindings loading DarwinBinding +0ms
started
  serialport/stream opening path: /dev/tty.usbmodem113401 +0ms
  serialport/binding-abstract open +0ms
  serialport/stream _read queueing _read for after open +2ms
  serialport/bindings/poller Creating poller +0ms
  serialport/stream opened path: /dev/tty.usbmodem113401 +42ms
  serialport/stream _read reading { start: 0, toRead: 65536 } +1ms
  serialport/binding-abstract read +47ms
  serialport/bindings/unixRead Starting read +0ms
  serialport/bindings/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -35,
  code: 'EAGAIN',
  syscall: 'read'
} +0ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +1ms
  serialport/bindings/poller Polling for "readable" +6ms
sending: ping
  serialport/stream _write 4 bytes of data +1s
  serialport/binding-abstract write 4 bytes +999ms
  serialport/bindings/unixWrite Starting write 4 bytes offset 0 bytesToWrite 4 +0ms
  serialport/bindings/unixWrite write returned: wrote 4 bytes +1ms
  serialport/bindings/unixWrite Finished writing 4 bytes +0ms
  serialport/stream binding.write write finished +2ms

I had this problem where it was not writing to the port. I introduced a delay of 4 seconds before writing and it started working.

I tried writing port.on('open') event but it didn’t work.

Is there any other elegant way of doing this?

This is the only way I can get my application to send successfully too, a somewhat arbitrary delay of 2000ms. Much lower and it stops working.

@reconbot presumably this is not the intended behaviour and .on('open') should be sufficient to have a usable port?

Edit: apparently it is entirely expected: https://serialport.io/docs/api-stream#serialportwrite

Some devices, like the Arduino, reset when you open a connection to them. In such cases, immediately writing to the device will cause transmitted data to be lost as the devices won’t be ready to receive the data. This is often worked around by having the Arduino send a “ready” byte that your Node program awaits before writing. You can also often get away with waiting a set amount, around 400ms. See the ReadyParser for a solution to this.

I created an issue for the bug you found 👌

It’s usually wrong baudrates if you don’t get any errors. You can try debug mode if you want to see what’s going on under the hood. https://serialport.io/docs/en/guide-debugging