[SOLVED] Bluesmirf > Error when sending data to Arduino

Problem
I want to communicate with my w7n64x machine and a Seeeduino Mega. Using the USB connection works fine for me, but when I connect to the Seeeduino using the Bluesmirf's Bluetooth connection I can only receive data on the pc, but not send to the Seeeduino. I have the Bluesmirf with the blue antenna (BlueSMiRF Installation Tutorial), therefore I use the default baud rate of 115200. When trying to send anything using the serial monitor of the Arduino IDE I receive an error prompt in the console. My design requires the transmission of commands, as listed in 'protocol'.

The Bluetooth connection is established, as shown in Bluesoleil's status information. The status information shows the data flow of incoming data from the Bluesmirf and outgoing data from the pc, which is corresponding to the bytes I send and receive. The green LED on the bluesmirf is turned on. I have this problem on 2 machines (w7nx64 and w7nx86), reinstalling the bluetooth driver was no success. LynxTerm could also not receive anything by trying the 'ver' test. To replace the power supply for ther Seeeduino did not help as well.

If anyone out there has any suggestions how I can fix this or need more information, please comment my post.Thanks

Error message from Arduino IDE when sending via serial port of Bluetooth connection

[img][/img]java.io.IOException: No error in nativeDrain
	at gnu.io.RXTXPort.nativeDrain(Native Method)
	at gnu.io.RXTXPort$SerialOutputStream.flush(RXTXPort.java:1201)
	at processing.app.Serial.write(Unknown Source)
	at processing.app.Serial.write(Unknown Source)
	at processing.app.SerialMonitor.send(Unknown Source)
	at processing.app.SerialMonitor.access$100(Unknown Source)
	at processing.app.SerialMonitor$3.actionPerformed(Unknown Source)
	at javax.swing.JTextField.fireActionPerformed(JTextField.java:492)
	at javax.swing.JTextField.postActionEvent(JTextField.java:705)
	at javax.swing.JTextField$NotifyAction.actionPerformed(JTextField.java:820)
	at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1636)
	at javax.swing.JComponent.processKeyBinding(JComponent.java:2851)
	at javax.swing.JComponent.processKeyBindings(JComponent.java:2886)
	at javax.swing.JComponent.processKeyEvent(JComponent.java:2814)
	at java.awt.Component.processEvent(Component.java:6040)
	at java.awt.Container.processEvent(Container.java:2041)
	at java.awt.Component.dispatchEventImpl(Component.java:4630)
	at java.awt.Container.dispatchEventImpl(Container.java:2099)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848)
	at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:704)
	at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:969)
	at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:841)
	at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:668)
	at java.awt.Component.dispatchEventImpl(Component.java:4502)
	at java.awt.Container.dispatchEventImpl(Container.java:2099)
	at java.awt.Window.dispatchEventImpl(Window.java:2475)
	at java.awt.Component.dispatchEvent(Component.java:4460)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Setup
This is my hardware setup

Code
This is the running code on the Seeeduino

#include <Wire.h>
#include <ADXL345.h>

int inStream = 0; 
int incoming=0;
int x,y,z; 
const int vibrePin = 10;
char command[50];
ADXL345 adxl; 
boolean accelIsOn =false;
boolean vibreIsOn = false;

void setup() {
  pinMode(vibrePin, OUTPUT);
  digitalWrite(vibrePin, LOW);
  Serial.begin(115200);
  accelInit();
  vibreOff();
  establishContact();
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.println("0,0,0");   // send an initial string
    delay(300);
  }
}

void accelInit() { 
  adxl.powerOn(); 
  
   //set activity/ inactivity thresholds (0-255)
  adxl.setActivityThreshold(75); //62.5mg per increment
  adxl.setInactivityThreshold(75); //62.5mg per increment
  adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?
 
  //look of activity movement on this axes - 1 == on; 0 == off 
  adxl.setActivityX(1);
  adxl.setActivityY(1);
  adxl.setActivityZ(1);
 
  //look of inactivity movement on this axes - 1 == on; 0 == off
  adxl.setInactivityX(1);
  adxl.setInactivityY(1);
  adxl.setInactivityZ(1);
 
  //look of tap movement on this axes - 1 == on; 0 == off
  adxl.setTapDetectionOnX(0);
  adxl.setTapDetectionOnY(0);
  adxl.setTapDetectionOnZ(1);
 
  //set values for what is a tap, and what is a double tap (0-255)
  adxl.setTapThreshold(50); //62.5mg per increment
  adxl.setTapDuration(15); //625?s per increment
  adxl.setDoubleTapLatency(80); //1.25ms per increment
  adxl.setDoubleTapWindow(200); //1.25ms per increment
 
  //set values for what is considered freefall (0-255)
  adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment
 
  //setting all interupts to take place on int pin 1
  //I had issues with int pin 2, was unable to reset it
  adxl.setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN );
 
  //register interupt actions - 1 == on; 0 == off  
  adxl.setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_FREE_FALL_BIT,  1);
  adxl.setInterrupt( ADXL345_INT_ACTIVITY_BIT,   1);
  adxl.setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1);
}

void accelOn(){
  adxl.readAccel(&x, &y, &z);  
  Serial.print(x);
  Serial.print(",");
  Serial.print(y);
  Serial.print(",");
  Serial.print(z);
  Serial.println(";");
      delay(50);  
}

void accelOff(){
  //nothing
}

void vibreOn(){
  digitalWrite(vibrePin, HIGH);
}

void vibreOff(){
  digitalWrite(vibrePin, LOW);
}

void calibrate(){
 // to implement
}

void resetIncoming(){
 incoming=0; 
memset(command, 0, sizeof(command));
}

void loop() {
  
  inStream = Serial.read();
  if(inStream >=0)
  {
    Serial.print(inStream, BYTE); 
    
    command[incoming] = char(inStream);
    incoming++;  
    
    processCommand();    
  }
      runCommand();
}

void processCommand(){
    
    if(strcmp (command, "AccelOn")==0){
        //schalte accelerometer ein und gebe daten aus
          accelIsOn = true;
            resetIncoming();
    }
    
   if(strcmp (command, "AccelOff")==0){
        //schalte accelerometer aus
        accelIsOn = false;
          resetIncoming();
    }
        
  if(strcmp (command, "VibreOn")==0){
        //schalte vibre ein
         vibreIsOn= true;
           resetIncoming();
    }
    
   if(strcmp (command, "VibreOff")==0){
        //schalte vibre aus
          vibreIsOn= false;
            resetIncoming();
    }
    
    if(strcmp (command, "Calibrate")==0){ 
        //kalibriere
        calibrate();
          resetIncoming();
    }
    
}
 
 void runCommand(){   
    if (accelIsOn){
     accelOn(); 
    }
      else{
       accelOff(); 
      }
      
      if(vibreIsOn){
        vibreOn();
      }
      else{
       vibreOff(); 
      }
  }

Protocol

  • To initialise the connection, the Seeeduino sends continously (0,0,0) until it receives something via the serial port.
  • Sending the command "AccelOn" makes the Seeeduino sending the data from the attached accelerometer.
  • Sending the command "AccelOff" stops the print out of the accelerometer data.
  • Sending the command "VibreOn" toggles the vibration motor on.
  • Sending the command "VibreOff" toggles the vibration motor off.
  • Sending the command "Calibrate" does nothing yet.

I managed it to get the bluesmirf into command mode. The datasheet (http://www.sparkfun.com/datasheets/Wireless/Bluetooth/rn-bluetooth-um.pdf) shows, that there is timeframe of 60 seconds after the bt module is turned on. I connected with bluesoleil and typed in lynx term '$$$' hit Enter and got a REPLY from the device. If I now enter 'ver' it sends me the firmware version:

Ver 4.77 05/12/09
(c) Roving Networks

So, if it is possible to send and receive data to and from the device, it must be possible to solve my problem. Since there is no vivid discussion about the issue, I will keep you up to date about any progress.

After deinstalling BlueSoleil and using only Windows bluetooth stack, the error disappeared. There is no response either. I think that I get closer to the error source.

edit: Yea, I reinstalled BlueSoleil and there comes the error again... So Windows stack and Bluesoleil are not working, any suggestions which software I can use instead?

edit: widcom couldn't find my bluetooth radio and putty (http://www.jhwarren.com/bluetooth-mate/) did not want to start a session...

To sum it up: there are a lot of people having the same problem. The Admin of this site (DFRobot Tech Support Forum) proposes to use Hyperterminal.

Another solution could be to use NewSoftSerial (NewSoftSerial | Arduiniana).

I wrote myself a program to use the RXTX java lib to connect to the Bluetooth serial port. Now I'am able so receive AND send. So the problem is definitively caused by software (could explain why LynxTerm was able to check the firmware version). If you are not into programming use my code. I'am not a programmer, but a little bit of googeling will help you to modify the program to your needs:

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.awt.event.*;
import java.awt.*; 

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

public class main {
	/** Command to turn Accelerometer on */
	static final String ACCELONSTRING = "AccelOn";
	static final String ACCELOFFSTRING = "AccelOff";
	static final String VIBREONSTRING = "VibreOn";
	static final String VIBREOFFSTRING = "VibreOff";
	static final String CALIBRATESTRING = "Calibrate";
	/** Buffered input stream from the port */
	static private InputStream in;
	/** Output stream to the port */
	static private OutputStream out;
	
	    public main()
	    {
	        super();
	    }
	    
	    void connect ( String portName ) throws Exception
	    {
	        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
	        if ( portIdentifier.isCurrentlyOwned() )
	        {
	            System.out.println("Error: Port is currently in use");
	        }
	        else
	        {
	            CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
	            
	            if ( commPort instanceof SerialPort )
	            {
	                SerialPort serialPort = (SerialPort) commPort;
	                serialPort.setSerialPortParams(19200,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
	                
	                in = serialPort.getInputStream();
	                out = serialPort.getOutputStream();
	                               
	                (new Thread(new SerialWriter(out))).start();
	                
	                serialPort.addEventListener(new SerialReader(in));
	                serialPort.notifyOnDataAvailable(true);
	                

	            }
	            else
	            {
	                System.out.println("Error: Das ist kein serieller Port!");
	            }
	        }     
	    }
	    
	    static void accelOn(){
	    	Boolean	sended = false;
	    	
	    if(!sended){
	    	try {
	    		
				out.write(ACCELONSTRING.getBytes());
				

	    	} catch (IOException e) {
	    		System.out.println("Fehler beim Senden");
			}
	    	
	    }
	    	sended =true;

	    }
	    
	    static void accelOff(){
	    	Boolean	sended = false;
	    	
		    if(!sended){
		    	try {
		    		
					out.write(ACCELOFFSTRING.getBytes());
					

		    	} catch (IOException e) {
		    		System.out.println("Fehler beim Senden");
				}
		    	
		    }
		    	sended =true;

		    }
	    
	    static void vibreOn(){
	    	Boolean	sended = false;
	    	
		    if(!sended){
		    	try {
		    		
					out.write(VIBREONSTRING.getBytes());
					

		    	} catch (IOException e) {
		    		System.out.println("Fehler beim Senden");
				}
		    	
		    }
		    	sended =true;

		    }
	    
	    static void vibreOff(){
	    	Boolean	sended = false;
	    	
		    if(!sended){
		    	try {
		    		
					out.write(VIBREOFFSTRING.getBytes());
					

		    	} catch (IOException e) {
		    		System.out.println("Fehler beim Senden");
				}
		    	
		    }
		    	sended =true;

		    }
	    
	    static void calibrate(){
	    	Boolean	sended = false;
	    	
		    if(!sended){
		    	try {
		    		
					out.write(CALIBRATESTRING.getBytes());
					

		    	} catch (IOException e) {
		    		System.out.println("Fehler beim Senden");
				}
		    	
		    }
		    	sended =true;

		    }
	    
	    /**
	     * Handles the keyboard input.
	     * @param: 'A' toggles accelerometer on and off
	     * @param: 'V' toggles vibro on and off
	     */
	    
	    public class KeyReader implements KeyListener{
	    	
	    private boolean accelIsOn=false;
		private boolean vibreIsOn=false;

		public void	keyPressed(KeyEvent e ){
	    	
	    		
	    	 	}
	    
	    public void keyTyped ( KeyEvent e ){  
	    	 
	    	 }  
	    	 
	    	  public void keyReleased ( KeyEvent e ){  
	    	
	    		  if(e.equals('A')){
	    			  if(!accelIsOn){
	    				  accelOn();
	    				  accelIsOn=true;
	    				  System.out.print(accelIsOn);
	    			  }else{
	    				  accelOff();
	    				  accelIsOn=false;
	    			  }
	  	    	}
	    		  if(e.equals('V')){
	    			  if(!vibreIsOn){
	    				  vibreOn();
	    				  vibreIsOn=true;
	    			  }else{
	    				  vibreOff();
	    				  vibreIsOn=false;
	    			  }
	  	    	}
	    	  } 
	    
	    
	    }
	    
	    /**
	     * Handles the input coming from the serial port. A new line character
	     * is treated as the end of a block. 
	     */
	    public static class SerialReader implements SerialPortEventListener 
	    {
	        private InputStream in;
	        private byte[] buffer = new byte[1024];
	        
	        public SerialReader ( InputStream in )
	        {
	            this.in = in;
	        }
	        
	        public void serialEvent(SerialPortEvent arg0) {
	            int data;
	            
	            //wenn daten kommen, dann schalte accel und vibro ein
	            
	            accelOn();
	            vibreOn();
	          
	            try
	            {
	                int len = 0;
	                while ( ( data = in.read()) > -1 )
	                {
	                	
	                    if ( data == '\n' ) {
	                        break;
	                    }
	                    buffer[len++] = (byte) data;
	                }
	                System.out.print(new String(buffer,0,len));
	            }
	            catch ( IOException e )
	            {
	                e.printStackTrace();
	                System.exit(-1);
	            }             
	        }

	    }

	    /** */
	    public static class SerialWriter implements Runnable 
	    {
	        OutputStream out;
	        
	        public SerialWriter ( OutputStream out )
	        {
	            this.out = out;
	        }
	        
	        public void run ()
	        {
	            try
	            {                
	                int c = 0;
	                while ( ( c = System.in.read()) > -1 )
	                {
	                    this.out.write(c);
	                }                
	            }
	            catch ( IOException e )
	            {
	                e.printStackTrace();
	                System.exit(-1);
	            }            
	        }
	    }

	

	/**
	 * @param args
	 */
	public static void main(String[] args) {		
		listPorts();
		 
		
		try
        {
            (new main()).connect("COM6");

        }
        catch ( Exception e )
        {
            e.printStackTrace();
        }
		
	}	
	
	
	/** Auflistung aller installierten Com Ports */
	    static void listPorts()
	    {
	        java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();
	        while ( portEnum.hasMoreElements() ) 
	        {
	            CommPortIdentifier portIdentifier = portEnum.nextElement();
	            System.out.println(portIdentifier.getName()  +  " - " +  getPortTypeName(portIdentifier.getPortType()) );
	        }        
	    }
	    
	    static String getPortTypeName ( int portType )
	    {
	        switch ( portType )
	        {
	            case CommPortIdentifier.PORT_I2C:
	                return "I2C";
	            case CommPortIdentifier.PORT_PARALLEL:
	                return "Parallel";
	            case CommPortIdentifier.PORT_RAW:
	                return "Raw";
	            case CommPortIdentifier.PORT_RS485:
	                return "RS485";
	            case CommPortIdentifier.PORT_SERIAL:
	                return "Serial";
	            default:
	                return "unknown type";
	        }
		
	}
	    
}