1

rs485 シリアル リンクを介して arduino と通信しようとしています。PCにUSBからシリアルrs485アダプターを接続し、arduino側にmax485を接続しています。開始するには、受け取ったものを送り返すスケッチをアップロードするだけです。

#include <SoftwareSerial.h> 
#define SSerialRX        10  //Serial Receive pin
#define SSerialTX        11  //Serial Transmit pin    
#define SSerialTxControl 3   //RS485 Direction control
#define RS485Transmit    HIGH
#define RS485Receive     LOW    
#define Pin13LED         13    

SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX    

void setup()
{
  pinMode(Pin13LED, OUTPUT);
  pinMode(SSerialTxControl, OUTPUT);    
  digitalWrite(SSerialTxControl, RS485Receive);
  RS485Serial.begin(300);
}//--(end setup )---    


void loop()
{
  if (RS485Serial.available()){
    delay(100);
    char x = RS485Serial.read();
    digitalWrite(Pin13LED, HIGH);
    digitalWrite(SSerialTxControl, RS485Transmit); // Enable RS485 Transmit
    Serial.write(x);
    RS485Serial.write(x); 
    Serial.flush();
    delay(10);
    digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit
    digitalWrite(Pin13LED, LOW);
    delay(200);
  }    

}//--(end main loop )---    

次に、接続をテストするために、シリアル ポートに文字を書き込み、応答をリッスンする python スクリプトを PC で実行します。

import serial
import time    

PORT1 = "/dev/ttyUSB0"    

try:
    rs485 = serial.Serial(PORT1, 300)
    while True:
        print 'loop'
        rs485.write('r')
        time.sleep(0.5)
        data = rs485.read()
        if data == '\0':
            print 'null'
        else:
            print data
        time.sleep(1)
except:
    rs485.close()

スクリプトを初めて起動すると、次のようになります。

giulio@giulio-vaio:~$ python rs485io.py
loop
r
loop
r
loop
^C

スクリプトを再度起動しようとすると、次のようにしか書き込まれません。

giulio@giulio-vaio:~$ python rs485io.py
loop
null
loop
null
loop
null
^C

PCを再起動した場合にのみ、再び機能し始めます(ちなみにubuntuを使用)。USBからシリアルへのコンバーターを抜き差ししても何も変わらず、arduinoを再起動しても同じ話です。ラズベリーパイで同じ構成を試しましたが、結果は同じです。USB ポートの変更が機能しません。arduino で同じスケッチを再度アップロードしても、何も起こりません。ピン 13 の LED が点滅するので、arduino は何かを送受信しています。serial.read() 関数が返されるので、何かが到着していますが、(最初の 1 回目以降は) null 文字 '\x00' です。ある肯定的なケースでは、再起動後、スクリプトをしばらく実行させようとしましたが、ctrl-c を押してスクリプトを再開するまで、すべてがうまくいきました。

これは、シリアル コンバーターを接続した後の dmesg です。

[ 6116.508264] usb 1-2.1.3: new full-speed USB device number 27 using ehci-pci
[ 6116.617247] usb 1-2.1.3: New USB device found, idVendor=1a86, idProduct=7523
[ 6116.617257] usb 1-2.1.3: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 6116.617264] usb 1-2.1.3: Product: USB2.0-Serial
[ 6116.617694] ch341 1-2.1.3:1.0: ch341-uart converter detected
[ 6116.621498] usb 1-2.1.3: ch341-uart converter now attached to ttyUSB0

この後どうすればいいのかわからないので、助けていただければ幸いです。

編集 :

PC を再起動する必要はありません。USB コンバーターを処理するモジュール ch341 をアンロードしてから再度ロードすると機能します。コードの先頭に次の 2 行を追加しました。

subprocess.Popen("modprobe -r ch341".split()).wait()
subprocess.Popen("modprobe ch341".split()).wait()

問題が本当に解決しないことはわかっていますが、機能します。

編集 2: ドキュメントhttp://lxr.free-electrons.com/source/Documentation/serial/serial-rs485.txtを見て、c (i' m は C が苦手なので、ご容赦ください)

#include (all the libraries needed)

/* Driver-specific ioctls: */
#define TIOCGRS485      0x542E
#define TIOCSRS485      0x542F
/* Open your specific device (e.g., /dev/mydevice): */    

int main(){
    const char *file1 = "/dev/ttyUSB0";
    const char *file2 = "output_cprog.txt";
    int fd = open (file1,O_WRONLY);
    if(fd < 0){
        printf("%s: %s\n","error opening ttyusb",strerror( errno ) );
    }
    int fq = open(file2,O_WRONLY);
    if( fq < 0){
        printf("%s: %s\n","errore apertura file",strerror( errno ));
    }    

    struct serial_rs485 rs485conf;
     // Enable RS485 mode:
    rs485conf.flags |= SER_RS485_ENABLED;
     // Set logical level for RTS pin equal to 1 when sending:
    rs485conf.flags |= SER_RS485_RTS_ON_SEND;
     // or, set logical level for RTS pin equal to 0 after sending:
    rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
     // Set rts delay before send, if needed:
    rs485conf.delay_rts_before_send = 10;
     // Set rts delay after send, if needed:
    rs485conf.delay_rts_after_send = 10;
    int ioc = ioctl (fd, TIOCSRS485, &rs485conf);
    if(ioc < 0){
        printf("%i\n",ioc);
        printf("ioctl error: %s\n", strerror( errno ));
    }    

    char *character = "f\n";
    write(fd,character,2);
    char *buffer;
    buffer = (char *) malloc(10);
    read(fd, buffer, 1);
    write(fq, buffer, 1);
    printf("received character: %s\n",buffer[0]);    

    if( close(fd) < 0){
        printf("%s: %s\n","error closing port",strerror( errno ));
    }
    if (close(fq) < 0){
        printf("%s: %s\n","error closing file",strerror( errno ));
    }
    return 0;
}

しかし、プログラムをコンパイルして実行すると、私が見るのはこれだけです:

giulio@giulio-vaio:~$ ./ioctlRS485.o 
-1
ioctl error: Inappropriate ioctl for device
received character: (null)

ドライバーhttps://github.com/torvalds/linux/blob/master/drivers/usb/serial/ch341.cを見ると、ioctlを処理するための適切な機能がまったくないと思います。

4

0 に答える 0