How to communicate with arduino through a C++ app or Linux and serial

It seems I cannot find any way to programatically serially connect to the arduino. I can use picocom and it works, but as soon as I try to use a c++ program using a class that works with other serial devices, it just does not work with arduino. It never gets data and instead just hangs waiting for data. I even tried doing "echo command > /dev/path" and then "cat /dev/path" which works for all serial devices but with arduino it's just not working.

Is there anything special I need to do when I connect? Or is there an easier way to interface with a C++ app? I'm using the Uno.

Are you using the right port?

I normally use the screen command as described here:

http://bec-systems.com/site/859/the-easy-way-to-get-serial-terminal-in-linux

for a rapid serial port (mind you I'm on a Mac, not Linux).

Are you sure the settings are correct for the Serial class you're using?

Is there anything special I need to do when I connect?

Is this a trick question? Of course there are things that you need to set BEFORE you connect. Whether you consider them "special" depends on the length of the bus, I guess.

Yeah I'm using the right port as I set an alias for it, and it works when I use picocom. So what are the things I need to do before I connect? This is the code for my C++ class, anything special I need to add like certain flags or something? This class works fine with other serial devices, so that's why I'm asking if there's anything special for arduino that other devices would not need.

SerialConnector::SerialConnector()
{
	m_Path="";
	m_conactive=false;
	DebugMode=false;
	m_fd=0;
}

SerialConnector::SerialConnector(string path)
{
	m_Path=path;
	m_conactive=false;
	DebugMode=false;
	m_fd=0;
}


void SerialConnector::ScreenOutput(string output)
{
	//if(DebugMode)LOGGER->Log(5, m_Path + ": " + output);
}




void SerialConnector::SetPath(string path)
{
	m_Path=path;
}


bool SerialConnector::Open()
{
	if(m_Path=="")
	{
		ScreenOutput("No path specified");
		return false;
	}


	
	//init stuff
	
	struct termios tio;


	memset(&tio,0,sizeof(tio));
	tio.c_iflag=0;
	tio.c_oflag=0;
	tio.c_cflag=CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
	tio.c_lflag=0;
	tio.c_cc[VMIN]=1;
	tio.c_cc[VTIME]=5;


	
	//connect
	m_fd=open(m_Path.c_str(), O_RDWR | O_NONBLOCK);	
	
	
    cfsetospeed(&tio,9600);            
	cfsetispeed(&tio,9600);            

	//this is required, it seems that it only needs to be called once per server reboot. It sets some kind of global thing that prevents the serial device (in my test: uk1104 from canakit) to go insane and spam junk
	tcsetattr(m_fd,TCSANOW,&tio);
	
	if (m_fd == -1 )
	{
		ScreenOutput("Unable to connect");
		m_conactive=false;
		return false;
	}

	m_conactive=true;
	
	return true;
}


void SerialConnector::Close()
{
	m_conactive=false;
	close(m_fd);
}


bool SerialConnector::ConActive()
{
	return m_conactive;
}


string SerialConnector::ReadLine(bool waitindef,bool nlonly)
{
	string ret;	

	if(!m_conactive)return "";
	
	//read a single line:
	
	char buff[1]; //array (the read takes an array, not a single char)
	int bytes=0;
	
	//TODO: Add some kind of safety guard to avoid getting stuck in an infinite "no data" loop 
	
		
	while(1)
	{
		bytes= read(m_fd,buff,1);
		
		if(bytes<0)
		{
			if(errno==11)
			{
				if(waitindef)
				{
					continue; //keep trying
				}
				break; //EAGAIN: No more data			
			}
			
			ScreenOutput("Error while reading.  Errno:" + BitStream::Int2Str(errno));
			return "";
		}
		else if(bytes==0)
		{
			//lost connection
			ScreenOutput("Lost connection");
			m_conactive=false;
			break; 
		}
		
		
		if(buff[0]=='\r')
		{
			if(!nlonly)
			{
				read(m_fd,buff,1);//read the following char which should be \n
				if(buff[0]=='\n')break;
			}
			else break;			
		}
		else
		{				
			ret.append(1,buff[0]);  			
		}
		
		
		if(ret.size()>1024) //hard coded limit to catch issue where device goes haywire and loops forever.  
		{
			break;
		}
		
	}
	
	return ret;
}


bool SerialConnector::WriteLine(string line,bool nlonly)
{
	if(!m_conactive)return false;
	
	string towrite = line + (nlonly? "\n" : "\r\n");
	
	return write(m_fd,towrite.c_str(),towrite.size());
}

The code to try connecting:

	SerialConnector con;
	con.SetPath("/dev/arduino-0");
	con.Open();
	
	con.WriteLine("");
	con.WriteLine("allstates");
	
	cout<<con.ReadLine()<<endl;	   //just hangs
	
	con.Close();

And finally the code of the arduino device itself:

#include <EEPROM.h>

int incomingByte = 0;
char buffer[100];
int pos=0;
int deviceid;

void setup() 
{
    //want all digital pins to be digital inputs, no PWM needed for this app
    pinMode(2, INPUT);
    pinMode(3, INPUT);
    pinMode(4, INPUT);
    pinMode(5, INPUT);
    pinMode(6, INPUT);
    pinMode(7, INPUT);
    pinMode(8, INPUT);
    pinMode(9, INPUT);
    pinMode(10, INPUT);
    pinMode(11, INPUT);
    pinMode(12, INPUT);
    
    //notes: cannot use pins 0,1 and 13 as they are reserved. 
    
        
    deviceid=EEPROM.read(0);    //read id
  
    Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}

void loop() 
{
        // send data only when you receive data:
        if (Serial.available() > 0) 
        {
                // read the incoming byte:
                incomingByte = Serial.read();  
                
               
                //filter unwanted chars:                
                if(incomingByte<13 || (incomingByte>14 && incomingByte<32) || incomingByte>126)return;
                
                
                
                //echo back what we typed:                
                Serial.print((char)incomingByte);
               
                //if enter pressed or reached end of buffer, process buffer            
                if(incomingByte==13 || pos>=99) 
                {
                    pos=0;
                    
                    Serial.print("\r\n");
                    
                    //process command
                    if(strcmp(buffer,"help")==0)CMD_help();
                    else if(strcmp(buffer,"id")==0)CMD_id();
                    else if(strcmp(buffer,"setid")==0)CMD_setid();
                    else if(strcmp(buffer,"astates")==0)CMD_astates();
                    else if(strcmp(buffer,"dstates")==0)CMD_dstates();
                    else if(strcmp(buffer,"allstates")==0)CMD_allstates();
                    else if(strcmp(buffer,"")!=0)
                    {
                      Serial.print("Unknown command: \"");
                      Serial.print(buffer);
                      Serial.print("\", type help for list of valid commands");
                    }
                    
                    Serial.flush();
                    
                    pos=0;
                    Serial.print("\r\n# ");  
                }
                else
                {                
                  buffer[pos]=incomingByte;
                  buffer[pos+1]=0;
                  pos++; 
                }
               
        }
}






void CMD_help()
{
    Serial.print("\r\n\r\n-------------------------------------------------------------------------------\r\n");  
    Serial.print("HAL9000 / EnviroState 1.0.0 [updated June 26 2012]  -  www.iceteks.com\r\n");
    Serial.print("-------------------------------------------------------------------------------\r\n");
    Serial.print("help             Show this screen\r\n");
    Serial.print("id               Show device id\r\n");
    Serial.print("setid            Set device id\r\n");
    Serial.print("astates          Show analog states\r\n");
    Serial.print("dstates          Show digital states\r\n");
    Serial.print("allstates        Show both analog and digital states\r\n");
}



void CMD_id()
{
  Serial.print(deviceid,DEC);
}


void CMD_setid()
{
  Serial.print("Cur id:");
  Serial.print(deviceid,DEC);
  Serial.print("\r\nnew id:");  

  //wait for data to be available
  while(Serial.available() == 0);
  
  deviceid = Serial.read(); 
  
  EEPROM.write(0,deviceid);
  
  Serial.print("\r\nID changed\r\n");
}


void CMD_astates()
{
  Serial.print("A0:");
  Serial.println(analogRead(A0));
  
  Serial.print("A1:");  
  Serial.println(analogRead(A1));
  
  Serial.print("A2:");  
  Serial.println(analogRead(A2));
  
  Serial.print("A3:");  
  Serial.println(analogRead(A3));
  
  Serial.print("A4:");  
  Serial.println(analogRead(A4));
  
  Serial.print("A5:");  
  Serial.println(analogRead(A5));
}

void CMD_dstates()
{
  Serial.print("D2:"); 
  Serial.println(digitalRead(2));
  Serial.print("D3:");   
  Serial.println(digitalRead(3));
  Serial.print("D4:");   
  Serial.println(digitalRead(4));
  Serial.print("D5:");   
  Serial.println(digitalRead(5));
  Serial.print("D6:");   
  Serial.println(digitalRead(6));
  Serial.print("D7:");   
  Serial.println(digitalRead(7));
  Serial.print("D8:");   
  Serial.println(digitalRead(8));
  Serial.print("D9:");   
  Serial.println(digitalRead(9));
  Serial.print("D10:");   
  Serial.println(digitalRead(10));
  Serial.print("D11:");   
  Serial.println(digitalRead(11));
  Serial.print("D12:");   
  Serial.println(digitalRead(12));
}


void CMD_allstates()
{
  CMD_astates();
  CMD_dstates();
}

Where do you set the baud rate, stop bits, parity, DTR use, etc. in that class?

The baud rate is here: (in the Open function)

cfsetospeed(&tio,9600);
cfsetispeed(&tio,9600);

Not sure about the other stuff, how would I set that and what should it be set to?