As the title, I need to send a 300-400 ms pulse through the serial port. My sensor need such a pulse to wake up. The program that my sensor's producer provides can do so in Windows. However I need to develop a similar program in ubuntu since my project is using ubuntu. Any pointing is also appreciated.
regards,
First of all you will want to determine on what pin you want to give that pulse. Have a look at the Wikipedia page on RS232 to see which signals exist. Although it's doable to send a pulse on Tx (Transmit Data) that's fairly uncommon, so I assume you will need to send out the pulse either via RTS or via DTR.
To do this you will need ioctl and this is how to do it, assuming you want to pulse DTR
int pulseDTR(int fd)
{
int status;
// get the current modem control lines status
if (ioctl(fd, TIOCMGET, &status) == -1) {
// handle the error
}
// Now set DTR high
status |= TIOCM_DTR;
// and apply
if (ioctl(fd, TIOCMSET, &status) == -1) {
// handle the error
}
// wait a bit
usleep (400*1000);
// Now set DTR low
status &= ~TIOCM_DTR;
// and apply
if (ioctl(fd, TIOCMSET, &status) == -1) {
// handle the error
}
return 0;
}
If you need to pulse RTS just replace TIOCM_DTR
by TIOCM_RTS
.
For more information about programming the serial port I'd recommend the Serial Programming Guide for POSIX Operating Systems and the Linux serial Howto.
EDIT: based on OP's comment sending a break is in fact what's needed. Sending a break means that the Tx line is pulled to logical 0 for a certain amount of time (and not a control signal). This is described in the Linux serial programming howto and is done as follows:
Using ioctl:
int ioctl( fd, TCSBRK, int arg );
Using the tc* calls
int tcsendbreak( fd, int arg );
Please note the comment from the Linux serial programming howto
Send a break: Here the action differs between the conventional
ioctl() call and the POSIX call. For the conventional call, an arg of '0' sets the break control line of the UART for 0.25 seconds. For the POSIX command, the break line is set for arg times 0.1 seconds.
EDIT2: the great thing about open source is that the sources are available :-) This is verbatim from the minicom source, and it's really great because it shows 3 ways to send a break:
/*
* Send a break
*/
void m_break(int fd)
{
#ifdef USE_SOCKET
if (portfd_is_socket)
return;
#endif
#ifdef POSIX_TERMIOS
tcsendbreak(fd, 0);
#else
# ifdef _V7
# ifndef TIOCSBRK
{
struct sgttyb sg, ng;
ioctl(fd, TIOCGETP, &sg);
ioctl(fd, TIOCGETP, &ng);
ng.sg_ispeed = ng.sg_ospeed = B110;
ng.sg_flags = BITS8 | RAW;
ioctl(fd, TIOCSETP, &ng);
write(fd, "\0\0\0\0\0\0\0\0\0\0", 10);
ioctl(fd, TIOCSETP, &sg);
}
# else
ioctl(fd, TIOCSBRK, 0);
sleep(1);
ioctl(fd, TIOCCBRK, 0);
# endif
# endif
#endif
}
tcsendbreak(fd, 0);
ioctl(fd, TIOCSBRK, 0);
followed by some sleep call followed by ioctl(fd, TIOCCBRK, 0);
should allow you to send a break signal with a finely tuned length.So, conclusion? Try first with tcsendbreak(fd, 0);
as it's the easiest, and if that's not giving a good result try ioctl(fd, TIOCSBRK, 0); some sort of sleep ; ioctl(fd, TIOCCBRK, 0);
. On a sane system the "emulated break" should not be necessary.