3
votes

I'm trying to get my Raspberry Pi/Node.js to communicate with an Arduino Uno using node-serialport. I'm having trouble with the following block of code:

Raspberry Pi

var SerialPort = require("serialport").SerialPort;
var serialPort = new SerialPort("/dev/ttyACM0", {
  baudrate: 9600
});

serialPort.on("open", function () {
  console.log('open');

  serialPort.on('data', function(data) {
    console.log('data received: ' + data);
  });

  serialPort.write(new Buffer('4','ascii'), function(err, results) {
    console.log('err ' + err);
    console.log('results ' + results);
  });
});

Arduino

// LED on pin 12
int led = 12;

// Incoming serial data
int data=0;

void setup() {                
  // Pin 12 set to OUTPUT
  pinMode(led, OUTPUT);

  // Start listening on the serialport
  Serial.begin(9600);
}

void loop() {

  if(Serial.available()>0){

      // Read from serialport
      data = Serial.read();      

      // Check and see if data received == 4
      if(data=='4') {   
        // Blink the LED 3 times
        for(int i=0;i<3;i++){
            digitalWrite(led, HIGH);
            delay(1000);
            digitalWrite(led,LOW);
            delay(1000);
        }

       // Reset data to 0
       data=0;
     }
  }
}

I am only able to get the Arduino to blink the LED if I wrap a for loop around the serialPort.write() function. At the 40th loop iteration or so the LED finally starts blinking and will continue blinking until serialPort.write() loop is finished. This leads me to believe that I'm encountering some sort of timing issue. I'm looking for a more elegent (and non-blocking) solution to blinking the LED on the Arduino via the Pi. Any help would be greatly appreciated.

Thanks! Bobby

2

2 Answers

2
votes

The problem had to do with Arduino's "AutoReset" see more here.

I didn't actually disable autoreset... I went ahead and implemented the code I posted above. I require user interaction to trigger SerialPort.write(). This works as long as there is a few seconds between when the serial connection is opened and the first write.

1
votes

My guess is that new Buffer('4','ascii') is doing an ASCII string, and not an ASCII character. The difference being that you're not sending 4, or 44444444… using your loop but 4\0 or 4\04\04\04\04\04\04\0… using your loop.

So when you do Serial.available(), it returns 2, as it got two byte buffered, but you only read one byte. As the buffer of the Arduino is a circular buffer that gets overwritten with new data over time, what can happen is that you're only reading the \0s, until over time the timings shift and you get to read only the 4s.

My advice would be to either read as many characters as there is in the buffer, or simply discard invalid reads, as Serial.read() return -1 when the buffer is empty:

const int led=12;

void setup() {                
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // Read from serialport
  int data = Serial.read();

  // Check and see if data received == 4
  // and thus discard data==-1 or data==`\0`
  if(data=='4') {   
    // Blink the LED 3 times
    for(int i=0;i<3;i++){
        digitalWrite(led, HIGH);
        delay(1000);
        digitalWrite(led,LOW);
        delay(1000);
    }
  }
}