fphammerle / python-cc1101

Python Library & Command Line Tool to Transmit RF Signals via CC1101 Transceivers
https://pypi.org/project/cc1101/
GNU General Public License v3.0
72 stars 14 forks source link

sending 25 bit ook signal. #185

Open adminy opened 1 month ago

adminy commented 1 month ago

transmit only takes bytes and I'd like to send 25 bits of information about 4 times,

my parameters are the following:

[~ (50kHz) ]            # define a base frequency
[_ (2100us) ]             # define a long gap (6 clks)
[0 (~344us) (1238us) ]   # define a short pulse and long gap (1:3)
[1 (~1032us) (344us) ]   # define a long pulse and short gap (3:1)

And the key is 0011011101100111101111000.

code = '006ecf78'

code = int(code, 16).to_bytes(4, byteorder='big')

print(code, len(code))

import cc1101, math

MESSAGE_BITS = 25
MESSAGE_REPEAT = 4

SYNC_WORD = bytes([255, 168])  # 168 might be sender-specific

with cc1101.CC1101() as transceiver:
    transceiver.set_base_frequency_hertz(433.92e6)
    transceiver.set_symbol_rate_baud(2048)
    transceiver.set_sync_mode(cc1101.SyncMode.TRANSMIT_16_MATCH_15_BITS, _carrier_sense_threshold_enabled=True)
    transceiver.set_sync_word(SYNC_WORD)
    transceiver.disable_checksum()

    transmission_length_bytes = math.ceil(MESSAGE_BITS * MESSAGE_REPEAT / 8)
    transceiver.set_packet_length_mode(cc1101.PacketLengthMode.FIXED)
    transceiver.set_packet_length_bytes(transmission_length_bytes - len(SYNC_WORD))

    transceiver._set_filter_bandwidth(mantissa=3, exponent=3)

    print(transceiver)
    transceiver.transmit(code)

    packet = transceiver._wait_for_packet(timeout=0, gdo0_gpio_line_name=b"GPIO24")
    print(packet)

Also not sure that this is the correct way to both receive and transmit at the same time. I suspect this makes sense in a callback way of doing this.

fphammerle commented 1 month ago

cc1101.transmit uses cc1101's "synchronous serial mode". as far as I understand cc1101's official docs that mode does not support sending fraction of bytes (see PKTCTRL0.PKT_FORMAT=1). if you are using on-off-keying modulation (OOK) without checksums you could just append low bits (signal off) at the end of each payload to fill up incomplete bytes. alternatively, you could use with transceiver.asynchronous_transmission() as pin: … (see PKTCTRL0.PKT_FORMAT=3 in cc1101's official docs), but then you will need to send your signal manually to pin GDO0.

_wait_for_packet would work as specified in your code sample above. however, that method is still private cause the interface is unstable (might change in future). callback is not implemented yet.

adminy commented 5 days ago

for _wait_for_packet I had to use the libgpiod python package. I have the code changes if you'd like a PR. Can there be multiple fixed values for packages received or would I have to use variable mode for that? Also I noticed some packages are not showing up. I wonder what I can do to receive all packages, maybe have less message repeats and count repeats another way? maybe automate the set_packet_length_bytes function.

fphammerle commented 5 days ago

for _wait_for_packet I had to use the libgpiod python package. I have the code changes if you'd like a PR.

Thanks, I am already using libgpiod, PR isn't needed for my purposes. https://github.com/fphammerle/python-cc1101/blob/v3.0.0/cc1101/_gpio.py#L65

Can there be multiple fixed values for packages received or would I have to use variable mode for that?

As far as I know, in fixed length mode CC1101 only supports a single length.

Also I noticed some packages are not showing up. I wonder what I can do to receive all packages, maybe have less message repeats and count repeats another way?

Sorry, I can't provide support here (I would need to analyze the signal).

adminy commented 4 days ago

The GPIO was missing the library call in the dll/so lib, because it seems I'm using a newer version of libgpiod. So this worked for me:

IMG_6772

I'll try see if I can improove the parsing in case the signal repeats, I'll post my solution here. see if we can improve on the receiving code.

adminy commented 4 days ago

Ok, so I've exhausted all options here, still not receiving anything at all.

import cc1101

with cc1101.CC1101() as transceiver:
    transceiver.set_base_frequency_hertz(433.92e6)
    transceiver.set_symbol_rate_baud(2048)
    transceiver.set_sync_mode(cc1101.SyncMode.NO_PREAMBLE_AND_SYNC_WORD)
    transceiver.disable_checksum()
    transceiver.set_packet_length_mode(cc1101.PacketLengthMode.VARIABLE)

    transceiver._set_filter_bandwidth(mantissa=3, exponent=3)
    transceiver._enable_receive_mode()
    print(transceiver) # CC1101(marcstate=startcal, base_frequency=433.92MHz, symbol_rate=2.05kBaud, modulation_format=ASK_OOK, sync_mode=NO_PREAMBLE_AND_SYNC_WORD, packet_length≤255B, output_power=(0xc6,0))

    while True:
        packet = transceiver._get_received_packet()
        if packet and packet.payload: print(packet.payload)

... and ... radio silence .... (except b'\xff\xff' appearing out of nowhere with no radio involved) any ideas what I could try @fphammerle ?

fphammerle commented 4 days ago

To verify that the settings above are correct, I would 1. record the original signal (e.g. with a RTL-SDR dongle), 2. transmit with your settings above & record the transmitted signal in the same way as 1. and then compare if 1. and 2. look similar (same base frequency, symbol rate etc.)

b'\xff\xff' are probably noise

adminy commented 3 days ago

the two variables i'm not sure about is the symbol rate and filter bandwidth. I didn't know the rtl_sdr dongle reports back a symbol rate, is this perhaps the sample rate?. I guess that's something I can check.

fphammerle commented 3 days ago

rtl_sdr dongle does not report the symbol rate. You need to (manually) derive the symbol rate from the signal captured by the rtl_sdr dongle.

the sample rate is the configured rate that the rtl_sdr dongle records in

adminy commented 3 days ago

I scanned with rtl sdr. here are the results: https://triq.org/pdv/#AAB0210306015003EC28108190908190909081818181819090818190818181819090818255+AAB0120301015003EC28108190908190909081818255 I have:

ASK bit_rate is the same as the baud_rate.

bits_per_second = (119 8) (1 / 0.279)

3410 baud samples per second

Receiver getting nothing still.

adminy commented 3 days ago

I did a little sanity check test by doing this:

    transceiver._enable_receive_mode()
    while True:
        packet = transceiver._get_received_packet()
        if packet and packet.payload:
            print(packet.payload)
            transceiver._enable_receive_mode()

So it looks like packet payload only changes if you call _enable_receive_mode() in a loop continuously after receiving packets. Also the GPIO rising EDGE only gets called once, perhaps I've got to listen to both RISING and FALLING edges?

fphammerle commented 2 days ago

Personally, I use _wait_for_packet (calls _enable_receive_mode before each _get_received_packet). Sorry, I can't provide any more support here.