PySerial tidak berbicara dengan Arduino

Saya telah menulis beberapa kode untuk mensimulasikan beberapa perangkat keras yang saya kerjakan dan mengunggahnya ke papan Arduino. Kode ini berfungsi. Saya mengetahui hal ini, karena saya mendapatkan respon yang diharapkan dari HyperTerminal.

Namun, ketika saya mencoba terhubung menggunakan PySerial, koneksi tidak error, tetapi saya tidak mendapat respons terhadap perintah yang saya kirimkan.

Mengapa hal ini bisa terjadi?

Kode piton

import serial

def main():
    sp = serial.Serial()
    sp.port = 'COM4'
    sp.baudrate = 19200
    sp.parity = serial.PARITY_NONE
    sp.bytesize = serial.EIGHTBITS
    sp.stopbits = serial.STOPBITS_ONE
    sp.timeout = 0.5
    sp.xonxoff = False
    sp.rtscts = False
    sp.dsrdtr = False

    sp.open()

    sp.write("GV\r\n".encode('ascii'))
    value = sp.readline()
    print value
    sp.write("GI\r\n".encode('ascii'))
    value = sp.readline()
    print value

    sp.close()
 
if __name__ == "__main__":
    main()

NB: kode pada Arduino mengirimkan kembali \r\n di akhir respon terhadap suatu perintah.

Konfigurasi HyperTerminal:

Konfigurasi COM4 di HyperTerminal

Sunting

Saya telah menemukan bahwa jika saya menambah batas waktu menjadi 10 detik dan menambahkan sp.readline() sebelum saya mengirim apa pun, maka saya mendapat respons untuk kedua perintah tersebut.

Berapa lama biasanya jabat tangan perangkat keras antara PySerial dan port Arduino atau USB RS-232?


person Matt Ellen    schedule 16.11.2011    source sumber
comment
Satu komentar kecil tentang pengiriman perintah ke REPL (command processor) seperti yang dilakukan di sini. Saya perhatikan perintah yang Anda kirimkan diakhiri dengan \r\n. Meskipun baris teks biasa biasanya diakhiri \r\n, perintah Terkirim biasanya hanya diakhiri dengan karakter tunggal \r, karena akan diketik oleh pengguna manusia. Jika \n dikirim, ini mungkin ditafsirkan sebagai awal dari perintah berikutnya dan berpotensi hang atau memicu hasil palsu lainnya yang tidak diinginkan.   -  person RufusVS    schedule 22.10.2018


Jawaban (5)


Tidak dapat memverifikasi ini tetapi bisa jadi Anda mencoba dan membaca sebelum ada data apa pun di sana, sehingga Anda tidak mendapat balasan kembali.

Untuk mengujinya, Anda dapat mencoba dan melakukan polling hingga ada data

value = None
while not value:
   value = sp.readline()
print value

Edit

Arduino akan diatur ulang ketika Anda membuka koneksi serial, data apa pun yang ditulis selama bootup kemungkinan besar akan masuk ke surga. Anda dapat menggunakan mode tidur selama 2 detik (tidak dapat menemukan waktu pasti yang dibutuhkan, kemungkinan besar akan berbeda-beda) sebelum Anda melakukan pembacaan/penulisan.

Alternatifnya, Anda dapat menulis surat sampai Anda mendapat tanggapan kembali, setelah Anda mendapat balasan, Anda mulai melakukan "pekerjaan nyata".

person ib.lundgren    schedule 16.11.2011
comment
Sayangnya, readline mengembalikan string kosong setelah waktu habis. Ini tidak berhasil untuk saya. Saya mencoba menunggu string yang tidak kosong, tetapi itu hanya menghasilkan loop tak terbatas. - person Matt Ellen; 16.11.2011
comment
Ah sayang sekali, sudahkah Anda mencoba tes arduino dasar yang hanya mengirim spam ke Serial.println untuk melihat apakah Anda bisa mendapatkan output sama sekali? - person ib.lundgren; 16.11.2011
comment
Ya, saya bisa mendapatkan keluaran. Awalnya saya hanya bisa mendapatkannya melalui HyperTerminal, tetapi saya menemukan bahwa masalahnya adalah penundaan antara koneksi dan kemampuan mengirim/menerima data. Saya telah memperbarui pertanyaannya. Terima kasih atas bantuan Anda sejauh ini. - person Matt Ellen; 16.11.2011

Untuk saat ini saya menggunakan solusi. Saya telah menyetel timeout menjadi 1,5 detik dan melakukan panggilan readline sebelum penulisan pertama.

Jadi sekarang kode Pythonnya terlihat seperti:

import serial

def main():
    sp = serial.Serial()
    sp.port = 'COM4'
    sp.baudrate = 19200
    sp.parity = serial.PARITY_NONE
    sp.bytesize = serial.EIGHTBITS
    sp.stopbits = serial.STOPBITS_ONE
    sp.timeout = 1.5 #1.5 to give the hardware handshake time to happen
    sp.xonxoff = False
    sp.rtscts = False
    sp.dsrdtr = False

    sp.open()

    sp.readline() #to give the hardware handshake time to happen

    sp.write("GV\r\n".encode('ascii'))
    value = sp.readline()
    print value
    sp.write("GI\r\n".encode('ascii'))
    value = sp.readline()
    print value

    sp.close()

if __name__ == "__main__":
    main()
person Matt Ellen    schedule 16.11.2011
comment
Saya tidak mengerti mengapa ini diperlukan tetapi menambahkan readline() sebelum di depan write juga berhasil untuk saya. - person wizofwor; 12.05.2015
comment
@wizofwor tidak diperlukan, oleh karena itu, ini hanya cara mudah untuk membuat perangkat lunak menunggu hingga perangkat keras siap. - person Matt Ellen; 26.06.2015

Saya juga mengalami masalah ini baru-baru ini dan inilah solusi saya:

import serial

ser = serial.Serial(4, timeout=2)
ser.setRTS(True)
ser.setRTS(False)
while 1:
    line = ser.readline()
    print(line)
ser.close

Ternyata ini akan berhasil mereset papan Arduino.

person Memphis    schedule 04.07.2012

Tambahkan penundaan setelah Anda membuka port saat Arduino diatur ulang dan bootloader mulai mendengarkan firmware baru. Jika ada sesuatu yang dikirim pada saat itu, MCU tetap terjebak di bootloader. Penundaan menyebabkan waktu bootloader habis.

sp.open()
time.sleep(2) # 2 seconds or possibly a bit less
sp.write("blahblah")
person nvd    schedule 16.08.2016

Anda dapat dengan mudah dan kuat menghubungkan dan berkomunikasi antara papan Python dan Arduino menggunakan perpustakaan yang kompatibel SerialTransfer.h dan pySerialTransfer. Pustaka ini secara otomatis membuat paket dan mengurai paket serial menggunakan penanda awal/akhir, pemeriksaan redundansi siklik, pengisian byte overhead yang konsisten, dan panjang muatan dinamis.

SerialTransfer.h dapat diinstal melalui Libraries Manager Arduino IDE dan pySerialTrasnfer dapat diinstal dengan pip.

Contoh Python:

from pySerialTransfer import pySerialTransfer as txfer

if __name__ == '__main__':
    try:
        link = txfer.SerialTransfer('COM13')

        link.txBuff[0] = 'h'
        link.txBuff[1] = 'i'
        link.txBuff[2] = '\n'

        link.send(3)

        while not link.available():
            if link.status < 0:
                print('ERROR: {}'.format(link.status))

        print('Response received:')

        response = ''
        for index in range(link.bytesRead):
            response += chr(link.rxBuff[index])

        print(response)
        link.close()

    except KeyboardInterrupt:
        link.close()

Contoh Arduino:

#include "SerialTransfer.h"
#include <SoftwareSerial.h>


SoftwareSerial mySerial(2, 3); // RX, TX
SerialTransfer myTransfer;


void setup()
{
  Serial.begin(115200);
  mySerial.begin(9600);
  myTransfer.begin(mySerial);
}

void loop()
{
  myTransfer.txBuff[0] = 'h';
  myTransfer.txBuff[1] = 'i';
  myTransfer.txBuff[2] = '\n';

  myTransfer.sendData(3);
  delay(100);

  if(myTransfer.available())
  {
    Serial.println("New Data");
    for(byte i = 0; i < myTransfer.bytesRead; i++)
      Serial.write(myTransfer.rxBuff[i]);
    Serial.println();
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");
    Serial.println(myTransfer.status);
  }
}
person P_B    schedule 10.02.2020