Home    Impressum / Datenschutz    Shop    Download    Links     Blog  

Ansteuerung des I2C-RS232-Modems mit Perl

Temperatur lesen vom LM75 mit dem I2C-RS232-Modem

 Zitat:

Hallo Hr. Horter,

Das Programm funktioniert so unter Windows und Linux.
 
Die Haupt-Ursache warum es Anfangs nicht so recht funktioniert hat war ein nicht eingestellter Timeout-Parameter.
Unter Linux kommt das Write-Kommando quasi sofort zurück (write background), das nachfolgende Read wird per default auch sofort ausgeführt.
Im Prinzip wird so gelesen, obwohl der write noch nicht fertig war. Nun, so schnell kann der PIC auch nicht reagieren.
Deshalb hat es auch mit der 20ms-Pause funktioniert. Der entscheidende "read_const_time"-Parameter muss (auf meinem System) auf mind. 5ms eingestellt werden.
Eine weitere Verkürzung bringt wieder den gleichen Effekt.

Viele Grüße und schönes Wochenende!
Thomas D.


#!/usr/bin/perl
#Testprogramm fuer Horter & Kalb I2C-Modem
#(C)2006 Thomas Dressler

use constant false=>0;
useconstant true=>1;
useTime::HiRes qw( usleep ualarm);
if ($#ARGV ==1) {
    $PortName=$ARGV[0];
    $Adresse=$ARGV[1];
    $quiet=0;

    $OS=$^O;
    if ($OS eq 'MSWin32') {
        eval ("use Win32::SerialPort qw { :PARAM :STAT };");
        die "$@\n" if ($@);
        $PortObj = new Win32::SerialPort ($PortName, $quiet)
    || die "Can't open $PortName: $^E\n"; # $quiet is optional
    } else {
        eval ("use Device::SerialPort qw { :PARAM :STAT };");
        die "$@\n" if ($@);
        $PortObj = new Device::SerialPort ($PortName, $quiet)
        || die "Can't open $PortName: $^E\n"; # $quiet is optional

    }

    $PortObj->databits(8);
    $PortObj->baudrate(19200);
    $PortObj->parity("none");
    $PortObj->stopbits(1);
    $PortObj->handshake("none");
    $PortObj->datatype('raw'); # in case an application needs_to_know
    $PortObj->binary(1);
    $PortObj->debug(1);
    # prints hardware messages like "Framing Error"
    $PortObj->error_msg(1);
    # prints function messages like "Waiting for CTS"
    $PortObj->user_msg(1);
    # wait 1ms for each character
    $PortObj->read_char_time(1);
    # 15 ms per unfulfilled "read" call (maybe more)
    $PortObj->read_const_time(15);


    if (! $PortObj->write_settings) {
        undef $PortObj;
        die "Write Settings failed!\n";
    }
    #Check Modem
    $cmd=chr(16);
    $PortObj->write($cmd);

    #($BlockingFlags, $InBytes, $OutBytes,
    #$LatchErrorFlags) = $PortObj->status;
    #print "Status:in-> ".$InBytes . ":out->".$OutBytes.
    #":Block->".$BlockingFlags. ":Error->".$LatchErrorFlags. "\n";
    #usleep(20000);

    $r=$PortObj->read(1);
    if ((ord($r)==192)) {
        print "I2C-Modem detected\n";
       
        #Get Version
        $cmd=chr(80);
        $PortObj->write($cmd);
        #usleep(20000);
        $v1=ord($PortObj->read(1));
        $v2=ord($PortObj->read(1));
        $version=chr($v1+48).".".chr($v2+48);
        print "Version $version\n";
   
        #read LM75
        $cmd=chr(128+1);
        $PortObj->write($cmd);
        $PortObj->write(chr($Adresse+1));
        #usleep(20000);
        $r=$PortObj->read(1);
        if ((ord($r)==192)) {
            $v1=ord($PortObj->read(1));
            $v2=ord($PortObj->read(1));
            if (($v1 & 128) == 0) {
                $T = $v1;
            }else{
                $T = $v1 - 255;
            }
            if (($v2 & 128) == 128) {
                $T = $T + 0.5;
            }
            print "Temperatur ".sprintf("%4.1f",$T)."°C\n^";
        } else {
            print "Error,Modem Code is:".ord($r)."\n";
        }
    }else {
        print "I2C-Modem not detected:".ord($r)."\n";
    }
    $PortObj->close;
}else{
    print "Usage: perl testmodem.pl \n";
    print "Windows: perl testmodem.pl 'COM1' 144\n";
    print "Unix: perl testmodem.pl '/dev/ttyS0' 144\n";
}

 
Perl-Quellcode für das I2C-RS232-Modem
perl-i2c-modem-test.pl (3 kB)
Perl-Quellcode mit einem Beispiel, wie das I2C-Modem angesprochen werden kann.
(Bitte mit der rechten Maustaste "speichern unter" wählen! )
perl_tests.zip (10 kB)
Hier ein Beispiel für den LM75 in Perl. Die Bibliotheken sind so gebaut, dass sich beliebige andere Geräte damit programmieren lassen. Insofern ist nur die LM75-Funktionalität ein Beispiel der Anwendung.
Die Perlscripte laufen unverändert auch unter Linux und sollten genauso auf anderen Unix-Maschinen laufen, wo sich das Device "Serialport" Modul von Perl installieren lässt.
Für Windows heißt das Modul Win32:.Serialport, welches zusätzlich installiert werden muss." (Autor: Thomas D.)