danjuliodesigns
YaBB Newbies
Offline
Posts: 1
Serial Port write data lost
Mar 22nd , 2008, 7:21pm
Has anyone else seen this (and hopefully worked around it). I have a simple processing program that sends a 3-byte string through the serial port to a device and waits for a response from the device. It seems that occasionally the data I am trying to write just gets lost. I use a serialEvent to receive data (it sets a flag). My program looks like 1. send command 2. wait for a flag to be set indicating we got data 3. display the data My wait loop sometimes just hangs forever (well, until a timeout expires). I have attached an external terminal to the serial interface and confirmed in those cases no data is transmitted. After the wait loop times out the next command is sent. I'm running Mac OS X 10.5.2 (PPC) using a FTDI 232R USB to serial interface. - Processing 0135 Beta - RXTX-2.1-7 - FTDI USBSerialDriver 2.1.7 The program looks like: /** * Simple Heart Rate Display * by Dan Julio. * * Send a Get Heartrate command to the HRMI device and * then display the received heartrate along with * status flags. * * The HRMI device must be configured for serial * operation with a baud rate of 57,600 baud (default * with no jumpers). * */ import processing.serial.*; Serial port; // The serial port byte[] rspCharArray = new byte[32]; // Where we'll put the raw data read from the HRMI device int[] rspArgArray = new int[3]; // Where we'll put the converted response values int validData = 0; int LINE_FEED = 10; // <LF> constant PFont fontA; int timeout; int timeoutCount = 0; void setup() { size(200, 200); // Stage size // Setup text fontA = loadFont("CourierNew36.vlw"); // Open the serial port with the default baud rate of 57600 // baud. I know that the FTDI 232R USB to serial interface // on my Mac is Serial.list()[2] so I always open that. // However the particular entry on your machine may be different. // Uncomment out the // // println(Serial.list()); // // command to identify the port to use. // Hack: Open the known device port = new Serial(this, Serial.list()[2], 57600); // Setup the serialEvent to be called when we receive complete response // packets from the HRMI device port.bufferUntil(LINE_FEED); } void draw() { // Send a command to get a single heart rate value validData = 0; port.write('G'); port.write('1'); port.write(LINE_FEED); // Wait for a response from the HRMI device. // // Includes a kludge to work around an issue somewhere in the // serial software from port.write() to actual hardware. On my // system data I load with port.write sometimes seems to be // lost (is never transmitted out the serial port). This code // aborts the response wait after a couple of seconds so the main // loop can issue another command. timeout = 0; while (validData == 0) { delay(500); timeout += 1; if (timeout > 4) { print("Timeout "); println(timeoutCount); timeoutCount++; validData = -1; } } if (validData != -1) { // Blank the display area fill(102); rect(0, 0, 200, 200); // Display the heart rate fill(204); textFont(fontA, 56); text(rspArgArray[2], 20, 50); // Display the count fill(204); textFont(fontA, 14); text("Count: ", 20, 100); text(rspArgArray[1], 75, 100); // Display the status flag information fill(10); textFont(fontA, 14); if ((rspArgArray[0] & 0x01) == 0x01) { text("Algorithm: Averaged", 20, 120); } else { text("Algorithm: Raw", 20, 120); } if ((rspArgArray[0] & 0x02) == 0x02) { text("No Heartbeat detected", 20, 140); } else { text("Heartbeat detected", 20, 140); } if ((rspArgArray[0] & 0x04) == 0x04) { text("(Re)acquiring Series", 20, 160); } if ((rspArgArray[0] & 0x08) == 0x08) { text("Too much bad data", 20, 180); } } } // Catch the event from the serial interface. This event seems to be // called even when there is no receive data (perhaps for the transmitted // data) so we make sure there is actually data to read before attempting // to do any processing. void serialEvent(Serial port) { if (port.readBytesUntil(LINE_FEED, rspCharArray) != 0) { // Read bytes until we get to the end of the packet converting // each ASCII digit into a number. We make use of the space // character between sets of digits to delimit numbers. // Argument 0: Status Flags // Argument 1: Second Count // Argument 2: Heartrate // int ArgIndex = 0; int CharIndex = 0; for (int i=0; i<3; i++) rspArgArray[i] = 0; while (rspCharArray[CharIndex] != LINE_FEED) { if (rspCharArray[CharIndex] != ((byte) ' ')) { rspArgArray[ArgIndex] = (rspArgArray[ArgIndex]*10) + (rspCharArray[CharIndex] - ((byte) '0')); } else { ArgIndex++; } CharIndex++; } validData = 1; } }