python-cc1101 icon indicating copy to clipboard operation
python-cc1101 copied to clipboard

sending 25 bit ook signal.

Open adminy opened this issue 1 year ago • 11 comments

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.

adminy avatar May 25 '24 23:05 adminy

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.

fphammerle avatar May 26 '24 07:05 fphammerle

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.

adminy avatar Jun 30 '24 10:06 adminy

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).

fphammerle avatar Jun 30 '24 10:06 fphammerle

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 avatar Jun 30 '24 17:06 adminy

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 ?

adminy avatar Jun 30 '24 23:06 adminy

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

fphammerle avatar Jul 01 '24 11:07 fphammerle

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.

adminy avatar Jul 01 '24 13:07 adminy

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

fphammerle avatar Jul 01 '24 14:07 fphammerle

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

  • 119 bytes or 119 * 8 bits of data.
  • Duration is 279.16 ms
  • sample rate is 250khz.
  • 69971 samples
  • 160 pulses

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 avatar Jul 01 '24 22:07 adminy

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?

adminy avatar Jul 02 '24 06:07 adminy

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

fphammerle avatar Jul 02 '24 12:07 fphammerle