harm
New Member
Posts: 5
|
Post by harm on Sept 14, 2013 19:22:14 GMT 1
Hi, 2 years ago I used BaCon with a FTDI USB device, and got help making this work. Since the FTDI USB device was not part of the kernel, I need an extra library, but in the end, all seemed to work. Now I am facing something more simple, but that made it even more confusing.... I am using puppy linux. I want to do serial communication using a USB-RS232 converter with a PL2303 chip. On both Slacko 5.3.3 (BaCon 1.0) as well as Precise 5.7.1 (BaCon 2.x) this registers nicely, and I see kernel modules usbserial.ko and PL2303.ko loaded. The device is connected at /dev/ttyUSB0. This is all perfect. Aint-it ? But how do I access it from BaCon What header file do I need to include ? On none at all ? Any suggestion is welcome. I included both BaCon versions, since the new BaCon 2.x may have better (different) support for (usb) serial devices. In the documentation however I still could not find an "OPEN COMx" basic statement. Since the serial port is far from dead in embedded systems (*), I can imagine support in BaCon is added. Harm (*)= Microsoft removed hyperterminal from W7 (COM=dead?), but that contradicts with languages like python that have support (very simple to use .. compliments).
|
|
|
Post by bigbass on Sept 14, 2013 21:11:51 GMT 1
|
|
|
Post by Pjot on Sept 14, 2013 22:15:52 GMT 1
Hi harm,
If we are to add something like 'OPEN "/dev/ttyUSB0" FOR SERIAL AS myserial', then there also must be a way of setting some options to the serial port. Unfortunately, there are a lot of options which can be set.
What options would you like to be able to set (linespeed, parity)? Any defaults for line break, RAW, XON/XOFF, BRK?
Thanks Peter
|
|
harm
New Member
Posts: 5
|
Post by harm on Sept 15, 2013 10:28:38 GMT 1
Hello Pjot,
most of the serial communication that is used in embedded systems today uses ascii (8 bit mode). no parity, 1 or 2 stop bits, baudrate varies.
For the other options it is depending very much on what you are trying to achieve.
I would use it for debugging, and small block transfers. Generally 3 wire ( so no hardware handshaking with either rts/cts or dtr/dsr). If anything then xon/xoff but I would be very happy with suggestions that do not even involve any handshaking. PC s are so damned fast that they have no problem keeping up with even 115200 baud. And block transfers from PC to target can easily be controlled from the BaCon side. Buffer sizes I have never had to change since my 486-33 so a typical 1k for both should be more than ok. It may even be that the buffer sizes are already set by the usb driver, so you have no control over it. RAW mode could be interesting for people that want to use it with their won protocol Xmodem or so.
What would be nice to have is
Opening a port including parameter setup , baudrate is mandatory. -closing a port -flushing the buffers (happens with opening and closing, but open-close is a clumsy way to achieve this). -having means to see if there is data in RX buffer and TX buffer (to continue program if nothing there). In QB this is done with an IF not EOF x THEN read the port x -Reading 1 char -writing 1 char
Extra could be
-reading a string until eol -writing a string
If this can be done, It would greatly enhance BaCon. I would appreciate it very much.
|
|
|
Post by Pjot on Sept 15, 2013 18:39:32 GMT 1
Hi harm, Well, I implemented the whole serial stuff in a generic way so you can set all (POSIX) options. This may look confusing, but at the same time it gives full flexibility over your serial port. I found some info here which helped me a lot. First, I added OPEN FOR SERIAL and CLOSE SERIAL to open and close the serial port. Secondly, with the new statement SETSERIAL all modes and settings for the serial port can be configured. There are 6 modes: IMODE (Input Mode), OMODE (Output Mode), CMODE (Control Mode), LMODE (Local Mode), SPEED and OTHER. Lastly, the statements GETBYTE and PUTBYTE should be used to read and write (binary) data to the port. Below an example program. Of course you have to download the latest beta to get it working BR, Peter PS see also 'man termios' for more control codes... ' Open the serial port OPEN "/dev/ttyS0" FOR SERIAL AS myserial
' Set speed - B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400 SETSERIAL myserial SPEED B38400
' Do not take a 0-byte as a BRK SETSERIAL myserial IMODE ~IGNBRK
' Set 8N1 - 8-bit characters... SETSERIAL myserial CMODE ~CSIZE SETSERIAL myserial CMODE CS8
' ...no parity... SETSERIAL myserial CMODE ~PARENB
' ...and 1 stop bit SETSERIAL myserial CMODE ~CSTOPB
' Set block - 0=noblock / 1=block SETSERIAL myserial OTHER VMIN = 0
' Read timeout = 0.5 seconds SETSERIAL myserial OTHER VTIME = 5
' Reserve memory area and set values there mem = MEMORY(2) POKE mem, 1 POKE mem+1, 4
' Send the data to the port PUTBYTE mem TO myserial SIZE 2
' Rerieve data (2 bytes) from the port GETBYTE mem FROM myserial SIZE 2
' Close the port CLOSE SERIAL myserial
|
|
harm
New Member
Posts: 5
|
Post by harm on Sept 16, 2013 7:47:20 GMT 1
Hi Pjot,
-edit- removed questions -edit-
I think I understand now what you are trying to do. There is one basic addition needed though. I need info to see if I get valuable data from the receive buffers. You could change GETBYTE into a function, that returns with a status. If 0 then serial buffers where empty, and you did not get valid data. Similar with PUTBYTE. If status=0 then buffers are full, and the PUTBYTE has failed.
Is that possible ?
Something like
IF (GETBYTE mem FROM myserial SIZE 1) THEN PRINT "SUCCES" PRINT "DATA RECEIVED IS :"; PRINT ASCII (PEEK mem) ELSE PRINT "FAILED, no new data" END IF
Then I notice you use "termios". I am not sure termios is installed in puppy linux. I have to check if it is. I did not notice it listed between the running processes, or kernel objects yet. I may have overlooked.
Regards,
Harm
P.S. BigBass : sorry I did not respond to your message. I forgot. You described how to get the correct drivers. I am not in need of the drivers, since they are in the kernel of both Slacko 533 as well as Precise 571. The question was: how to easily use them from BaCon.
|
|
|
Post by Pjot on Sept 16, 2013 17:31:38 GMT 1
Hi harm, I see - however, PUTBYTE and GETBYTE are statements and therefore do not return a value. But I can add an optional parameter which contains the amount of data written/read, similar to the RECEIVE statement. For example: GETBYTE mem FROM myserial CHUNK 10 SIZE amount
So, the SIZE keyword is used to contain the amount of data actually received, while CHUNK is used to determine the amount of bytes to obtain from the buffer. I'll set it up as follows: if both the CHUNK and SIZE keyword are present, then CHUNK determines the amount of data to read/write, and SIZE will determine the variable where to store the actual bytes read/written. If only CHUNK is present, or only SIZE is present, then this determines the amount of data to read/write. Hope this suits your needs! Peter PS the OPEN FOR SERIAL uses a generic 'open'/'close' libc API, so the SERIAL keyword may better be replaced by something like DEVICE, as it can use open/close any device or device file or file within Linux...
|
|
|
Post by Pjot on Sept 16, 2013 19:33:59 GMT 1
So it's done, please refer to the program below for the changes. Hope it explains how it all works. Please use the latest beta to test. For ' termios', this is part of libc and should be available on any POSIX compliant Unix environment. Rgrds Peter ' Open the serial port OPEN "/dev/ttyUSB0" FOR DEVICE AS myserial
' Set speed - any of these: B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800, ' B9600, B19200, B38400, B57600, B115200, B230400 SETSERIAL myserial SPEED B38400
' Ignore the BREAK signal SETSERIAL myserial IMODE ~IGNBRK
' Set 8N1 - 8-bit characters... SETSERIAL myserial CMODE ~CSIZE SETSERIAL myserial CMODE CS8
' ...no parity... SETSERIAL myserial CMODE ~PARENB
' ...and 1 stop bit SETSERIAL myserial CMODE ~CSTOPB
' Set if read is blocking - 0=noblock / 1=block SETSERIAL myserial OTHER VMIN = 0
' Read timeout = 0.5 seconds SETSERIAL myserial OTHER VTIME = 5
' Reserve memory area and set values to send there mem = MEMORY(5) FOR x = 0 TO 4 POKE mem+x, x+1 NEXT
' Send the data to the port, amount of sent data ' is kept in variable 'sent' PUTBYTE mem TO myserial CHUNK 5 SIZE sent PRINT "Sent: ", sent
' Retrieve data (5 bytes) from the port, amount of ' received data is kept in variable 'received' GETBYTE mem FROM myserial CHUNK 5 SIZE received PRINT "Received: ", received
' Close the port CLOSE DEVICE myserial
|
|
|
Post by vovchik on Sept 16, 2013 19:45:00 GMT 1
Dear Peter,
Very useful addition, so many thanks. I think one day I will now try to reprogram one of my old sat receivers that gets accessed via the serial port...
With kind regards, vovchik
|
|
harm
New Member
Posts: 5
|
Post by harm on Sept 17, 2013 7:44:07 GMT 1
I will download the latest BaCon tonight and try this out. If I understand the implementation correct then I will have to do some buffer handling in Basic.
' Open the serial port OPEN "/dev/ttyUSB0" FOR DEVICE AS myserial
'I have split up buffers for TX and RX because for larger transfers there ' will be data comming into RX buffers while TX is not yet empty.
' Reserve TX memory area and set values to send there bufsize = 5 memt = MEMORY(bufsize) 'just put sommething in the buffer, ascii values) FOR x = 0 TO (bufsize-1) POKE mem+x, x+48 NEXT
' Reserve RX memory area and set values to send there memr = MEMORY(bufsize)
' Send the data to the port, amount of sent data ' is kept in variable 'sent' PUTBYTE memt TO myserial CHUNK bufsize SIZE sent ' if I did not send all 5 bytes I need to do a retry for the rest, ' actually this is best done in a loop, but this is to explain. IF send < bufsize THEN 'the message did not fit in the TX buffer remain = bufsize-sent PUTBYTE memt+remain TO myserial CHUNK remain SIZE sent ELSE PRINT "done" ENDIF
' Retrieve data (5 bytes) from the port, amount of ' received data is kept in variable 'received' pointer = 0 REPEAT GETBYTE memr+pointer FROM myserial CHUNK 1 SIZE received pointer=pointer+received ' do stuff in the time you have to wait for the remainder of the message to come in. UNTIL received EQ 0
PRINT "Received: ", pointer
' Close the port CLOSE DEVICE myserial For RX the buffer handling in Basic is not really needed if you have time to spare. But if you do the buffer handling in basic you can do stuff in between the GETBYTE.
For TX it will depend on the buffer size in the usbserial stack. If that is large enough, you will not have to do anything.
Above is untested code, but this is what I will try tonight, when I have the BaCon beta version installed.
|
|
harm
New Member
Posts: 5
|
Post by harm on Sept 17, 2013 19:45:27 GMT 1
Hi Pjot,
I copied the bacon.bash onto my local folder, and after changing attibutes to executable, I could compile (Puppy linux Precise 5.7.1).
./bacon.bash test.bac
Used your code to start (see below) and found following: termios is used in "canonical mode" where it only accepts strings. I detected this in a 2PC system with serial connection, and terminal (hyperterminal windows) program. Canonical mode also ignores the VMIN and VTIME
I could send text until I hit <CR> and then the BaCon program would return from the GETBYTE. It waited at GETBYTE until the <CR> was received. This is actually the mode I want to use, so that helps me, but it will not allow you to send via "PUTBYTE" the characters you had in the example (there is no CHR$(13) or <CR>).
Sending data did not work at all. Not even when I did put a valid string, terminated with <CR> in the buffer "mem", or a bunch of <CR>'s. It did reply with sent=5 though.
But the text I typed in on the other terminal got replied. So i think the serial port is in ECHO mode. Once the serial port is closed the echo was gone. Even when I used separate buffers for TX and RX, the echo remained.
Program I played with
' Open the serial port OPEN "/dev/ttyUSB0" FOR DEVICE AS myserial
' Set speed - any of these: B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800, ' B9600, B19200, B38400, B57600, B115200, B230400 SETSERIAL myserial SPEED B9600
' Ignore the BREAK signal SETSERIAL myserial IMODE ~IGNBRK
' Set 8N1 - 8-bit characters... SETSERIAL myserial CMODE ~CSIZE SETSERIAL myserial CMODE CS8
' ...no parity... SETSERIAL myserial CMODE ~PARENB
' ...and 1 stop bit SETSERIAL myserial CMODE ~CSTOPB
' Set if read is blocking - 0=noblock / 1=block SETSERIAL myserial OTHER VMIN = 0
' Read timeout = 0.5 seconds SETSERIAL myserial OTHER VTIME = 5
' Reserve memory area and set values to send there mem = MEMORY(5) FOR x = 0 TO 4 POKE mem+x, 13 NEXT x
' Send the data to the port, amount of sent data ' is kept in variable 'sent' PUTBYTE mem TO myserial CHUNK 5 SIZE sent PRINT "Sent: ", sent
' Retrieve data (5 bytes) from the port, amount of ' received data is kept in variable 'received' GETBYTE mem FROM myserial CHUNK 5 SIZE received PRINT "Received: ", received
FOR i=0 TO received j = PEEK(mem+i) PRINT CHR$(j); NEXT i
' Close the port CLOSE DEVICE myserial
|
|
|
Post by Pjot on Sept 18, 2013 13:11:26 GMT 1
Hi harm, Thanks for your feedback. As mentioned, the Terminal Input Output System (termios) is part of libc. There is a very interesting guide in the GCC documentation on how to configure the terminal. For example, you mention that the serial port is using "Canonical mode". But this can be unset using SETSERIAL: SETSERIAL myserial LMODE ~ICANON
Similarly, any echoing can be switched off as well: SETSERIAL myserial LMODE ~ECHO
As mentioned before, the Linux terminal implementation contains a lot of configurable options. There are 6 modes (IMODE for Input Mode, OMODE for Output Mode, CMODE for Control Mode, LMODE for Local Mode, SPEED and OTHER). You may need to fiddle around a bit with all these options to get your application working... HTH, Peter
|
|
|
Post by alexfish on Mar 2, 2023 1:51:26 GMT 1
Hi All
it took some time to solve one issue
in post above not getting data ?
I was facing same issues
thinking Stop Bit
so in short , working on grbl "Gcode" based board , in this case have a one based on marlin
found that setting stop bit 0 after the code and then add NL$ after it works here
and the here = , the board has a sd card , 'hence can work offline' , on line sd can be accessed
The Stop bit + the wait (Sleep) , for testing card was removed , hence the message no media
the code and the result
' Open the serial port OPEN "/dev/ttyACM0" FOR DEVICE AS myserial ' Set speed - any of these: B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800, ' B9600, B19200, B38400, B57600, B115200, B230400 SETSERIAL myserial SPEED B115200
'Set 8N1 - 8-bit characters... SETSERIAL myserial CMODE ~CSIZE SETSERIAL myserial CMODE CS8
' ...no parity... SETSERIAL myserial CMODE ~PARENB
' ...and 1 stop bit see below SETSERIAL myserial CMODE ~CSTOPB
' Set if read is blocking - 0=noblock / 1=block SETSERIAL myserial OTHER VMIN = 0
' Read timeout = 0.5 seconds SETSERIAL myserial OTHER VTIME = 500
' Reserve memory area and set values to send there mem = MEMORY(5) mem2 = MEMORY(256) 'FOR x = 0 TO 4 POKE mem+0, ASC("M") POKE mem+1, ASC("2") POKE mem+2, ASC("0") 'need 0 here POKE mem+3, 0 POKE mem+4, ASC(NL$)
' Send the data to the port, amount of sent data ' is kept in variable 'sent' PUTBYTE mem TO myserial CHUNK 5 SIZE sent PRINT "Sent: ", sent SLEEP 500
GETBYTE mem2 FROM myserial CHUNK 256 SIZE received PRINT "Received: ", received
FOR i=0 TO received j = PEEK(mem2+i) PRINT (CHR$(j)); NEXT i ' Close the port CLOSE DEVICE myserial
The Result
./serial Sent: 5 Received: 17 echo:No media ok
BR Alex
Added: using bCNC: results bit
ok echo:No media M20 ok
|
|
|
Post by alexfish on Mar 2, 2023 2:15:27 GMT 1
using cserial lib
' https://github.com/rm5248/CSerial
OPTION PARSE FALSE
PRAGMA INCLUDE <cserial/c_serial.h>
PRAGMA OPTIONS -I /usr/local PRAGMA LDFLAGS -lcserial
LOCAL * m_port TYPE c_serial_port_t LOCAL m_lines TYPE c_serial_control_lines_t LOCAL status,bytes_read ,data_length ,x LOCAL data[255] TYPE uint8_t LOCAL msg[255] TYPE uint8_t LOCAL port_list TYPE char**
Port$ = "/dev/ttyACM0"
IF FILEEXISTS(Port$) THEN c_serial_new( &m_port, NULL ) c_serial_set_global_log_function( c_serial_stderr_log_function ) IF ( c_serial_set_port_name( m_port, Port$) < 0 ) THEN PRINT Port$ ,": Fail" END ELSE
c_serial_set_baud_rate( m_port, CSERIAL_BAUD_115200 ) c_serial_set_data_bits( m_port, CSERIAL_BITS_8 ) c_serial_set_stop_bits( m_port, CSERIAL_STOP_BITS_1 ) c_serial_set_parity( m_port, CSERIAL_PARITY_NONE ) c_serial_set_flow_control( m_port, CSERIAL_FLOW_NONE )
status = c_serial_open( m_port )
IF status < 0 THEN PRINT Port$, " : Open = Fail" END ELSE PRINT Port$, "Open = OK" printf( "Baud rate is %d\n", c_serial_get_baud_rate( m_port ) ) ' send some bits msg[0] = ASC("M") msg[1] = ASC("2") msg[2] = ASC("0") 'skip one byte 'msg[3] = '\0' msg[4] = ASC(NL$) LOCAL res = 5 data_length=255 c_serial_write_data( m_port, msg, &res) PRINT "SENT " , status 'found important SLEEP 500 REPEAT status = c_serial_read_data( m_port, data, &data_length, &m_lines ) PRINT "stat " , status UNTIL data_length > 0 FOR t = 0 TO data_length PRINT CHR$(data[t]); NEXT c_serial_close( m_port ) END IF END IF
END IF
PRINT "Done"
results
./serial2 cserial: [TRACE] c_serial_set_global_log_function - Have set new log function /dev/ttyACM0Open = OK Baud rate is 115200 SENT 0 stat 0 echo:No media ok Done BR Alex
|
|
|
Post by Pjot on Mar 2, 2023 7:15:16 GMT 1
Thanks Alex,
Glad to see that it seems to be working, even after all these years!
BR PEter
|
|