Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to send/receive data via HC-12/UART in Python

I've written some code to communicate between two Raspberry Pi's, using identical HC-12 433Mhz transceivers. I was able to successfully echo between the two Pi's using a direct serial connection and echo/cat, however am unable to replicate this using HC-12s, which theoretically work by a similar principal. I'm using the port ttyAMA0 on both for this example, but ttyS0 is also available and have tried every combination of these ports.

The following code is common to both the sending and receiving, just writing once for sake of brevity:

import serial
import time

ser = serial.Serial(
    port = "/dev/ttyAMA0",
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS
)
print("Serial status: " + str(ser.isOpen()))

This is the sending program:

while True:
    print("Sending...")
    ser.write("hello\n".encode())
    time.sleep(1)

And the receiving program:

while True:
    print("Receiving...")
    data = ser.readlines()
    print(data.decode())

The sending program simply loops as expected, but the receiver prints "Receiving...", and then nothing.

When I keyboard interrupt the receiving program at that point, it says it is currently up to data = ser.readlines().

Any help would be much appreciated - I've spent the better part of the last week trawling and exhausting forums and READMEs to no avail, and this is literally my last option. Am close to insanity on this one!

like image 496
Woodman Avatar asked Jul 02 '20 13:07

Woodman


People also ask

How does HC 12 work?

The HC-12 is a half-duplex wireless serial communication module with 100 channels in the 433.4-473.0 MHz range that is capable of transmitting up to 1 km. This project will begin by using the HC-12 to create a wireless link between two computers and end with a second article that creates a simple wireless GPS tracker.

What is HC 12?

HC-12 wireless serial port communication module is a new-generation multichannel embedded wireless data transmission module. Its wireless working frequency band is 433.4-473.0MHz, multiple channels can be set, with the stepping of 400 KHz, and there are totally 100 channels.


Video Answer


2 Answers

The pyserial readlines() function relies on the timeout parameter to know when end-of-file is reached - this is warned about in the doco. So with no timeout, the end never occurs, so it keeps buffering all lines read forever.

So you can just add a timeout to the serial port open, and your existing code will begin to work.

ser = serial.Serial(
    port     = "/dev/ttyAMA0",
    baudrate = 9600,
    parity   = serial.PARITY_NONE,
    stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS,
    timeout  = 2                        # seconds     # <-- HERE
)

A better approach might be to use readline() (note singular, no 's'), for each line in turn:

print( "Receiving..." )
while True:
    try:
        data = ser.readline()
        print( data.decode() )
        # TODO - something with data
    except:
        print( "Error reading from port" )
        break

As that will allow the code to act on the input line-by-line.

like image 193
Kingsley Avatar answered Sep 20 '22 04:09

Kingsley


Use Serial.read_until method. The default termination character is \n.

For example,

data = ser.read_until()
print(data)
like image 34
Oluwafemi Sule Avatar answered Sep 18 '22 04:09

Oluwafemi Sule