hacking OF serial for OSX10.6

This is a little funky but it caused some serious embarrassment for me when I was trying to get some simple OF+Arduino examples running in a workshop earlier today. I had to hack a bit at setup() in ofSerial to get it to work properly in 10.6. I never had this problem in 10.5, so I’m not sure what’s changed, but I’m going to snoop around and see what I can figure out. In the meantime, I’m wondering: a) has anyone else run into this with an Arduino? b) does anyone more savvy about Unix port stuff see something egregious in this?

== edit: forgot to add changes to the header:

  
  
//---------------------------------------------  
	#if defined( TARGET_OSX )  
	//---------------------------------------------  
  
	    ofLog(OF_LOG_NOTICE,"ofSerialInit: opening port %s @ %d bps", portName.c_str(), baud);  
		fd = open(portName.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);  
		if(fd == -1){  
			ofLog(OF_LOG_ERROR,"ofSerial: unable to open port");  
			return false;  
		}  
	        // we want exclusive access, this is different  
		success = ioctl(fd, TIOCEXCL);  
		if(success != -1) {  
			// this is also different  
			success = fcntl(fd, F_SETFL, 0);  
		} else {  
			ofLog(OF_LOG_ERROR,"ofSerial: can't lock port :(");  
			return false;  
		}  
                if(success == -1) {  
			ofLog(OF_LOG_ERROR,"ofSerial: can't lock filedescriptor :(");  
			return false;  
		}  
  
		struct termios options;  
		success = tcgetattr(fd,&oldoptions);  
		if (success == -1) {  
			ofLog(OF_LOG_ERROR,"ofSerial: can't get old options");  
			return false;  
		}  
		options = oldoptions;  
                // NOTE: cfsetispeed & cfsetospeed switch statement omitted here for brevity  
  
		/*options.c_cflag |= (CLOCAL | CREAD);  
		options.c_cflag &= ~PARENB;  
		options.c_cflag &= ~CSTOPB;  
		options.c_cflag &= ~CSIZE;  
		options.c_cflag |= CS8;*/  
		  
		cfmakeraw(&options);  
	  
		// set tty attributes (raw-mode in this case)  
		success = tcsetattr(fd, TCSANOW, &options);  
		if (success == -1) {  
			ofLog(OF_LOG_ERROR,"ofSerial: can't set attibutes on port descriptor");  
			return false;  
		}  
		success = ioctl(fd, IOSSIOSPEED, &baud);  
		success = ioctl(fd, IOSSDATALAT, 3); // an arbitrary length of time to wait for the latency  
  
		bInited = true;  
		ofLog(OF_LOG_NOTICE,"sucess in opening serial connection");  
  
	    return true;  
	//---------------------------------------------  
    #endif  
  
  

The big difference here is making the arduino blocking, which could be bad potentially, but makes it actually work for me. I’d be curious to hear what anybody thinks of this. Thanks!

ofSerial.h:

  
  
#if defined ( TARGET_OSX )  
	#include <IOKit/IOKitLib.h>  
	#include <IOKit/serial/IOSerialKeys.h>  
	#include <IOKit/IOBSD.h>  
	#include <IOKit/serial/ioss.h>  
#endif  
  

I’ve been having the same problems. I’ve resorted to using Processing for this project. Let me know if you sort if out. Can’t use Firmata, even with your hack so let me know if you come up with anything. I added in some extra logging…

ofLog(OF_LOG_ERROR,“ofSerial: trouble reading from port: fd %d, errno %d, error %s”, fd, errno, strerror(errno));

…to the place where the error is and I’m getting this…

OF_ERROR: ofSerial: trouble reading from port: fd 4, errno 35, error Resource temporarily unavailable

Same here,
on osX 10.6.2, working around it with OSC and max-msp for now…
best

I just tested this with the Standard Firmata sketch and my hacked ofSerial running at 57600 and it works fine for me but it runs ridiculously slowly, which I’d like to get figured out. I’m just connecting the same as with ofserial:

  
ard.connect("/dev/cu.usbserial-A6004nTt", 57600);  

If you add a

  
printf("errno %i", errno)  

right after the call to open in ofSerial do you get anything back?

this might be of interest if you’re using Arduino 17: http://www.mail-archive.com/pd-list@iem.at/msg32599.html

Just a quick update here, added this:

  
int ofSerial::available(){  
  
	if (!bInited){  
		ofLog(OF_LOG_ERROR,"ofSerial: serial not inited");  
		return OF_SERIAL_ERROR;  
	}  
  
	int numBytes = 0;  
  
	#if defined( TARGET_OSX )  
		ioctl(fd,FIONREAD,&numBytes);  
	#endif  
  

to read properly. Also, in ofArduino.cpp, I did the following:

  
  
void ofArduino::update(){  
	int dataRead=0;  
	// try to empty the _port buffer  
	//while (dataRead<512) {  
	while (dataRead<16) {  
  

because emptying the port was stacking up, the calls to UNIX read() were getting up to ~200ms after letting the app run for a while. I’m not sure why the buffer needs to be so big, but it seems a little excessive? If you’re working with firmata you’ll probably want to tweak this to fit your needs. Maybe even just adding an int bufferSize to ofArduino might be a good idea.

Hey thanks for debugging this.
Are things still running slower do you think?

I posted it as an issue / bug on our github http://github.com/openframeworks/openFr-…-/issue/186

With the smaller buffer I think it runs fine, but we might want to make that a parameter in ofArduino for people who want speed vs size of buffer. I also might have broken something with my update, so I’ve been looking into that too. I’ll post whatever I figure out here. Thanks!

cf http://forum.openframeworks.cc/t/a-bug-in-ofserial::readbyte/773/2">A bug in ofSerial::readByte()]http://forum.openframeworks.cc/t/a-bug-in-ofserial::readbyte/773/2, i think Jet’s fix there is better…