Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Dreamspinner

macrumors member
Original poster
Dec 17, 2012
39
0
I'm trying to send an ASCII string with CRLF appended, to a device via a serial port.

Code:
NSString *sendString = [[inputTextField stringValue] stringByAppendingString:@"\n\r"];

//[inputTextField stringValue] is "AP1090;".	

if([self.port isOpen]) { // in case an error occured while opening the port
  [self.port writeString:sendString usingEncoding:NSUTF8StringEncoding error:NULL];
}

When looking at the value of sendString in the debugger it shows:
Code:
sendString	__NSCFString *	0x0000000101917800@"AP1090;\n\r\x0e\x19\x10"

What are the extra characters "x0e\x19\x10" and are they supposed to be there?

The device is not responding.
 
Last edited by a moderator:

Dreamspinner

macrumors member
Original poster
Dec 17, 2012
39
0
CRLF is "\r\n", not "\n\r".

You might want to refer to an ASCII code chart:
http://en.wikipedia.org/wiki/ASCII

Among other uses, it can show you what the unexpected control characters are.

Finally, you need to look at what the actual bytes being sent are.

Good eye, thanks. Changing to "\r\n" changed the appended control codes to "\t\e\x10". Still no response from the device.

The left panel of the debugger shows the string as above. So far I haven't been able to figure out how t o log, or otherwise see the UTF8 string.

The big question remains, is "AP1090;\r\n\\t\e\x10" a valid ASCII string that the serial port will understand?
 
Last edited:

chown33

Moderator
Staff member
Aug 9, 2009
10,706
8,346
A sea of green
Good eye, thanks. Changing to "\r\n" changed the appended control codes to "\t\e\x10". Still no response from the device.

The left panel of the debugger shows the string as above. So far I haven't been able to figure out how t o log, or otherwise see the UTF8 string.

The big question remains, is "AP1090;\r\n\\t\e\x10" a valid ASCII string that the serial port will understand?

You need to provide a lot more details.

What is the name of the serial-port software you're using?
What is the actual serial-port adapter? (I assume a USB-to-serial adapter, but I'm just guessing)
Do you have any other hardware that would help visualize serial-port output, such as an oscilloscope or logic analyzer (or simple LED) you can hook to the TX out?

How is the serial-port configured for handshaking (RTS/CTS, ctrl-S/ctrl-Q)?

What is the other device the serial port is connected to?
Where is its serial protocol documented? (e.g. what's the simplest go/no-go command you could send it over the serial-port)

What is your experience in working with serial ports is in general?
What is your experience on working with OS X or Posix serial ports in particular?

If that seems like a lot of questions, it is, but your post history doesn't give me much to go on. You might benefit by reading the following article:
http://www.mikeash.com/getting_answers.html


In your posted code, I have no idea what class the 'port' property is, but that seems like a very important detail to me. That's why I asked what serial-port library you're using.

Likewise, if the port is on a "/dev/tty.*" device-name, then it won't respond until the connected device asserts DCD (if you don't know what DCD is, you should study a reference on serial ports.

The "/dev/cu.*" device-names don't have a DCD-asserted restriction. That goes back to how the port was opened and initialized, and what library (if any) you used to open and init it. See here:
http://osdir.com/ml/hardware.gps.gpsd.devel/2005-04/msg00110.html


In general, a serial-port is just a transparent pipe for bytes. You send some out, you get some in. It makes no sense to ask, "What will the serial port understand?", because the serial port itself is transparent to what's sent over it. One exception to this is if you have software flow-control enabled, also known as ctrl-S/ctrl-Q or XON/XOFF (see Flow Control in the Wikipedia serial port article).


You also need to dig down into the details of what the UTF8 representation of the NSString really is, i.e. what the actual bytes are, and exactly how many bytes there are.

Your debugger output looks to me like it's either a damaged string, or the debugger is showing more than it should. You can convert an NSString to an NSData using an encoding; look at the NSString class reference for methods that return NSData.
 

Dreamspinner

macrumors member
Original poster
Dec 17, 2012
39
0
You need to provide a lot more details.

What is the name of the serial-port software you're using?
What is the actual serial-port adapter? (I assume a USB-to-serial adapter, but I'm just guessing)
Do you have any other hardware that would help visualize serial-port output, such as an oscilloscope or logic analyzer (or simple LED) you can hook to the TX out?

How is the serial-port configured for handshaking (RTS/CTS, ctrl-S/ctrl-Q)?

What is the other device the serial port is connected to?
Where is its serial protocol documented? (e.g. what's the simplest go/no-go command you could send it over the serial-port)

What is your experience in working with serial ports is in general?
What is your experience on working with OS X or Posix serial ports in particular?

If that seems like a lot of questions, it is, but your post history doesn't give me much to go on. You might benefit by reading the following article:
http://www.mikeash.com/getting_answers.html


In your posted code, I have no idea what class the 'port' property is, but that seems like a very important detail to me. That's why I asked what serial-port library you're using.

Likewise, if the port is on a "/dev/tty.*" device-name, then it won't respond until the connected device asserts DCD (if you don't know what DCD is, you should study a reference on serial ports.

The "/dev/cu.*" device-names don't have a DCD-asserted restriction. That goes back to how the port was opened and initialized, and what library (if any) you used to open and init it. See here:
http://osdir.com/ml/hardware.gps.gpsd.devel/2005-04/msg00110.html


In general, a serial-port is just a transparent pipe for bytes. You send some out, you get some in. It makes no sense to ask, "What will the serial port understand?", because the serial port itself is transparent to what's sent over it. One exception to this is if you have software flow-control enabled, also known as ctrl-S/ctrl-Q or XON/XOFF (see Flow Control in the Wikipedia serial port article).


You also need to dig down into the details of what the UTF8 representation of the NSString really is, i.e. what the actual bytes are, and exactly how many bytes there are.

Your debugger output looks to me like it's either a damaged string, or the debugger is showing more than it should. You can convert an NSString to an NSData using an encoding; look at the NSString class reference for methods that return NSData.

Now THAT"s a reply! The links look informative, I'll dig into them later.
The serial lib is AMSerialPort.
Using a USB/serial cable with FTDI chip.
No diagnostic hardware.
No handshaking - they're "/dev/cu.*" ports
The connected devices (not at the same time) are an antenna rotor and a radio transceiver. It's another project to get 'em both going in the saame program....:eek:
The simplest command would be "FA;" for the radio, and "AP1090;" followed by "AM1;" for the rotor.
port is of type AMSrialPort
I have a pretty good background programming for Windoze using Delphi. I'm a real newbie with Cocoa/Objective C.

A better question maybe would have been "Is this an ASCII string the device will understand". My thinking was that the string was malformed. What would converting it to NSData show me that I'm not already seeing?
 

chown33

Moderator
Staff member
Aug 9, 2009
10,706
8,346
A sea of green
Now THAT"s a reply! The links look informative, I'll dig into them later.
The serial lib is AMSerialPort.
Using a USB/serial cable with FTDI chip.
No diagnostic hardware.
No handshaking - they're "/dev/cu.*" ports
The connected devices (not at the same time) are an antenna rotor and a radio transceiver. It's another project to get 'em both going in the saame program....:eek:
The simplest command would be "FA;" for the radio, and "AP1090;" followed by "AM1;" for the rotor.
port is of type AMSrialPort
I have a pretty good background programming for Windoze using Delphi. I'm a real newbie with Cocoa/Objective C.
Please read the "Getting Answers" link I provided. All the above should have been in your first post, to provide context.


A better question maybe would have been "Is this an ASCII string the device will understand".
No one would be able to answer that without knowing what the device is, or what its protocol is.

A better question would be "Why does there appear to be extra characters in the debugger, and are they really there in the serial output?".

The debugger question might be answered by getting the length of the string in the debugger, and showing that value. If that length excludes the spurious extra characters, then it's a debugger issue (a bug or possibly an antifeature). If the length includes the spurious characters, then something else is wrong.

Once again, this is the Break It Down principle. A string has two characteristics: its length and the characters it contains. If the display of contained characters appears wrong, then look at the length to see how much of what's displayed is real.


Addressing the question of "Are they really there in the serial output" would require getting the data out the serial port, in an observable or actionable form. That is, in a way it can be seen or acted upon.

There are diagnostic tools for this, but their cost varies a lot. A simple one is to set a slow baud rate and drive an LED through a current-limiting resistor. A small speaker or amplifier/speaker combination can also work. Different patterns of characters have recognizable audio characteristics.

Another simple approach is to loop the TX to the RX pin, and see what comes in. This will transfer the data all the way through the AMSerialPort classes, out to the driver, and out the USB-to-serial chip. That makes it a pretty good test for the software elements, especially if you add a blinkenlite LED on the looped-back TX pin.

Other tools include small oscilloscopes, logic analyzers, data-capture devices, and line analyzers. For example, a microcontroller with a serial-port driving a 2-line LCD display can receive and display text like a tiny line-analyzer. Here's a tiny handheld scope:
http://www.gabotronics.com/


Personally, I wouldn't even be trying to send actual command-strings until after I'd proved that the basic serial-port functionality worked, by writing a test program. I'd use TX-RX loopback, and have it write a progressive series of characters, which it also reads back (separately, to avoid deadlock) and verifies.

Writing test programs isn't nearly as much fun as making stuff move on command, but writing tests (especially basic functional tests) is an essential part of engineering.


My thinking was that the string was malformed. What would converting it to NSData show me that I'm not already seeing?
If the spurious characters are preserved, and appear in the NSData (and the NSData length reflects their presence), then you have confirmation that the characters are really there in the NSString, and aren't just a debugger artifact.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
chown33 has provided a ton of useful info. I just wanted to add a small detail: Objective-C is a superset of C. If code is C, that code is Objective-C. It *may* be easier to have reusable C routines that fiddle with the raw commands, and you can just call these from your Obj-C code. Hell, there might already be a C library available for your device.

In any event, do what chown33 has suggested, but also consider that in Objective-C you can still use a unsigned char array to store raw bytes and/or NS(Mutable)Data to wrap and unwrap your raw bytes. If you're not really wanting to store a string, NSString might not be the ideal type to choose.

-Lee
 

Dreamspinner

macrumors member
Original poster
Dec 17, 2012
39
0
Please read the "Getting Answers" link I provided. All the above should have been in your first post, to provide context.



No one would be able to answer that without knowing what the device is, or what its protocol is.

A better question would be "Why does there appear to be extra characters in the debugger, and are they really there in the serial output?".

The debugger question might be answered by getting the length of the string in the debugger, and showing that value. If that length excludes the spurious extra characters, then it's a debugger issue (a bug or possibly an antifeature). If the length includes the spurious characters, then something else is wrong.

Once again, this is the Break It Down principle. A string has two characteristics: its length and the characters it contains. If the display of contained characters appears wrong, then look at the length to see how much of what's displayed is real.


Addressing the question of "Are they really there in the serial output" would require getting the data out the serial port, in an observable or actionable form. That is, in a way it can be seen or acted upon.

There are diagnostic tools for this, but their cost varies a lot. A simple one is to set a slow baud rate and drive an LED through a current-limiting resistor. A small speaker or amplifier/speaker combination can also work. Different patterns of characters have recognizable audio characteristics.

Another simple approach is to loop the TX to the RX pin, and see what comes in. This will transfer the data all the way through the AMSerialPort classes, out to the driver, and out the USB-to-serial chip. That makes it a pretty good test for the software elements, especially if you add a blinkenlite LED on the looped-back TX pin.

Other tools include small oscilloscopes, logic analyzers, data-capture devices, and line analyzers. For example, a microcontroller with a serial-port driving a 2-line LCD display can receive and display text like a tiny line-analyzer. Here's a tiny handheld scope:
http://www.gabotronics.com/


Personally, I wouldn't even be trying to send actual command-strings until after I'd proved that the basic serial-port functionality worked, by writing a test program. I'd use TX-RX loopback, and have it write a progressive series of characters, which it also reads back (separately, to avoid deadlock) and verifies.

Writing test programs isn't nearly as much fun as making stuff move on command, but writing tests (especially basic functional tests) is an essential part of engineering.



If the spurious characters are preserved, and appear in the NSData (and the NSData length reflects their presence), then you have confirmation that the characters are really there in the NSString, and aren't just a debugger artifact.

Thanks again for your suggestions. Most of them are beyond my knowledge level at this time. I have a lot of study to do.

I'll pop the string into an NSData object and also check the length and see where that shakes out. Probably with time, this will get easier, but right now, I'm missing Delphi....:confused:

----------

chown33 has provided a ton of useful info. I just wanted to add a small detail: Objective-C is a superset of C. If code is C, that code is Objective-C. It *may* be easier to have reusable C routines that fiddle with the raw commands, and you can just call these from your Obj-C code. Hell, there might already be a C library available for your device.

In any event, do what chown33 has suggested, but also consider that in Objective-C you can still use a unsigned char array to store raw bytes and/or NS(Mutable)Data to wrap and unwrap your raw bytes. If you're not really wanting to store a string, NSString might not be the ideal type to choose.

-Lee

Thanks, yes he has! The more I ask, the less I know I know. I feel sorta like I bought a shiny new sports car, and now have to wind the armature for the starter motor to use it. :D
 

chown33

Moderator
Staff member
Aug 9, 2009
10,706
8,346
A sea of green
Thanks again for your suggestions. Most of them are beyond my knowledge level at this time. I have a lot of study to do.

If you can put a button in a window, tie it to an action, and write a single character to the serial port, then you can make a test program that does exactly that. Click the button, write exactly one character. That's it.

Now, see if it does anything. Hook up an LED and a current-limiting resistor to the TX output. When you click the button, does the LED flicker or blink? If not, what baud-rate are you using? Too fast and you can't see it. So go back and slow the baud-rate down to 150 baud. That will give a character-time of about 1/15 second, which should easily be visible on an LED.

Unsure of how to hook up an LED or a resistor? Well, that's why I asked you to list your diagnostic capabilities (scope, line analyzer, etc.). Since you mentioned a radio and an antenna rotor, I was assuming some basic electronics skill.

Those questions I posted weren't just rhetorical or generalized. If you don't tell us what kind of circuit diagnostic capabilities you have at hand, then we don't know if an LED/resistor combo is outside your skills or not.


I'll pop the string into an NSData object and also check the length and see where that shakes out. Probably with time, this will get easier, but right now, I'm missing Delphi....:confused:
Please describe exactly what you're missing from Delphi. Be specific.

If Delphi can do thing but you don't know how to do thing in Xcode, then we can't possibly tell you how to do thing in Xcode, or whether Xcode has a thing-like feature, if we don't know what the thing actually is.

For example, I can probably tell you how to use a few commands in Terminal to write some data to the serial-port, without using Xcode or AMSerialPort. It wouldn't be interactive, but it would be a simple way to test whether the serial-port is working at all. If you want me to post that, then first post the output from this command, when you copy and paste it into a Terminal window:
Code:
ls -la /dev/cu.*
I have several serial-ports on my Mac right now, and a project I've been working on for a while fundamental relies on serial communication. One of my serial-adapters has the Prolific PL2303 chips, the other has FTDI, but the Terminal commands would be the same either way, only the device pathname would change.
 

Dreamspinner

macrumors member
Original poster
Dec 17, 2012
39
0
If you can put a button in a window, tie it to an action, and write a single character to the serial port, then you can make a test program that does exactly that. Click the button, write exactly one character. That's it.

Now, see if it does anything. Hook up an LED and a current-limiting resistor to the TX output. When you click the button, does the LED flicker or blink? If not, what baud-rate are you using? Too fast and you can't see it. So go back and slow the baud-rate down to 150 baud. That will give a character-time of about 1/15 second, which should easily be visible on an LED.

Unsure of how to hook up an LED or a resistor? Well, that's why I asked you to list your diagnostic capabilities (scope, line analyzer, etc.). Since you mentioned a radio and an antenna rotor, I was assuming some basic electronics skill.

Those questions I posted weren't just rhetorical or generalized. If you don't tell us what kind of circuit diagnostic capabilities you have at hand, then we don't know if an LED/resistor combo is outside your skills or not.



Please describe exactly what you're missing from Delphi. Be specific.

If Delphi can do thing but you don't know how to do thing in Xcode, then we can't possibly tell you how to do thing in Xcode, or whether Xcode has a thing-like feature, if we don't know what the thing actually is.

For example, I can probably tell you how to use a few commands in Terminal to write some data to the serial-port, without using Xcode or AMSerialPort. It wouldn't be interactive, but it would be a simple way to test whether the serial-port is working at all. If you want me to post that, then first post the output from this command, when you copy and paste it into a Terminal window:
Code:
ls -la /dev/cu.*
I have several serial-ports on my Mac right now, and a project I've been working on for a while fundamental relies on serial communication. One of my serial-adapters has the Prolific PL2303 chips, the other has FTDI, but the Terminal commands would be the same either way, only the device pathname would change.

Thanks. I don't need to test the port(s), all hardware is working well. Sure, I could create a little box to blink a LED, but I can test just as well by seeing if the device responds. Writing "FA;" to the port is as easy as toggling DTR.

In Delphi, I'd drop a serial port component on a form (like one would drop a button). In the property inspector, I'd name it, set a few properties, and have a working (but not yet useful) program. Add a few text boxes for I/O and maybe a couple of buttons and a (very) few lines of code. ET voila! If I started a new serial port app from scratch, I haven't a clue how to incorporate the AMSerialPort .... whatever the term is. Library? Component?

If I want to change the name of a program in Delphi, it's easy. In Xcode/Cocoa, so far impossible. I've read a ton of posts on how to do it, and none have worked.

It's not that I think one environment is necessarily better than another, it's a matter of familiarity. I'll get there.

My experience with USB/serial adapters on Windows tells me the Prolific chips don't work as well/reliably as the FTDI. Probably a driver issue.
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.