Serial port not working?

10,703

Solution 1

I recently dabbled into this. The Arduino automatically resets when it receives serial communication from most things other than the Arduino IDE. This is why you can send from the IDE but not node.js.

I have an Uno and put a capacitor between Reset and Ground.Here's a page with some good info on the subject.
Good luck. http://arduino.cc/playground/Main/DisablingAutoResetOnSerialConnection

Solution 2

I use node on a daily basis to send actions to my Arduino via usb or via bt and it works great in both cases. I think your problem comes from sending letters. You should send a buffer instead, with the ascii value of the letter, just like that:

myPort.write(Buffer([myValueToBeSent]));

also, for this, I think you would be better with some "logic" interface, with data headers, number of actions, stuff like that. It is no required for you but it will make your code more robust and easier to modify in the future.

Here is an example of how I do it. First, Node:

var dataHeader = 0x0f, //beginning of the data stream, very useful if you intend to send a batch of actions
myFirstAction = 0x01,
mySecondAction = 0x02,
myThirdAction = 0x03;

You then call them like you did:

everyone.now.MyBatchOfActions = function() {
    sp.write(Buffer([dataHeader]));

    sp.write(Buffer([0x03])); // this is the number of actions for the Arduino code

    sp.write(Buffer([myFirstAction]));
    sp.write(Buffer([mySecondAction]));
    sp.write(Buffer([myThirdAction]));
}

This way it is easy on the Arduino to Serial.read() the data: (Note that you need to define data header and data footer somewhere)

void readCommands(){
    while(Serial.available() > 0){

        // Read first byte of stream.
        uint8_t numberOfActions;
        uint8_t recievedByte = Serial.read();

        // If first byte is equal to dataHeader, lets do
        if(recievedByte == DATA_HEADER){
            delay(10);

            // Get the number of actions to execute
            numberOfActions = Serial.read();

            delay(10);

            // Execute each actions
            for (uint8_t i = 0 ; i < numberOfActions ; i++){

                // Get action type
                actionType = Serial.read();

                if(actionType == 0x01){
                    // do you first action
                }
                else if(actionType == 0x02{
                    // do your second action
                }
                else if(actionType == 0x03){
                    // do your third action
                }
            }
        }
    }
}

I hope I'm clear and I hope it helps! Cheers!

Solution 3

In my case the issue was the reset, but that the serial port was opened - but not available for write until the reset has finished. Putting a 3s delay before writing to the port fixed the issue. Writing ASCII was not an issue.

Solution 4

On the capacitor and reset issue... There is a small capacitor between one of the serial control lines and reset on the Arduino in the later models. This capacitor causes the Arduino to reset when the port is opened but otherwise does not interfere with normal serial operation.

This reset trick allows the code upload to reset the Arduino as part of the upload process. When the Arduino starts up the code boot loader runs first for a short time before the loaded code runs.

The upload process is: Reset the Arduino which starts the boot loader, start the upload process in the Arduino IDE, establish communications, upload, then run the loaded code. When the Arduino starts up it waits for uploads for a short period of time, if none are received, it moves on to running the code.

I find this very useful as it allows us to effectively reset the Arduino just by closing and opening the port. In the old Arduino's, without this capacitor, you had to press the reset button at the right time to get the code to upload. And the timing was such that the Arduino spent much more time waiting before it started with the uploaded code.

In the problem described here, I do not believe he was having any troubles due to the reset trick used. It should have had only the effect of resetting the Arduino when he opened the serial port, and from the looks of his information, this is a desired side-effect.

Share:
10,703
Ryan Walmsley
Author by

Ryan Walmsley

Updated on June 17, 2022

Comments

  • Ryan Walmsley
    Ryan Walmsley almost 2 years

    I made a program that sends out data to my arduino which detects what was sent and then turns on the correct pin according to what key is pressed.

    When using the arduino software from my windows computer the arduino sketch works fine, I can make each pin turn on and off by sending either W A S Or D.

    When sending via node the RX light on the arduino flashes but nothing else happens.

    Can anyone help?

    Node.js program:

    var httpServer = require('http').createServer(function(req, response){ /* Serve your static files */ })
    httpServer.listen(8080);
    
    var nowjs = require("now");
    var everyone = nowjs.initialize(httpServer);
    
    everyone.now.logStuff = function(msg){
        console.log(msg);
    }
    
    var SerialPort = require('serialport2').SerialPort;
    var assert = require('assert');
    
    var portName;
    
    if (process.platform == 'win32') {
      portName = 'COM4';
    } else if (process.platform == 'darwin') {
      portName = '/dev/cu.usbserial-A800eFN5';
    } else {
      portName = '/dev/ttyUSB0';
    }
    
    var readData = '';
    var sp = new SerialPort();
    
    sp.on('close', function (err) {
      console.log('port closed');
    });
    
    sp.on('error', function (err) {
      console.error("error", err);
    });
    
    sp.on('open', function () {
      console.log('port opened... Press reset on the Arduino.');
    });
    
    sp.open(portName, {
      baudRate: 9600,
      dataBits: 8,
      parity: 'none',
      stopBits: 1,
      flowControl: false
    });
    
    everyone.now.forward = function() {
    sp.write("w");
    }
    
    everyone.now.back = function() {
    sp.write("s");
    }
    
    everyone.now.left = function() {
    sp.write("a");
    }
    
    everyone.now.right = function() {
    sp.write("d");
    }
    
    sp.on('data', function(data) {
      console.log(data.toString());
    });
    

    Arduino Program:

    void setup(){
      Serial.begin(9600);
      Serial.write("READY");
      //Set all the pins we need to output pins
      pinMode(8, OUTPUT);
      pinMode(9, OUTPUT);
      pinMode(10, OUTPUT);
      pinMode(11, OUTPUT);
    }
    
    void loop (){
      if (Serial.available() > 0) {
    
        //read serial as a character
        char ser = Serial.read();
        Serial.write(ser);
        //NOTE because the serial is read as "char" and not "int", the read value must be compared to character numbers
        //hence the quotes around the numbers in the case statement
        switch (ser) {
          case 'w':
            move(8);
            break;
          case 's':
            move(9);
            break;
          case 'a':
            move(10);
            break;
          case 'q':
            move(10);
            move(8);        
            break;
          case 'd':
            move(11);
            break;
          case 'e':
            move(11);
            move(8);
            break;
        }
      }
    }
    
    void move(int pin){
      Serial.print(pin);  
      digitalWrite(pin, HIGH);
      delay(1);
      digitalWrite(pin, LOW);
    }
    
  • Ryan Walmsley
    Ryan Walmsley almost 12 years
    Hmm, but the examples even ask for you to reboot the arduino :S
  • ZnArK
    ZnArK almost 12 years
    In order for the IDE to upload code, it has to be able to reboot the Arduino. So, whenever you do an upload, you have to remove the capacitor, let it upload, then replace the capacitor for serial to work properly (without restarting). Your code looks good, especially if it works properly when sending serial data from the IDE.
  • Ryan Walmsley
    Ryan Walmsley almost 12 years
    Hmm, but when using the IDE it sends, when using node It don't. At the moment I'm waiting for a Logic Level Converter so I can use it with the serial ports on my Raspberry Pi. If it don't work when I do that then I will post again ;)
  • ZnArK
    ZnArK almost 12 years
    That's perfectly correct, without the capacitor/resistor, you have few choices for serial communication. I'm quite sure that your node.JST app will work once you try adding this.
  • Ryan Walmsley
    Ryan Walmsley almost 12 years
    I think this done it, But i then decided to just use the GPIO pins on the Pi when I got a Bigtrak Jr for it instead.
  • Visual Micro
    Visual Micro over 11 years
    The arduino will reboot when you connect with serial only if the dtr pin on the serial is high. So in your example the dtr of the SerialPort is defaulting to high/enabled. You should find a setting on the SerialPort to disable DTR. In C# I think it is SerialPort.DtrEnabled=false
  • Ben
    Ben over 8 years
    Visual Micro, I can confirm your remark about disabling DTR in C# and that works with Arduino. For node.js I found this article barryvandam.com/node-js-communicating-with-arduino where they initialize the serialport with 'flowControl: false' I expect this should not send any signal on the DTR/DTS pins: serialPort = new SerialPort(portName, { baudrate: 9600, dataBits: 8, parity: 'none', stopBits: 1, flowControl: false });