Go Down

Topic: Morse Code programming (Read 2 times) previous topic - next topic

Steen

#15
May 08, 2012, 07:29 pm Last Edit: May 08, 2012, 07:32 pm by Steen Reason: 1
I made this program that reads the button responses and sends them to the pc as a usb keyboard. it runs the way you did, and it runs perfectly fine... the code may not be the most clean one, but it does its job :)

Code: [Select]

#include "UsbKeyboard.h"

double cnt = 0;
int btnPin = 0;
double pauseCnt = 0;
boolean printCode = true;
int ledPin = 13;
int recPin = 1;
int psLengthPin = 6;
int psLengthPot = A0;
int dashLengthPot = A1;

double spd = 1;
double dashLength = 1;
boolean setSpd = true;
int buzzPin = 3;

int recCode[6] = {0,0,0,0,0,0};
int recPlace = 0;
int morseLts[246] = {/*A*/1,2,0,0,0,0 , /*B*/2,1,1,1,0,0 , /*C*/2,1,2,1,0,0 , /*D*/2,1,1,0,0,0 , /*E*/1,0,0,0,0,0 , /*F*/1,1,2,1,0,0 , /*G*/2,2,1,0,0,0 , /*H*/1,1,1,1,0,0 , /*I*/1,1,0,0,0,0 , /*J*/1,2,2,2,0,0 , /*K*/2,1,2,0,0,0 , /*L*/1,2,1,1,0,0 , /*M*/2,2,0,0,0,0 , /*N*/2,1,0,0,0,0 , /*O*/2,2,2,0,0,0 , /*P*/1,2,2,1,0,0 , /*Q*/2,2,1,2,0,0 , /*R*/1,2,1,0,0,0 , /*S*/1,1,1,0,0,0 , /*T*/2,0,0,0,0,0 , /*U*/1,1,2,0,0,0 , /*V*/1,1,1,2,0,0 , /*W*/1,2,2,0,0,0 , /*X*/2,1,1,2,0,0 , /*Y*/2,1,2,2,0,0 , /*Z*/2,2,1,1,0,0 , /*1*/1,2,2,2,2,0 , /*2*/1,1,2,2,2,0 , /*3*/1,1,1,2,2,0 , /*4*/1,1,1,1,2,0 , /*5*/1,1,1,1,1,0 , /*6*/2,1,1,1,1,0 , /*7*/2,2,1,1,1,0 , /*8*/2,2,2,1,1,0 , /*9*/2,2,2,2,1,0 , /*0*/2,2,2,2,2,0 , /*enter*/ 2,1,1,1,2,1, /*esc*/ 2,1,2,2,1,1, /*bcksp*/ 1,2,2,1,1,2 , /*tab*/ 1,1,2,2,0,0 , /*space*/1,2,1,2,0,0};

void setup() {
 
 pinMode(btnPin, INPUT);
 digitalWrite(btnPin, HIGH);
 
 pinMode(ledPin, OUTPUT);
 digitalWrite (ledPin, HIGH);
 
 pinMode(recPin, OUTPUT);
 digitalWrite(recPin, LOW);
 
 pinMode(psLengthPin, INPUT);
 digitalWrite(psLengthPin, HIGH);
 
 pinMode(buzzPin, OUTPUT);
 digitalWrite(buzzPin, LOW);
 
 pinMode(8, OUTPUT);
 pinMode(9, OUTPUT);
 pinMode(10, OUTPUT);
 digitalWrite(8, HIGH);
 digitalWrite(9, LOW);
 digitalWrite(10, LOW);
 
 TIMSK0&=!(1<<TOIE0);
 
 cli();
 
 usbDeviceDisconnect();
 delayMs(250);
 usbDeviceConnect();
 
 sei();
}

void loop() {
 
 UsbKeyboard.update();
 
 if(digitalRead(psLengthPin) == LOW) {
   
   spd = map(analogRead(psLengthPot), 0, 1024, 500, 10000);
   dashLength = map(analogRead(dashLengthPot), 0, 1024, 1000, 40000);
   //getSpd(spd);
 }
 else if(digitalRead(btnPin) == LOW) {
   setSpd = true;
   cnt++;
   pauseCnt = 0;
   printCode = true;
   digitalWrite(buzzPin, HIGH);
 }
 else {
   digitalWrite(buzzPin, LOW);
   pauseCnt++;
   if(cnt>(100)) {
     if(cnt<(dashLength/3)) {
       //Serial.print(cnt);
       //Serial.println("\tDot");
       
       if(recPlace<6) {
         recCode[recPlace] = 1;
         recPlace++;
       }
       
     }
     else if(cnt<dashLength) {
       //Serial.print(cnt);
       //Serial.println("\tDash");
       
       if(recPlace<6) {
         recCode[recPlace] = 2;
         recPlace++;
       }
       
     }
   }
   if(pauseCnt>=spd && printCode) {
       printCode = false;
       int checkVal = 0;
       int placeBuff = 0;
       boolean maySpace = true;
       
       for(int i=0; i<=240; i+=6) {
         checkVal = 0;
         for(int j=0; j<=5; j++) {
           if(recCode[j]==morseLts[i+j]) {
             checkVal++;
           }
           else {
             checkVal = 0;
           }
         }
         if(checkVal == 6) {
           digitalWrite(recPin, HIGH);
           //Serial.print((char)(97 + (i/4)));
           UsbKeyboard.sendKeyStroke(4+(i/6));
           digitalWrite(ledPin, !digitalRead(ledPin)); // Toggle status LED
           checkVal = 0;
           //maySpace = false;
           digitalWrite(recPin, LOW);
           break;
         }
       }        
       /*
       if(maySpace) {
         for(int i=0; i<=5; i++) {
           if(recCode[i] == morseLts[154+i]) {
             //Serial.print(" ");
             checkVal++;
           }
         }
         if(checkVal == 6) {
           digitalWrite(recPin, HIGH);
           //Serial.print(" ");
           UsbKeyboard.sendKeyStroke(44);
           digitalWrite(recPin, LOW);
         }
       }
       */
       for(int i=0; i<=5; i++) {
         recCode[i] = 0;
       }
       recPlace = 0;
     }
   cnt = 0;
 }
}

void delayMs(unsigned int ms)
{
 for (int i = 0; i < ms; i++) {
   delayMicroseconds(1000);
 }
}

int getSpd(int nr) {
 
 digitalWrite(8, LOW);
 digitalWrite(9, LOW);
 digitalWrite(10, LOW);
 
 if(nr>=0 && nr<1) {
   digitalWrite(8, HIGH);
 } else if(nr>=1 && nr<2) {
   digitalWrite(9, HIGH);
 } else if(nr>=2 && nr<=3) {
   digitalWrite(10, HIGH);
 }
}


it reads the values from 2 potmeters as length from dash/dot and length of the pause between two letters. this way you can set it up completely the way you want, at every speed you want. There is this led that flashes when the char is recognized, and the buzzer buzzes as long as you press the button

Grumpy_Mike

Code: [Select]
if(  (dash_in_progress == 1) && (millis() >=dashEndmillis) ) { //
      dash_in_progress = 0;
      leddashState = LOW;
}

When is this ever written out to the actual LED?

CrossRoads

Code: [Select]
[code]
case 'b':    
     dot();
     dot();
     dash();
     break;

you need an off space in between the characters, otherwise one ends and it goes right into next:

Code: [Select]

     dot();
     character_space();
     dot();
     letter_space(); // or relaxTime, whatever you call this
     dash();
     letter_space();
     break;


Code: [Select]

void letter_space(){
 letterSpaceEndmillis = millis(); // capture the start time time of the space
 letter_space_in_progress = 1; // set flag
 }


then in loop:
Code: [Select]

if(  (letter_space_in_progress == 1) && (millis() >=letter_spaceEndmillis) ) { //
     letter_space_in_progress = 0;
     // end of dot & dash already turn the ledPin off, no need to here
}


I was thinking, you probably need to change this around some, to that each dot & dash & space, & then character, has time to finish before the next one starts:

   if (Serial.available() > 0 && inbyte ==0) { // nothing in progress
   int inByte = Serial.read(); //let inByte change for next switch:case call
   // in Byte is nonzero now
   }

then keep track of a dot/dash/space as it occurs:
void dot(){
 dotEndmillis;
 dot_in_progress = 1;
 leddotState = HIGH;
 digitalWrite (ledPin, leddotState);
 }



// inByte is nonzero
   case 'c':    
     dash();
     letter_space();
     dot();
      letter_space();
      dot();
      letter_space();
     // end each character by clearing inByte
     inByte = 0;
     break;
[/code]

This is still very linear tho, the program needs a way to know whether each dot/dash/space is done; if not don't start the next one, but do continue to do other stuff, and when a dot/dash/space is done, start the next one in the sequence, so maybe a switch:case inside the switch:case?
Code: [Select]

void loop(){

   if( (dot_in_progress == 1) && (millis() >=dotEndmillis) ) { //
     dot_in_progress = 0;
     digitalWrite (ledPin, LOW);  // turn off theLED
     ledPinState = LOW;  // note the LED state
   }
if(  (dash_in_progress == 1) && (millis() >=dashEndmillis) ) { //
     dash_in_progress = 0;
     digitalWrite (ledPin, LOW);
     ledPinState = LOW;
}
// same for letter space,word space

// then allow switch(inByte) if the previous dot/dash/space ended
if (ledPinState == 0){
switch (inByte){
:
:
   case 'c':    
    char_code = char_code+1;
     switch (char_code){
     case 1:
           dash();
           char_code = char_code+1;
           break;
     case 2:
           letter_space();
           char_code = char_code+1;
           break;
    case 3:
           dot();
           char_code = char_code+1;
           break;
    case 4:
      letter_space();
           char_code = char_code+1;
           break;
      case 5:
           dot();
           char_code = char_code+1;
           break;
      case 6:
           letter_space();
     // end each character by clearing inByte & char_code
     char_code = 0;
     inByte = 0;
     break;
   } // end switch char_code
:
:
}// end switch inByte



Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

The Clever Monkey


I have been trying for a little while to come up with a program for a morse code transmitter. It uses an led to flash what is typed into the serial monitor. The problem is that all of the code I have seen on the Internet uses delay and I can't use that because I am eventually going to have to have it send and receive at the same time. Can anyone one provide with something similar to delay that won't stop everything. I have been trying to work with millis, but it is getting complicated.


You may have already seen this one: http://hackaday.com/2012/05/11/morse-code-interpreter/
I yield() for co-routines.

Go Up