Trybotics Logo

Interrupt Servie Routines using an Arduino 2560 Mega © GPL3+

DESCRIPTION

The primary purpose of this project is to demonstrate the interrupt system on the Arduino. I used an Arduino Mega 2560 because I needed four hardware interrupts, one per message. Each interrupt invokes its own ISR (Interrupt Service Routine.)

This project is a Morse Code (CW) program to emulate a Memory Keyer with a speaker and a flashing LED. It has four pre-defined memories, similar to traditional Ham Radio memory keyers. The text is shown on a 0.91" OLED display. Users can change these four messages to anything they want by altering them in the code. It would also be relatively simple to send the output to a transmitter to key a Ham radio. However, most modern transceivers have built-in memory keyers, and you can buy similar stand-alone keyers to do this. That said, there's nothing like building your own! If nothing else, it's a tool for learning Morse Code by ear. The sketch sends the code relatively fast, and this can be slowed down (or increased) by changing one value, "dotLength" up or down from the default value of 40.

When learning how to use Arduinos, I struggled with hardware interrupts and how to link them to Interrupt Service Routines properly. The documentation is quite clear once you know how to do it, but like many, I learn by doing and following examples. I couldn't find a lot of samples on the Internet that did what I wanted, so I did what I should have done in the first place; study the documentation and learn to do it correctly on my own. It's quite easy once you understand the concept, and hopefully, this project will inspire other Arduino aficionados to use this powerful aspect of the hardware/software interaction. Note that in addition to the push buttons, each pin has a 10K pullup resistor.

Description:

The primary purpose of this project is to demonstrate the interrupt system on the Arduino. I used an Arduino Mega 2560 because I needed four hardware interrupts, one per message. Each interrupt invokes its own ISR (Interrupt Service Routine.)

This project is a Morse Code (CW) program to emulate a Memory Keyer with a speaker and a flashing LED. It has four pre-defined memories, similar to traditional Ham Radio memory keyers. The text is shown on a 0.91" OLED display. Users can change these four messages to anything they want by altering them in the code. It would also be relatively simple to send the output to a transmitter to key a Ham radio. However, most modern transceivers have built-in memory keyers, and you can buy similar stand-alone keyers to do this. That said, there's nothing like building your own! If nothing else, it's a tool for learning Morse Code by ear. The sketch sends the code relatively fast, and this can be slowed down (or increased) by changing one value, "dotLength" up or down from the default value of 40.

When learning how to use Arduinos, I struggled with hardware interrupts and how to link them to Interrupt Service Routines properly. The documentation is quite clear once you know how to do it, but like many, I learn by doing and following examples. I couldn't find a lot of samples on the Internet that did what I wanted, so I did what I should have done in the first place; study the documentation and learn to do it correctly on my own. It's quite easy once you understand the concept, and hopefully, this project will inspire other Arduino aficionados to use this powerful aspect of the hardware/software interaction. Note that in addition to the push buttons, each pin has a 10K pullup resistor.

Description:

Morse Code Interrupt Driven SketchArduino
Simply download to Arduino Mega with the IDE
/*
 *   Simple Arduino CW program to emulate a Memory Keyer 
 *   with sound and a flashing LED Has 4 pre-defined memories.
 *   Text is shown on a 0.91" OLED display. We are using an 
 *   Arduino Mega 2560 because we need 4 hardware interrupts
 *   
 *   Paul M Dunphy, VE1DX
 *   
 *   March 2020
 */
 
#include "U8glib.h"
U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);

char *myMem[] = {
                 "CQ CQ VE1DX TEST",  
                 "DE VE1DX 5NN 05",
                 "TU DE VE1DX TEST",  
                 "AGN ?"
                 };
char mess[100];                

const char* MorseTable[] = {
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  // space, !, ", #, $, %, &, '
  NULL, "-.-.--", ".-..-.", ".----.","...-.-", NULL, NULL,NULL,
  // ( ) * + , - . /
  "-.--.", "-.--.-", NULL, ".-.-.", "--..--", "-....-", ".-.-.-", "-..-.",
  // 0 1 2 3 4 5 6 7
  "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...",
  // 8 9 : ; < = > ?
  "---..", "----.", "---...", "-.-.-.", NULL, "-...-", NULL, "..--..",
  // @ A B C D E F G
  ".--.-.", ".-", "-...", "-.-.", "-..", ".", "..-.", "--.",
  // H I J K L M N O
  "....", "..", ".---", "-.-", ".-..", "--", "-.", "---",
  // P Q R S T U V W
  ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--",
  // X Y Z [ \ ] ^ _
  "-..-", "-.--", "--..", NULL, NULL, NULL, NULL, "..--.-",
  // ' a b c d e f g
  NULL, ".-", "-...", "-.-.", "-..", ".", "..-.", "--.",
  // h i j k l m n o
  "....", "..", ".---", "-.-", ".-..", "--", "-.", "---",
  // p q r s t u v w
  ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--",
  // x y z { | } ~ DEL
  "-..-", "-.--", "--..", NULL, NULL, NULL, NULL, NULL,
};

int dotLength = 40;
int dashLength = dotLength * 3;
int CW_pin = A0;
int flashPin = 13;
int freq = 650;
int Pin2 = 2;
int Pin3 = 3;
int Pin18 = 18;
int Pin19 = 19;
volatile int mess_number = 0;
volatile int buttonState = 0;

volatile boolean pressed = false;


void clearOLED(){
    u8g.firstPage(); 
    do {
    } while( u8g.nextPage() );
}



void prompt(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 0, 22, "Press 1-4");
}



void showText(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 0, 22, mess);
}



void setup()
  {
    clearOLED();    
    memset(mess,0,strlen(mess));
    pinMode(flashPin, OUTPUT);
    pinMode(CW_pin, OUTPUT);
    pinMode(Pin2, INPUT_PULLUP);
    pinMode(Pin3, INPUT_PULLUP);
    pinMode(Pin18, INPUT_PULLUP);
    pinMode(Pin19, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(Pin2), ISR_2, RISING);
    attachInterrupt(digitalPinToInterrupt(Pin3), ISR_3, RISING);
    attachInterrupt(digitalPinToInterrupt(Pin18), ISR_18, RISING);
    attachInterrupt(digitalPinToInterrupt(Pin19), ISR_19, RISING);
  }



void loop() 
  {
  int i = 0; 
  char ch;
  
  u8g.firstPage(); 
  do {
       prompt();
     } while( u8g.nextPage() );

  
  if (pressed == true) 
    { 
      strcpy(mess, myMem[mess_number-1]);
      
      u8g.firstPage(); 
      do {
         showText();
         } while( u8g.nextPage() );

      ch = mess[i];
      while (ch != NULL )
        {
          i++;
          makeDashDot(MorseTable[ch]);
          delay(dotLength * 2);
          ch = mess[i];
         }
       pressed = false;
       i = 0; 
     }

  }
  


void makeDashDot(const char * morseCode)
{
  int i = 0;
  while (morseCode[i] != 0)
  {
    if (morseCode[i] == '.') {
      dot();
    } else if (morseCode[i] == '-') {
      dash();
    }
    i++;
  }
}



void dot()
{
  digitalWrite(flashPin, HIGH);
  tone(CW_pin, freq);
  delay(dotLength);
  digitalWrite(flashPin, LOW);
  noTone(CW_pin);
  delay(dotLength);
}



void dash()
{
  digitalWrite(flashPin, HIGH);
  tone(CW_pin, freq);
  delay(dashLength);
  digitalWrite(flashPin, LOW);
  noTone(CW_pin);
  delay(dotLength);
}


void ISR_2()          
{    
   noInterrupts();   
   buttonState = digitalRead(Pin2);                                                             
   mess_number = 1;
   pressed = true;
   interrupts();
}



void ISR_3()          
{       
   noInterrupts();    
   buttonState = digitalRead(Pin3);                                                           
   mess_number = 2;
   pressed = true;
   interrupts();
}



void ISR_18()          
{     
   noInterrupts();  
   buttonState = digitalRead(Pin18);                                                               
   mess_number = 3;
   pressed = true;
   interrupts();   
}



void ISR_19()          
{              
   noInterrupts();       
   buttonState = digitalRead(Pin19);                                                 
   mess_number = 4;
   pressed = true;
   interrupts();
}

Description:

CW Keyer with Interrupts
Cw keyer w1ons1mdzn


YOU MIGHT ALSO LIKE