msalerno <> kirjoitti 11.07.2005:
> I have a device that uses the dsr for communications. Basically what I
> am trying to do is get a count of how many pulses it sends per second.
[snip]
> my $pulse = 0!=($ModemStatus & MS_DSR_ON);
[snip]
> if ($pulse == 1){
> usleep(1); # sleep one milisecond if change detected.
> }
Here's one major problem: $pulse will be 1 if the DSR line is on, not
if it has changed.
Anyway, here's how I'd rewrite your script:
#!/usr/bin/perl -w
use strict;
use Time::HiRes qw(time sleep);
use Device::SerialPort qw(

ARAM :STAT 0.07 );
use constant SAMPLE_STEP => 1/1000; # sample once per msec
use constant REPORT_STEP => 1; # report once per second
# Open Serial Port
my $PortObj = new Device::SerialPort ('/dev/ttyS0')
or die "Cannot open Port: $!\n";
my $lastdsr = $PortObj->modemlines & MS_DSR_ON;
my $t0 = time;
while (1) {
my $changes = 0;
while (time < $t0 + REPORT_STEP) {
my $dsr = $PortObj->modemlines & MS_DSR_ON;
$changes++ if $dsr xor $lastdsr;
$lastdsr = $dsr;
sleep SAMPLE_STEP;
}
printf "%02d-%02d-%02d: %d - %.2f - %.2f\n",
(localtime int $t0)[2, 1, 0], $changes,
$changes / (3.4 * REPORT_STEP),
$changes / (2.5 * REPORT_STEP);
$t0 += REPORT_STEP;
}
I haven't tested this code, as I don't have Device::SerialPort
installed, nor do I have any suitable signal source available either.
But I'm fairly confident it should work.
The code counts state changes in both directions. If you only want to
count transitions from off to on, replace "xor" with "and not".
I'm assuming that SAMPLE_STEP is sufficiently small that no pulses can
ever be missed. Therefore I haven't bothered to synchronize the inner
loop; the actual time between samples will be SAMPLE_STEP plus however
long it takes to execute the inner loop.
The outer loop, however, is synchronized, which means you'll get
reports exactly once every REPORT_STEP seconds on average, and there
should be no statistical bias in the output (ignoring possible
floating point roundoff errors). Actually, I think your original code
would've worked the same way, had it worked correctly at all.
Note that there's really nothing Perl-specific about this. The same
code could be trivially ported to C or Java or just about any other
language. Only the interfaces to the serial port and the system timer
would change.
--
Ilmari Karonen
To reply by e-mail, please replace ".invalid" with ".net" in address.