Cat ttyUSB
From Wirespeed
(Redirected from Cat ttyUSB0)
A simple little PERL script that just outputs all data that is available on /dev/ttyUSB0 from the command line. Combines very well with Plot real time data using Gnuplot to draw real time plots. And of course you want some udev rules.
Contents |
Command line options
--device=... Full path name to the device file. Eg. /dev/ttyUSB0 (default) --(no-)flush Flush the serial buffer. This is useful after resetting Arduino, it usually sends a lot of NUL bytes to facilitate reprogramming. --(no-)reset Resets the Arduino after succesful (re)connect. --reset-once Resets the Arduino at start of the script. If the USB bus receives a reset, the Arduino will not be reset and connection will be restored. --(no-)restart Tries to reconnect after a USB bus reset. Default is '--restart'.
Script
#!/usr/bin/perl # # (c) J.P. Hendrix # http://wirespeed.xs4all.nl/mediawiki # # Script to echo all data sent from Arduino to PC # To set up proper udev rules, refer to http://wirespeed.xs4all.nl/mediawiki/index.php/Udev_rules_file_for_Arduino_boards # use warnings; use strict; use Device::SerialPort; use Getopt::Long; my $PortObj; $| = 1; # make the output line bufferend my %parameters; GetOptions (\%parameters , 'device=s' , 'flush!' , 'reset!' , 'reset-once!' , 'restart!' ); my $PortName = $parameters{ 'device' } || "/dev/ttyUSB0"; my $restart = $parameters{ 'restart' } || 1; if ( ! -e $PortName ) { die "Device '$PortName' does not exist." } ### ### This sub is to be called when the program exits so the lockfile is removed ### and memory is freed. ### sub finalize { print STDERR "Finalize: "; if ( defined( $PortObj ) ) { $PortObj->close || die "failed to close"; undef $PortObj; print STDERR "done."; } print STDERR "\n"; }; ### ### When a Ctrl-C is received, clean up after us. ### $SIG{ INT } = sub { finalize; die "\nSIGINT received. Quitting"; }; $SIG{ KILL } = sub { finalize; die "\nSIGINT received. Quitting"; }; my $lockfile = $PortName; $lockfile =~ s/dev/tmp/; # my $file_exists = ""; if ( -e "$lockfile" ) { # $file_exists = "Manually remove $lockfile when sure the device is not in use.\n"; die "Manually remove $lockfile when sure the device is not in use.\n"; } my $restartRequired = 0; do { print STDERR "Initializing serial port $PortName (115200, 8N1) ...\n"; my $quiet = 'false'; my $data; my $count; ### ### Open the serial port device to the Arduino ### if ( $PortObj = new Device::SerialPort ($PortName, $quiet, $lockfile) ) { $restartRequired = 0 } else { $restartRequired = 1; } if ( not $restartRequired ) { $PortObj->databits( 8 ); $PortObj->baudrate( 115200 ); $PortObj->parity( "none" ); $PortObj->stopbits( 1 ); $PortObj->handshake( "none" ); $PortObj->read_char_time( 0 ); # $PortObj->read_const_time( 60000 ); $PortObj->read_const_time( 20 ); ### ### Reset Arduino ### if ( ! defined( $parameters{ 'reset' } ) or $parameters{ 'reset' } ) { print STDERR "Resetting Arduino ...\n"; $PortObj->pulse_dtr_on( 200 ); # Reset Arduino if ( $parameters{ 'reset-once' } ) { $parameters{ 'reset' } = 0; } } ### ### Flush serial buffer ### if ( ! defined( $parameters{ 'flush' } ) or $parameters{ 'flush' } ) { print STDERR "Flushing serial buffer ...\n"; #$PortObj->lookclear; # Doesn't work! my ( $count, $data ) = $PortObj->read( 1 ); while ( $count != 0 ) { ( $count, $data ) = $PortObj->read( $count ); } } print STDERR "Receiving serial data ...\n"; ( $count, $data ) = $PortObj->read( 1 ); while ( ord( $data ) == 0x00 ) { ( $count, $data ) = $PortObj->read( 1 ); } } while ( not $restartRequired ) { if ( ( $data ne ) ) { printf $data; }; ( $count, $data ) = $PortObj->read( 1 ) or $restartRequired = $restart; } finalize; sleep 1; } until ( not $restartRequired );
Use case 1
Arduino sketch
A simple interrupt driven clock counting days, hours, minutes and seconds.
// timer example from electronicsblog.net
#define LED 13
#define TimerInit 3036
// 1 sec 65536 - 16000000 /256 = 3036, with CLKPR=0
// 10Hz => 65536 - 16000000 / (256 * 10 ) = 59286
boolean x = false;
int d = 0;
int h = 0;
int m = 0;
int s = 0;
ISR( TIMER1_OVF_vect ) {
TCNT1 = TimerInit; // set initial value to remove time error (16bit counter register)
digitalWrite( LED , x );
x = !x;
s += 1;
if ( s > 59 ) { s = 0; m += 1; }
if ( m > 59 ) { m = 0; h += 1; }
if ( h > 24 ) { h = 0; d += 1; }
Serial.print( d );
Serial.print( "-" );
Serial.print( h );
Serial.print( ":" );
Serial.print( m );
Serial.print( ":" );
Serial.println( s );
}
void setup() {
pinMode( LED , OUTPUT );
CLKPR = _BV( CLKPCE );
CLKPR = 0; // prescaler 2**n
TIMSK1 = 0x01; // enabled global and timer overflow interrupt;
TCCR1A = 0x00; // normal operation page 148 (mode0);
TCNT1 = TimerInit; // set initial value to remove time error (16bit counter register)
TCCR1B = 0x04; // start timer/ set clock
Serial.begin( 115200 );
};
void loop () {
// Do nothing
};// timer example from electronicsblog.net
#define LED 13
#define TimerInit 3036
// 1 sec 65536 - 16000000 /256 = 3036, with CLKPR=0
// 10Hz => 65536 - 16000000 / (256 * 10 ) = 59286
boolean x = false;
int d = 0;
int h = 0;
int m = 0;
int s = 0;
ISR( TIMER1_OVF_vect ) {
TCNT1 = TimerInit; // set initial value to remove time error (16bit counter register)
digitalWrite( LED , x );
x = !x;
s += 1;
if ( s > 59 ) { s = 0; m += 1; }
if ( m > 59 ) { m = 0; h += 1; }
if ( h > 24 ) { h = 0; d += 1; }
Serial.print( d );
Serial.print( "-" );
Serial.print( h );
Serial.print( ":" );
Serial.print( m );
Serial.print( ":" );
Serial.println( s );
}
void setup() {
pinMode( LED , OUTPUT );
CLKPR = _BV( CLKPCE );
CLKPR = 0; // prescaler 2**n
TIMSK1 = 0x01; // enabled global and timer overflow interrupt;
TCCR1A = 0x00; // normal operation page 148 (mode0);
TCNT1 = TimerInit; // set initial value to remove time error (16bit counter register)
TCCR1B = 0x04; // start timer/ set clock
Serial.begin( 115200 );
};
void loop () {
// Do nothing
};
In action
while [ `date +%S` -ne 57 ]; do true; done; ./cat_ttyUSB.pl --device=/dev/ttyUSB002 --reset-once --flush | awk '{now=strftime("%d-%T "); print now $0}'
Initializing serial port /dev/ttyUSB002 (115200, 8N1) ...
Resetting Arduino ...
Flushing serial buffer ...
Receiving serial data ...
09-10:26:01 0-0:0:1
09-10:26:02 0-0:0:2
09-10:26:03 0-0:0:3
09-10:26:04 0-0:0:4
...
09-10:48:13 0-0:22:13
09-10:48:14 0-0:22:14
09-10:48:15 0-0:22:15
Finalize: done.
Initializing serial port /dev/ttyUSB002 (115200, 8N1) ...
Flushing serial buffer ...
Receiving serial data ...
09-10:48:22 0-0:22:22
09-10:48:23 0-0:22:23
09-10:48:24 0-0:22:24
09-10:48:25 0-0:22:25
Use case 2
Receive data from Arduino during 10 seconds, then kill the program. Dump STDOUT as hexadecimal. More verbose information is printed to STDOUT.
$ { /usr/bin/timeout -s SIGINT 10 /home/jhendrix/bin/cat_ttyUSB0.pl --device=/dev/arduinoMega1280-001; } | hexdump -C
Initializing serial port /dev/arduinoMega1280-001 (115200, 8N1) ... Resetting Arduino ... Flushing serial buffer ... Receiving serial data ... SIGINT received. Quitting at /home/jhendrix/bin/cat_ttyUSB0.pl line 41. 00000000 4c 44 52 0d 0a 35 32 0d 0a |LDR..52..| 00000009

