On Oct 31, 2006, at 5:24 PM, remin@elgen.dk wrote:
hello to all,
i am new in this forum... so forgive me if this subject has been posted before! (is there an archive of old posts on the beginners list? i cant see it at http://www.lists.squeakfoundation.org/cgi-bin/ezmlm-browse)
anyways: is there any good tutorials/examples on how to communicate with the serial port? for beginners of squeak?
i am building a physical computer interface and display which i would like to control the functionality of with squeak. the physical controller is the arduino board (www.arduino.cc) linked to the computer via USB (since my laptop has no serial plug i use a serial->USB converter). the serial monitor in the arduino environment works perfectly fine (i get lots of input), so i guess the USB signal is treated like a serial signal via the arduino USB/ serial software/drivers.
Hi Jacob,
What operating system are you running on?
I also have an Arduino. I use Mac OS X, and my board shows up as a Unix device, in /dev/cu.usbserial-something or other. (I'm afraid I've left the board at the lab so I can't check right now! :)
Squeak has a SerialPort class, but I'm not sure how to get it to recognize serial ports on OS X. I hear it works well on Windows - and maybe Linux - but I'll leave explaining it to folks who know better. It looks like Ned Konz wrote a short introduction to it recently, at
http://lists.squeakfoundation.org/pipermail/beginners/2006-October/ 001230.html
(The rest of the archives are at "http://lists.squeakfoundation.org/ pipermail/beginners/" - I think it must just be on a different mailing list system than the page you found.)
On OS X, I've instead written a small C library to read and write the serial port, and talked to it using Squeak's "FFI" functionality. (FFI stands for Foreign Function Interface, and it's a way to call external libraries from Squeak.) I've had success talking to the Arduino this way.
I'd be happy to share my Unix/OS X code if it would help - let me know!
Benjamin Schroeder
Benjamin Schroeder wrote:
On Oct 31, 2006, at 5:24 PM, remin@elgen.dk wrote:
hello to all,
i am new in this forum... so forgive me if this subject has been posted before! (is there an archive of old posts on the beginners list? i cant see it at http://www.lists.squeakfoundation.org/cgi-bin/ezmlm-browse)
anyways: is there any good tutorials/examples on how to communicate with the serial port? for beginners of squeak?
i am building a physical computer interface and display which i would like to control the functionality of with squeak. the physical controller is the arduino board (www.arduino.cc) linked to the computer via USB (since my laptop has no serial plug i use a serial->USB converter). the serial monitor in the arduino environment works perfectly fine (i get lots of input), so i guess the USB signal is treated like a serial signal via the arduino USB/serial software/drivers.
Hi Jacob,
What operating system are you running on?
I also have an Arduino. I use Mac OS X, and my board shows up as a Unix device, in /dev/cu.usbserial-something or other. (I'm afraid I've left the board at the lab so I can't check right now! :)
Squeak has a SerialPort class, but I'm not sure how to get it to recognize serial ports on OS X.
The stock SerialPort doesn't work, AFAICT, on OS/X. The source code is stubbed out.
John McIntosh did a new serial port interface for OS/X (and other Unixes) that uses the standard termios calls but I am not sure what its status is now. When he wrote it I was still using Linux on my main machine and tried to port it to Linux but then didn't finish.
It is also possible that an async file handle would work but you'd have to figure out a way to do serial-specific stuff.
I don't know enough OS/X details to be able to suggest a simple way to get the stock SerialPort plugin code for Linux to be able to work on OS/X.
The main problem with the existing SerialPort plugin is that it identifies ports by a SmallInteger. Which assumes some kind of repeatable way to map from /dev/cu.* names to numbers, and I don't know if there's a call to actually enumerate serial ports on OS/X.
I suppose that we could use a hash function to map from a name to a port number both in Squeak and in the plugin, but that's a bit of a pain.
When I did the serial port plugin on Linux I took advantage of the fact that most serial ports ended up with names like /dev/ttyS0 etc., and just made the value of the last character equal to the port number.
The problem on OS/X is that the device driver is free to name device instances whatever it wants to. And they can come and go, so a simple enumeration by alphabetical order wouldn't work well. You'd have to repeat the same enumeration in Squeak to get the number.
That is as if you'd done this:
ls /dev/cu.* | sort | cat -n
which on my system results in:
nedsmini:ned $ ls /dev/cu.* | sort | cat -n 1 /dev/cu.Bluetooth-Modem 2 /dev/cu.Bluetooth-PDA-Sync 3 /dev/cu.modem 4 /dev/cu.usbserial
But these numbers would only be valid between changes in available serial ports.
Ideally we'd have an interface that could also take a String or ByteArray with the name of the port.
I suppose the call could be polymorphic, taking either a String or a SmallInteger.
I hear it works well on Windows - and maybe Linux - but I'll leave explaining it to folks who know better. It looks like Ned Konz wrote a short introduction to it recently, at
http://lists.squeakfoundation.org/pipermail/beginners/2006-October/001230.html
(The rest of the archives are at "http://lists.squeakfoundation.org/pipermail/beginners/" - I think it must just be on a different mailing list system than the page you found.)
On OS X, I've instead written a small C library to read and write the serial port, and talked to it using Squeak's "FFI" functionality. (FFI stands for Foreign Function Interface, and it's a way to call external libraries from Squeak.) I've had success talking to the Arduino this way.
I'd be happy to share my Unix/OS X code if it would help - let me know!
I'd like to see the code too. I'd be willing to put it on one of my servers if you'd like.
Another possibility is to make a little proxy program that you could connect to using a named pipe that would just talk to the serial port. Its command protocol would have to support all the SerialPort primitives.
Hi Ned, everyone,
Ideally we'd have an interface that could also take a String or ByteArray with the name of the port.
I suppose the call could be polymorphic, taking either a String or a SmallInteger.
I think this is a good idea - and not too hard to make resilient on different platforms. I'm not too familiar with plugins, but does the plugin function just get an oop, and hence can decide whether it's a String or SmallInteger or some other thing when it runs?
I'd like to see the code too. I'd be willing to put it on one of my servers if you'd like.
Thanks for the offer. I've attached the code to this message - hopefully attachments come through this list OK. I will post a web page about it soon, but you (or anyone) should feel free to post it anywhere you'd like as well.
Another possibility is to make a little proxy program that you could connect to using a named pipe that would just talk to the serial port. Its command protocol would have to support all the SerialPort primitives.
This is a decent idea too. We did something like this when starting out with the Squeak/.NET bridge.
Some notes about the serial mini-library follow - please ask any questions or report any rough edges as needed. This library is mostly just what I've needed so far, so it is (to say the least) very incomplete.
----
Before I start, I want to give a word of caution: please make a copy of your image before using this code, at least in the early going. I don't mean to sound alarmist, but part of the Squeak code does involve a loop that reads from the serial port - and, while I think I have made that safe in the case of restarting the image (by shutting down the read loop, and protecting against null pointers in the C code), I have not tested it extensively.
----
This is a very basic serial communications mechanism, but maybe we can expand it into something general (or use it to update the built- in SerialPort plugin). The C code is pared down from some sample code I found, but I'm afraid I don't remember where (it was a couple of months ago).
The C code does not have many options - the only parameter besides the port is speed. We could add options for parity, stop bits, etc. as needed.
I wrote the code in Squeak 3.8 - hopefully it will work as well in a 3.9 image, but I haven't tested it there. The two things that I can think of being a problem are
- the underscore style of assignment - does this file in OK on 3.9?
- FFI - this might need to be loaded from SqueakMap for 3.9
Let me know if this is a problem and I can investigate.
Here are some steps for getting started.
1. Install the C framework.
Copy the "libserialport.framework" folder to your home directory's Library/Frameworks folder.
You can also build a new copy of the framework if you'd like, or if you find the one from the zip doesn't work on your system. (I used Mac OS X 10.4.8, with gcc 4.0.0.)
2. "File in" the Smalltalk code.
Go to a "file list" in Squeak. (On the World menu, choose "open..." and then "file list". Navigate to wherever the "SimpleSerialPort.st" is stored. (It might be easiest to put a copy in the same folder as your image, but that's not strictly necessary.)
Select "SimpleSerialPort.st" and press the "install" button, above. This will add the serial port code to your system.
3. Determine what name the system has given to your serial port.
As Ned said, the serial device driver on OS X doesn't assign names in any particular sequence. Go to a Terminal and do
ls /dev/cu.*
and see what's there. There will probably only be one entry that references USB and serial - otherwise you could try doing the "ls" with the device there and without it, as OS X will remove the entry when the device is not connected.
If you are using an Arduino, and have the serial monitor working, you can also go to the "Serial Port" menu in the Arduino software and see what is selected there.
4. Determine the speed at which you want to talk to the port.
This is the serial baud rate - for Arduino, it's also listed in the menus.
4.5 Save your image (if you'd like)!
5. Try to connect to the serial device.
Here is an example of reading from a USB-connected GPS module - communication with the Arduino is similar (but I've left mine at the lab again).
port := SimpleSerialPort newOnPort: '/dev/cu.usbserial-A1000pPF' speed: 4800.
port available. "print me - results in the number of bytes available"
port readCharacter. "print me" "results in something like $G"
port close.
You can also use "readByte" to read bytes as numbers instead of ASCII. To write bytes to the port, just use "writeByte:", "writeCharacter:", or "writeString:".
Note that "readByte" will hang if there are no bytes available. I think that it should be interruptible, as the looping is in Smalltalk code, not inside the C library.
Those are the basics!
Please remember to close the port ("port close", above) when you are done. This is one of the rough edges in my library - there is a separate thread that buffers data read from the underlying port, and it will not go away unless the port is closed.
Please post any questions, thoughts, problems, etc.
Thanks, Benjamin Schroeder
On Thu, Nov 02, 2006 at 10:13:44PM -0500, Benjamin Schroeder wrote:
Hi Ned, everyone,
Ideally we'd have an interface that could also take a String or ByteArray with the name of the port.
I suppose the call could be polymorphic, taking either a String or a SmallInteger.
I think this is a good idea - and not too hard to make resilient on different platforms. I'm not too familiar with plugins, but does the plugin function just get an oop, and hence can decide whether it's a String or SmallInteger or some other thing when it runs?
Yes, that's exactly right.
Dave
beginners@lists.squeakfoundation.org