Thursday 6 June 2019

20m WSPR Beacon


Below is the software. Looks like the formatting has been affected when it was copied over. Auto format in the Arduino IDE works great!

*****************************************************************


#include <DDS.h>
#include <SoftwareSerial.h>

#define RESET 2
#define FQ_UD 3
#define W_CLK 4
#define DATA 5
#define HighPWR_LED 6
#define LowPWR_LED 7
#define TX_LED 8
#define Percent25_LED 9
#define Percent50_LED 10
#define Percent75_LED 11
#define Percent100_LED 12
#define SerialTX 13
#define SerialRX A0
#define Tone0_LED A1
#define Tone1_LED A2
#define Tone2_LED A3
#define Tone3_LED A4

const int GPS_BUFFER_SIZE = 200;                              // The maximum size allowed for an NMEA sentence.
char sentence[GPS_BUFFER_SIZE] = {0};
volatile int _sentenceIndex = 0;
volatile char character = 0;
volatile int SymbolIndex = 0;
volatile int TX = 0;
volatile int Power = 0;
volatile int _UTCMinutes, _UTCSeconds = 0;
volatile long freq = 0;

const byte LowPWR_WSPR_Data[] = {3, 1, 2, 0, 2, 2, 0, 2, 3, 2, 0, 0, 1, 1, 1, 0, 2, 2, 3, 2, 2, 3, 2, 3, 1, 3, 3, 2, 0, 2, 0, 2,
                                 0, 2, 3, 2, 2, 3, 2, 1, 0, 0, 2, 0, 0, 0, 1, 0, 1, 3, 2, 2, 1, 3, 0, 3, 0, 2, 2, 1, 3, 0, 3, 0,
                                 2, 0, 0, 3, 3, 2, 3, 2, 3, 2, 3, 0, 1, 0, 0, 1, 2, 2, 1, 2, 1, 3, 0, 0, 0, 3, 3, 0, 1, 0, 1, 2,
                                 2, 2, 3, 0, 0, 0, 2, 0, 3, 0, 0, 3, 0, 0, 3, 3, 3, 2, 3, 1, 2, 0, 1, 3, 2, 3, 0, 0, 2, 1, 3, 1,
                                 2, 0, 0, 2, 2, 3, 0, 1, 0, 2, 1, 3, 0, 0, 0, 2, 2, 0, 0, 3, 3, 0, 3, 0, 3, 3, 2, 2, 2, 1, 3, 2,
                                 2, 0
                                };

const byte HighPWR_WSPR_Data[] = {3, 1, 2, 0, 2, 0, 0, 2, 3, 0, 0, 2, 1, 3, 1, 2, 2, 2, 3, 2, 2, 3, 2, 3, 1, 3, 3, 0, 0, 0, 0, 0,
                                  0, 2, 3, 0, 2, 1, 2, 3, 0, 0, 2, 0, 0, 0, 1, 0, 1, 1, 2, 0, 1, 1, 0, 3, 0, 0, 2, 1, 3, 0, 3, 0,
                                  2, 0, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2, 1, 0, 0, 1, 2, 2, 1, 0, 1, 1, 0, 0, 0, 1, 3, 2, 1, 0, 1, 0,
                                  2, 2, 3, 0, 0, 2, 2, 0, 3, 2, 0, 1, 0, 2, 3, 1, 3, 0, 3, 1, 2, 2, 1, 3, 2, 1, 0, 2, 2, 3, 3, 1,
                                  2, 0, 0, 2, 2, 1, 0, 3, 0, 2, 1, 1, 0, 0, 0, 2, 2, 0, 0, 3, 3, 2, 3, 0, 3, 1, 2, 0, 2, 3, 3, 0,
                                  2, 0
                                 };

// Create the objects
DDS dds(W_CLK, FQ_UD, DATA, RESET);
SoftwareSerial mySerial(SerialRX, SerialTX);

void setup()
{
  // Initialize the AD9850
  dds.init();
  dds.trim(125000000);
  dds.setFrequency(0);

  // Initialize the Software serial port
  mySerial.begin(38400);

  pinMode(HighPWR_LED, OUTPUT);
  pinMode(LowPWR_LED, OUTPUT);
  pinMode(TX_LED, OUTPUT);
  pinMode(Percent25_LED, OUTPUT);
  pinMode(Percent50_LED, OUTPUT);
  pinMode(Percent75_LED, OUTPUT);
  pinMode(Percent100_LED, OUTPUT);
  pinMode(Tone0_LED, OUTPUT);
  pinMode(Tone1_LED, OUTPUT);
  pinMode(Tone2_LED, OUTPUT);
  pinMode(Tone3_LED, OUTPUT);

  digitalWrite(HighPWR_LED, LOW);
  digitalWrite(LowPWR_LED, LOW);
  digitalWrite(TX_LED, LOW);
  digitalWrite(Percent25_LED, LOW);
  digitalWrite(Percent50_LED, LOW);
  digitalWrite(Percent75_LED, LOW);
  digitalWrite(Percent100_LED, LOW);
  digitalWrite(Tone0_LED, LOW);
  digitalWrite(Tone1_LED, LOW);
  digitalWrite(Tone2_LED, LOW);
  digitalWrite(Tone3_LED, LOW);
}


void loop()
{
  if (TX == 0)
  {
    if (mySerial.available())
    {
      character = mySerial.read();                                                    // Get a single character
      sentence[_sentenceIndex] = character;                                           // Append the current character to the sentence
      _sentenceIndex++;

      if (_sentenceIndex == GPS_BUFFER_SIZE)                                          // Check for overrun of the sentence array. If so, restart
        _sentenceIndex = 0;

      if (character == '\r')                                                          // Carriage return. Look for RMC sentence
      {
        _sentenceIndex = 0;                                                           // Reset index counter ready for next timet

        if ((sentence[4] == 'R') && (sentence[5] == 'M') && (sentence[6] == 'C'))
        {
          _UTCSeconds = (10 * (sentence[12] - 48) + (sentence[13] - 48));
          _UTCMinutes = (10 * (sentence[10] - 48) + (sentence[11] - 48));

          if ((_UTCMinutes % 2 == 0) && ((_UTCSeconds == 0) || (_UTCSeconds == 1) || (_UTCSeconds == 2)))
            TX = 1;
        }
      }
    }
  }

  if (TX == 1)
  {
    digitalWrite(TX_LED, HIGH);                                                        // Turn on the TX LED
    freq = random(14097000, 14097200);                                                 // Select a random TX frequency

    if (Power == 0)
      for (SymbolIndex = 0; SymbolIndex <= 161; SymbolIndex++)
      {
        dds.setFrequency(freq + (LowPWR_WSPR_Data[SymbolIndex] * 1.4648));             // Change DDS freq
        ToneLEDs(LowPWR_WSPR_Data[SymbolIndex]);                                       // Update tone LEDs
        ProgressLEDs(SymbolIndex);                                                     // Update progress LEDs
        delay(683);
      }

    if (Power == 1)
      for (SymbolIndex = 0; SymbolIndex <= 161; SymbolIndex++)
      {
        dds.setFrequency(freq + (HighPWR_WSPR_Data[SymbolIndex] * 1.4648));             // Change DDS freq
        ToneLEDs(HighPWR_WSPR_Data[SymbolIndex]);                                       // Update tone LEDs
        ProgressLEDs(SymbolIndex);                                                      // Update progress LEDs
        delay(683);
      }

    dds.setFrequency(0);                                                                // Turn off the DDS
    ToneLEDs(4);                                                                        // Turn off the tone LEDs
    ProgressLEDs(0);                                                                    // Turn off the progress LEDs
    digitalWrite(TX_LED, LOW);                                                          // Turn off the TX LED
    TX = 0;
    Power = !Power;                                                                     // Toggle transmit power
    PowerLEDs(Power);                                                                   // Toggle power level LED
  }
}


void ToneLEDs(int x)
{
  switch (x)
  {
    case 4:
      digitalWrite(Tone0_LED, LOW);
      digitalWrite(Tone1_LED, LOW);
      digitalWrite(Tone2_LED, LOW);
      digitalWrite(Tone3_LED, LOW);
      break;
    case 3:
      digitalWrite(Tone0_LED, LOW);
      digitalWrite(Tone1_LED, LOW);
      digitalWrite(Tone2_LED, LOW);
      digitalWrite(Tone3_LED, HIGH);
      break;
    case 2:
      digitalWrite(Tone0_LED, LOW);
      digitalWrite(Tone1_LED, LOW);
      digitalWrite(Tone2_LED, HIGH);
      digitalWrite(Tone3_LED, LOW);
      break;
    case 1:
      digitalWrite(Tone0_LED, LOW);
      digitalWrite(Tone1_LED, HIGH);
      digitalWrite(Tone2_LED, LOW);
      digitalWrite(Tone3_LED, LOW);
      break;
    case 0:
      digitalWrite(Tone0_LED, HIGH);
      digitalWrite(Tone1_LED, LOW);
      digitalWrite(Tone2_LED, LOW);
      digitalWrite(Tone3_LED, LOW);
      break;
  }
}


void ProgressLEDs(int x)
{
  if (x <= 30)
  {
    digitalWrite(Percent25_LED, LOW);
    digitalWrite(Percent50_LED, LOW);
    digitalWrite(Percent75_LED, LOW);
    digitalWrite(Percent100_LED, LOW);
  }
  if ((x > 30) && (x <= 70))
  {
    digitalWrite(Percent25_LED, LOW);
    digitalWrite(Percent50_LED, LOW);
    digitalWrite(Percent75_LED, LOW);
    digitalWrite(Percent100_LED, HIGH);
  }
  if ((x > 70) && (x <= 110))
  {
    digitalWrite(Percent25_LED, LOW);
    digitalWrite(Percent50_LED, LOW);
    digitalWrite(Percent75_LED, HIGH);
    digitalWrite(Percent100_LED, HIGH);
  }
  if ((x > 110) && (x <= 150))
  {
    digitalWrite(Percent25_LED, LOW);
    digitalWrite(Percent50_LED, HIGH);
    digitalWrite(Percent75_LED, HIGH);
    digitalWrite(Percent100_LED, HIGH);
  }
  if (x > 150)
  {
    digitalWrite(Percent25_LED, HIGH);
    digitalWrite(Percent50_LED, HIGH);
    digitalWrite(Percent75_LED, HIGH);
    digitalWrite(Percent100_LED, HIGH);
  }
}


void PowerLEDs(int x)
{
  switch (x)
  {
    case 0:
      digitalWrite(LowPWR_LED, HIGH);
      digitalWrite(HighPWR_LED, LOW);
      break;
    case 1:
      digitalWrite(LowPWR_LED, LOW);
      digitalWrite(HighPWR_LED, HIGH);
      break;
  }
}
*************************************************************

The link to the GENWSPR file is: http://www.g4jnt.com/JTModesBcns.htm





5 comments:

  1. Hello Charlie, i can't compile this :-(
    Where did you download the library:
    #include

    thanks Daniel/Germany

    ReplyDelete
  2. Ohh the software cuts the Library name :-(
    The name is: DDS.h

    ReplyDelete
  3. Hi David. This was in the README file for the DDS library:

    DDS : A Library to host an AD9850 DDS Module on Arduino, using soft SPI

    This is a library which controls the widely available,
    low-cost Direct Digital Synthesis ('DDS') Modules,
    based on the Analog Devices 9850 chip
    on the Arduino.

    For more information:
    http://m0xpd.blogspot.co.uk/2014/03/dds-and-duedds-libraries.html

    Four IO lines are required to connect to the AD9850 module...
    (W_CLK, FQ_UD, DATA & RESET).

    To download and use this Library, click the Download ZIP button (on the RHS of this screen).
    Uncompressed the downloaded ZIP archive and rename the folder DDS.
    Put this DDS folder in you Arduino Libraries folder and restart the Arduino IDE.

    To control multiple DDS Modules, see here:
    http://m0xpd.blogspot.co.uk/2015/06/handling-two-dds-modules-in-library.html

    ReplyDelete
  4. Thank you Charlie, now i can compile the sketch :-)
    Will set up the LEDs and the AD module.
    I like the Si5351 more, its only half the size and 2 ports A4/A5

    Great videos and a lot of calculations on your papers for all the resistors..etc!

    ReplyDelete

Note: only a member of this blog may post a comment.