Search code examples
node.jsnode-serialport

Node.js stops responding when using serialport


I'm using node.js for the first time with a simple website to control a motor.

On the website are 2 buttons: "Left" and "Right". You have to press and hold the "Left" or "Right" button to turn the motor. When you let the button go the motor stops. The motor is connected to an Arduino on the serialport on the server. It works, but

Problem

When I use it on my phone and spam the buttons the server sometimes stops responding for everyone until I restart the server. I thought the functions were called too fast because of the WiFi latency. So I tried calling the functions in the Chrome console.

LeftPressed();LeftReleased();LeftPressed();LeftReleased();

And indeed, after running them a few times the server stops responding. No error, no crash..

When I remove motorPort.write(message); keeps the server responding.

How can I prevent the server from stopping to respond?

Client (Javascript in browser)

function LeftPressed() {      
    socket.emit('steer', { left: true });
}
function LeftReleased() {       
    socket.emit('steer', { left: false });
}
function RightPressed() {        
    socket.emit('steer', { right: true });
}
function RightReleased() {        
    socket.emit('steer', { right: false });
}

Server (node.js)

const SerialPort = require("serialport");
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server)    
const motorPort = new SerialPort('/dev/arduinoUnoMicroUSB', {
    baudrate: 9600,
});

app.use(express.static('web'));
server.listen(8081, function () {
    console.log("Server running...");
});

io.on('connection', function (socket) {  
    socket.on('steer', function (data) {
        var message = "2"; //stop   

        if (data.left != undefined) {
            console.log("Left: " + data.left); //log to Console (below)
            if (data.left) {
                message = "1" //turn left
            }
        }    

        if (data.right != undefined) {
            console.log("Right: " + data.right);
            if (data.right) {
                message = "3"; //turn right
            }
        }    

        motorPort.write(message); //send message over serial port            
    });   
});

Console output example: "Left" button clicked

Server running...
Left: true        //pressed   (motor turning left)
Left: false       //released  (motor stops)

Solution

  • I got it working with this. It's not 100% perfect, but at least the server keeps responding. If you think there is a better way, I am always open for improvements.

    const SerialPort = require("serialport");
    const express = require('express');
    const app = express();
    const server = require('http').createServer(app);
    const io = require('socket.io')(server);
    const motorPort = new SerialPort('/dev/arduinoUnoMicroUSB', {
        baudrate: 9600,
    });
    
    app.use(express.static('web'));
    server.listen(8081, function () {
        console.log("Server running...");
    });
    var ready = true;
    var NotSendMessages = [];
    io.on('connection', function (socket) {
        socket.on('steer', function (data) {
            var message = "2"; //stop   
            if (data.left != undefined) {
                console.log("Left: " + data.left);
                if (data.left) {
                    message = "1" //turn left
                }
            }
    
            if (data.right != undefined) {
                console.log("Right: " + data.right);
                if (data.right) {
                    message = "3"; //turn right
                }
            }
            if (!ready) {
                console.log("cats!!!");
                NotSendMessages.push(message);
            } else {
                send(message);
            }
        });
    });
    function send(message) {
        motorPort.write(message, function () {
            ready = false;
            motorPort.drain(function () {
                motorPort.flush(function () {
                    ready = true;
                });
            });
        });
    }
    setInterval(function () {
        if (NotSendMessages.length > 0 && ready) {
            send(NotSendMessages.shift());
        }
    }, 50);