jgromes / RadioLib

Universal wireless communication library for embedded devices
https://jgromes.github.io/RadioLib/
MIT License
1.6k stars 400 forks source link

CW receive support #545

Closed 4I1DVL closed 2 years ago

4I1DVL commented 2 years ago

Hi! How can I view the output CW from SX1278 to CWget? or CW Skimmer?

I'm using arduino uno connected to another board/shield with SX1278. It should be able to receive CW beacons. My problem is how I can verify this. I connected the arduino (with the sx1278) to my laptop via USB. I hope someone can help me.

P.S. I'm a noob at this.

jgromes commented 2 years ago

Not sure what is the question about - RadioLib doesn't support CW reception, only transmission at the moment. To receive, you will have to use something else, such as software-defined radio.

4I1DVL commented 2 years ago

Will RadioLib support CW reception anytime soon? Do you know if there are other libraries that will allow me to do this using SX1278 (Transceiver IC)? Thank you so much for replying. Really appreciate it. been stuck with this for a few days already.

jgromes commented 2 years ago

That's tricky - the primary issue is that SX1278 (and all the other modules supported by RadioLib) were designed to transmit digital packets. All the ham radio modes in RadioLib (CW, RTTY, SSTV, AX.25 etc.) are more or less a hack.

For CW reception, there might be a way to do it, either with direct mode reception or just sampling the CW signal by RSSI measurement, but it might depend on the mode you're using - SSB (emulated by transmitting 2-FSK), FM (AFSK) or AM (ook) modulated CW?

4I1DVL commented 2 years ago

I am using AM (OOK) modulated CW.

4I1DVL commented 2 years ago

Hi, it's me again. Do you have an idea how I can input the RSSI to PC?

jgromes commented 2 years ago

You can call the getRSSI() method (which returns the isntant RSSI measurement in dBm) and print the result to the Serial port, though I suspect you will have to write some custom program for receiving the data on the other side.

EDIT: Here's what that looks like - you can see the dots and dashes:

Screenshot_28

However, it should be possible to demodulate completely on Arduino side - for example, by putting the radio to receive direct mode, then measuring the pulse length on the DIO2 pin. This is something I will have to investigate further.

jgromes commented 2 years ago

So after playing around a little bit with pulseIn, I was able to write a very simple "demodulator" for the OOK CW. The pulse length and count values work only for 400 Hz 20 WPM CW, but it should be usable, so at least in theory, receiving and decoding CW is perfectly doable in RadioLib:

// include the library
#include <RadioLib.h>

// SX1278 has the following connections:
// NSS pin:   10
// DIO0 pin:  2
// RESET pin: 9
// DIO1 pin:  3
SX1278 radio = new Module(5, 2, 9, 3);

// DIO2 pin:  5
const int pin = 4;

// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1278 radio = RadioShield.ModuleA;

void setup() {
  Serial.begin(9600);
  //pinMode(pin, INPUT);

  // initialize SX1278 with FSK modem at 9600 bps
  Serial.print(F("[SX1278] Initializing ... "));
  int state = radio.beginFSK();
  if (state == RADIOLIB_ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  // after that, set mode to OOK
  Serial.print(F("[SX1278] Switching to OOK ... "));
  state = radio.setOOK(true);
  if(state == RADIOLIB_ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while(true);
  }

  // start direct mode reception
  radio.receiveDirect();
}

int count = 0;
void loop() {
  int duration = pulseIn(pin, LOW, 4000);
  if(duration > 1200 && duration < 1300) {
    //Serial.println(duration);
    count++;
  } else if(count > 0) {
    //Serial.println(count);

    if(count > 20 && count < 30) {
      Serial.println('.');

    } else if(count > 60 && count < 80) {
      Serial.println('-');

    }

    count = 0;
  }
}

The code above will demodulate square wave "tones" coming from SX1278 DIO2, then based on the length of the tone decide if it's a dot or dash. It doesn't decode the dots and dashes into characters, but it works as a proof of concept. I'll work on further integration into the library, but you should be able to use this.

jgromes commented 2 years ago

@4I1DVL so I finally had the time to fully integrate this into the library - you can find a working example here: https://github.com/jgromes/RadioLib/blob/master/examples/Morse/Morse_Receive_AM/Morse_Receive_AM.ino

At the moment, only AM mode is supported - I'm not sure if other modes will be possible as well, that might be worth further investigation.